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..0cdaa9e28 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,10 +13,10 @@ 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://www.youtube.com/playlist?list=PLyADkcfPLU8ywCXZPaDbQ_JZJL0CGDN5Z "Watch Videos") -[](https://discord.gg/hmaD7Se "Feedback & Help") -[](https://www.patreon.com/simibubi "Support Us") +[](https://github.com/Creators-of-Create/Create/issues "Report Issues") +[](https://www.youtube.com/channel/UCrKV2QTuyGcv4E3eSJpBiYA/playlists "Watch Videos") +[](https://discord.gg/hmaD7Se "Feedback & Help") +[](https://www.patreon.com/simibubi "Support Us") - Support for Minecraft 1.12: Not planned - Support for Fabric: Not planned diff --git a/build.gradle b/build.gradle index c1cdabd3f..d8cd566cd 100644 --- a/build.gradle +++ b/build.gradle @@ -1,46 +1,49 @@ 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'); ext.buildnumber = 0 project.buildnumber = System.getenv('BUILD_NUMBER') != null ? System.getenv('BUILD_NUMBER') : "custom" -version = "mc${minecraft_version}_v${mod_version}" + (dev ? "+${buildnumber}" : '') +version = "mc${minecraft_version}_v${mod_version}" + (dev && !buildnumber.equals("custom") ? "+${buildnumber}" : '') group = 'com.simibubi.create' archivesBaseName = 'create' -sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' +java.toolchain.languageVersion = JavaLanguageVersion.of(8) minecraft { - mappings channel: 'snapshot', version: '20200920-mixed-1.16.3' - accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + mappings channel: 'official', version: "${minecraft_version}" + 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.remapRefMap', 'true' + property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg" mods { create { source sourceSets.main @@ -52,6 +55,8 @@ minecraft { workingDirectory project.file('run/server') arg '-mixin.config=create.mixins.json' property 'forge.logging.console.level', 'info' + property 'mixin.env.remapRefMap', 'true' + property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg" mods { create { source sourceSets.main @@ -64,6 +69,8 @@ minecraft { property 'forge.logging.markers', 'REGISTRIES,REGISTRYDUMP' property 'forge.logging.console.level', 'debug' property 'fml.earlyprogresswindow', 'false' + property 'mixin.env.remapRefMap', 'true' + property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg" args '--mod', 'create', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources') mods { create { @@ -82,30 +89,40 @@ 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/" + // Location of the maven that hosts JEI files (and TiC) + 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" + /*maven { + // Location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "https://modmaven.k-4u.nl" }*/ maven { - //location of the maven for vazkii's mods - name "blamejared" - url "http://maven.blamejared.com/" + // Location of the maven for vazkii's mods + name = "blamejared" + url = "http://maven.blamejared.com/" } maven { - //location of the maven for mixed mappings and registrate + // Location of the maven for mixed mappings, Registrate, and Flywheel name = "tterrag maven" url = "https://maven.tterrag.com/" } maven { url = "https://www.cursemaven.com" + content { + includeGroup "curse.maven" + } + } + maven { + //location of the maven for dynamic trees + url "http://harleyoconnor.com/maven" } } @@ -116,24 +133,32 @@ 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") - // at runtime, use the full JEI jar - runtimeOnly fg.deobf("mezz.jei:jei-1.16.4:${jei_version}") + if (findProject(':Flywheel') != null) { + implementation project(':Flywheel') // jozu: I use a gradle workspace with both projects + } else { + implementation fg.deobf("com.jozufozu.flywheel:Flywheel:${flywheel_version}") + } + + // Compile against the JEI API but do not include it at runtime + 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.5:${jei_version}") // implementation fg.deobf("curse.maven:druidcraft-340991:3101903") + implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta12.1") + // 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.115") + //runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252") - annotationProcessor 'org.spongepowered:mixin:0.8:processor' + annotationProcessor 'org.spongepowered:mixin:0.8.2:processor' } jar { @@ -162,6 +187,40 @@ reobf { shadowJar {} } + +task sourcesJar(type: Jar) { + from sourceSets.main.allSource + archiveBaseName.set(project.archivesBaseName) + archiveVersion.set("${project.version}") + archiveClassifier.set('sources') +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + from javadoc.destinationDir + archiveClassifier.set('javadoc') +} + +artifacts { + archives jar, shadowJar, sourcesJar, javadocJar +} + +publishing { + tasks.publish.dependsOn 'build' + publications { + mavenJava(MavenPublication) { + artifact shadowJar + artifact sourcesJar + artifact javadocJar + } + } + + repositories { + if (project.hasProperty('mavendir')) { + maven { url mavendir } + } + } +} + String getChangelogText() { def changelogFile = file('changelog.txt') String str = '' @@ -212,13 +271,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/changelog.txt b/changelog.txt index 191b1ac85..e69de29bb 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,64 +0,0 @@ -0.2.4d: -More tiny bugfixes; we appreciate the reports! -Changes -- Cart assemblers now have several behaviours depending on the rail type they were placed on -Fixes -- Fixed dedicated server crash when using the Schematicannon -- Fixed blockzappers placing waterlogged blocks -- Updated chinese localization -- Added missing recipe for Dark Scoria - -0.2.4c: -A hotfix for our dear users over in Multiplayer. -Fixes -- (0.2.4b) Fixed server crash when Cart Assembler accelerates held Minecarts -- Fixed build errors of previous version - -0.2.4a: -Just a few Bug-Fixes since the recent 1.15 release. Enjoy! -Fixes -- Fixed pistons moving at inconsistent speeds, overshooting their bounds -- Fixed belts not moving entities -- Fixed diagonal belts teleporting entities miles away -- Fixed tree fertilizer not working -- Patched some localization gaps -- Fixed pulley placing down ropes when destroyed while moving -- Fixed inconsistencies with glue removal and placement -- Fixed crash when placing a crafter between two colliding rotation sources -- Fixed cases of self-powering loops caused by blocks rotated using the wrench -- Fixed Extendo Grip animation for left-handed players -- Fixed encoding of degree symbols in tooltips - -0.2.4: -Welcome to the future! Glad you are still here. -Warning -- Do NOT transfer world or schematic data from 1.14. This version is incompatible with any of the prior versions! -New -- Ported Create to Minecraft 1.15.2 -- Added Nixie Tubes -- Added the Extendo Grip -- Added support for TerraForged worldgen -Changes -- Removed Windowlogging, might come back as a stand-alone -- Removed Blazing, Shadow Steel and Gilded Quartz Toolsets -- Massively reworked Create palettes, offering a whole bunch of new patterns! -- The Creative Motor can now face in any direction -- The Creative Motor, Encased Fan and other directional blocks will now reverse their effective rotation when oriented backwards -- Redstone link receivers now emit their signal with the level of the strongest transmitter of the same frequency -- Changed the way cart assemblers react to redstone input -- Blocks that couldn't be placed when a contraption disassembles, now drop as items -- Some fixes regarding inconsistencies with Super Glue placement -- Deployers no longer consume food -- Deployers can now feed players -- Ploughs no longer break blocks if farmland is below them -- Super glue can no longer be removed while inbetween two blocks -Fixes -- Fixed Bells duplicating themselves when moved by a contraption -- Fixed moved Deployers in breaking mode getting stuck on fluids or bedrock -- Schematicannons can no longer place water in the nether -- Fixed bug with extractors not always being able to pull from moved contraptions -- Fixed deployers not able to place certain foods on campfires -- Fixed fire-immune creatures taking damage from heated air currents -- Endermen now take damage from washing fans -- Fixed crash when assembled minecarts pick up the block below their assembler -- Schematicannons can no longer place lit furnaces \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 6f4a1d878..e77ab6368 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,20 +1,27 @@ # 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.2e +minecraft_version = 1.16.5 +forge_version = 36.2.0 + +# build dependency versions +forgegradle_version = 4.1.+ +mixingradle_version = 0.7-SNAPSHOT +shadow_version = 6.1.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.10 +flywheel_version = 1.16-0.2.3.44 +jei_version = 7.7.1.116 # 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..e708b1c02 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..549d84424 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-6.9-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..4f906e0c8 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" @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ 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"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f9553162f..107acd32c 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 @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @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 set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..ecc4e7182 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'Create' diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 7f62cb3f8..90889ce8b 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -23,12 +23,16 @@ e555e3c2b2d3f01440e48db4ba88f7e00fd99b6f assets/create/blockstates/basin.json f25693a9429f6337149ff24f27900dc4eb82a7c2 assets/create/blockstates/belt.json cf9045eb16e5299a1d917c4cb536289f49411276 assets/create/blockstates/birch_window.json 94a1a91403eb4b035fec48071e7fcae57a8a6abd assets/create/blockstates/birch_window_pane.json +8d257089491a1f6e87544242c9fe9af0127b4f88 assets/create/blockstates/black_nixie_tube.json e0f1e44c9bce4a7478592cf3a8ee7b91d9083d65 assets/create/blockstates/black_sail.json 58b07d2af6030342f0354f6d3fd0ee128d2d74b4 assets/create/blockstates/black_seat.json +73db8bd55bd5bd21f939ee9eb4b4b02209d9c5ed assets/create/blockstates/black_toolbox.json a71ddf3291bd13d7877f2fe32c42f50407f99afb assets/create/blockstates/black_valve_handle.json 923aeb2a556f67bc0526f237dd97af2d37b4c9f1 assets/create/blockstates/blaze_burner.json +b619f127c38e9ffdb4e45bb32e5cea35863622f3 assets/create/blockstates/blue_nixie_tube.json ec2ab87734acc209e6be3bc4898b1199f819bfd3 assets/create/blockstates/blue_sail.json 4854d1ef52130a7887aecc60bcaffbd66f0871a8 assets/create/blockstates/blue_seat.json +dea175335c5db0abe758cd208dc984c22506a176 assets/create/blockstates/blue_toolbox.json 9d7341a5cae5d47788c595167946dfb6441cebd1 assets/create/blockstates/blue_valve_handle.json ee1299a15fca849eb42bf81507f85a54c167bbfe assets/create/blockstates/brass_belt_funnel.json 8b1dd00adcc7e74c5a9feed069e2610b15a338cb assets/create/blockstates/brass_block.json @@ -36,10 +40,12 @@ b8dd6e505943e06706d0718ece620ab3cf943650 assets/create/blockstates/brass_casing. 288bad07593a8a2c8efaf44bba0ffb0011d36cd3 assets/create/blockstates/brass_encased_shaft.json adfbd6cc5e44a0f431180aedbe65a19428299d8e assets/create/blockstates/brass_funnel.json 672eedcd3520c6d39603449165a23be9c612c620 assets/create/blockstates/brass_tunnel.json +9526a0758dcfda9fbbf75c01548e96bb5887a52f assets/create/blockstates/brown_nixie_tube.json 11ebdd9bd0815833e62ec1bea03a4cdd86ce00f3 assets/create/blockstates/brown_sail.json e81608346d43406ee72cae0f78b8bcfb37ba2d75 assets/create/blockstates/brown_seat.json +bd73bfdbe88c58883cc15fe31a9dac7860482ca3 assets/create/blockstates/brown_toolbox.json 322289524c058fac66bbe76b4924c3b0c0c33b84 assets/create/blockstates/brown_valve_handle.json -1ef072f86d95fd84638bbb6c298603eb311d1e53 assets/create/blockstates/cart_assembler.json +225a67e01348387f2c82b690a56785ab439a3a1c assets/create/blockstates/cart_assembler.json 7299cea212d879d6d5611bd139b24768b9af236f assets/create/blockstates/chiseled_dark_scoria.json 0f01f813388d3e6907c1cfd992e4b21c914e267e assets/create/blockstates/chiseled_dolomite.json 324488e0c228f38f2597b2f76849e962bc1a7d90 assets/create/blockstates/chiseled_gabbro.json @@ -68,8 +74,10 @@ f0031f5e970b3d5695472ed384950b8631b015ed assets/create/blockstates/creative_moto fe2f78b94c20944399101e7369e2d43324297fb6 assets/create/blockstates/crushing_wheel.json a1dd6cb3daa97ea871290ef7b178d28b564ee2a2 assets/create/blockstates/crushing_wheel_controller.json b1126c191877cff86b4e2de83e1fcbd151451cb7 assets/create/blockstates/cuckoo_clock.json +d986774dc41e5f01c6f3ffd10765df94f196922d assets/create/blockstates/cyan_nixie_tube.json b496452f2f7dbbba385e1fc10b560ec266e4b5e7 assets/create/blockstates/cyan_sail.json 4de72f65bff4e5d9c8153fa3adeee6b61d6f912b assets/create/blockstates/cyan_seat.json +8e14112e948e492da8151b773c1fa40bf1467490 assets/create/blockstates/cyan_toolbox.json 2c04d57e56849f243aec8a1e769574d24daac1e9 assets/create/blockstates/cyan_valve_handle.json 1726b1b9e04a0634e7e1fdcf1cf4cc898efc5c2f assets/create/blockstates/dark_oak_window.json 50d4627d8e8b5adade12de764ab528ddacfa9ea5 assets/create/blockstates/dark_oak_window_pane.json @@ -174,13 +182,18 @@ a4b0337149cb0617cc60061477c7178d37dbb831 assets/create/blockstates/granite_cobbl d97fdea02187e63f6b63913357c79a18660d676d assets/create/blockstates/granite_cobblestone_stairs.json 2f29568407970ea0e3807e0553e0584d127a9014 assets/create/blockstates/granite_cobblestone_wall.json f8659e81cd2a623475a6a9aca59149e82de56b1c assets/create/blockstates/granite_pillar.json +4478ee1b4c7a17deea77ee0d1234a19725889671 assets/create/blockstates/gray_nixie_tube.json 5c40c4a27e1dec747a467dd251700c72a6ceb07d assets/create/blockstates/gray_sail.json a5ec5401ba9f3e102a2e1b35837f643847afbca4 assets/create/blockstates/gray_seat.json +191d2cc56af51349688ccb2dea75801a9bc9de85 assets/create/blockstates/gray_toolbox.json 5f17a5868616b33eb157965a661046cab7a1427f assets/create/blockstates/gray_valve_handle.json +747579dd8e635533c15208cec25afe445ff4774a assets/create/blockstates/green_nixie_tube.json 52b849faef96b8ab9d9d64a1518c8f299af057b8 assets/create/blockstates/green_sail.json 13059309684db0cc7a0f1f4fce2407cf06cce80a assets/create/blockstates/green_seat.json +e91dcebe132d5b745df0f6c5b1c90d5fc4e8af52 assets/create/blockstates/green_toolbox.json f4a0fc68e8daaa0a47cdc951ced4310057a874b0 assets/create/blockstates/green_valve_handle.json 6ab675fa06317e6d07c0c1a453e7bb43e3f46b3b assets/create/blockstates/hand_crank.json +34076c9caafe48daa87cc783e96d4c81b0b164c0 assets/create/blockstates/haunted_bell.json 4572b90f5d6c586e145f2c7a55664c3cb734bd2b assets/create/blockstates/honey.json be3bef7e091d8b50bfc1c6b7275946d1f636aefd assets/create/blockstates/horizontal_framed_glass.json 18d9fdaa1352a7e2ec91135e46dae5c02ccd8f8f assets/create/blockstates/horizontal_framed_glass_pane.json @@ -198,14 +211,21 @@ a4cfcdc038af0f93a58d88ea8860b34d73632ff4 assets/create/blockstates/layered_dolom 038f532f7364c1e793196fcc5856df9ceff93578 assets/create/blockstates/layered_limestone.json 8535d628f8834be62cdf62ef4b60c2ce3a7af99f assets/create/blockstates/layered_scoria.json 419d7fffc5cbd392f10211afa8d17e3eb8df8380 assets/create/blockstates/layered_weathered_limestone.json +6a3c81d62c7c5a5fa2f4a1e239319d83875bbe55 assets/create/blockstates/lectern_controller.json +e0c8fc35bfa28f025bdc14085b01b179e36c9f96 assets/create/blockstates/light_blue_nixie_tube.json 029904f21970947a4423a6e0c8c65c4e02f2e8e6 assets/create/blockstates/light_blue_sail.json 2a0a8b1715700bf1e284ee57ef9f7f163c12f3ee assets/create/blockstates/light_blue_seat.json +527f32e0d2b5b975cfeb515542098bb2d5224755 assets/create/blockstates/light_blue_toolbox.json 9bee040558a6b24e21f837fc808e17fae1883e71 assets/create/blockstates/light_blue_valve_handle.json +745b940c71575afbfac1786ffe1a23dcb62d5e70 assets/create/blockstates/light_gray_nixie_tube.json 93537c4e2ab86218a777e7b000c3fcd55a80b1cd assets/create/blockstates/light_gray_sail.json d9a2551e001bb315d071bb9f1f013323a66a5d09 assets/create/blockstates/light_gray_seat.json +0c40d13637f00a533175d29ba67559461101ead5 assets/create/blockstates/light_gray_toolbox.json 8bea8c86de8c218c8932eef140f0ed439e173156 assets/create/blockstates/light_gray_valve_handle.json +3bee155fee49a9f85403f018a51e60c0e536d51c assets/create/blockstates/lime_nixie_tube.json ba2c4e3ddafa3c89a72cc243b14e8518fab369aa assets/create/blockstates/lime_sail.json 1de3a88c003df03f5006e1bbaa0236589aba08ad assets/create/blockstates/lime_seat.json +db46a5b6d0b595293a672236d0a64548b0816cab assets/create/blockstates/lime_toolbox.json 179a3e68b9f2e289eafe0e98e768befbbf91c5c2 assets/create/blockstates/lime_valve_handle.json c4dcb169bd1dffe8501bff455e3eb6ba979f60ab assets/create/blockstates/limesand.json e7cb0b25e511610b46dfd219e0cc5ea60a79d56b assets/create/blockstates/limestone.json @@ -219,9 +239,11 @@ e7c7b952137c4cb615988ea59b9f14303c9a4dfe assets/create/blockstates/limestone_bri 10513d55f7c621162a13d474d8f4eb54305d0f60 assets/create/blockstates/limestone_cobblestone_wall.json b7506b862d13b3f915c60d38bb7a20afc935f70a assets/create/blockstates/limestone_pillar.json 69790737767e06f000c7824749c46664a123160e assets/create/blockstates/linear_chassis.json -07bae932a163b81f8749f98287b4fb4949fe0b8b assets/create/blockstates/lit_blaze_burner.json +56b111c8a345627e9f37deac141138064271c2f1 assets/create/blockstates/lit_blaze_burner.json +e99e9c5cf03334a48d9d071e1590bc8f286d3cf6 assets/create/blockstates/magenta_nixie_tube.json 85a58ac539775f90903d9ce66374f3f2ffd4fecf assets/create/blockstates/magenta_sail.json 84c494d24cc58af274fdd054896c680e8095d2d0 assets/create/blockstates/magenta_seat.json +2334006c152d6773040ca03ef3b3d26a58f0dfa0 assets/create/blockstates/magenta_toolbox.json 3bfce5016e5c929b74368dc2d734e62ae34587a4 assets/create/blockstates/magenta_valve_handle.json 3b3250d6e209403a93d025604a8081087965016e assets/create/blockstates/mechanical_arm.json ddcf4bb281e046fbb1026b8f46a2cf12448598df assets/create/blockstates/mechanical_bearing.json @@ -249,12 +271,13 @@ a3ae5fb61cb07ae6fcb78ba68435bda8c31d4430 assets/create/blockstates/mossy_granite 3feafb33a6ba03687a521c1b196536c0427fff77 assets/create/blockstates/mossy_weathered_limestone.json b1126c191877cff86b4e2de83e1fcbd151451cb7 assets/create/blockstates/mysterious_cuckoo_clock.json 8d56251190c94204fa238ff32734a0761273669f assets/create/blockstates/natural_scoria.json -0f7635a4fec6961ec09788b3c5e3992ed1fdfde7 assets/create/blockstates/nixie_tube.json +f090a023bebb8590ed609d0c624277703b4699a4 assets/create/blockstates/nixie_tube.json 36e46e65003a8d0b8555fe5e8f8dc980d6559bc5 assets/create/blockstates/nozzle.json cf60989f63f02067fc4e4ad25033ac83167cdeb0 assets/create/blockstates/oak_window.json 4a796509c3953171f04f957351282205840b3760 assets/create/blockstates/oak_window_pane.json b0be3d4ff92cb123ec21ec2788db35d0f392ba8a assets/create/blockstates/orange_sail.json 5764a24f6c4fa552b61d2a02135adfc7d93c2e10 assets/create/blockstates/orange_seat.json +7541e5efb98cddf8cdf62138b674458cda877a4c assets/create/blockstates/orange_toolbox.json 1445074ec21a3735ea912b624c0f9f18a450d2d3 assets/create/blockstates/orange_valve_handle.json 8e2028e1a0450a592eed5e10276ba19b1195a206 assets/create/blockstates/ornate_iron_window.json f59198fd966927e21e9bf76e64de533d05ea893b assets/create/blockstates/ornate_iron_window_pane.json @@ -303,8 +326,11 @@ c17d334e938dcb742550ba8307ca8266a1fc9b49 assets/create/blockstates/paved_weather cb23aef25f3106b06c8fa8f152c638bb0d2185d8 assets/create/blockstates/paved_weathered_limestone_slab.json d62b0992cec1de45dad1f2c273132225f4ef33a0 assets/create/blockstates/paved_weathered_limestone_stairs.json e29e245d06c46dac94fcd0e01a9bf7fa8e02fb87 assets/create/blockstates/paved_weathered_limestone_wall.json +005cc195712aca252326ae8239ed0caf9a69a314 assets/create/blockstates/peculiar_bell.json +06ad2ce2f1730488d51daf12b4a985c86d43bbb4 assets/create/blockstates/pink_nixie_tube.json 30971f2f76fe56f144178c33ad6bde5fc9fb61c3 assets/create/blockstates/pink_sail.json 919a79e4a4a5fab0aac3ef48e1c786017d6aa001 assets/create/blockstates/pink_seat.json +588ebcdb4c1d8d4c75225e92f26d6cf80cac2f15 assets/create/blockstates/pink_toolbox.json 471a3bb474a0ae0453143888d561256cce894e3f assets/create/blockstates/pink_valve_handle.json 975c97018e9e2419943eaab43aed0970e96feaf7 assets/create/blockstates/piston_extension_pole.json 2f764f460aa1d75ba995da180bc6f8d2bd9db385 assets/create/blockstates/polished_dark_scoria.json @@ -337,12 +363,16 @@ ad721e3911f48c61c3639edac1896680a31451ff assets/create/blockstates/polished_weat e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggle_latch.json 3a739f9d4276828d83f2d2750bf3227c87bcd438 assets/create/blockstates/pulley_magnet.json 469e430d96cb0a5e1aaf6b7cc5d401d488c9e600 assets/create/blockstates/pulse_repeater.json +83ad917bb7f528e68d64f3859b3bf1236080d454 assets/create/blockstates/purple_nixie_tube.json d06cd9a1101b18d306a786320aab12018b1325d6 assets/create/blockstates/purple_sail.json 92957119abd5fbcca36a113b2a80255fd70fc303 assets/create/blockstates/purple_seat.json +b78c6057ef94b03f541a17e625b3778ca526a6ad assets/create/blockstates/purple_toolbox.json 61035f8afe75ff7bbd291da5d8690bcbebe679eb assets/create/blockstates/purple_valve_handle.json 4439fc83a8c7370ab44b211a3fd48abde20a4728 assets/create/blockstates/radial_chassis.json +3735f396cf8e8bab0793ce2bfa281b29af73919e assets/create/blockstates/red_nixie_tube.json 45877c4d90a7185c2f304edbd67379d800920439 assets/create/blockstates/red_sail.json da1b08387af7afa0855ee8d040f620c01f20660a assets/create/blockstates/red_seat.json +27fad7876f5a2de16f13dfde16d4a05dfe093989 assets/create/blockstates/red_toolbox.json 722fc77bbf387af8a4016e42cbf9501d2b968881 assets/create/blockstates/red_valve_handle.json 8929677f2cc5354aa19ef182af69f9f0b41eb242 assets/create/blockstates/redstone_contact.json c29213b77ac0c78d8979c5f6188d2b265696f9b9 assets/create/blockstates/redstone_link.json @@ -385,7 +415,7 @@ a8094531617e27a545c4815ab2062bf0ffca3633 assets/create/blockstates/turntable.jso c4db76b9d36cfb098df0d158cb6f8b82768ebe14 assets/create/blockstates/vertical_framed_glass_pane.json 3a5da54d9763e9512cfaa47b25226b79738b25f3 assets/create/blockstates/warped_window.json 19ef7a16c82f07d304fb60d121845185d189aecf assets/create/blockstates/warped_window_pane.json -d995547bcd71603ba7378d8998098e462030bfd0 assets/create/blockstates/water_wheel.json +d31fce8315c8715521d66b5dcc166c84e949dd1d assets/create/blockstates/water_wheel.json f182669f7547964f9f2ef67916568556870def7b assets/create/blockstates/weathered_limestone.json 27e6740834c0f673acc3531371512daa6dcab025 assets/create/blockstates/weathered_limestone_bricks.json abb74e4f4c2b9851670cb6ad794281b0f7be0f5a assets/create/blockstates/weathered_limestone_bricks_slab.json @@ -397,31 +427,34 @@ fd7a9c7095372485081436c91489cadb2b0c514e assets/create/blockstates/weathered_lim dfa5662bfd5a70bcd87673b1c40bf9106d5e2365 assets/create/blockstates/weathered_limestone_cobblestone_wall.json c77b46d8b459e5c7cc495393546f3fcca8a1fa1d assets/create/blockstates/weathered_limestone_pillar.json c838c0792511ca2e14493b40032bb1370fac588a assets/create/blockstates/weighted_ejector.json +aef042718ae54973cbafdb4507c32944d722e99d assets/create/blockstates/white_nixie_tube.json 512bf17c9ea309b1f7da54440f923530d25e467c assets/create/blockstates/white_sail.json 4647010162eb4c350fad236d860317eaa1884c77 assets/create/blockstates/white_seat.json +3695510f11231c8a5c1a0be94a92703e4b5a0f9c assets/create/blockstates/white_toolbox.json 89000903d0ab8139e919abea7aa0361b34c24e55 assets/create/blockstates/white_valve_handle.json c4cd1131113667da0180898b5db3ebad609db8ba assets/create/blockstates/windmill_bearing.json d4f804f2818376950ef28fc8d6250419f4e12218 assets/create/blockstates/wooden_bracket.json +de1557d79eebf1cd469d098639cd6b5518b52b61 assets/create/blockstates/yellow_nixie_tube.json e03c48512967845fce09d84b955d3bc7b480fedc assets/create/blockstates/yellow_sail.json a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.json +bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbox.json 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 +5ae77ed97ee05a7ed98999178677e576c1140007 assets/create/lang/en_ud.json +5a7c0c3ea8d5fe01289b4eb2ea4f175bad825672 assets/create/lang/en_us.json +474dbefbecbec7e8e5969d7226a8c8a0c7a75325 assets/create/lang/unfinished/de_de.json +4d0c0f13e5447af9103b50e9ed845590634a8133 assets/create/lang/unfinished/es_es.json +5ad47cb60df592b461672e224dfb89167f8861e1 assets/create/lang/unfinished/fr_fr.json +216065d27084497ffed7cacddfe86cab542643d9 assets/create/lang/unfinished/it_it.json +e74e7450bb11ebe75b14630ea500a442c90d5d55 assets/create/lang/unfinished/ja_jp.json +29bf73836a76028d8eaef57bec7331b7f8df5fc3 assets/create/lang/unfinished/ko_kr.json +1c9e4860d53f73ce8eb9c3e6667e934cdea4e14b assets/create/lang/unfinished/nl_nl.json +e27542eb76681655d427cfbfe4826ee318b29ce0 assets/create/lang/unfinished/pl_pl.json +4cb49ac9acc2bac92522318fa326f4854d3ae836 assets/create/lang/unfinished/pt_br.json +ee8a147e1e86c1163a21452b5ea90d9d89dd3b09 assets/create/lang/unfinished/ru_ru.json +ed48c2e55f86cbc6005b2c222f0a5d6a01e996ad assets/create/lang/unfinished/zh_cn.json +dca24cfe0020830653e191b03fdd0400c890be1f 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 @@ -491,11 +524,15 @@ a5f0ed76e27d2ca706445f7f7c5f9270f98e34f9 assets/create/models/block/birch_window f40c4d4ea6c037158f4b9862a7c11e6024a261e6 assets/create/models/block/birch_window_pane_post.json dbfd2a996820d885d9741a3f168aa36c3538cfbd assets/create/models/block/birch_window_pane_side.json 557b35671ec417597259ba8d0239fe18c14c3d20 assets/create/models/block/birch_window_pane_side_alt.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/black_nixie_tube.json 2b59d6f937cd542eba670689c30fe16887dfd9a0 assets/create/models/block/black_sail.json 97d79ab99c0fb278a9b5dc54e1c6563868f87b76 assets/create/models/block/black_seat.json +fd31e42c40ceec10c4973f3c4ac728a3c2144d49 assets/create/models/block/black_toolbox.json 02747ea1a0e5d4a1cd466bf26878885a89d347fa assets/create/models/block/black_valve_handle.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/blue_nixie_tube.json d876627b6e519c6f3f59c7c27cc7b0f903206f7c assets/create/models/block/blue_sail.json e58b00a7222152d7facbe0e82f00933b974df747 assets/create/models/block/blue_seat.json +a79f5632a2d489355317021b6ad383c30d208b30 assets/create/models/block/blue_toolbox.json c7f91468b196fbda137e6b31764870b3bbfda6b6 assets/create/models/block/blue_valve_handle.json 213e99062a7f2a5e7464082d7975066bc6fc45e0 assets/create/models/block/bracket/cog/ground_metal.json 16e824026066d930187d812e77e2e582c0d3c1cc assets/create/models/block/bracket/cog/ground_wooden.json @@ -532,8 +569,10 @@ fd6f6607a4742fa87dfe1768927a29dc4975ce7a assets/create/models/block/brass_funnel a959e03ca339badb49fe58ba53d86a84352e91f3 assets/create/models/block/brass_tunnel/t_left.json 0585fbe58da3a8ed0dc98cc7ed79ac067312078d assets/create/models/block/brass_tunnel/t_right.json a0612a633756433e1b37ddc6d290aa1fc07839ef assets/create/models/block/brass_tunnel/window.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/brown_nixie_tube.json 8ab097caaa0db0915ae9254f7d65092d9171bc60 assets/create/models/block/brown_sail.json 4eed0ad902f5e84f2b6c160f3283e8028640e77d assets/create/models/block/brown_seat.json +81ce3254c2dbe73668ced13b3ee0ab2462f9d51f assets/create/models/block/brown_toolbox.json 6c39677f8c3a84280835c717ea1ef569b7c76a1b assets/create/models/block/brown_valve_handle.json db7279f05c1d89e21da8887a15d3a1cfff4a9cf2 assets/create/models/block/chiseled_dark_scoria.json 22d4ad2de48739ab754f8dfcd6f84ad2267abf8b assets/create/models/block/chiseled_dolomite.json @@ -585,8 +624,10 @@ a6eea01609266b757342984889af16234ecd5189 assets/create/models/block/creative_top 14a14ab7c1a812a5ac8e282747f125461bf6b1d5 assets/create/models/block/crimson_window_pane_post.json b9e6d8befe3f2281413288e0350425987256e238 assets/create/models/block/crimson_window_pane_side.json bcbfa40524cff0314d9e764a64f90f2095d14064 assets/create/models/block/crimson_window_pane_side_alt.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/cyan_nixie_tube.json 68843a02a32c156afad85830877b83f9b51c5147 assets/create/models/block/cyan_sail.json 6704782830b3d872321e895b6903709c18e3778f assets/create/models/block/cyan_seat.json +9d92e6340036cbcf5886fa9d36047ba938b51294 assets/create/models/block/cyan_toolbox.json f45ef4a5f0aa8482d493661673b1c0ab6d061157 assets/create/models/block/cyan_valve_handle.json f5ac5007454cb04490e36f39e9047cc90501b2f6 assets/create/models/block/dark_oak_window.json d1914f0b453d360221b14ff128f5a5040441a0c6 assets/create/models/block/dark_oak_window_pane_noside.json @@ -812,12 +853,20 @@ ddc8bf8dc62464d424ab812f801dd7a1f68072d0 assets/create/models/block/granite_cobb 87f6b4e30f2cdd0ddb3b48e43f15317b386597e6 assets/create/models/block/granite_cobblestone_wall_side.json 5c7340740d822deae7aa32c15c36531476862fbb assets/create/models/block/granite_cobblestone_wall_side_tall.json f55c5825c63f345a95e822a2113e76b5a62d8f7c assets/create/models/block/granite_pillar.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/gray_nixie_tube.json a68cd40ffb769b195437107f4a2c2188b222b74a assets/create/models/block/gray_sail.json 6eb5e59e803e1055968b90f3099cd0a17a1d3fd5 assets/create/models/block/gray_seat.json +38c5d8f0d4c4fff545c825cf9ae2f50387590e9c assets/create/models/block/gray_toolbox.json 7e213be39cc928363bf2b096f055439211050b8d assets/create/models/block/gray_valve_handle.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/green_nixie_tube.json 17b651233c62b928f0228562a7f6e7a2b7b2d6b7 assets/create/models/block/green_sail.json 1438b8ce54ac5557b8f10dcef94f3525eae19461 assets/create/models/block/green_seat.json +33f82e8da2b6e9b5df34157f91f2f01a542c7a33 assets/create/models/block/green_toolbox.json cc7ce9b6bc687ad5027a67c3bf22bdf5bcd71674 assets/create/models/block/green_valve_handle.json +29e09bf70184cc1d09fce31aea908a2ab56fa9e4 assets/create/models/block/haunted_bell_ceiling.json +942c2ae8a3546bd91f8489094f9e7516ff026e61 assets/create/models/block/haunted_bell_double_wall.json +44371c13450dd41d84769a3a50250de1d86e75c5 assets/create/models/block/haunted_bell_floor.json +57e48a613ce2c81992623a46792fca4bcafb33ce assets/create/models/block/haunted_bell_single_wall.json 5163171ed77af879fa06f290bf24b1bb99735c94 assets/create/models/block/honey.json b1e94d2858c3a8807def6c5131b6f63fe586fb91 assets/create/models/block/horizontal_framed_glass.json d13df8a5920c5778d98081fb0e97f045e2fd46a2 assets/create/models/block/horizontal_framed_glass_pane_noside.json @@ -840,14 +889,20 @@ e1add9f62cf886a7989f7ebb545906da16ad7a41 assets/create/models/block/layered_dolo cecf946818c65370b685dfeaade50819183acb41 assets/create/models/block/layered_limestone.json 258fb9644d396872719c56ae1ca89f50667a1077 assets/create/models/block/layered_scoria.json 60b05926e706d5dd27f3cb4997120c948797f2f4 assets/create/models/block/layered_weathered_limestone.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/light_blue_nixie_tube.json 19bd08ad6ac351e6eee2131f7b4c11a768bf8f08 assets/create/models/block/light_blue_sail.json 1a28b07da68d1461cd04c971ae548d94165e0cf3 assets/create/models/block/light_blue_seat.json +f7ad67c312235e8b83ec44e0a3f37ad2ed4d4d42 assets/create/models/block/light_blue_toolbox.json 68e01f8d8a31f07f236383e19b49ae1be4cbe3f4 assets/create/models/block/light_blue_valve_handle.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/light_gray_nixie_tube.json 73f14b905d5fdb433751a33b963852de6491722a assets/create/models/block/light_gray_sail.json 292bec1b9f962b17b29147d982a9b177618b7eb9 assets/create/models/block/light_gray_seat.json +1fbb180e0cd56220876fe8e7ee2aaa1ce57c0d0b assets/create/models/block/light_gray_toolbox.json 42338c4965da63962ea08077dc9e899aaf4c3c65 assets/create/models/block/light_gray_valve_handle.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/lime_nixie_tube.json 8292d043ebfe280340526a6a0f96d4160099e213 assets/create/models/block/lime_sail.json 31c9474210d8535c5417021fe042d4cc31e17328 assets/create/models/block/lime_seat.json +70e8eae2dcb116ca452bc2e847bed87869a75cf6 assets/create/models/block/lime_toolbox.json 74008bd0d775b0e2e96b43be2e51d0f3c3abdf21 assets/create/models/block/lime_valve_handle.json fccac0de94fff5f4e180fc9dbddeb0f8ddf3baab assets/create/models/block/limesand.json 3c49d63386b3f5326051edbf6e2f0f8f0e2ff4f3 assets/create/models/block/limestone.json @@ -874,8 +929,10 @@ c54e5a17495f88fa21b3488e8da32a365452c36c assets/create/models/block/limestone_co 7991d6620d2225b1a026e2b62dc076cf0a33613d assets/create/models/block/linear_chassis_bottom.json 56e585805c6235552ce5e15ff2f125ff8ec0fa2d assets/create/models/block/linear_chassis_top.json 12b35c916e3ee83ee4fd1e309c73403dec9a7297 assets/create/models/block/linear_chassis_top_bottom.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/magenta_nixie_tube.json ec6b5f636e163ff5e361d486cf628ca1af4849a1 assets/create/models/block/magenta_sail.json cbee001cd1bb1125a97d1bb2d1e6e5a68f129303 assets/create/models/block/magenta_seat.json +fa56f9bec902e6fea9cc25e6f474ee00c3dc558d assets/create/models/block/magenta_toolbox.json bc5a03a5552eb4a518abefe5e8615f14ee13ca29 assets/create/models/block/magenta_valve_handle.json 2e67f27a895c9163a5d1be62897d5e66b119767a assets/create/models/block/mechanical_bearing.json edf6ee4e590ebf162c00aa952d992f1bee2cad8a assets/create/models/block/mossy_andesite.json @@ -888,6 +945,7 @@ de9b0f933881cc735ae0acf2bd71e6eafa732ff8 assets/create/models/block/mossy_limest f88a9558a20033d4955e7b6de4f8aa23b1a11b9f assets/create/models/block/mossy_scoria.json 8c3296378aa7e5dc1bc7dfdde2f0a436b8bb8b78 assets/create/models/block/mossy_weathered_limestone.json 50f28bf7a7de95caf12b4f040994f0f3da72a55a assets/create/models/block/natural_scoria.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/nixie_tube.json e3cd8b33b8c5f0543e4f6728a5b3e05642f9efe1 assets/create/models/block/oak_window.json 54a3b3158f8c914788812aa44515b798b2a9e2f3 assets/create/models/block/oak_window_pane_noside.json b9c27f90d4d258e3fdcd713aaa42142f5d46a79e assets/create/models/block/oak_window_pane_noside_alt.json @@ -896,6 +954,7 @@ b9c27f90d4d258e3fdcd713aaa42142f5d46a79e assets/create/models/block/oak_window_p b3e056a176e86660fc2d3a51f9ba8b01eebb56c5 assets/create/models/block/oak_window_pane_side_alt.json ff9b51fcaffe54e321b9479f035f4ea7b278bfec assets/create/models/block/orange_sail.json fda0628a09ef726e3e8323b2f38b6a3e612dc2ca assets/create/models/block/orange_seat.json +ba86892a5f633b0256b7b4d9a661779d8f483257 assets/create/models/block/orange_toolbox.json 3b07f3f1985495051d173725b01ddd52b5f70ac4 assets/create/models/block/orange_valve_handle.json de5ecd753303b2c5dc3819299b9a316f0d7035f6 assets/create/models/block/ornate_iron_window.json cc9614e892b12c6053d45a35d534eddf36285cf1 assets/create/models/block/ornate_iron_window_pane_noside.json @@ -1034,8 +1093,14 @@ f924c6104378768a3a645f5e77f9ed80d2c31e5a assets/create/models/block/paved_weathe 46e3eeeefd47f7e6007e53bb1b22de2c6c2a5923 assets/create/models/block/paved_weathered_limestone_wall_post.json c7941c0bcbdf7ec7e2d34679afac744cf81b7489 assets/create/models/block/paved_weathered_limestone_wall_side.json 39aaea370e31fa032e471d3b8f0ebf0586ee1a03 assets/create/models/block/paved_weathered_limestone_wall_side_tall.json +29e09bf70184cc1d09fce31aea908a2ab56fa9e4 assets/create/models/block/peculiar_bell_ceiling.json +942c2ae8a3546bd91f8489094f9e7516ff026e61 assets/create/models/block/peculiar_bell_double_wall.json +44371c13450dd41d84769a3a50250de1d86e75c5 assets/create/models/block/peculiar_bell_floor.json +57e48a613ce2c81992623a46792fca4bcafb33ce assets/create/models/block/peculiar_bell_single_wall.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/pink_nixie_tube.json 1b5f9e819cd4b5f5fe6e8c24920b916e8d93c95e assets/create/models/block/pink_sail.json ecc60ce7ee6b753073a99c597db95d6d9df3d438 assets/create/models/block/pink_seat.json +56b893cf30b33c825cbd6d00b8fc02b4f96aa8b0 assets/create/models/block/pink_toolbox.json 7ada61878d3a3c1d3cc33bcf9a80c21b8f9aaff2 assets/create/models/block/pink_valve_handle.json 84fdb35acc12ae9580496f458def3e49aa0551ea assets/create/models/block/polished_dark_scoria.json 5ca3d6cbbf1fdd6437d9951b9d2937838ec480f1 assets/create/models/block/polished_dark_scoria_slab.json @@ -1103,8 +1168,10 @@ f22d7d8263dcabd726aa04784031ae9062633579 assets/create/models/block/powered_togg e6097d9ab9dc9954cbc750020bc33c7a423b73c6 assets/create/models/block/powered_toggle_latch_on_powered.json 622239a3a09fcac7235b9670eb395a530839a59b assets/create/models/block/pulse_repeater_powered.json d469dce70d15759baed35025b8c7fa403c8b3b26 assets/create/models/block/pulse_repeater_pulsing.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/purple_nixie_tube.json b56fad63b82434564bc41ae9c01e3b427203fb5b assets/create/models/block/purple_sail.json 96adc7865ebe64b43865bc2fe914830c11258856 assets/create/models/block/purple_seat.json +5f7b588729634be592b67309ff475a72693ca338 assets/create/models/block/purple_toolbox.json 062406aacf25e099f9b28a3bf7cacfcaa1da4ef6 assets/create/models/block/purple_valve_handle.json 27d64a828607f94296c0b86cdb35fad996bc5d23 assets/create/models/block/radial_chassis_side_x.json 7d1439a0b06e4014e396d498a9e42168f67773a5 assets/create/models/block/radial_chassis_side_x_sticky.json @@ -1112,8 +1179,10 @@ a9885a3f69e3e2a2812c33bafd9140fcc5cc7c25 assets/create/models/block/radial_chass 92a48c22cf2af0a3156844322f6bb469883608fb assets/create/models/block/radial_chassis_side_y_sticky.json 522f4733118d6fba172696e9478c8f9fe88b236e assets/create/models/block/radial_chassis_side_z.json bffca231a146a6ac49e028f3790cdcbf375e98b0 assets/create/models/block/radial_chassis_side_z_sticky.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/red_nixie_tube.json f0099576080a0f2bb09dd85e55777bad69f9f265 assets/create/models/block/red_sail.json 12d4f4119b994c5d71c96ab3aa09beb89dad1e10 assets/create/models/block/red_seat.json +8b3de1161707901173accaf66c1f45233be8f8bd assets/create/models/block/red_toolbox.json 0064825ee3c1702c524d34abb6adb66906586851 assets/create/models/block/red_valve_handle.json 61ce6e1ba7fee30683c86b09ec35da4fbff8f9cb assets/create/models/block/refined_radiance_casing.json 0fa50139aa2ff171feaecf3062b2037fab10b786 assets/create/models/block/scoria.json @@ -1192,11 +1261,15 @@ acf3900465101f9dd78d2301eab1063cdb461582 assets/create/models/block/weathered_li 7f1582fe36aa94be4352b8eda89c8ebf7a353333 assets/create/models/block/weathered_limestone_cobblestone_wall_side.json 3235d3148535283e9e9b4ee336b92055e7c6bf01 assets/create/models/block/weathered_limestone_cobblestone_wall_side_tall.json 8c6feec0411e95f9aae18f9f38b4e045156857e8 assets/create/models/block/weathered_limestone_pillar.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/white_nixie_tube.json 1377e12f56dce1466ce44078d7154870c5cf7b2a assets/create/models/block/white_seat.json +94f882c4bf1664a9acfe57e1eccfd8129134aaaa assets/create/models/block/white_toolbox.json 899f33d51cf36cb1c283bc7e6363f9d451e5736e assets/create/models/block/white_valve_handle.json f2bee22fe03ac047fbe73ca2c5c759f09bf646df assets/create/models/block/windmill_bearing.json +71cd22dc2d847d317f19afb4b21802fbf5347e0b assets/create/models/block/yellow_nixie_tube.json 071ca07daceea4d0db7ed41e815d47589fdb14b7 assets/create/models/block/yellow_sail.json 0a0e2cc973e35586ae00ed17b919383868e992e8 assets/create/models/block/yellow_seat.json +4a3f7dbbcc00be047e862a1b908021f916151292 assets/create/models/block/yellow_toolbox.json 55edee7b0833ab19b98694fab21ae0c8e91f76fd assets/create/models/block/yellow_valve_handle.json 36c27bad342c82aa8dc097da87637dca042cce17 assets/create/models/block/zinc_block.json f3059145a84ddbd54d08167e984112c7baf5ef4a assets/create/models/block/zinc_ore.json @@ -1227,11 +1300,13 @@ ffdb36349fa2e50451c208585162b6a8386ec494 assets/create/models/item/belt_connecto 9044243882cfd49a2827e1b910a4c9b0e46daa47 assets/create/models/item/birch_window.json d537fffaede521efa525fb2a7f9863fe6a80054e assets/create/models/item/birch_window_pane.json 22632bd681c8a605f0845f7549770389a741156a assets/create/models/item/black_seat.json +41967bd41a318f703182b5df8525ff4858db2682 assets/create/models/item/black_toolbox.json 56a6baedc608792cd6ab72a1c4fd53046cbda070 assets/create/models/item/black_valve_handle.json 80a6e8b00709fe0521aca5b789ae17485ed9c56d assets/create/models/item/blaze_burner.json 6e350231e9f217019883096b4f0bb95ab0af4728 assets/create/models/item/blaze_cake.json 5d4e5c22295f9b5cc62cf6e74fe1384fbbb319f9 assets/create/models/item/blaze_cake_base.json 0e1977585128fc0ecef640f72e5fc5e9fb47ef92 assets/create/models/item/blue_seat.json +c637be1586260cf91e6da57c71c33f4515008227 assets/create/models/item/blue_toolbox.json bec96ebf3369d3cffa9bb1b8bf9f2a5cd5d0ef96 assets/create/models/item/blue_valve_handle.json 17d340c3678bd24cb085ba49490b2b4cb341a9e7 assets/create/models/item/brass_block.json f5a18f4279c2e845a5967b1c2f9e807c2bb77afb assets/create/models/item/brass_casing.json @@ -1243,6 +1318,7 @@ d5e8b577aee56671e117a4a2ac93e58680b51949 assets/create/models/item/brass_ingot.j f7aca6aff65e1de269a99cf2a280d9841b7a0076 assets/create/models/item/brass_sheet.json 427bef12405e2a99fbf49e27ea5944add244252a assets/create/models/item/brass_tunnel.json 24df6f8391d8ba09cef46e69d65d32ea770745cd assets/create/models/item/brown_seat.json +9d66f8bdc2db7cacf52168d5a267d5f52a2b351c assets/create/models/item/brown_toolbox.json 54211d3bdbeba2ea4dbaed43daa740ae3331640f assets/create/models/item/brown_valve_handle.json 329c17cd2ac693babf6f05d0be94cfb1683a87cc assets/create/models/item/builders_tea.json 3e232a103f7f916fc11edb4d541ca99fe7b44181 assets/create/models/item/cart_assembler.json @@ -1273,6 +1349,8 @@ 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 +db68f1fcc5b91f3ee0cc023538d965d76dd13506 assets/create/models/item/creative_blaze_cake.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 @@ -1295,6 +1373,7 @@ b359064405d189e2802969715cd5f682ddbf0bb1 assets/create/models/item/crushed_urani 823c91f63565db54ec3944a1e90e7aee18e41062 assets/create/models/item/crushing_wheel.json dae5cffa4e1263d6a113469f79fba8695fa8232a assets/create/models/item/cuckoo_clock.json 3e3edc9ccded444496d3336926b93bbf1234cd84 assets/create/models/item/cyan_seat.json +8ad7b5e1f0baf9df082a9250f57c7229d07e82ea assets/create/models/item/cyan_toolbox.json 523cd531eadaadc45fb356ca58b99a8fe206c3a7 assets/create/models/item/cyan_valve_handle.json f786a43e296d9f10d7c302fe3ae9cddf4ba9984e assets/create/models/item/dark_oak_window.json 515d55b1ce18543fdb44b194901040fd29e75818 assets/create/models/item/dark_oak_window_pane.json @@ -1408,22 +1487,24 @@ c1bb87fdbbefaf74e1ead186c43417a051ab3965 assets/create/models/item/granite_cobbl 55d1257e4ff2e505c941975f51736eb43e53860b assets/create/models/item/granite_cobblestone_wall.json b84a947a1b297513c85bb8d2dbbb780304c95e43 assets/create/models/item/granite_pillar.json e7daa31c1fc445d542bad476dfe1d6a8811f2070 assets/create/models/item/gray_seat.json +e93e0d31a92f7f6faa758966e347568c56a2ddee assets/create/models/item/gray_toolbox.json 0f4981408b08a736ff3eb5bdf1823cd7019ae9fe assets/create/models/item/gray_valve_handle.json 1c9c9157a06108bf58967bfc4fb069c35d20e90a assets/create/models/item/green_seat.json +94cf943dd6621674790cc4b70c3d5f3620ae0dc7 assets/create/models/item/green_toolbox.json ecb9f32f62d3fa43fb226ab85adc2eb229fdfb77 assets/create/models/item/green_valve_handle.json 398b1a7c76c7bdb6a23b1248fdce98f6d835467f assets/create/models/item/hand_crank.json dee43bf1a9c211a752fac2c07aeba123f7f0c914 assets/create/models/item/handheld_worldshaper.json +e17d9c90e621e9a39f38bb2d90a122f09a5f169d assets/create/models/item/haunted_bell.json f0d5af58e23e2705b3ef675c30bdf85ed9567c57 assets/create/models/item/honey_bucket.json 068729724f5f7b276b9bc378e533898a92e8debe assets/create/models/item/honeyed_apple.json 955e8accadb47f9b360e5fd48cd959c507b00f2d assets/create/models/item/horizontal_framed_glass.json f0e3b2b8a553b6e61746c922c27302dabfff71b6 assets/create/models/item/horizontal_framed_glass_pane.json ff92f6a9dfb73a6ee1eaaed3279c89390ff04a80 assets/create/models/item/hose_pulley.json -d9f222e963f8f8910ca9dbc3c31842ef149f7a1f assets/create/models/item/integrated_circuit.json +153a185852af79654f0fb216c4b1b8e69c85ee8a assets/create/models/item/incomplete_precision_mechanism.json 9d605ce0da83a73b535bce45c107e604364e2b20 assets/create/models/item/iron_sheet.json 52e435014cb03e93411666c4799ebff206e55fc9 assets/create/models/item/item_drain.json 83fa8699318e51f838b483b40b3e897c34ed53d1 assets/create/models/item/jungle_window.json 766323f6026c3505a75db2dee2996d342370d9c2 assets/create/models/item/jungle_window_pane.json -fe89522b2bd9b4393b8afa2a97f6db4277a8a4b4 assets/create/models/item/lapis_sheet.json bcaaf60d9a853cce90169dabcb36d29a3ce19e18 assets/create/models/item/large_cogwheel.json 281e2b055c6eb6994ca306c8957fc80a98fb5473 assets/create/models/item/layered_andesite.json 7afeb6170b37cb464ea91be18928d21970d556d3 assets/create/models/item/layered_dark_scoria.json @@ -1435,10 +1516,13 @@ ad40f8eb28bea731131aeaffee55abecb8bc6a56 assets/create/models/item/layered_limes e7585210cf4754c89b4ba3dc95827b75029f0523 assets/create/models/item/layered_scoria.json 2df30e7f8cacc1efd6e025564d495f782e0dc697 assets/create/models/item/layered_weathered_limestone.json be2b6d54afc515d93d6d5b3023c506c53cc946f8 assets/create/models/item/light_blue_seat.json +06c81dc35110b580a52fbfca78c60665156cb002 assets/create/models/item/light_blue_toolbox.json 34c308977750da24db80bf2ea2dd6cfc22ea1db6 assets/create/models/item/light_blue_valve_handle.json 1b36382eae41b35585e5659cda019310731000fc assets/create/models/item/light_gray_seat.json +b90d9b897793324371a4e32725dcc76f8a132cbb assets/create/models/item/light_gray_toolbox.json a89d397ac14482a973f7937f046dbf8e42d017bc assets/create/models/item/light_gray_valve_handle.json 2127f20dca4421802812e249b3caca6230a37eee assets/create/models/item/lime_seat.json +e36a80686d7813cdc4db0d309ca7e14884c0dc7a assets/create/models/item/lime_toolbox.json 785b008d703728497f5f941e3211d6e10389f1b5 assets/create/models/item/lime_valve_handle.json a29733a916141abf84492a288fe9ac4ed531f47d assets/create/models/item/limesand.json e0a1c6102acc10a36de5ae87da629dd3d676e204 assets/create/models/item/limestone.json @@ -1452,7 +1536,9 @@ 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 +cf29193c19b15f2b12edeecaf41e14602be4d247 assets/create/models/item/magenta_toolbox.json 928c5e3747fb758d2610475258cc168b0d4ee7b6 assets/create/models/item/magenta_valve_handle.json 932facf4bf93b471e8630f4132a4284a9f4d0d39 assets/create/models/item/mechanical_arm.json e19c7a06697adc2da9d66c5c81e1c6ff131acb65 assets/create/models/item/mechanical_bearing.json @@ -1485,6 +1571,7 @@ bafe601f186e868819da3d29f7be7dc96f9ba790 assets/create/models/item/nixie_tube.js 7a336a340f3e4927d7a35f9d79e8a03693b802aa assets/create/models/item/oak_window.json d0a6219860420f910300e86cbec1b08d4b47f436 assets/create/models/item/oak_window_pane.json 25dfcc8b6f085722f6b2a0c686b77d437e61542e assets/create/models/item/orange_seat.json +a951cefc4b35f5a2d5b7c7ed689384a20b3c9115 assets/create/models/item/orange_toolbox.json 62ac36250e2505f23ea4d2c3b4630239c049f276 assets/create/models/item/orange_valve_handle.json 0ffe242e3165d9a0e3fe16ad4c4ca91c7e9828b2 assets/create/models/item/ornate_iron_window.json 7d7da05da6248abc177e89988ed5c2aff1151767 assets/create/models/item/ornate_iron_window_pane.json @@ -1533,7 +1620,9 @@ d60c4fb6e0e68d8f6c137a0c601145c342236c18 assets/create/models/item/paved_limesto 5ec22c676e301a7004ff7d127d20b46f49063c64 assets/create/models/item/paved_weathered_limestone_slab.json d81f85aea5e683539a0f3c805c154b76a9d88a9d assets/create/models/item/paved_weathered_limestone_stairs.json 910eaf2f571bae883b888d13f305bd848d278577 assets/create/models/item/paved_weathered_limestone_wall.json +477cf0b4dd4482353668f6307f3f94d0fd77dd62 assets/create/models/item/peculiar_bell.json 9664f171c7856661776c5c4ef0b6880a77db648e assets/create/models/item/pink_seat.json +1c95a98a6f55eb74626e6a51fb5a896f97741681 assets/create/models/item/pink_toolbox.json 7d12cc24b86fcb3f0ca6fee650d1dee683859c0d assets/create/models/item/pink_valve_handle.json 04ce23dc141bedccc75b4512263da8b498f13205 assets/create/models/item/piston_extension_pole.json 1f7846aa06c3c22614c98cbec9112cc8632fa1b8 assets/create/models/item/polished_dark_scoria.json @@ -1563,16 +1652,20 @@ e95125318055b8557afd7d108488cf0bdd81fe49 assets/create/models/item/polished_scor d98a1d479dff88d7a6f084f2c9de8fbbf80961ef assets/create/models/item/polished_weathered_limestone_wall.json 0e5638cdbf04d7af2222ec15fbe1d960385ea237 assets/create/models/item/portable_fluid_interface.json 3bc60b0d9884c2ee0f1dd530e90fceb699eea737 assets/create/models/item/portable_storage_interface.json +b97c891ebe74e7850ef1f982e4cc043338baa30f assets/create/models/item/potato_cannon.json 417c301eb7e54f14c564975570f59d048cc88987 assets/create/models/item/powdered_obsidian.json 1e501c1f2e9250aaaadcf17db62646d08177d4e1 assets/create/models/item/powered_latch.json 3a6dfc7f36e31ebfcd650c3144a7f2210e8a4f9f assets/create/models/item/powered_toggle_latch.json +7459efc8f20d093a8b0ef987eaace8cb0ad0aaa8 assets/create/models/item/precision_mechanism.json 4a3c3d81097d56bbd3aefeeb9eb7db87f514b5b4 assets/create/models/item/propeller.json 4b8a27ff05ed5331889dfc4b0b4562f3e94b0dfe assets/create/models/item/pulse_repeater.json a598b2f5eb34b061e81efb8a55267a02f8e08a61 assets/create/models/item/purple_seat.json +f309695ba0470c5228f38443f09bad85d09de8bd assets/create/models/item/purple_toolbox.json e5138f9e37ca4d24cda2eb7b24a021eb7c8ae21c assets/create/models/item/purple_valve_handle.json efbda15b53084acdac2d36b8e0a764a9ab34d723 assets/create/models/item/radial_chassis.json fc05c4492da3d17add7e410323a47456c0d21e0e assets/create/models/item/red_sand_paper.json 3e251514aa698076b73fdbfef720b78b21d3bd93 assets/create/models/item/red_seat.json +7d3bbb52975ab67b9f9aabe61fdf0cd2d63d5fc2 assets/create/models/item/red_toolbox.json b959a1b35105c2c21933418bd29ce12a090716f8 assets/create/models/item/red_valve_handle.json b9a4ac219a27e60a82f55129f2df5ae6183981e2 assets/create/models/item/redstone_contact.json 52e561abeb954d0349e640566de92ef80ccbf919 assets/create/models/item/redstone_link.json @@ -1641,17 +1734,19 @@ c36834070e12d25cd9e818d0d0181e267584b483 assets/create/models/item/weighted_ejec 9502a51ed2f6a110b6d41731a5948be4d70c8af8 assets/create/models/item/whisk.json c6253e0f8db3c3992d3f78fe5045e276d39d5b22 assets/create/models/item/white_sail.json 69328eb4f91c4407fbcad5e3c4b88363f1a9572c assets/create/models/item/white_seat.json +29d8e92edf11c79091e49689a97ab700121cdeb3 assets/create/models/item/white_toolbox.json be7a2d59d43083d7f2427193dcb9d68004224dd3 assets/create/models/item/white_valve_handle.json d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bearing.json 500abf752654a904d78a967f6c6d29a75a4821ab assets/create/models/item/wooden_bracket.json 2527b52413965a3e84b4718e08a9b8bb30a741ea assets/create/models/item/wrench.json 4b49bc2418410cded5f0b7da3430f1a22e049f18 assets/create/models/item/yellow_seat.json +4a34f526f9310198424d1f96a0c1d748ae5cccbf assets/create/models/item/yellow_toolbox.json 790daf016f980801e7587b548a325082c65f6f03 assets/create/models/item/yellow_valve_handle.json 9365b5cf29e35d070d077c54520f6cc780aeb842 assets/create/models/item/zinc_block.json 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 +58880e397902f8ca5b3b59ed4423e626109ddc4c assets/create/sounds.json 0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json 187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json 0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json @@ -1672,15 +1767,16 @@ de13a091928d5ab539d567411dd5c522cdcdd668 data/create/advancements/brass_casing.j 9531baa67bb3aee5e2723b1ab0578ff87bcb42b0 data/create/advancements/chromatic_eob.json f37551a788dfb3ff3d65db97a03c0420edf2c041 data/create/advancements/chute.json 0ffacd497176afdb26670783b65d383ac6236c19 data/create/advancements/clockwork_bearing.json +fcb3a56a40d245a2fc95799b4b4da90756b58bd6 data/create/advancements/clockwork_component_eob.json 870ca791c418a1bc24f7b12284f5788c84911b92 data/create/advancements/compact.json d1015e059a2f2008a364b6d045a011a6d671f20d data/create/advancements/copper_casing.json 8e2a12a26218a46665c46f350ef9c3418a901988 data/create/advancements/crafter.json d1fbc14303c7327e9fc02e505e7e434591b7f785 data/create/advancements/crushing_wheel.json e9e1789de5cd5577a801a09d489a13f2c98779dc data/create/advancements/cuckoo.json 2a96fad5b44b62f233c9af5b4a637faf32ce24af data/create/advancements/deployer.json -eb8e7c13163923d2f88c999c6eb5afa4b7d2426e data/create/advancements/dual_extendo_grip.json +20e04d0ac916996efedc35ab80e2b4ac4001582c data/create/advancements/dual_extendo_grip.json 04eaf829696d735244c0e4798dd3bdeb26e13a32 data/create/advancements/electron_tube.json -36622ff02345cdc2404230c48de9ed42b1b9bd1d data/create/advancements/extendo_grip.json +e15f8093da07cb2292de49620f2aa776f5a6099a data/create/advancements/extendo_grip.json b1699baaadaac7ebce642c09428519d156e21594 data/create/advancements/fan.json 5aa76cba3b40a1c234ffa84a89ecca630990fc0f data/create/advancements/fan_lava.json 716a9816558300a3652ed8d8d568517017813f5c data/create/advancements/fan_smoke.json @@ -1693,8 +1789,6 @@ ea0f8acb7c3692b569269e62927725d968a65251 data/create/advancements/hose_pulley.js 9f642faf92b75a28c564e90be8448b9a4328af5e data/create/advancements/infinite_chocolate.json a933fa5e7217e2ffe123ae035cfbc9210ba69fd5 data/create/advancements/infinite_lava.json a8ab0e4ffba358d23f9efaa9f51245b6d490a8be data/create/advancements/infinite_water.json -9beb622c79e9f5ce2397c22222cac0faf272f388 data/create/advancements/integrated_circuit.json -316bed3d8985d0a371200967d7edd2936f1b9f94 data/create/advancements/integrated_circuit_eob.json 4d7cb129877d6cd68fda66159818e47ca44db078 data/create/advancements/item_drain.json b61d958815f1c2530c11c88c9081d5c794d7f807 data/create/advancements/its_alive.json 9d68fed495a37fc78184e43e432c3181da84d19c data/create/advancements/lava_wheel.json @@ -1711,7 +1805,10 @@ c9c4060ed207226b69fada2d61e01a97d7077eae data/create/advancements/nixie_tube.jso 449eb8a9e6102bb342c96eb8b19e743eb6979bfa data/create/advancements/pipe_collision.json 4b621e5bb48fbb120853ec02c05c915d86bd6dd8 data/create/advancements/pipe_spill.json 72025d8bf73ab8096c29f12d0c8d9a346f09cd64 data/create/advancements/polished_rose_quartz.json +69c45c653458d3076313bba3483bf26fb3946292 data/create/advancements/potato_cannon.json +6378090ee972356a3b772aa3d140cf52d396e60d data/create/advancements/precision_mechanism.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 +1835,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,12 +1873,48 @@ 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 +d06d9445256ae19d0a8a37e97983b168fd4d774e data/create/advancements/recipes/create.base/crafting/curiosities/black_toolbox_from_main_toolbox.json +343846c20104684b3a948e5c3a9948dd30839808 data/create/advancements/recipes/create.base/crafting/curiosities/black_toolbox_from_other_toolbox.json +acdf76187497b3101e9ec6101e2164e11277a68a data/create/advancements/recipes/create.base/crafting/curiosities/blue_toolbox_from_main_toolbox.json +3a8b083c1f4c67feade27a877e774f435b8e58da data/create/advancements/recipes/create.base/crafting/curiosities/blue_toolbox_from_other_toolbox.json +bb138bedd2aec741fa54b6b52be384fdbd741249 data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox.json +963555b6f24b35150769c3ff68a9a57c4968c9a6 data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox_from_main_toolbox.json +502e8ea5b0f9cc0ca90a1018d907ffe6f3b051a3 data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox_from_other_toolbox.json +f2afe58a26566aac8abce76f0ab6d0924c5badb6 data/create/advancements/recipes/create.base/crafting/curiosities/cyan_toolbox_from_main_toolbox.json +dea244d3f78e4aaf13132d48dcf071e5046bf154 data/create/advancements/recipes/create.base/crafting/curiosities/cyan_toolbox_from_other_toolbox.json +e28c741eed426658edda99c52eeacb4ccdcac0c2 data/create/advancements/recipes/create.base/crafting/curiosities/gray_toolbox_from_main_toolbox.json +b8df907dc00d4c28e74ba59faf9d66765ea43a6f data/create/advancements/recipes/create.base/crafting/curiosities/gray_toolbox_from_other_toolbox.json +ecd1f21c20804cbe65e7ace983d9a78c5003e8c0 data/create/advancements/recipes/create.base/crafting/curiosities/green_toolbox_from_main_toolbox.json +7969a391535586641e8da6ae6cd6d0eff2090369 data/create/advancements/recipes/create.base/crafting/curiosities/green_toolbox_from_other_toolbox.json +f174c871c7a4e8403bbf17c0e13572dc6cb31f90 data/create/advancements/recipes/create.base/crafting/curiosities/light_blue_toolbox_from_main_toolbox.json +b65a5e3f181c7ae5b63f89a51a40ad4d5d01827b data/create/advancements/recipes/create.base/crafting/curiosities/light_blue_toolbox_from_other_toolbox.json +d89ac200d23375a24cd62847e2be3108738ec948 data/create/advancements/recipes/create.base/crafting/curiosities/light_gray_toolbox_from_main_toolbox.json +2809c5b8f3d51b3319ae514006ec8baf38c7a8c2 data/create/advancements/recipes/create.base/crafting/curiosities/light_gray_toolbox_from_other_toolbox.json +152eacfd9d34c377d7380663542c22cea88b92ca data/create/advancements/recipes/create.base/crafting/curiosities/lime_toolbox_from_main_toolbox.json +acc82b0304550c4a0f8247c12b9fe92465ceee8b data/create/advancements/recipes/create.base/crafting/curiosities/lime_toolbox_from_other_toolbox.json +e89c8d11f098150a87e4724943269f421b3d63f0 data/create/advancements/recipes/create.base/crafting/curiosities/magenta_toolbox_from_main_toolbox.json +357899f0b14102faf4fff8bf290f854c2af38ba4 data/create/advancements/recipes/create.base/crafting/curiosities/magenta_toolbox_from_other_toolbox.json d531f87f425d199aee4777a588c1cd6cab6f5173 data/create/advancements/recipes/create.base/crafting/curiosities/minecart_coupling.json +7736bf31def6c117a92cfdc7ff007e51f10a7fa7 data/create/advancements/recipes/create.base/crafting/curiosities/orange_toolbox_from_main_toolbox.json +6eb8ae16950fb299f0762b20badac6beb88b9482 data/create/advancements/recipes/create.base/crafting/curiosities/orange_toolbox_from_other_toolbox.json +a8c72e7e02fd0843d33fa4c5d43de81f29bc3aa4 data/create/advancements/recipes/create.base/crafting/curiosities/peculiar_bell.json +8d9894f687a21da528a3065ee1041ff1cccb3428 data/create/advancements/recipes/create.base/crafting/curiosities/pink_toolbox_from_main_toolbox.json +988ece3fc6f3257826f16107b995c5649b2e4e85 data/create/advancements/recipes/create.base/crafting/curiosities/pink_toolbox_from_other_toolbox.json +c645dd051a8d06fdb2d09083ba632c44b7794e9e data/create/advancements/recipes/create.base/crafting/curiosities/purple_toolbox_from_main_toolbox.json +2a4d5fa85d0c306791c67f283c4298200f2a6cd8 data/create/advancements/recipes/create.base/crafting/curiosities/purple_toolbox_from_other_toolbox.json +0567ca2d349306df05adaebe3e056fc4f75e287f data/create/advancements/recipes/create.base/crafting/curiosities/red_toolbox_from_main_toolbox.json +c71be67bfa6fac32be60424049cb221e10840016 data/create/advancements/recipes/create.base/crafting/curiosities/red_toolbox_from_other_toolbox.json 2eef3201017af03f6a2f0f015645e3ff5e25d9c1 data/create/advancements/recipes/create.base/crafting/curiosities/wand_of_symmetry.json +bb1650d8a9a5877bf64964a2d92f8a93364637f4 data/create/advancements/recipes/create.base/crafting/curiosities/white_toolbox_from_main_toolbox.json +514974b3b902a910358453b10619cbc1ac13476d data/create/advancements/recipes/create.base/crafting/curiosities/white_toolbox_from_other_toolbox.json +13180b17064fedda97cfaa18e4158e2bfcd6b332 data/create/advancements/recipes/create.base/crafting/curiosities/yellow_toolbox_from_main_toolbox.json +8ab0365e0aa21ecd1a671d7c0b8717626951e2cb data/create/advancements/recipes/create.base/crafting/curiosities/yellow_toolbox_from_other_toolbox.json 80155fa8e28e7de87adad3dc2cd79564496d7ef7 data/create/advancements/recipes/create.base/crafting/kinetics/adjustable_chain_gearshift.json 92416ced6ede6965fd728e1c7336bb05a3e41ea2 data/create/advancements/recipes/create.base/crafting/kinetics/analog_lever.json 3e9753006da898d4569bbeabf95997e8c90847c8 data/create/advancements/recipes/create.base/crafting/kinetics/attribute_filter.json @@ -1975,7 +2110,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 +2125,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 +2140,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 +2156,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 +2173,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 +2240,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 +2255,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 +2271,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 +2286,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 +2301,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 +2436,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 +2451,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 +2466,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 +2481,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 @@ -2361,7 +2502,7 @@ e0b9edc5e59647e7dd99be17369b263dadf407d4 data/create/advancements/refined_radian fc12b590ab8f5ac901db21c67ba3850f157e1421 data/create/advancements/root.json c1f162e773518f6b1481221e3e63f9ba33fed647 data/create/advancements/shadow_steel.json 6c1a67e193a4c5af356b31a1d5b5e9d3faeca87e data/create/advancements/shifting_gears.json -a7d278d8ce8e2769c0b9c89f547d4775eabe671b data/create/advancements/speed_controller.json +65132cb27041c848230781cca8020a2e5ae4365e data/create/advancements/speed_controller.json a203d509a6038f0bad707e232a425388e62e1ae1 data/create/advancements/speedometer.json f7bb8f08a08e22ec1e6bb098d65d06233e8fbcec data/create/advancements/splitter_tunnel.json b69d174d7a5e9eab8ca013b66bc9d02244d7f9a3 data/create/advancements/spout.json @@ -2398,12 +2539,16 @@ d3202a337c15c8b8ec41fa5879bb94327bb75057 data/create/loot_tables/blocks/andesite c7f81e30c31837a287d6d6040cdb02c7dec11441 data/create/loot_tables/blocks/belt.json 67a8e2513c3cb09e6fe80279fda94f79d5018c37 data/create/loot_tables/blocks/birch_window.json bf1d5843f93533f84bc4adec5b77da2114fa2025 data/create/loot_tables/blocks/birch_window_pane.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/black_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/black_sail.json cccc209d172cc7bac76f1b4ac79085ee90742ab2 data/create/loot_tables/blocks/black_seat.json +c51ad9a71e41bb3ffa807b441ebd1946ea226a68 data/create/loot_tables/blocks/black_toolbox.json f3573f47b8a914aa222633893e158f84fcd6f3d8 data/create/loot_tables/blocks/black_valve_handle.json a2313c9b7d114396fca3c86a740d23fce3873679 data/create/loot_tables/blocks/blaze_burner.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/blue_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/blue_sail.json 3834f7ac2bbc42cead02d4973842adb9ad97e6bf data/create/loot_tables/blocks/blue_seat.json +dc8e1f43464c5a9b28d4cbd37203682fc2a9621f data/create/loot_tables/blocks/blue_toolbox.json fcddccd1bf45c2f4ad5f1520e209a4f04487274a data/create/loot_tables/blocks/blue_valve_handle.json 1dbc446abe190b2832b2ce7d52c2f2d2bdd45949 data/create/loot_tables/blocks/brass_belt_funnel.json 70d9d4def43d5b31fa7cdc5ca5002c71cf4a90b0 data/create/loot_tables/blocks/brass_block.json @@ -2411,8 +2556,10 @@ fcddccd1bf45c2f4ad5f1520e209a4f04487274a data/create/loot_tables/blocks/blue_val b127cb6920e6d7d9c8b2402cb186402a9a8dd3fc data/create/loot_tables/blocks/brass_encased_shaft.json 1dbc446abe190b2832b2ce7d52c2f2d2bdd45949 data/create/loot_tables/blocks/brass_funnel.json 6c8e784677d1a843b6c707484c79751acdb46ebc data/create/loot_tables/blocks/brass_tunnel.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/brown_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/brown_sail.json d415862a0abe20e8c5c2c8125bb672065330a9bc data/create/loot_tables/blocks/brown_seat.json +be90d95c41b95c30243b26f462cb51b33400ba26 data/create/loot_tables/blocks/brown_toolbox.json fedfe922f568c06adc2dfdd641b9abc90ba5af8a data/create/loot_tables/blocks/brown_valve_handle.json 0be542fef3bc0e1a0d556883568a1400a8b97df1 data/create/loot_tables/blocks/cart_assembler.json ab820bbaaf67c6697dfbab33c05fb73b18c70bfb data/create/loot_tables/blocks/chiseled_dark_scoria.json @@ -2427,7 +2574,7 @@ d76113310fc56eca6382d44df174096f2210d416 data/create/loot_tables/blocks/clutch.j 673ba3a5deae9133b917d16c9eb87fe4c2873c8a data/create/loot_tables/blocks/cogwheel.json 096af6b5df6e87d36cb936eea9b00982a554f4af data/create/loot_tables/blocks/content_observer.json 80c2cb21714651116a71f449368c06bb22e841ce data/create/loot_tables/blocks/controller_rail.json -662b8d41803ef166d20850653b36759de719206c data/create/loot_tables/blocks/copper_backtank.json +41992d0c81379e0693a1a5ec3e6ee4ada381df34 data/create/loot_tables/blocks/copper_backtank.json f38802b919c49f162f102d6e5d94113f05bf4ab1 data/create/loot_tables/blocks/copper_block.json 5a65a18ea787130ac7b8f5652bfa5ed187446649 data/create/loot_tables/blocks/copper_casing.json 31a51237763c374b7cdf39b9b62c14e965871047 data/create/loot_tables/blocks/copper_ore.json @@ -2442,12 +2589,14 @@ ba084fc3c680c9dea0d03fc664a831dfed18e52e data/create/loot_tables/blocks/crimson_ c28fa42746a4d5ca2f824001b67e58673810169e data/create/loot_tables/blocks/crushing_wheel.json 205f5899101262f31f5c1a88bb7d954918d08d04 data/create/loot_tables/blocks/crushing_wheel_controller.json d370ee874b5b6b98e9a8c368218fe61f644d956d data/create/loot_tables/blocks/cuckoo_clock.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/cyan_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/cyan_sail.json 49a14b9e93abdf02a7aef9c0c4085ac89617fae4 data/create/loot_tables/blocks/cyan_seat.json +6b4281aa990a190722d56c32bd03e21b508f5f49 data/create/loot_tables/blocks/cyan_toolbox.json 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 +2617,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 +2673,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 @@ -2548,13 +2697,18 @@ fa0ddf45d108f55550164113cb5cfd002586a9d4 data/create/loot_tables/blocks/granite_ feca8a1f62e0e13fcb2252d5f782d74938b84431 data/create/loot_tables/blocks/granite_cobblestone_stairs.json 1d225a68b09d6f389aa7ed48aa05979bdaa482a9 data/create/loot_tables/blocks/granite_cobblestone_wall.json 87a4ac3db5ec80613b940abccc72fc4b37cee0ba data/create/loot_tables/blocks/granite_pillar.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/gray_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/gray_sail.json d014357b3a467b23473c8223f32471a04a9ff94c data/create/loot_tables/blocks/gray_seat.json +bfe072e94774289c9d011d68b1cea04cf740fc75 data/create/loot_tables/blocks/gray_toolbox.json 35f916fd0f8465a070270615dbddd716ff68d5bb data/create/loot_tables/blocks/gray_valve_handle.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/green_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/green_sail.json a71599eecd3f1179e3d0367623460e798828aa6d data/create/loot_tables/blocks/green_seat.json +7f0179039e85cb61f60aa1db49bb8c45ce58207d data/create/loot_tables/blocks/green_toolbox.json 865ebead9601b29e6326dc9e1d4c1ca92f3b7a3b data/create/loot_tables/blocks/green_valve_handle.json 9bdc47ea3ffc52f037f12f40f387e6b72a352c4e data/create/loot_tables/blocks/hand_crank.json +c61b386376d19aaf89df3447a26b976a672efec5 data/create/loot_tables/blocks/haunted_bell.json 22012e7759f1dbccbb06bcaf0311a54190270825 data/create/loot_tables/blocks/horizontal_framed_glass.json 5d3f585539942f13bbc458a0a002849c1f034fc1 data/create/loot_tables/blocks/horizontal_framed_glass_pane.json 1b28cc5e1e535aa0c62d4a75ad76fcb40bf6232c data/create/loot_tables/blocks/hose_pulley.json @@ -2571,17 +2725,24 @@ fa8a5922f7346a15a80b5c7e5dfc26d24ea98728 data/create/loot_tables/blocks/layered_ 197ecf9c00c06f6014ecbec678a5466492902cb0 data/create/loot_tables/blocks/layered_limestone.json 0ec9e366708637a01e600a2a12cc267d81b3f69b data/create/loot_tables/blocks/layered_scoria.json 54816065cd735dfe53b1eb551110ba18c6e3746a data/create/loot_tables/blocks/layered_weathered_limestone.json +4b34cda34416f58045b10e61a0c8ae2b29cb0794 data/create/loot_tables/blocks/lectern_controller.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/light_blue_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/light_blue_sail.json b403848d3a4b4ad7a048e70c21e200e40d0c67e3 data/create/loot_tables/blocks/light_blue_seat.json +f99311437dd0ba8b13dee786bf10a50879386981 data/create/loot_tables/blocks/light_blue_toolbox.json 32afe3fff74ccda4151567961fa6c0b8e3735358 data/create/loot_tables/blocks/light_blue_valve_handle.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/light_gray_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/light_gray_sail.json 0cc2b20cb6e2dae6cf9d759c85926663f6066c99 data/create/loot_tables/blocks/light_gray_seat.json +21bd11fba85a8dc66f6c97df3863ccc496602fde data/create/loot_tables/blocks/light_gray_toolbox.json 8cc64a1dfb7ce7be2c063248d912c68ad2fe999c data/create/loot_tables/blocks/light_gray_valve_handle.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/lime_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/lime_sail.json f7893090c6ecb4862c90c408b7f9ce8316f8b608 data/create/loot_tables/blocks/lime_seat.json +a9ea20a8dce75489356e0124c218dce0c25dd1fc data/create/loot_tables/blocks/lime_toolbox.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 @@ -2593,8 +2754,10 @@ ebb8f7a60d6d9debc53a1f16749d61b980dd1d18 data/create/loot_tables/blocks/limeston 371115e5ceb08c07a9ab2371509960c31e0baa8a data/create/loot_tables/blocks/limestone_pillar.json aa751d2e8a7889907c08c4bec6f6ca266230b6d7 data/create/loot_tables/blocks/linear_chassis.json 4005c244387ea824202c4c7cd44403e537d9766b data/create/loot_tables/blocks/lit_blaze_burner.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/magenta_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/magenta_sail.json 9e5e017cd3b4f544f487a5ca22ef610a4addc8ec data/create/loot_tables/blocks/magenta_seat.json +66271e9a73981cfa07b3aa5abae845670f37afa4 data/create/loot_tables/blocks/magenta_toolbox.json 517e983d7387ec0d86845d4cf3deaa6d68c71170 data/create/loot_tables/blocks/magenta_valve_handle.json e64c32da44b7e92dbef36fcb448c42b9bd9ae47c data/create/loot_tables/blocks/mechanical_arm.json 90ddf7b5c3b61758a4ad12a1e6ef16fe6ebf7794 data/create/loot_tables/blocks/mechanical_bearing.json @@ -2628,6 +2791,7 @@ d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/nixie_tu 90cc4d5857f47c48e2b82f394de9567023c5c8ce data/create/loot_tables/blocks/oak_window_pane.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/orange_sail.json 2333aaea940816b6bc8454ba24e0c9f52af94ac0 data/create/loot_tables/blocks/orange_seat.json +de05f444ab1776b77e4d9e50411feb26530f2473 data/create/loot_tables/blocks/orange_toolbox.json 13338687962ef5b48dd9d142a2a862637d5c6953 data/create/loot_tables/blocks/orange_valve_handle.json 267e9e24fac93e3496a80fcb6ed8e9d1c329d2d2 data/create/loot_tables/blocks/ornate_iron_window.json 1fe77a16f4c86993b5fb30f1f48362787fd7cd0b data/create/loot_tables/blocks/ornate_iron_window_pane.json @@ -2676,8 +2840,11 @@ dfeba5c6de20e9ec0252e43b7c4046f017284d3d data/create/loot_tables/blocks/paved_we 09789862582b5409cd446f734cd53b6f807342cf data/create/loot_tables/blocks/paved_weathered_limestone_slab.json 67b9227237ed2a8c09c4183c0f2ab1b3bd07084b data/create/loot_tables/blocks/paved_weathered_limestone_stairs.json d3e4ab984aef19ee21a1c5b868eb3fde96c05afd data/create/loot_tables/blocks/paved_weathered_limestone_wall.json +3a54eca6d503c154a2235ad5b6be4653abd4b6e3 data/create/loot_tables/blocks/peculiar_bell.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/pink_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/pink_sail.json 6f32e1217986407e41358e9417de63602c78e810 data/create/loot_tables/blocks/pink_seat.json +0185cbfd1e039a2c7c1b625561049706adf02931 data/create/loot_tables/blocks/pink_toolbox.json d85b09659f08a73513c57b1b2e5ec7fc4b6f340a data/create/loot_tables/blocks/pink_valve_handle.json 1087b6c6d88dc7c71ed81e1d3e180fe065e6d098 data/create/loot_tables/blocks/piston_extension_pole.json 05302657546d8d410e367e84d4d5e01f01523236 data/create/loot_tables/blocks/polished_dark_scoria.json @@ -2710,12 +2877,16 @@ fbe98efcb1a5970b6795fdbbb671fee704c0945f data/create/loot_tables/blocks/portable a3fb7d3e3bf9dc73ce754002f10c469d57db1f71 data/create/loot_tables/blocks/powered_toggle_latch.json 205f5899101262f31f5c1a88bb7d954918d08d04 data/create/loot_tables/blocks/pulley_magnet.json e8fb62c91226ac107dee45c5ebc54c8dd0aee224 data/create/loot_tables/blocks/pulse_repeater.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/purple_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/purple_sail.json d7f6caa568e6508177a644fb78dc18ce26c9b2c0 data/create/loot_tables/blocks/purple_seat.json +06c233a9a1aeec64fbd41d3134555ebc535de965 data/create/loot_tables/blocks/purple_toolbox.json 773e4dc856044dabfe9d2323cbda0460dfb626ee data/create/loot_tables/blocks/purple_valve_handle.json 768420dab8785909891e52c4d77a182d99ba11d3 data/create/loot_tables/blocks/radial_chassis.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/red_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/red_sail.json 71b0fa3b174efe94a2a735ab2426c376c0ef674a data/create/loot_tables/blocks/red_seat.json +2f15d3f98121a4a1348bd3c44c59cbb52619b12e data/create/loot_tables/blocks/red_toolbox.json 59ee0fd35978068fbce0882e0b207db7eeb202c0 data/create/loot_tables/blocks/red_valve_handle.json f5907a694206facc01f61f3428f72488486761c7 data/create/loot_tables/blocks/redstone_contact.json 886a0c1386fb12104b736a15689030aaff771270 data/create/loot_tables/blocks/redstone_link.json @@ -2726,8 +2897,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 +2930,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 @@ -2770,18 +2941,23 @@ a89f425c47c3831071b556697169a3124370aed7 data/create/loot_tables/blocks/weathere e8f3af61d9a2fd1ff5b32c9bb474ed005e6d70c4 data/create/loot_tables/blocks/weathered_limestone_cobblestone_wall.json 54358a64639957cc66ffa5296ff45723f7adf00e data/create/loot_tables/blocks/weathered_limestone_pillar.json e3969f1c5966c4992b3280a06e1d6c5000c37df5 data/create/loot_tables/blocks/weighted_ejector.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/white_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/white_sail.json 969eda31556feb5a68e350762848d17453275fee data/create/loot_tables/blocks/white_seat.json +7c210ac011b1eda2255773278ae7daa59b1576aa data/create/loot_tables/blocks/white_toolbox.json 79fe374f8e677088f928a3a49ff5eeed6128d165 data/create/loot_tables/blocks/white_valve_handle.json 941ea78ea7c0f0061c3d3569ecea333ae6a16bf1 data/create/loot_tables/blocks/windmill_bearing.json 728c8719e653825c030913df94ce845fdc6d79b7 data/create/loot_tables/blocks/wooden_bracket.json +d3ea271bb5774c73d44ab2e73195c9d5a4ff9c92 data/create/loot_tables/blocks/yellow_nixie_tube.json 28ae0ee8a0b1fb6becae6264de687fe17940708e data/create/loot_tables/blocks/yellow_sail.json 37ead431a278928a09b260ae06a448e2c791a73e data/create/loot_tables/blocks/yellow_seat.json +cbe175f9036f0de82d4f8a03aa0e932a37d25ea3 data/create/loot_tables/blocks/yellow_toolbox.json 899bb208908a2f9bec5e544ff47526f3e24db720 data/create/loot_tables/blocks/yellow_valve_handle.json 94661e726b3d19271550359ae898a5590939512e data/create/loot_tables/blocks/zinc_block.json 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,14 +3021,51 @@ 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 +739a1d004c4be50cda2d706a64b797f66c3ca9c8 data/create/recipes/compacting/honey.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 +0de0507bc9bb44271b21a64cceb7cd94f7dbe61d data/create/recipes/crafting/curiosities/black_toolbox_from_main_toolbox.json +e89b2dd52cfe2d4d723f49aeec8f4f8c37a82dca data/create/recipes/crafting/curiosities/black_toolbox_from_other_toolbox.json +5588aa83b6fbb2ee3dc01e95b3261ccc38e40ad1 data/create/recipes/crafting/curiosities/blue_toolbox_from_main_toolbox.json +19c9fe34e311e7a11114acc10cc3777fc95ed3ab data/create/recipes/crafting/curiosities/blue_toolbox_from_other_toolbox.json +4754ca20a7efdf382f32be150f38bdf4e8183fc4 data/create/recipes/crafting/curiosities/brown_toolbox.json +7635daa89502a79cc5b99b146c1097fa166958e5 data/create/recipes/crafting/curiosities/brown_toolbox_from_main_toolbox.json +14a85c9011a6ca667ac83e95dd7e8eabfac4a4c5 data/create/recipes/crafting/curiosities/brown_toolbox_from_other_toolbox.json +39e6d65af1c8ca0dec19e5b15a2f0e28e69542eb data/create/recipes/crafting/curiosities/cyan_toolbox_from_main_toolbox.json +39e055d841536e691c798acc09145f821eeb32ae data/create/recipes/crafting/curiosities/cyan_toolbox_from_other_toolbox.json +567a09f08bbbd5fd8eb34555bb9e62e7066c8c93 data/create/recipes/crafting/curiosities/gray_toolbox_from_main_toolbox.json +f6ee1a69e32851487a753a27290c7fee163de87f data/create/recipes/crafting/curiosities/gray_toolbox_from_other_toolbox.json +5e0e201caff1f11092c8dc5a524bab00dec52848 data/create/recipes/crafting/curiosities/green_toolbox_from_main_toolbox.json +9c9d9e1c9a0b76561b2fd97fe5a9adc7660935af data/create/recipes/crafting/curiosities/green_toolbox_from_other_toolbox.json +3750f44691883b644ce80b869f69785a151c63ce data/create/recipes/crafting/curiosities/light_blue_toolbox_from_main_toolbox.json +3511ddf935de95789db27cd546b51835051b0612 data/create/recipes/crafting/curiosities/light_blue_toolbox_from_other_toolbox.json +6f6e22a1d7d27098dfa15cdd7a9dc841116dd085 data/create/recipes/crafting/curiosities/light_gray_toolbox_from_main_toolbox.json +b2d9ddb013d550f335c28a64360aad5a2c9ef109 data/create/recipes/crafting/curiosities/light_gray_toolbox_from_other_toolbox.json +0b55ab5174983f503355c52e6bff1cfb199d833b data/create/recipes/crafting/curiosities/lime_toolbox_from_main_toolbox.json +8e50132d045351427ad33aec3463437f93024970 data/create/recipes/crafting/curiosities/lime_toolbox_from_other_toolbox.json +8912a48550b1e763a75eb8db0412d39992350cde data/create/recipes/crafting/curiosities/magenta_toolbox_from_main_toolbox.json +53fa044e156eae089c3bdd037b168169f3dedde8 data/create/recipes/crafting/curiosities/magenta_toolbox_from_other_toolbox.json 660e92da2b1b6698b1c0df74bd74a56a25fb3eca data/create/recipes/crafting/curiosities/minecart_coupling.json +0639c9c090321f4f95576df3b79f73138dd47b37 data/create/recipes/crafting/curiosities/orange_toolbox_from_main_toolbox.json +8ff510405b3890f3de0f1f11b733f081a2abafaf data/create/recipes/crafting/curiosities/orange_toolbox_from_other_toolbox.json +1f8f96ab57363166b7e132a1dd082001a5a0d5f0 data/create/recipes/crafting/curiosities/peculiar_bell.json +a47f561abcf3521f1407101c37e13e5a888403be data/create/recipes/crafting/curiosities/pink_toolbox_from_main_toolbox.json +84a4f2a38a73aa704a6eadfa6e30942ceace60c6 data/create/recipes/crafting/curiosities/pink_toolbox_from_other_toolbox.json +4f158ed3edf7451d1c2aa7d50efbbc58a4d5b7d0 data/create/recipes/crafting/curiosities/purple_toolbox_from_main_toolbox.json +46d792a2e1252b42b4c7975a8c76c9b818cdfafe data/create/recipes/crafting/curiosities/purple_toolbox_from_other_toolbox.json +9f0adcbf9abe39cb8ae9dfc4ea02953f8103acc9 data/create/recipes/crafting/curiosities/red_toolbox_from_main_toolbox.json +574f0198e7f0c683ae96221ec69d3a88c39f10e6 data/create/recipes/crafting/curiosities/red_toolbox_from_other_toolbox.json fcbc04d0a7eaf820a74bc7e4736a4a581e0a9dff data/create/recipes/crafting/curiosities/wand_of_symmetry.json +ef8e81e889747a35669ccd5851e43d0349225115 data/create/recipes/crafting/curiosities/white_toolbox_from_main_toolbox.json +3222feaa77a392b45da97a410e268641998864c6 data/create/recipes/crafting/curiosities/white_toolbox_from_other_toolbox.json +71272236f542469e82b92f5208122b18f72f365d data/create/recipes/crafting/curiosities/yellow_toolbox_from_main_toolbox.json +56e3950037a751edd931942ccc52563228680cb2 data/create/recipes/crafting/curiosities/yellow_toolbox_from_other_toolbox.json cc56d21a25286a9024e506dde9fa161230eaf46d data/create/recipes/crafting/kinetics/adjustable_chain_gearshift.json 88de51b451469698665b7319e5b9cfb9a87ae3e0 data/create/recipes/crafting/kinetics/analog_lever.json cf1f3a6306d47025cebe153cf05949ef69ccbe5a data/create/recipes/crafting/kinetics/attribute_filter.json @@ -2921,7 +3134,7 @@ d214afbd44e580f5fd1ebb4f16f07ffe34d87cba data/create/recipes/crafting/kinetics/l d7d96071874a87edf7bbdcf7a462f95a130d2991 data/create/recipes/crafting/kinetics/magenta_seat.json 5836881feef8fa8b18e4cceb9c3a9a2748b8cf3a data/create/recipes/crafting/kinetics/magenta_seat_from_other_seat.json 2ea43d6527dcb734578067ff442ec20395b0093b data/create/recipes/crafting/kinetics/magenta_valve_handle_from_other_valve_handle.json -f3f3d484de6411652472db0ca52c612c23f81278 data/create/recipes/crafting/kinetics/mechanical_arm.json +659cd6acdd15511c4b0a396740118b99b76a619d data/create/recipes/crafting/kinetics/mechanical_arm.json 946389078db31de69a7dc4fec5feebddf48dcfc3 data/create/recipes/crafting/kinetics/mechanical_bearing.json a5c7aad0d86cbb66b8688d295e62547da4a2ce0f data/create/recipes/crafting/kinetics/mechanical_crafter.json 4372830100d39c4a89ff397a62b01940e1a28cb3 data/create/recipes/crafting/kinetics/mechanical_drill.json @@ -2956,7 +3169,7 @@ af84b939ced1c0254a27469f857f571afbadc4f6 data/create/recipes/crafting/kinetics/r 0827e86e4b5f9d7023ccc19922bcbbaefd5b42d8 data/create/recipes/crafting/kinetics/red_seat_from_other_seat.json 5a10019d23726940152e26af3239d55d16bc7880 data/create/recipes/crafting/kinetics/red_valve_handle_from_other_valve_handle.json af525e135eb927b64462120d201ecae7a7ec61ed data/create/recipes/crafting/kinetics/rope_pulley.json -e9f1597d40f62c2247b319303f375f0da271346f data/create/recipes/crafting/kinetics/rotation_speed_controller.json +1b918eb77b3e0fb2234c4c2c0d52e730ae7f3ffa data/create/recipes/crafting/kinetics/rotation_speed_controller.json d0d7fb94621f6f02fa3137666f20e677022d9d5b data/create/recipes/crafting/kinetics/sail_frame.json 66922e18791c87fadb7629cdf32d3dd2f50ccd13 data/create/recipes/crafting/kinetics/secondary_linear_chassisfrom_conversion.json a17db27e61baa45f8a6ecb46a6d2a5a464704f8b data/create/recipes/crafting/kinetics/sequenced_gearshift.json @@ -3082,26 +3295,27 @@ fd565e84aff897968be805c03623757c11ea57ed data/create/recipes/cutting/oak_log.jso 2bf4234c994073addb7341fa1ef8b721572dde37 data/create/recipes/cutting/oak_wood.json 2cd588872f6bbf63686a92a12735aa65d1960fe3 data/create/recipes/cutting/spruce_log.json 5ae29d81388c3d0d7966e703b6e9463ea58221ef data/create/recipes/cutting/spruce_wood.json -9f14b915695407155fdf806b1e5ecf91e0860c5b data/create/recipes/cutting/stripped_acacia_log.json -c7f0e3b7a46676ede1ed775ec8aa8b969e1fe598 data/create/recipes/cutting/stripped_acacia_wood.json -4c657d8ff753789853c8d705fb5ae01caeef5cc1 data/create/recipes/cutting/stripped_birch_log.json -53f47375955f65844c077c8bb06a9eeb67e0b53f data/create/recipes/cutting/stripped_birch_wood.json -c2d6c83bb3144c6013e169de8f54c5f380ad094f data/create/recipes/cutting/stripped_crimson_hyphae.json -affb6d0e171d77a6a27fc83b1a916eb95ed89516 data/create/recipes/cutting/stripped_crimson_stem.json -9cab5363d43559823d4679da0a64a0a603983cb6 data/create/recipes/cutting/stripped_dark_oak_log.json -c63bc7d8a81b3499390de84fc49d726c9018896d data/create/recipes/cutting/stripped_dark_oak_wood.json -e923bfbc5d9b02e020693378723b4d55fc60f79a data/create/recipes/cutting/stripped_jungle_log.json -2dba1962f0a267d72444ec448432b81143fc42da data/create/recipes/cutting/stripped_jungle_wood.json -ff68462a712267db1f1124d37a4877217edd5c85 data/create/recipes/cutting/stripped_oak_log.json -84ffcff96d79f88012bceae0e346da6be4da9802 data/create/recipes/cutting/stripped_oak_wood.json -2b5f34ba42521004f999140056c997b07acde4e9 data/create/recipes/cutting/stripped_spruce_log.json -6c3776c4d4190dba4f70d1f6995715002b37b3a8 data/create/recipes/cutting/stripped_spruce_wood.json -135e9d58965c5715eb6c34a637714f61b38714f7 data/create/recipes/cutting/stripped_warped_hyphae.json -f3c2cd996214e92e95e452d0f6e86ada59e65c78 data/create/recipes/cutting/stripped_warped_stem.json +7326bd8a2ec38c22dd7ce4bba5d732b1eaad2651 data/create/recipes/cutting/stripped_acacia_log.json +56a7b89a750ff320e9939ab811260e05056b7c60 data/create/recipes/cutting/stripped_acacia_wood.json +5bf1850bbb48e743b05f8d582f41a1736d5948f1 data/create/recipes/cutting/stripped_birch_log.json +0e487a41951e758cf523145dcbaaa2087d9ea718 data/create/recipes/cutting/stripped_birch_wood.json +9efc61317fbda72fc2924aa3f9113cced46aad77 data/create/recipes/cutting/stripped_crimson_hyphae.json +22b36652bef66fbcae960a5f6c0b4b0df3216eca data/create/recipes/cutting/stripped_crimson_stem.json +bb6fc75a5d21ad5cb17907a452b40f280b774349 data/create/recipes/cutting/stripped_dark_oak_log.json +0ead24be657900834f15dd19cafee385c9b3db44 data/create/recipes/cutting/stripped_dark_oak_wood.json +e3e08b3a69356be3e169ee3c6df9983c7c136b9c data/create/recipes/cutting/stripped_jungle_log.json +d59b1c12331db8a91e9284ed5b9b1e60f7357b94 data/create/recipes/cutting/stripped_jungle_wood.json +21b544e00ecad0a209e3dd7d1c65a698cdfdd889 data/create/recipes/cutting/stripped_oak_log.json +a9a78bafc9a90a5cd71cfa8ed8604584eea3ee17 data/create/recipes/cutting/stripped_oak_wood.json +42a519e2150a2578b9588068efa627626f8920f6 data/create/recipes/cutting/stripped_spruce_log.json +0bbac641024c34d7f38872ace1343e123f281a37 data/create/recipes/cutting/stripped_spruce_wood.json +fcf37b9ee3d691f1fd9c70fa297555eadceb039f data/create/recipes/cutting/stripped_warped_hyphae.json +f6462f1593d1275db331b0a8fc3f5d09bac60b23 data/create/recipes/cutting/stripped_warped_stem.json a022f2d541f04a9e2bed6b72af4e74703076fcbe data/create/recipes/cutting/warped_hyphae.json 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 +3332,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 +3349,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 @@ -3152,7 +3368,6 @@ ff39e629b242ae91e23aec86b0a1f757dd938305 data/create/recipes/dolomite_pillar.jso b4a8d14d9a20e812e0acb691b5b511a87e8b0576 data/create/recipes/dolomite_pillar_from_dolomite_stonecutting.json d81ceba2946286d374801e698a4ca2116395cbad data/create/recipes/emptying/builders_tea.json 20b7c7c62fa2e33199e08188dd8836844a6d9cfd data/create/recipes/emptying/honey_bottle.json -28a0f9a45671de2e6db19fa66374e245feeed142 data/create/recipes/emptying/milk_bucket.json 0e11aa1accb71ed62e212f23a7069b7b7b4e8119 data/create/recipes/fancy_andesite_bricks_from_andesite_stonecutting.json 8b86fc9a9416adeaab3f26192a73a481887675c3 data/create/recipes/fancy_andesite_bricks_slab.json c7b762b25c7a6705dba3e922e981be851ac4f36b data/create/recipes/fancy_andesite_bricks_slab_from_fancy_andesite_bricks_stonecutting.json @@ -3224,11 +3439,11 @@ d2ab9ce73636773165564506580f2ec13bd1fc50 data/create/recipes/fancy_weathered_lim 244f27eadefefbc966ac384ac087c57d19484321 data/create/recipes/filling/gunpowder.json c8ca74a6cd071308a1750a2ad1153e79422598a0 data/create/recipes/filling/honey_bottle.json d20703b67dd5e4c9b75718db02d575b1c7415c12 data/create/recipes/filling/honeyed_apple.json -c83e77a9799b6ca34dd73aa76b56159f2103c48c data/create/recipes/filling/milk_bucket.json 08ce1420d1551ecfef5988977436c087123851a6 data/create/recipes/filling/redstone.json 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 +3460,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 +3490,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 @@ -3290,15 +3507,16 @@ bbf64f7eb3868e354756e57348493e2b1ae6b0d9 data/create/recipes/limestone_cobblesto 88fa2b1ab746d5e13a8afd6e7e7d80ad843e0016 data/create/recipes/limestone_cobblestone_wall_from_limestone_cobblestone_stonecutting.json 327bb8a6535b60bb65d0dda9d5205e988bc82526 data/create/recipes/limestone_pillar.json c2e15ac0c9109bad3face6d13efc32d7116b4c25 data/create/recipes/limestone_pillar_from_limestone_stonecutting.json -88173753ceaf121c5430bbf928a40e3c046dbfe0 data/create/recipes/mechanical_crafting/crushing_wheel.json -357cb3a50ebedcc347396c5cb26a04eb4bd96fea data/create/recipes/mechanical_crafting/extendo_grip.json -de7fea84434753873dfa2b929d9b5f5f86ac6a5c data/create/recipes/mechanical_crafting/flywheel.json -e491fd8a8873308270f9dc2a57ac8f2c70431dcc data/create/recipes/mechanical_crafting/furnace_engine.json -ce17f8ab6e051f45a12e55f1642ad1b8a0f8510f data/create/recipes/mechanical_crafting/integrated_circuit.json +66674d07de63aada0991d2fdff07e22e00450135 data/create/recipes/mechanical_crafting/crushing_wheel.json +599f8b87c24c131350ba7ceb69a0c8b9829c62bc data/create/recipes/mechanical_crafting/extendo_grip.json +f26ed47c10cc63613759b0f8ae4ef349000de60d data/create/recipes/mechanical_crafting/flywheel.json +2dc00d6e4c159e06ab2a705e666e83e4238a7814 data/create/recipes/mechanical_crafting/furnace_engine.json +b77911c169b6205a09001a09ca074eb2234f0d29 data/create/recipes/mechanical_crafting/potato_cannon.json 98f877bf8f3f8a686fc6cf7479a0fba5744248ce data/create/recipes/milling/allium.json 8c7e1cbc87c7ca7df2bf949957e89422fef8ad94 data/create/recipes/milling/aluminum_ore.json bcff4d30ae09a0729bce8b2dbde4ddd6719a998b data/create/recipes/milling/andesite.json ac3f1c92115a113a1ea7e5543c1e061e3d2a0b36 data/create/recipes/milling/azure_bluet.json +83fc4663a012e78cebbb0f08e01a10df06b04873 data/create/recipes/milling/beetroot.json 95d673bb272d273c2ad25bf01723dd978642faed data/create/recipes/milling/blue_orchid.json 25d008621c461a1f6fef0e45913dc8654c645ea3 data/create/recipes/milling/bone.json 8c09dc48b3e3c3c6bfdc4ed7683bdee860802172 data/create/recipes/milling/bone_meal.json @@ -3338,6 +3556,7 @@ bda581c2039f41f7d55527814a46903f10da7e05 data/create/recipes/milling/rose_bush.j 54be62a1bf098a370d315f79068ec326e4f4d6c2 data/create/recipes/milling/saddle.json 8bc6124293f4efb5f2d0fa4a3166c6d00a88a14c data/create/recipes/milling/sand.json 42c5837c16132632da52325cddea3cdbb318e822 data/create/recipes/milling/sandstone.json +d11b247b41fc1c36c75a68a56eca8404367707f8 data/create/recipes/milling/sea_pickle.json 87e30347cc28aa5fb2daefae4c25fa81ce92b0f1 data/create/recipes/milling/silver_ore.json 1e14bd30032aab6dfaff5bca50c791332ffc1aaa data/create/recipes/milling/sugar_cane.json af2beca9f934601ad029f34bad08be3cee07f6b4 data/create/recipes/milling/sunflower.json @@ -3354,8 +3573,11 @@ b3cc5e61bab40ca6135dc1f706f3ab447e9f78bf data/create/recipes/mixing/andesite_all ce9dc7dacb85cb23a7187c19a115b40e597ad36b data/create/recipes/mixing/andesite_alloy_from_zinc.json 3417f9399ce0fb32fc4bce94c772b40d780c9006 data/create/recipes/mixing/brass_ingot.json ab602a53a5d8d057aad910dd1c5529cde2d587ab data/create/recipes/mixing/chocolate.json +d3bf74bb3826cf2dccaf7377b8b3e0fdaa38f1aa data/create/recipes/mixing/chocolate_melting.json 0e29b4ce13750aab5a60ae54cbec8776569b35e0 data/create/recipes/mixing/chromatic_compound.json d9a3dff1288d675ab812eef1eb73cb27dcc71bd2 data/create/recipes/mixing/crushed_brass.json +ec331b1de31bbe2795aec729e931726ec4f4534f data/create/recipes/mixing/dough_by_mixing.json +ffba306dbb52e4d7afeaec183b92821dbc402a7c data/create/recipes/mixing/honey.json cd9a78454bce20cf3557f5c44febae77ebd43e54 data/create/recipes/mixing/lava_from_cobble.json 0f89b3f2d81585591513619b8d1e8694eb874316 data/create/recipes/mixing/tea.json 1998c6f84f871d6da58ec29d729401d18f8f1aa1 data/create/recipes/mossy_andesite_from_andesite_stonecutting.json @@ -3443,7 +3665,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 +3673,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 +3681,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 +3689,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 +3697,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 +3705,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 @@ -3495,10 +3717,10 @@ eae06580a0a5f486cde35426716d50fcb3ba5bb3 data/create/recipes/polished_weathered_ 4a51cb6066e87613c13bdc6d3427929080ef1def data/create/recipes/pressing/copper_ingot.json 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 @@ -3515,6 +3737,9 @@ f7b7ff190929ae525297fecb3c116f32fc05fd88 data/create/recipes/scoria_cobblestone_ a9096822db9d12b6014d6d34e52de5821305c03f data/create/recipes/scoria_cobblestone_wall_from_scoria_cobblestone_stonecutting.json a513468ce4d55fe3b3919bd76ba2bd5b6fac4d4e data/create/recipes/scoria_pillar.json 2e0ecbd3619f080d0fc6fe48307c5a5bcc2e91b4 data/create/recipes/scoria_pillar_from_scoria_stonecutting.json +1b6bec69b00c44e74951973d69caae53d85383cb data/create/recipes/sequenced_assembly/cogwheel.json +3bc3d13856f9ab8ccc47c3188cfd839f6db2359b data/create/recipes/sequenced_assembly/large_cogwheel.json +b49a0da57a179edc087eee224221ded22fd1be01 data/create/recipes/sequenced_assembly/precision_mechanism.json 4e817b521623966fa24186731a70f0e14c03168e data/create/recipes/smelting/aluminum_ingot_compat_silents_mechanisms.json ae90f50589bc06b44765ac8cbb9fbdc2b58fdb32 data/create/recipes/smelting/brass_ingot_from_crushed.json 64cbf425effba00ff2e31d95cffc2be2e0191932 data/create/recipes/smelting/bread.json @@ -3629,6 +3854,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,35 +3871,41 @@ 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 +6558ef43f28c92cc558fbfc572f38496f1ed479e 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 +57b942386a15c874d1ca9cd6a8032c11a5599fc2 data/create/tags/blocks/fan_transparent.json c81ea194e808985847159b201140d4aa4cbcca65 data/create/tags/blocks/safe_nbt.json c9ac7e3e5ec18554e7184168d65e9b8e44ef5610 data/create/tags/blocks/sails.json 6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json +d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/blocks/toolboxes.json 50936b211d94167a35ec78c89954082a336b6269 data/create/tags/blocks/valve_handles.json eac71740fb12bdb38b5dfaa2268613d7ba82b809 data/create/tags/blocks/windmill_sails.json 74700d556ca80c7a1db5fd4efb09c3ddb26cad66 data/create/tags/blocks/windowable.json +893a01e6004d6d8272bd1658e98da88bb572ee57 data/create/tags/blocks/wrench_pickup.json 081f5aa35602fc27af2ca01ea9f2fd5e7eb284dc data/create/tags/items/create_ingots.json 94c62bf22678ef55b2b8a5398a7960e5b00682dc data/create/tags/items/crushed_ores.json +bce28787b0271382842823d04a977912a88b01c2 data/create/tags/items/sandpaper.json 6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/items/seats.json -c7efc23c08d5e3602c84ff43dac18f72b1cfced3 data/create/tags/items/upright_on_belt.json +d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/items/toolboxes.json +2f4044c2989b9a8aa394c88617d67a6a310e6b1b data/create/tags/items/upright_on_belt.json 50936b211d94167a35ec78c89954082a336b6269 data/create/tags/items/valve_handles.json +05ca51cdc60a5e109b5a0e3b782de13d34ebcb24 data/forge/tags/blocks/cobblestone.json 16bcb8fcbe9170c2c11f1ca8d99d8b36cd812bbd data/forge/tags/blocks/glass/colorless.json 81d3eb40b048160fcc2d6bb7ff12b49276297efd data/forge/tags/blocks/glass_panes.json 4b700ee8aa748c2ec70c29ef1589844879c0deae data/forge/tags/blocks/ores.json 4a0b13a9835106de9a1dd0a71a02372abb48e7b6 data/forge/tags/blocks/ores/copper.json d5ea262a0f5fb210612d22521818e26cf08e591a data/forge/tags/blocks/ores/zinc.json +55196ee770ad20602211e26864dd62a58b2e985c data/forge/tags/blocks/stone.json 508730d3822c54d355329bf6a33d58071653afad data/forge/tags/blocks/storage_blocks.json ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/blocks/storage_blocks/brass.json f6c8f34ceb475546dba5cc6ff288863ea795d20b data/forge/tags/blocks/storage_blocks/copper.json 7f71a774800111e50b42de0e6159ed2d2a807d32 data/forge/tags/blocks/storage_blocks/zinc.json +2072c51afc5bbc6c9d64fd086803193d8a3c40de data/forge/tags/blocks/wg_stone.json 6b73c57912934d09233ad2966110968a6109f2c9 data/forge/tags/fluids/chocolate.json 391c9b2be5740aea943a8a5fe27eb327e2d973b0 data/forge/tags/fluids/honey.json -aa729fedc4fcca0f0a18bf7b00075af06bf5357f data/forge/tags/fluids/milk.json d6a4e4fe1204b718010543a28a9b9ec4e0977bd7 data/forge/tags/fluids/tea.json d9ffc62a496946fc4848934e7c0a6e917337f8be data/forge/tags/items/beacon_payment.json +5af3164b14c92d2d6e235b5d4eebd93cbee37c0a data/forge/tags/items/buckets/honey.json 05ca51cdc60a5e109b5a0e3b782de13d34ebcb24 data/forge/tags/items/cobblestone.json 16bcb8fcbe9170c2c11f1ca8d99d8b36cd812bbd data/forge/tags/items/glass/colorless.json 81d3eb40b048160fcc2d6bb7ff12b49276297efd data/forge/tags/items/glass_panes.json @@ -3688,12 +3920,12 @@ cc82188fe8d986f4457301ed4f75ae833d263601 data/forge/tags/items/nuggets/brass.jso 4b700ee8aa748c2ec70c29ef1589844879c0deae data/forge/tags/items/ores.json 4a0b13a9835106de9a1dd0a71a02372abb48e7b6 data/forge/tags/items/ores/copper.json d5ea262a0f5fb210612d22521818e26cf08e591a data/forge/tags/items/ores/zinc.json -0ecf8a5392faf244b8cab3c7ddd45d5b34954050 data/forge/tags/items/plates.json +5d5ec04a61ff2b1ad19210e2859a9c96cc246ef8 data/forge/tags/items/plates.json 39f0d70ec10597e85df7c4783bbc5e0e4a5ffb80 data/forge/tags/items/plates/brass.json c3dab5fe379bc1b7b10d4a0ba7009eee1b75a27c data/forge/tags/items/plates/copper.json fb9bfb4c84ed9cf2da8c4b2fbc4cd4d9f37d3016 data/forge/tags/items/plates/gold.json 04d947ed7a5066f3cfe75a8dc564fe2dca8a9c93 data/forge/tags/items/plates/iron.json -4d598b23d07b6a0bfd89da11a30ce119a8660632 data/forge/tags/items/plates/lapis_lazuli.json +55196ee770ad20602211e26864dd62a58b2e985c data/forge/tags/items/stone.json 508730d3822c54d355329bf6a33d58071653afad data/forge/tags/items/storage_blocks.json ff1900963bc4cd8ceffa78d58ef1952ceacb2fb7 data/forge/tags/items/storage_blocks/brass.json f6c8f34ceb475546dba5cc6ff288863ea795d20b data/forge/tags/items/storage_blocks/copper.json @@ -3707,6 +3939,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/blockstates/black_nixie_tube.json b/src/generated/resources/assets/create/blockstates/black_nixie_tube.json new file mode 100644 index 000000000..6c876afd9 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/black_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/black_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/black_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/black_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/black_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/black_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/black_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/black_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/black_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/black_toolbox.json b/src/generated/resources/assets/create/blockstates/black_toolbox.json new file mode 100644 index 000000000..9641add4d --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/black_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/black_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/black_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/black_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/black_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/black_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/black_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/black_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/black_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/blue_nixie_tube.json b/src/generated/resources/assets/create/blockstates/blue_nixie_tube.json new file mode 100644 index 000000000..e0b3c3cbf --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/blue_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/blue_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/blue_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/blue_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/blue_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/blue_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/blue_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/blue_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/blue_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/blue_toolbox.json b/src/generated/resources/assets/create/blockstates/blue_toolbox.json new file mode 100644 index 000000000..3f3aa455c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/blue_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/blue_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/blue_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/blue_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/blue_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/blue_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/blue_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/blue_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/blue_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/brown_nixie_tube.json b/src/generated/resources/assets/create/blockstates/brown_nixie_tube.json new file mode 100644 index 000000000..ac0598ea6 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/brown_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/brown_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/brown_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/brown_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/brown_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/brown_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/brown_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/brown_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/brown_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/brown_toolbox.json b/src/generated/resources/assets/create/blockstates/brown_toolbox.json new file mode 100644 index 000000000..f0ccd296a --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/brown_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/brown_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/brown_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/brown_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/brown_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/brown_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/brown_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/brown_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/brown_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/cart_assembler.json b/src/generated/resources/assets/create/blockstates/cart_assembler.json index 0349a4837..3fe0c5550 100644 --- a/src/generated/resources/assets/create/blockstates/cart_assembler.json +++ b/src/generated/resources/assets/create/blockstates/cart_assembler.json @@ -1,88 +1,152 @@ { "variants": { - "powered=false,rail_type=regular,shape=north_south": { + "backwards=false,powered=false,rail_type=regular,shape=north_south": { "model": "create:block/cart_assembler/block_regular" }, - "powered=true,rail_type=regular,shape=north_south": { + "backwards=true,powered=false,rail_type=regular,shape=north_south": { + "model": "create:block/cart_assembler/block_regular", + "y": 180 + }, + "backwards=false,powered=true,rail_type=regular,shape=north_south": { "model": "create:block/cart_assembler/block_regular_powered" }, - "powered=false,rail_type=powered_rail,shape=north_south": { + "backwards=true,powered=true,rail_type=regular,shape=north_south": { + "model": "create:block/cart_assembler/block_regular_powered", + "y": 180 + }, + "backwards=false,powered=false,rail_type=powered_rail,shape=north_south": { "model": "create:block/cart_assembler/block_powered_rail" }, - "powered=true,rail_type=powered_rail,shape=north_south": { + "backwards=true,powered=false,rail_type=powered_rail,shape=north_south": { + "model": "create:block/cart_assembler/block_powered_rail", + "y": 180 + }, + "backwards=false,powered=true,rail_type=powered_rail,shape=north_south": { "model": "create:block/cart_assembler/block_powered_rail_powered" }, - "powered=false,rail_type=detector_rail,shape=north_south": { + "backwards=true,powered=true,rail_type=powered_rail,shape=north_south": { + "model": "create:block/cart_assembler/block_powered_rail_powered", + "y": 180 + }, + "backwards=false,powered=false,rail_type=detector_rail,shape=north_south": { "model": "create:block/cart_assembler/block_detector_rail" }, - "powered=true,rail_type=detector_rail,shape=north_south": { + "backwards=true,powered=false,rail_type=detector_rail,shape=north_south": { + "model": "create:block/cart_assembler/block_detector_rail", + "y": 180 + }, + "backwards=false,powered=true,rail_type=detector_rail,shape=north_south": { "model": "create:block/cart_assembler/block_detector_rail_powered" }, - "powered=false,rail_type=activator_rail,shape=north_south": { + "backwards=true,powered=true,rail_type=detector_rail,shape=north_south": { + "model": "create:block/cart_assembler/block_detector_rail_powered", + "y": 180 + }, + "backwards=false,powered=false,rail_type=activator_rail,shape=north_south": { "model": "create:block/cart_assembler/block_activator_rail" }, - "powered=true,rail_type=activator_rail,shape=north_south": { + "backwards=true,powered=false,rail_type=activator_rail,shape=north_south": { + "model": "create:block/cart_assembler/block_activator_rail", + "y": 180 + }, + "backwards=false,powered=true,rail_type=activator_rail,shape=north_south": { "model": "create:block/cart_assembler/block_activator_rail_powered" }, - "powered=false,rail_type=controller_rail,shape=north_south": { + "backwards=true,powered=true,rail_type=activator_rail,shape=north_south": { + "model": "create:block/cart_assembler/block_activator_rail_powered", + "y": 180 + }, + "backwards=false,powered=false,rail_type=controller_rail,shape=north_south": { "model": "create:block/cart_assembler/block_controller_rail" }, - "powered=true,rail_type=controller_rail,shape=north_south": { - "model": "create:block/cart_assembler/block_controller_rail_powered" - }, - "powered=false,rail_type=controller_rail_backwards,shape=north_south": { + "backwards=true,powered=false,rail_type=controller_rail,shape=north_south": { "model": "create:block/cart_assembler/block_controller_rail", "y": 180 }, - "powered=true,rail_type=controller_rail_backwards,shape=north_south": { + "backwards=false,powered=true,rail_type=controller_rail,shape=north_south": { + "model": "create:block/cart_assembler/block_controller_rail_powered" + }, + "backwards=true,powered=true,rail_type=controller_rail,shape=north_south": { "model": "create:block/cart_assembler/block_controller_rail_powered", "y": 180 }, - "powered=false,rail_type=regular,shape=east_west": { + "backwards=false,powered=false,rail_type=regular,shape=east_west": { "model": "create:block/cart_assembler/block_regular", "y": 270 }, - "powered=true,rail_type=regular,shape=east_west": { + "backwards=true,powered=false,rail_type=regular,shape=east_west": { + "model": "create:block/cart_assembler/block_regular", + "y": 90 + }, + "backwards=false,powered=true,rail_type=regular,shape=east_west": { "model": "create:block/cart_assembler/block_regular_powered", "y": 270 }, - "powered=false,rail_type=powered_rail,shape=east_west": { + "backwards=true,powered=true,rail_type=regular,shape=east_west": { + "model": "create:block/cart_assembler/block_regular_powered", + "y": 90 + }, + "backwards=false,powered=false,rail_type=powered_rail,shape=east_west": { "model": "create:block/cart_assembler/block_powered_rail", "y": 270 }, - "powered=true,rail_type=powered_rail,shape=east_west": { + "backwards=true,powered=false,rail_type=powered_rail,shape=east_west": { + "model": "create:block/cart_assembler/block_powered_rail", + "y": 90 + }, + "backwards=false,powered=true,rail_type=powered_rail,shape=east_west": { "model": "create:block/cart_assembler/block_powered_rail_powered", "y": 270 }, - "powered=false,rail_type=detector_rail,shape=east_west": { + "backwards=true,powered=true,rail_type=powered_rail,shape=east_west": { + "model": "create:block/cart_assembler/block_powered_rail_powered", + "y": 90 + }, + "backwards=false,powered=false,rail_type=detector_rail,shape=east_west": { "model": "create:block/cart_assembler/block_detector_rail", "y": 270 }, - "powered=true,rail_type=detector_rail,shape=east_west": { + "backwards=true,powered=false,rail_type=detector_rail,shape=east_west": { + "model": "create:block/cart_assembler/block_detector_rail", + "y": 90 + }, + "backwards=false,powered=true,rail_type=detector_rail,shape=east_west": { "model": "create:block/cart_assembler/block_detector_rail_powered", "y": 270 }, - "powered=false,rail_type=activator_rail,shape=east_west": { + "backwards=true,powered=true,rail_type=detector_rail,shape=east_west": { + "model": "create:block/cart_assembler/block_detector_rail_powered", + "y": 90 + }, + "backwards=false,powered=false,rail_type=activator_rail,shape=east_west": { "model": "create:block/cart_assembler/block_activator_rail", "y": 270 }, - "powered=true,rail_type=activator_rail,shape=east_west": { + "backwards=true,powered=false,rail_type=activator_rail,shape=east_west": { + "model": "create:block/cart_assembler/block_activator_rail", + "y": 90 + }, + "backwards=false,powered=true,rail_type=activator_rail,shape=east_west": { "model": "create:block/cart_assembler/block_activator_rail_powered", "y": 270 }, - "powered=false,rail_type=controller_rail,shape=east_west": { + "backwards=true,powered=true,rail_type=activator_rail,shape=east_west": { + "model": "create:block/cart_assembler/block_activator_rail_powered", + "y": 90 + }, + "backwards=false,powered=false,rail_type=controller_rail,shape=east_west": { "model": "create:block/cart_assembler/block_controller_rail", "y": 270 }, - "powered=true,rail_type=controller_rail,shape=east_west": { - "model": "create:block/cart_assembler/block_controller_rail_powered", - "y": 270 - }, - "powered=false,rail_type=controller_rail_backwards,shape=east_west": { + "backwards=true,powered=false,rail_type=controller_rail,shape=east_west": { "model": "create:block/cart_assembler/block_controller_rail", "y": 90 }, - "powered=true,rail_type=controller_rail_backwards,shape=east_west": { + "backwards=false,powered=true,rail_type=controller_rail,shape=east_west": { + "model": "create:block/cart_assembler/block_controller_rail_powered", + "y": 270 + }, + "backwards=true,powered=true,rail_type=controller_rail,shape=east_west": { "model": "create:block/cart_assembler/block_controller_rail_powered", "y": 90 } diff --git a/src/generated/resources/assets/create/blockstates/cyan_nixie_tube.json b/src/generated/resources/assets/create/blockstates/cyan_nixie_tube.json new file mode 100644 index 000000000..d86bae904 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/cyan_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/cyan_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/cyan_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/cyan_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/cyan_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/cyan_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/cyan_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/cyan_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/cyan_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/cyan_toolbox.json b/src/generated/resources/assets/create/blockstates/cyan_toolbox.json new file mode 100644 index 000000000..497aa4ab3 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/cyan_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/cyan_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/cyan_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/cyan_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/cyan_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/cyan_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/cyan_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/cyan_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/cyan_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/gray_nixie_tube.json b/src/generated/resources/assets/create/blockstates/gray_nixie_tube.json new file mode 100644 index 000000000..801e85e1e --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/gray_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/gray_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/gray_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/gray_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/gray_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/gray_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/gray_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/gray_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/gray_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/gray_toolbox.json b/src/generated/resources/assets/create/blockstates/gray_toolbox.json new file mode 100644 index 000000000..69b09774f --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/gray_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/gray_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/gray_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/gray_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/gray_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/gray_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/gray_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/gray_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/gray_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/green_nixie_tube.json b/src/generated/resources/assets/create/blockstates/green_nixie_tube.json new file mode 100644 index 000000000..919f0f810 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/green_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/green_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/green_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/green_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/green_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/green_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/green_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/green_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/green_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/green_toolbox.json b/src/generated/resources/assets/create/blockstates/green_toolbox.json new file mode 100644 index 000000000..caf60c8ea --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/green_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/green_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/green_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/green_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/green_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/green_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/green_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/green_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/green_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/haunted_bell.json b/src/generated/resources/assets/create/blockstates/haunted_bell.json new file mode 100644 index 000000000..aff248286 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/haunted_bell.json @@ -0,0 +1,124 @@ +{ + "variants": { + "attachment=floor,facing=north,powered=false": { + "model": "create:block/haunted_bell_floor" + }, + "attachment=ceiling,facing=north,powered=false": { + "model": "create:block/haunted_bell_ceiling" + }, + "attachment=single_wall,facing=north,powered=false": { + "model": "create:block/haunted_bell_single_wall" + }, + "attachment=double_wall,facing=north,powered=false": { + "model": "create:block/haunted_bell_double_wall" + }, + "attachment=floor,facing=south,powered=false": { + "model": "create:block/haunted_bell_floor", + "y": 180 + }, + "attachment=ceiling,facing=south,powered=false": { + "model": "create:block/haunted_bell_ceiling", + "y": 180 + }, + "attachment=single_wall,facing=south,powered=false": { + "model": "create:block/haunted_bell_single_wall", + "y": 180 + }, + "attachment=double_wall,facing=south,powered=false": { + "model": "create:block/haunted_bell_double_wall", + "y": 180 + }, + "attachment=floor,facing=west,powered=false": { + "model": "create:block/haunted_bell_floor", + "y": 270 + }, + "attachment=ceiling,facing=west,powered=false": { + "model": "create:block/haunted_bell_ceiling", + "y": 270 + }, + "attachment=single_wall,facing=west,powered=false": { + "model": "create:block/haunted_bell_single_wall", + "y": 270 + }, + "attachment=double_wall,facing=west,powered=false": { + "model": "create:block/haunted_bell_double_wall", + "y": 270 + }, + "attachment=floor,facing=east,powered=false": { + "model": "create:block/haunted_bell_floor", + "y": 90 + }, + "attachment=ceiling,facing=east,powered=false": { + "model": "create:block/haunted_bell_ceiling", + "y": 90 + }, + "attachment=single_wall,facing=east,powered=false": { + "model": "create:block/haunted_bell_single_wall", + "y": 90 + }, + "attachment=double_wall,facing=east,powered=false": { + "model": "create:block/haunted_bell_double_wall", + "y": 90 + }, + "attachment=floor,facing=north,powered=true": { + "model": "create:block/haunted_bell_floor" + }, + "attachment=ceiling,facing=north,powered=true": { + "model": "create:block/haunted_bell_ceiling" + }, + "attachment=single_wall,facing=north,powered=true": { + "model": "create:block/haunted_bell_single_wall" + }, + "attachment=double_wall,facing=north,powered=true": { + "model": "create:block/haunted_bell_double_wall" + }, + "attachment=floor,facing=south,powered=true": { + "model": "create:block/haunted_bell_floor", + "y": 180 + }, + "attachment=ceiling,facing=south,powered=true": { + "model": "create:block/haunted_bell_ceiling", + "y": 180 + }, + "attachment=single_wall,facing=south,powered=true": { + "model": "create:block/haunted_bell_single_wall", + "y": 180 + }, + "attachment=double_wall,facing=south,powered=true": { + "model": "create:block/haunted_bell_double_wall", + "y": 180 + }, + "attachment=floor,facing=west,powered=true": { + "model": "create:block/haunted_bell_floor", + "y": 270 + }, + "attachment=ceiling,facing=west,powered=true": { + "model": "create:block/haunted_bell_ceiling", + "y": 270 + }, + "attachment=single_wall,facing=west,powered=true": { + "model": "create:block/haunted_bell_single_wall", + "y": 270 + }, + "attachment=double_wall,facing=west,powered=true": { + "model": "create:block/haunted_bell_double_wall", + "y": 270 + }, + "attachment=floor,facing=east,powered=true": { + "model": "create:block/haunted_bell_floor", + "y": 90 + }, + "attachment=ceiling,facing=east,powered=true": { + "model": "create:block/haunted_bell_ceiling", + "y": 90 + }, + "attachment=single_wall,facing=east,powered=true": { + "model": "create:block/haunted_bell_single_wall", + "y": 90 + }, + "attachment=double_wall,facing=east,powered=true": { + "model": "create:block/haunted_bell_double_wall", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/lectern_controller.json b/src/generated/resources/assets/create/blockstates/lectern_controller.json new file mode 100644 index 000000000..8b7b2962b --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/lectern_controller.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=north,has_book=false,powered=false": { + "model": "minecraft:block/lectern" + }, + "facing=south,has_book=false,powered=false": { + "model": "minecraft:block/lectern", + "y": 180 + }, + "facing=west,has_book=false,powered=false": { + "model": "minecraft:block/lectern", + "y": 270 + }, + "facing=east,has_book=false,powered=false": { + "model": "minecraft:block/lectern", + "y": 90 + }, + "facing=north,has_book=true,powered=false": { + "model": "minecraft:block/lectern" + }, + "facing=south,has_book=true,powered=false": { + "model": "minecraft:block/lectern", + "y": 180 + }, + "facing=west,has_book=true,powered=false": { + "model": "minecraft:block/lectern", + "y": 270 + }, + "facing=east,has_book=true,powered=false": { + "model": "minecraft:block/lectern", + "y": 90 + }, + "facing=north,has_book=false,powered=true": { + "model": "minecraft:block/lectern" + }, + "facing=south,has_book=false,powered=true": { + "model": "minecraft:block/lectern", + "y": 180 + }, + "facing=west,has_book=false,powered=true": { + "model": "minecraft:block/lectern", + "y": 270 + }, + "facing=east,has_book=false,powered=true": { + "model": "minecraft:block/lectern", + "y": 90 + }, + "facing=north,has_book=true,powered=true": { + "model": "minecraft:block/lectern" + }, + "facing=south,has_book=true,powered=true": { + "model": "minecraft:block/lectern", + "y": 180 + }, + "facing=west,has_book=true,powered=true": { + "model": "minecraft:block/lectern", + "y": 270 + }, + "facing=east,has_book=true,powered=true": { + "model": "minecraft:block/lectern", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/light_blue_nixie_tube.json b/src/generated/resources/assets/create/blockstates/light_blue_nixie_tube.json new file mode 100644 index 000000000..ee587b332 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/light_blue_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/light_blue_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/light_blue_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/light_blue_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/light_blue_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/light_blue_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/light_blue_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/light_blue_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/light_blue_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/light_blue_toolbox.json b/src/generated/resources/assets/create/blockstates/light_blue_toolbox.json new file mode 100644 index 000000000..e90b53614 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/light_blue_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/light_blue_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/light_blue_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/light_blue_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/light_blue_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/light_blue_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/light_blue_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/light_blue_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/light_blue_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/light_gray_nixie_tube.json b/src/generated/resources/assets/create/blockstates/light_gray_nixie_tube.json new file mode 100644 index 000000000..1243138f5 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/light_gray_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/light_gray_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/light_gray_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/light_gray_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/light_gray_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/light_gray_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/light_gray_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/light_gray_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/light_gray_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/light_gray_toolbox.json b/src/generated/resources/assets/create/blockstates/light_gray_toolbox.json new file mode 100644 index 000000000..a4fdede71 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/light_gray_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/light_gray_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/light_gray_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/light_gray_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/light_gray_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/light_gray_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/light_gray_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/light_gray_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/light_gray_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/lime_nixie_tube.json b/src/generated/resources/assets/create/blockstates/lime_nixie_tube.json new file mode 100644 index 000000000..76f298bf3 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/lime_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/lime_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/lime_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/lime_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/lime_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/lime_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/lime_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/lime_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/lime_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/lime_toolbox.json b/src/generated/resources/assets/create/blockstates/lime_toolbox.json new file mode 100644 index 000000000..43aeddf74 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/lime_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/lime_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/lime_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/lime_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/lime_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/lime_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/lime_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/lime_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/lime_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/lit_blaze_burner.json b/src/generated/resources/assets/create/blockstates/lit_blaze_burner.json index 5befc1351..041032bdf 100644 --- a/src/generated/resources/assets/create/blockstates/lit_blaze_burner.json +++ b/src/generated/resources/assets/create/blockstates/lit_blaze_burner.json @@ -1,7 +1,10 @@ { "variants": { - "": { + "flame_type=regular": { "model": "create:block/blaze_burner/block_with_fire" + }, + "flame_type=soul": { + "model": "create:block/blaze_burner/block_with_soul_fire" } } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/magenta_nixie_tube.json b/src/generated/resources/assets/create/blockstates/magenta_nixie_tube.json new file mode 100644 index 000000000..396bfcbea --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/magenta_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/magenta_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/magenta_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/magenta_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/magenta_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/magenta_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/magenta_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/magenta_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/magenta_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/magenta_toolbox.json b/src/generated/resources/assets/create/blockstates/magenta_toolbox.json new file mode 100644 index 000000000..3378cd903 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/magenta_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/magenta_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/magenta_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/magenta_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/magenta_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/magenta_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/magenta_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/magenta_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/magenta_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/nixie_tube.json b/src/generated/resources/assets/create/blockstates/nixie_tube.json index aa96a9615..8a59ef4bb 100644 --- a/src/generated/resources/assets/create/blockstates/nixie_tube.json +++ b/src/generated/resources/assets/create/blockstates/nixie_tube.json @@ -1,36 +1,36 @@ { "variants": { "ceiling=false,facing=north": { - "model": "create:block/nixie_tube/block", + "model": "create:block/nixie_tube", "y": 180 }, "ceiling=true,facing=north": { - "model": "create:block/nixie_tube/block", + "model": "create:block/nixie_tube", "x": 180, "y": 180 }, "ceiling=false,facing=south": { - "model": "create:block/nixie_tube/block" + "model": "create:block/nixie_tube" }, "ceiling=true,facing=south": { - "model": "create:block/nixie_tube/block", + "model": "create:block/nixie_tube", "x": 180 }, "ceiling=false,facing=west": { - "model": "create:block/nixie_tube/block", + "model": "create:block/nixie_tube", "y": 90 }, "ceiling=true,facing=west": { - "model": "create:block/nixie_tube/block", + "model": "create:block/nixie_tube", "x": 180, "y": 90 }, "ceiling=false,facing=east": { - "model": "create:block/nixie_tube/block", + "model": "create:block/nixie_tube", "y": 270 }, "ceiling=true,facing=east": { - "model": "create:block/nixie_tube/block", + "model": "create:block/nixie_tube", "x": 180, "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/orange_toolbox.json b/src/generated/resources/assets/create/blockstates/orange_toolbox.json new file mode 100644 index 000000000..b11c165b5 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/orange_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/orange_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/orange_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/orange_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/orange_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/orange_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/orange_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/orange_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/orange_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/peculiar_bell.json b/src/generated/resources/assets/create/blockstates/peculiar_bell.json new file mode 100644 index 000000000..c688d01c7 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/peculiar_bell.json @@ -0,0 +1,124 @@ +{ + "variants": { + "attachment=floor,facing=north,powered=false": { + "model": "create:block/peculiar_bell_floor" + }, + "attachment=ceiling,facing=north,powered=false": { + "model": "create:block/peculiar_bell_ceiling" + }, + "attachment=single_wall,facing=north,powered=false": { + "model": "create:block/peculiar_bell_single_wall" + }, + "attachment=double_wall,facing=north,powered=false": { + "model": "create:block/peculiar_bell_double_wall" + }, + "attachment=floor,facing=south,powered=false": { + "model": "create:block/peculiar_bell_floor", + "y": 180 + }, + "attachment=ceiling,facing=south,powered=false": { + "model": "create:block/peculiar_bell_ceiling", + "y": 180 + }, + "attachment=single_wall,facing=south,powered=false": { + "model": "create:block/peculiar_bell_single_wall", + "y": 180 + }, + "attachment=double_wall,facing=south,powered=false": { + "model": "create:block/peculiar_bell_double_wall", + "y": 180 + }, + "attachment=floor,facing=west,powered=false": { + "model": "create:block/peculiar_bell_floor", + "y": 270 + }, + "attachment=ceiling,facing=west,powered=false": { + "model": "create:block/peculiar_bell_ceiling", + "y": 270 + }, + "attachment=single_wall,facing=west,powered=false": { + "model": "create:block/peculiar_bell_single_wall", + "y": 270 + }, + "attachment=double_wall,facing=west,powered=false": { + "model": "create:block/peculiar_bell_double_wall", + "y": 270 + }, + "attachment=floor,facing=east,powered=false": { + "model": "create:block/peculiar_bell_floor", + "y": 90 + }, + "attachment=ceiling,facing=east,powered=false": { + "model": "create:block/peculiar_bell_ceiling", + "y": 90 + }, + "attachment=single_wall,facing=east,powered=false": { + "model": "create:block/peculiar_bell_single_wall", + "y": 90 + }, + "attachment=double_wall,facing=east,powered=false": { + "model": "create:block/peculiar_bell_double_wall", + "y": 90 + }, + "attachment=floor,facing=north,powered=true": { + "model": "create:block/peculiar_bell_floor" + }, + "attachment=ceiling,facing=north,powered=true": { + "model": "create:block/peculiar_bell_ceiling" + }, + "attachment=single_wall,facing=north,powered=true": { + "model": "create:block/peculiar_bell_single_wall" + }, + "attachment=double_wall,facing=north,powered=true": { + "model": "create:block/peculiar_bell_double_wall" + }, + "attachment=floor,facing=south,powered=true": { + "model": "create:block/peculiar_bell_floor", + "y": 180 + }, + "attachment=ceiling,facing=south,powered=true": { + "model": "create:block/peculiar_bell_ceiling", + "y": 180 + }, + "attachment=single_wall,facing=south,powered=true": { + "model": "create:block/peculiar_bell_single_wall", + "y": 180 + }, + "attachment=double_wall,facing=south,powered=true": { + "model": "create:block/peculiar_bell_double_wall", + "y": 180 + }, + "attachment=floor,facing=west,powered=true": { + "model": "create:block/peculiar_bell_floor", + "y": 270 + }, + "attachment=ceiling,facing=west,powered=true": { + "model": "create:block/peculiar_bell_ceiling", + "y": 270 + }, + "attachment=single_wall,facing=west,powered=true": { + "model": "create:block/peculiar_bell_single_wall", + "y": 270 + }, + "attachment=double_wall,facing=west,powered=true": { + "model": "create:block/peculiar_bell_double_wall", + "y": 270 + }, + "attachment=floor,facing=east,powered=true": { + "model": "create:block/peculiar_bell_floor", + "y": 90 + }, + "attachment=ceiling,facing=east,powered=true": { + "model": "create:block/peculiar_bell_ceiling", + "y": 90 + }, + "attachment=single_wall,facing=east,powered=true": { + "model": "create:block/peculiar_bell_single_wall", + "y": 90 + }, + "attachment=double_wall,facing=east,powered=true": { + "model": "create:block/peculiar_bell_double_wall", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/pink_nixie_tube.json b/src/generated/resources/assets/create/blockstates/pink_nixie_tube.json new file mode 100644 index 000000000..582f2c3ef --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/pink_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/pink_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/pink_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/pink_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/pink_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/pink_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/pink_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/pink_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/pink_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/pink_toolbox.json b/src/generated/resources/assets/create/blockstates/pink_toolbox.json new file mode 100644 index 000000000..847ea1127 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/pink_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/pink_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/pink_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/pink_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/pink_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/pink_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/pink_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/pink_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/pink_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/purple_nixie_tube.json b/src/generated/resources/assets/create/blockstates/purple_nixie_tube.json new file mode 100644 index 000000000..b08bd6e3c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/purple_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/purple_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/purple_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/purple_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/purple_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/purple_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/purple_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/purple_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/purple_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/purple_toolbox.json b/src/generated/resources/assets/create/blockstates/purple_toolbox.json new file mode 100644 index 000000000..6860868ca --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/purple_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/purple_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/purple_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/purple_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/purple_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/purple_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/purple_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/purple_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/purple_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/red_nixie_tube.json b/src/generated/resources/assets/create/blockstates/red_nixie_tube.json new file mode 100644 index 000000000..99ababb7c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/red_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/red_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/red_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/red_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/red_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/red_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/red_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/red_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/red_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/red_toolbox.json b/src/generated/resources/assets/create/blockstates/red_toolbox.json new file mode 100644 index 000000000..36cfc7bcf --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/red_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/red_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/red_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/red_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/red_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/red_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/red_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/red_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/red_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/water_wheel.json b/src/generated/resources/assets/create/blockstates/water_wheel.json index c9b0731b7..fe99163df 100644 --- a/src/generated/resources/assets/create/blockstates/water_wheel.json +++ b/src/generated/resources/assets/create/blockstates/water_wheel.json @@ -1,5 +1,12 @@ { "variants": { + "facing=down": { + "model": "create:block/water_wheel", + "x": 180 + }, + "facing=up": { + "model": "create:block/water_wheel" + }, "facing=north": { "model": "create:block/water_wheel", "x": 90 diff --git a/src/generated/resources/assets/create/blockstates/white_nixie_tube.json b/src/generated/resources/assets/create/blockstates/white_nixie_tube.json new file mode 100644 index 000000000..c1541c94d --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/white_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/white_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/white_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/white_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/white_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/white_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/white_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/white_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/white_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/white_toolbox.json b/src/generated/resources/assets/create/blockstates/white_toolbox.json new file mode 100644 index 000000000..0b2e80919 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/white_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/white_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/white_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/white_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/white_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/white_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/white_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/white_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/white_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/yellow_nixie_tube.json b/src/generated/resources/assets/create/blockstates/yellow_nixie_tube.json new file mode 100644 index 000000000..370874c55 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/yellow_nixie_tube.json @@ -0,0 +1,38 @@ +{ + "variants": { + "ceiling=false,facing=north": { + "model": "create:block/yellow_nixie_tube", + "y": 180 + }, + "ceiling=true,facing=north": { + "model": "create:block/yellow_nixie_tube", + "x": 180, + "y": 180 + }, + "ceiling=false,facing=south": { + "model": "create:block/yellow_nixie_tube" + }, + "ceiling=true,facing=south": { + "model": "create:block/yellow_nixie_tube", + "x": 180 + }, + "ceiling=false,facing=west": { + "model": "create:block/yellow_nixie_tube", + "y": 90 + }, + "ceiling=true,facing=west": { + "model": "create:block/yellow_nixie_tube", + "x": 180, + "y": 90 + }, + "ceiling=false,facing=east": { + "model": "create:block/yellow_nixie_tube", + "y": 270 + }, + "ceiling=true,facing=east": { + "model": "create:block/yellow_nixie_tube", + "x": 180, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/yellow_toolbox.json b/src/generated/resources/assets/create/blockstates/yellow_toolbox.json new file mode 100644 index 000000000..bc51011d8 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/yellow_toolbox.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=north,waterlogged=false": { + "model": "create:block/yellow_toolbox" + }, + "facing=south,waterlogged=false": { + "model": "create:block/yellow_toolbox", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/yellow_toolbox", + "y": 270 + }, + "facing=east,waterlogged=false": { + "model": "create:block/yellow_toolbox", + "y": 90 + }, + "facing=north,waterlogged=true": { + "model": "create:block/yellow_toolbox" + }, + "facing=south,waterlogged=true": { + "model": "create:block/yellow_toolbox", + "y": 180 + }, + "facing=west,waterlogged=true": { + "model": "create:block/yellow_toolbox", + "y": 270 + }, + "facing=east,waterlogged=true": { + "model": "create:block/yellow_toolbox", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/lang/en_ud.json b/src/generated/resources/assets/create/lang/en_ud.json index 12c9bc03a..c34a7b3bd 100644 --- a/src/generated/resources/assets/create/lang/en_ud.json +++ b/src/generated/resources/assets/create/lang/en_ud.json @@ -24,12 +24,16 @@ "block.create.belt": "\u0287\u05DF\u01DD\u15FA", "block.create.birch_window": "\u028Dopu\u0131M \u0265\u0254\u0279\u0131\u15FA", "block.create.birch_window_pane": "\u01DDu\u0250\u0500 \u028Dopu\u0131M \u0265\u0254\u0279\u0131\u15FA", + "block.create.black_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u029E\u0254\u0250\u05DF\u15FA", "block.create.black_sail": "\u05DF\u0131\u0250S \u029E\u0254\u0250\u05DF\u15FA", "block.create.black_seat": "\u0287\u0250\u01DDS \u029E\u0254\u0250\u05DF\u15FA", + "block.create.black_toolbox": "xoq\u05DFoo\u27D8 \u029E\u0254\u0250\u05DF\u15FA", "block.create.black_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u029E\u0254\u0250\u05DF\u15FA", "block.create.blaze_burner": "\u0279\u01DDu\u0279n\u15FA \u01DDz\u0250\u05DF\u15FA", + "block.create.blue_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u01DDn\u05DF\u15FA", "block.create.blue_sail": "\u05DF\u0131\u0250S \u01DDn\u05DF\u15FA", "block.create.blue_seat": "\u0287\u0250\u01DDS \u01DDn\u05DF\u15FA", + "block.create.blue_toolbox": "xoq\u05DFoo\u27D8 \u01DDn\u05DF\u15FA", "block.create.blue_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u01DDn\u05DF\u15FA", "block.create.brass_belt_funnel": "\u05DF\u01DDuun\u2132 \u0287\u05DF\u01DD\u15FA ss\u0250\u0279\u15FA", "block.create.brass_block": "ss\u0250\u0279\u15FA \u025Fo \u029E\u0254o\u05DF\u15FA", @@ -37,8 +41,10 @@ "block.create.brass_encased_shaft": "\u0287\u025F\u0250\u0265S p\u01DDs\u0250\u0254u\u018E ss\u0250\u0279\u15FA", "block.create.brass_funnel": "\u05DF\u01DDuun\u2132 ss\u0250\u0279\u15FA", "block.create.brass_tunnel": "\u05DF\u01DDuun\u27D8 ss\u0250\u0279\u15FA", + "block.create.brown_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N u\u028Do\u0279\u15FA", "block.create.brown_sail": "\u05DF\u0131\u0250S u\u028Do\u0279\u15FA", "block.create.brown_seat": "\u0287\u0250\u01DDS u\u028Do\u0279\u15FA", + "block.create.brown_toolbox": "xoq\u05DFoo\u27D8 u\u028Do\u0279\u15FA", "block.create.brown_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B u\u028Do\u0279\u15FA", "block.create.cart_assembler": "\u0279\u01DD\u05DFq\u026F\u01DDss\u2C6F \u0287\u0279\u0250\u0186", "block.create.chiseled_dark_scoria": "\u0250\u0131\u0279o\u0254S \u029E\u0279\u0250\u15E1 p\u01DD\u05DF\u01DDs\u0131\u0265\u0186", @@ -69,8 +75,10 @@ "block.create.crushing_wheel": "\u05DF\u01DD\u01DD\u0265M bu\u0131\u0265sn\u0279\u0186", "block.create.crushing_wheel_controller": "\u0279\u01DD\u05DF\u05DFo\u0279\u0287uo\u0186 \u05DF\u01DD\u01DD\u0265M bu\u0131\u0265sn\u0279\u0186", "block.create.cuckoo_clock": "\u029E\u0254o\u05DF\u0186 oo\u029E\u0254n\u0186", + "block.create.cyan_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N u\u0250\u028E\u0186", "block.create.cyan_sail": "\u05DF\u0131\u0250S u\u0250\u028E\u0186", "block.create.cyan_seat": "\u0287\u0250\u01DDS u\u0250\u028E\u0186", + "block.create.cyan_toolbox": "xoq\u05DFoo\u27D8 u\u0250\u028E\u0186", "block.create.cyan_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B u\u0250\u028E\u0186", "block.create.dark_oak_window": "\u028Dopu\u0131M \u029E\u0250O \u029E\u0279\u0250\u15E1", "block.create.dark_oak_window_pane": "\u01DDu\u0250\u0500 \u028Dopu\u0131M \u029E\u0250O \u029E\u0279\u0250\u15E1", @@ -175,13 +183,18 @@ "block.create.granite_cobblestone_stairs": "s\u0279\u0131\u0250\u0287S \u01DDuo\u0287s\u01DD\u05DFqqo\u0186 \u01DD\u0287\u0131u\u0250\u0279\u2141", "block.create.granite_cobblestone_wall": "\u05DF\u05DF\u0250M \u01DDuo\u0287s\u01DD\u05DFqqo\u0186 \u01DD\u0287\u0131u\u0250\u0279\u2141", "block.create.granite_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DD\u0287\u0131u\u0250\u0279\u2141", + "block.create.gray_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u028E\u0250\u0279\u2141", "block.create.gray_sail": "\u05DF\u0131\u0250S \u028E\u0250\u0279\u2141", "block.create.gray_seat": "\u0287\u0250\u01DDS \u028E\u0250\u0279\u2141", + "block.create.gray_toolbox": "xoq\u05DFoo\u27D8 \u028E\u0250\u0279\u2141", "block.create.gray_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u028E\u0250\u0279\u2141", + "block.create.green_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N u\u01DD\u01DD\u0279\u2141", "block.create.green_sail": "\u05DF\u0131\u0250S u\u01DD\u01DD\u0279\u2141", "block.create.green_seat": "\u0287\u0250\u01DDS u\u01DD\u01DD\u0279\u2141", + "block.create.green_toolbox": "xoq\u05DFoo\u27D8 u\u01DD\u01DD\u0279\u2141", "block.create.green_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B u\u01DD\u01DD\u0279\u2141", "block.create.hand_crank": "\u029Eu\u0250\u0279\u0186 pu\u0250H", + "block.create.haunted_bell": "\u05DF\u05DF\u01DD\u15FA p\u01DD\u0287un\u0250H", "block.create.honey": "\u028E\u01DDuoH", "block.create.horizontal_framed_glass": "ss\u0250\u05DF\u2141 p\u01DD\u026F\u0250\u0279\u2132 \u05DF\u0250\u0287uoz\u0131\u0279oH", "block.create.horizontal_framed_glass_pane": "\u01DDu\u0250\u0500 ss\u0250\u05DF\u2141 p\u01DD\u026F\u0250\u0279\u2132 \u05DF\u0250\u0287uoz\u0131\u0279oH", @@ -199,14 +212,21 @@ "block.create.layered_limestone": "\u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u028E\u0250\uA780", "block.create.layered_scoria": "\u0250\u0131\u0279o\u0254S p\u01DD\u0279\u01DD\u028E\u0250\uA780", "block.create.layered_weathered_limestone": "\u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u0279\u01DD\u028E\u0250\uA780", + "block.create.lectern_controller": "\u0279\u01DD\u05DF\u05DFo\u0279\u0287uo\u0186 u\u0279\u01DD\u0287\u0254\u01DD\uA780", + "block.create.light_blue_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u01DDn\u05DF\u15FA \u0287\u0265b\u0131\uA780", "block.create.light_blue_sail": "\u05DF\u0131\u0250S \u01DDn\u05DF\u15FA \u0287\u0265b\u0131\uA780", "block.create.light_blue_seat": "\u0287\u0250\u01DDS \u01DDn\u05DF\u15FA \u0287\u0265b\u0131\uA780", + "block.create.light_blue_toolbox": "xoq\u05DFoo\u27D8 \u01DDn\u05DF\u15FA \u0287\u0265b\u0131\uA780", "block.create.light_blue_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u01DDn\u05DF\u15FA \u0287\u0265b\u0131\uA780", + "block.create.light_gray_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u028E\u0250\u0279\u2141 \u0287\u0265b\u0131\uA780", "block.create.light_gray_sail": "\u05DF\u0131\u0250S \u028E\u0250\u0279\u2141 \u0287\u0265b\u0131\uA780", "block.create.light_gray_seat": "\u0287\u0250\u01DDS \u028E\u0250\u0279\u2141 \u0287\u0265b\u0131\uA780", + "block.create.light_gray_toolbox": "xoq\u05DFoo\u27D8 \u028E\u0250\u0279\u2141 \u0287\u0265b\u0131\uA780", "block.create.light_gray_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u028E\u0250\u0279\u2141 \u0287\u0265b\u0131\uA780", + "block.create.lime_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u01DD\u026F\u0131\uA780", "block.create.lime_sail": "\u05DF\u0131\u0250S \u01DD\u026F\u0131\uA780", "block.create.lime_seat": "\u0287\u0250\u01DDS \u01DD\u026F\u0131\uA780", + "block.create.lime_toolbox": "xoq\u05DFoo\u27D8 \u01DD\u026F\u0131\uA780", "block.create.lime_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u01DD\u026F\u0131\uA780", "block.create.limesand": "pu\u0250s\u01DD\u026F\u0131\uA780", "block.create.limestone": "\u01DDuo\u0287s\u01DD\u026F\u0131\uA780", @@ -221,8 +241,10 @@ "block.create.limestone_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DDuo\u0287s\u01DD\u026F\u0131\uA780", "block.create.linear_chassis": "s\u0131ss\u0250\u0265\u0186 \u0279\u0250\u01DDu\u0131\uA780", "block.create.lit_blaze_burner": "\u0279\u01DDu\u0279n\u15FA \u01DDz\u0250\u05DF\u15FA \u0287\u0131\uA780", + "block.create.magenta_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u0250\u0287u\u01DDb\u0250W", "block.create.magenta_sail": "\u05DF\u0131\u0250S \u0250\u0287u\u01DDb\u0250W", "block.create.magenta_seat": "\u0287\u0250\u01DDS \u0250\u0287u\u01DDb\u0250W", + "block.create.magenta_toolbox": "xoq\u05DFoo\u27D8 \u0250\u0287u\u01DDb\u0250W", "block.create.magenta_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u0250\u0287u\u01DDb\u0250W", "block.create.mechanical_arm": "\u026F\u0279\u2C6F \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW", "block.create.mechanical_bearing": "bu\u0131\u0279\u0250\u01DD\u15FA \u05DF\u0250\u0254\u0131u\u0250\u0265\u0254\u01DDW", @@ -256,6 +278,7 @@ "block.create.oak_window_pane": "\u01DDu\u0250\u0500 \u028Dopu\u0131M \u029E\u0250O", "block.create.orange_sail": "\u05DF\u0131\u0250S \u01DDbu\u0250\u0279O", "block.create.orange_seat": "\u0287\u0250\u01DDS \u01DDbu\u0250\u0279O", + "block.create.orange_toolbox": "xoq\u05DFoo\u27D8 \u01DDbu\u0250\u0279O", "block.create.orange_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u01DDbu\u0250\u0279O", "block.create.ornate_iron_window": "\u028Dopu\u0131M uo\u0279I \u01DD\u0287\u0250u\u0279O", "block.create.ornate_iron_window_pane": "\u01DDu\u0250\u0500 \u028Dopu\u0131M uo\u0279I \u01DD\u0287\u0250u\u0279O", @@ -304,8 +327,11 @@ "block.create.paved_weathered_limestone_slab": "q\u0250\u05DFS \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u028C\u0250\u0500", "block.create.paved_weathered_limestone_stairs": "s\u0279\u0131\u0250\u0287S \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u028C\u0250\u0500", "block.create.paved_weathered_limestone_wall": "\u05DF\u05DF\u0250M \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u028C\u0250\u0500", + "block.create.peculiar_bell": "\u05DF\u05DF\u01DD\u15FA \u0279\u0250\u0131\u05DFn\u0254\u01DD\u0500", + "block.create.pink_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u029Eu\u0131\u0500", "block.create.pink_sail": "\u05DF\u0131\u0250S \u029Eu\u0131\u0500", "block.create.pink_seat": "\u0287\u0250\u01DDS \u029Eu\u0131\u0500", + "block.create.pink_toolbox": "xoq\u05DFoo\u27D8 \u029Eu\u0131\u0500", "block.create.pink_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u029Eu\u0131\u0500", "block.create.piston_extension_pole": "\u01DD\u05DFo\u0500 uo\u0131su\u01DD\u0287x\u018E uo\u0287s\u0131\u0500", "block.create.polished_dark_scoria": "\u0250\u0131\u0279o\u0254S \u029E\u0279\u0250\u15E1 p\u01DD\u0265s\u0131\u05DFo\u0500", @@ -338,12 +364,16 @@ "block.create.powered_toggle_latch": "\u0265\u0254\u0287\u0250\uA780 \u01DD\u05DFbbo\u27D8 p\u01DD\u0279\u01DD\u028Do\u0500", "block.create.pulley_magnet": "\u0287\u01DDub\u0250W \u028E\u01DD\u05DF\u05DFn\u0500", "block.create.pulse_repeater": "\u0279\u01DD\u0287\u0250\u01DDd\u01DD\u1D1A \u01DDs\u05DFn\u0500", + "block.create.purple_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u01DD\u05DFd\u0279n\u0500", "block.create.purple_sail": "\u05DF\u0131\u0250S \u01DD\u05DFd\u0279n\u0500", "block.create.purple_seat": "\u0287\u0250\u01DDS \u01DD\u05DFd\u0279n\u0500", + "block.create.purple_toolbox": "xoq\u05DFoo\u27D8 \u01DD\u05DFd\u0279n\u0500", "block.create.purple_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u01DD\u05DFd\u0279n\u0500", "block.create.radial_chassis": "s\u0131ss\u0250\u0265\u0186 \u05DF\u0250\u0131p\u0250\u1D1A", + "block.create.red_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N p\u01DD\u1D1A", "block.create.red_sail": "\u05DF\u0131\u0250S p\u01DD\u1D1A", "block.create.red_seat": "\u0287\u0250\u01DDS p\u01DD\u1D1A", + "block.create.red_toolbox": "xoq\u05DFoo\u27D8 p\u01DD\u1D1A", "block.create.red_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B p\u01DD\u1D1A", "block.create.redstone_contact": "\u0287\u0254\u0250\u0287uo\u0186 \u01DDuo\u0287sp\u01DD\u1D1A", "block.create.redstone_link": "\u029Eu\u0131\uA780 \u01DDuo\u0287sp\u01DD\u1D1A", @@ -398,22 +428,29 @@ "block.create.weathered_limestone_cobblestone_wall": "\u05DF\u05DF\u0250M \u01DDuo\u0287s\u01DD\u05DFqqo\u0186 \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM", "block.create.weathered_limestone_pillar": "\u0279\u0250\u05DF\u05DF\u0131\u0500 \u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM", "block.create.weighted_ejector": "\u0279o\u0287\u0254\u01DD\u0638\u018E p\u01DD\u0287\u0265b\u0131\u01DDM", + "block.create.white_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u01DD\u0287\u0131\u0265M", "block.create.white_sail": "\u05DF\u0131\u0250S \u01DD\u0287\u0131\u0265M", "block.create.white_seat": "\u0287\u0250\u01DDS \u01DD\u0287\u0131\u0265M", + "block.create.white_toolbox": "xoq\u05DFoo\u27D8 \u01DD\u0287\u0131\u0265M", "block.create.white_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u01DD\u0287\u0131\u0265M", "block.create.windmill_bearing": "bu\u0131\u0279\u0250\u01DD\u15FA \u05DF\u05DF\u0131\u026Fpu\u0131M", "block.create.wooden_bracket": "\u0287\u01DD\u029E\u0254\u0250\u0279\u15FA u\u01DDpooM", + "block.create.yellow_nixie_tube": "\u01DDqn\u27D8 \u01DD\u0131x\u0131N \u028Do\u05DF\u05DF\u01DD\u028E", "block.create.yellow_sail": "\u05DF\u0131\u0250S \u028Do\u05DF\u05DF\u01DD\u028E", "block.create.yellow_seat": "\u0287\u0250\u01DDS \u028Do\u05DF\u05DF\u01DD\u028E", + "block.create.yellow_toolbox": "xoq\u05DFoo\u27D8 \u028Do\u05DF\u05DF\u01DD\u028E", "block.create.yellow_valve_handle": "\u01DD\u05DFpu\u0250H \u01DD\u028C\u05DF\u0250\u039B \u028Do\u05DF\u05DF\u01DD\u028E", "block.create.zinc_block": "\u0254u\u0131Z \u025Fo \u029E\u0254o\u05DF\u15FA", "block.create.zinc_ore": "\u01DD\u0279O \u0254u\u0131Z", + "enchantment.create.capacity": "\u028E\u0287\u0131\u0254\u0250d\u0250\u0186", + "enchantment.create.potato_recovery": "\u028E\u0279\u01DD\u028Co\u0254\u01DD\u1D1A o\u0287\u0250\u0287o\u0500", "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.potato_projectile": "\u01DD\u05DF\u0131\u0287\u0254\u01DD\u0638o\u0279\u0500 o\u0287\u0250\u0287o\u0500", "entity.create.seat": "\u0287\u0250\u01DDS", "entity.create.stationary_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u028E\u0279\u0250uo\u0131\u0287\u0250\u0287S", "entity.create.super_glue": "\u01DDn\u05DF\u2141 \u0279\u01DDdnS", - "fluid.create.milk": "\u029E\u05DF\u0131W", "fluid.create.potion": "uo\u0131\u0287o\u0500", "fluid.create.tea": "\u0250\u01DD\u27D8 s,\u0279\u01DDp\u05DF\u0131n\u15FA", "item.create.andesite_alloy": "\u028Eo\u05DF\u05DF\u2C6F \u01DD\u0287\u0131s\u01DDpu\u2C6F", @@ -437,6 +474,8 @@ "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.creative_blaze_cake": "\u01DD\u029E\u0250\u0186 \u01DDz\u0250\u05DF\u15FA \u01DD\u028C\u0131\u0287\u0250\u01DD\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", @@ -465,13 +504,17 @@ "item.create.handheld_worldshaper": "\u0279\u01DDd\u0250\u0265sp\u05DF\u0279oM \u01DD\u028C\u0131\u0287\u0250\u01DD\u0279\u0186", "item.create.honey_bucket": "\u0287\u01DD\u029E\u0254n\u15FA \u028E\u01DDuoH", "item.create.honeyed_apple": "\u01DD\u05DFdd\u2C6F p\u01DD\u028E\u01DDuoH", - "item.create.integrated_circuit": "\u0287\u0131n\u0254\u0279\u0131\u0186 p\u01DD\u0287\u0250\u0279b\u01DD\u0287uI", + "item.create.incomplete_cogwheel": "\u05DF\u01DD\u01DD\u0265\u028Dbo\u0186 \u01DD\u0287\u01DD\u05DFd\u026Fo\u0254uI", + "item.create.incomplete_large_cogwheel": "\u05DF\u01DD\u01DD\u0265\u028Dbo\u0186 \u01DDb\u0279\u0250\uA780 \u01DD\u0287\u01DD\u05DFd\u026Fo\u0254uI", + "item.create.incomplete_precision_mechanism": "\u026Fs\u0131u\u0250\u0265\u0254\u01DDW uo\u0131s\u0131\u0254\u01DD\u0279\u0500 \u01DD\u0287\u01DD\u05DFd\u026Fo\u0254uI", "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", + "item.create.potato_cannon": "uouu\u0250\u0186 o\u0287\u0250\u0287o\u0500", "item.create.powdered_obsidian": "u\u0250\u0131p\u0131sqO p\u01DD\u0279\u01DDp\u028Do\u0500", + "item.create.precision_mechanism": "\u026Fs\u0131u\u0250\u0265\u0254\u01DDW uo\u0131s\u0131\u0254\u01DD\u0279\u0500", "item.create.propeller": "\u0279\u01DD\u05DF\u05DF\u01DDdo\u0279\u0500", "item.create.red_sand_paper": "\u0279\u01DDd\u0250\u0500 pu\u0250S p\u01DD\u1D1A", "item.create.refined_radiance": "\u01DD\u0254u\u0250\u0131p\u0250\u1D1A p\u01DDu\u0131\u025F\u01DD\u1D1A", diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 427d2c658..720ad9b66 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -27,12 +27,16 @@ "block.create.belt": "Belt", "block.create.birch_window": "Birch Window", "block.create.birch_window_pane": "Birch Window Pane", + "block.create.black_nixie_tube": "Black Nixie Tube", "block.create.black_sail": "Black Sail", "block.create.black_seat": "Black Seat", + "block.create.black_toolbox": "Black Toolbox", "block.create.black_valve_handle": "Black Valve Handle", "block.create.blaze_burner": "Blaze Burner", + "block.create.blue_nixie_tube": "Blue Nixie Tube", "block.create.blue_sail": "Blue Sail", "block.create.blue_seat": "Blue Seat", + "block.create.blue_toolbox": "Blue Toolbox", "block.create.blue_valve_handle": "Blue Valve Handle", "block.create.brass_belt_funnel": "Brass Belt Funnel", "block.create.brass_block": "Block of Brass", @@ -40,8 +44,10 @@ "block.create.brass_encased_shaft": "Brass Encased Shaft", "block.create.brass_funnel": "Brass Funnel", "block.create.brass_tunnel": "Brass Tunnel", + "block.create.brown_nixie_tube": "Brown Nixie Tube", "block.create.brown_sail": "Brown Sail", "block.create.brown_seat": "Brown Seat", + "block.create.brown_toolbox": "Brown Toolbox", "block.create.brown_valve_handle": "Brown Valve Handle", "block.create.cart_assembler": "Cart Assembler", "block.create.chiseled_dark_scoria": "Chiseled Dark Scoria", @@ -72,8 +78,10 @@ "block.create.crushing_wheel": "Crushing Wheel", "block.create.crushing_wheel_controller": "Crushing Wheel Controller", "block.create.cuckoo_clock": "Cuckoo Clock", + "block.create.cyan_nixie_tube": "Cyan Nixie Tube", "block.create.cyan_sail": "Cyan Sail", "block.create.cyan_seat": "Cyan Seat", + "block.create.cyan_toolbox": "Cyan Toolbox", "block.create.cyan_valve_handle": "Cyan Valve Handle", "block.create.dark_oak_window": "Dark Oak Window", "block.create.dark_oak_window_pane": "Dark Oak Window Pane", @@ -178,13 +186,18 @@ "block.create.granite_cobblestone_stairs": "Granite Cobblestone Stairs", "block.create.granite_cobblestone_wall": "Granite Cobblestone Wall", "block.create.granite_pillar": "Granite Pillar", + "block.create.gray_nixie_tube": "Gray Nixie Tube", "block.create.gray_sail": "Gray Sail", "block.create.gray_seat": "Gray Seat", + "block.create.gray_toolbox": "Gray Toolbox", "block.create.gray_valve_handle": "Gray Valve Handle", + "block.create.green_nixie_tube": "Green Nixie Tube", "block.create.green_sail": "Green Sail", "block.create.green_seat": "Green Seat", + "block.create.green_toolbox": "Green Toolbox", "block.create.green_valve_handle": "Green Valve Handle", "block.create.hand_crank": "Hand Crank", + "block.create.haunted_bell": "Haunted Bell", "block.create.honey": "Honey", "block.create.horizontal_framed_glass": "Horizontal Framed Glass", "block.create.horizontal_framed_glass_pane": "Horizontal Framed Glass Pane", @@ -202,14 +215,21 @@ "block.create.layered_limestone": "Layered Limestone", "block.create.layered_scoria": "Layered Scoria", "block.create.layered_weathered_limestone": "Layered Weathered Limestone", + "block.create.lectern_controller": "Lectern Controller", + "block.create.light_blue_nixie_tube": "Light Blue Nixie Tube", "block.create.light_blue_sail": "Light Blue Sail", "block.create.light_blue_seat": "Light Blue Seat", + "block.create.light_blue_toolbox": "Light Blue Toolbox", "block.create.light_blue_valve_handle": "Light Blue Valve Handle", + "block.create.light_gray_nixie_tube": "Light Gray Nixie Tube", "block.create.light_gray_sail": "Light Gray Sail", "block.create.light_gray_seat": "Light Gray Seat", + "block.create.light_gray_toolbox": "Light Gray Toolbox", "block.create.light_gray_valve_handle": "Light Gray Valve Handle", + "block.create.lime_nixie_tube": "Lime Nixie Tube", "block.create.lime_sail": "Lime Sail", "block.create.lime_seat": "Lime Seat", + "block.create.lime_toolbox": "Lime Toolbox", "block.create.lime_valve_handle": "Lime Valve Handle", "block.create.limesand": "Limesand", "block.create.limestone": "Limestone", @@ -224,8 +244,10 @@ "block.create.limestone_pillar": "Limestone Pillar", "block.create.linear_chassis": "Linear Chassis", "block.create.lit_blaze_burner": "Lit Blaze Burner", + "block.create.magenta_nixie_tube": "Magenta Nixie Tube", "block.create.magenta_sail": "Magenta Sail", "block.create.magenta_seat": "Magenta Seat", + "block.create.magenta_toolbox": "Magenta Toolbox", "block.create.magenta_valve_handle": "Magenta Valve Handle", "block.create.mechanical_arm": "Mechanical Arm", "block.create.mechanical_bearing": "Mechanical Bearing", @@ -259,6 +281,7 @@ "block.create.oak_window_pane": "Oak Window Pane", "block.create.orange_sail": "Orange Sail", "block.create.orange_seat": "Orange Seat", + "block.create.orange_toolbox": "Orange Toolbox", "block.create.orange_valve_handle": "Orange Valve Handle", "block.create.ornate_iron_window": "Ornate Iron Window", "block.create.ornate_iron_window_pane": "Ornate Iron Window Pane", @@ -307,8 +330,11 @@ "block.create.paved_weathered_limestone_slab": "Paved Weathered Limestone Slab", "block.create.paved_weathered_limestone_stairs": "Paved Weathered Limestone Stairs", "block.create.paved_weathered_limestone_wall": "Paved Weathered Limestone Wall", + "block.create.peculiar_bell": "Peculiar Bell", + "block.create.pink_nixie_tube": "Pink Nixie Tube", "block.create.pink_sail": "Pink Sail", "block.create.pink_seat": "Pink Seat", + "block.create.pink_toolbox": "Pink Toolbox", "block.create.pink_valve_handle": "Pink Valve Handle", "block.create.piston_extension_pole": "Piston Extension Pole", "block.create.polished_dark_scoria": "Polished Dark Scoria", @@ -341,12 +367,16 @@ "block.create.powered_toggle_latch": "Powered Toggle Latch", "block.create.pulley_magnet": "Pulley Magnet", "block.create.pulse_repeater": "Pulse Repeater", + "block.create.purple_nixie_tube": "Purple Nixie Tube", "block.create.purple_sail": "Purple Sail", "block.create.purple_seat": "Purple Seat", + "block.create.purple_toolbox": "Purple Toolbox", "block.create.purple_valve_handle": "Purple Valve Handle", "block.create.radial_chassis": "Radial Chassis", + "block.create.red_nixie_tube": "Red Nixie Tube", "block.create.red_sail": "Red Sail", "block.create.red_seat": "Red Seat", + "block.create.red_toolbox": "Red Toolbox", "block.create.red_valve_handle": "Red Valve Handle", "block.create.redstone_contact": "Redstone Contact", "block.create.redstone_link": "Redstone Link", @@ -401,24 +431,32 @@ "block.create.weathered_limestone_cobblestone_wall": "Weathered Limestone Cobblestone Wall", "block.create.weathered_limestone_pillar": "Weathered Limestone Pillar", "block.create.weighted_ejector": "Weighted Ejector", + "block.create.white_nixie_tube": "White Nixie Tube", "block.create.white_sail": "White Sail", "block.create.white_seat": "White Seat", + "block.create.white_toolbox": "White Toolbox", "block.create.white_valve_handle": "White Valve Handle", "block.create.windmill_bearing": "Windmill Bearing", "block.create.wooden_bracket": "Wooden Bracket", + "block.create.yellow_nixie_tube": "Yellow Nixie Tube", "block.create.yellow_sail": "Yellow Sail", "block.create.yellow_seat": "Yellow Seat", + "block.create.yellow_toolbox": "Yellow Toolbox", "block.create.yellow_valve_handle": "Yellow Valve Handle", "block.create.zinc_block": "Block of Zinc", "block.create.zinc_ore": "Zinc Ore", + "enchantment.create.capacity": "Capacity", + "enchantment.create.potato_recovery": "Potato Recovery", + "entity.create.contraption": "Contraption", + "entity.create.crafting_blueprint": "Crafting Blueprint", "entity.create.gantry_contraption": "Gantry Contraption", + "entity.create.potato_projectile": "Potato Projectile", "entity.create.seat": "Seat", "entity.create.stationary_contraption": "Stationary Contraption", "entity.create.super_glue": "Super Glue", - "fluid.create.milk": "Milk", "fluid.create.potion": "Potion", "fluid.create.tea": "Builder's Tea", @@ -443,6 +481,8 @@ "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.creative_blaze_cake": "Creative Blaze Cake", "item.create.crushed_aluminum_ore": "Crushed Aluminum Ore", "item.create.crushed_brass": "Crushed Brass", "item.create.crushed_copper_ore": "Crushed Copper Ore", @@ -471,13 +511,17 @@ "item.create.handheld_worldshaper": "Creative Worldshaper", "item.create.honey_bucket": "Honey Bucket", "item.create.honeyed_apple": "Honeyed Apple", - "item.create.integrated_circuit": "Integrated Circuit", + "item.create.incomplete_cogwheel": "Incomplete Cogwheel", + "item.create.incomplete_large_cogwheel": "Incomplete Large Cogwheel", + "item.create.incomplete_precision_mechanism": "Incomplete Precision Mechanism", "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", + "item.create.potato_cannon": "Potato Cannon", "item.create.powdered_obsidian": "Powdered Obsidian", + "item.create.precision_mechanism": "Precision Mechanism", "item.create.propeller": "Propeller", "item.create.red_sand_paper": "Red Sand Paper", "item.create.refined_radiance": "Refined Radiance", @@ -622,8 +666,8 @@ "advancement.create.flywheel.desc": "Successfully connect an engine to the Flywheel.", "advancement.create.overstress_flywheel": "High levels of Stress", "advancement.create.overstress_flywheel.desc": "Overstress a Furnace Engine.", - "advancement.create.integrated_circuit": "Complex Calculation", - "advancement.create.integrated_circuit.desc": "Assemble an Integrated Circuit.", + "advancement.create.precision_mechanism": "Complex Curiosities", + "advancement.create.precision_mechanism.desc": "Assemble a Precision Mechanism.", "advancement.create.mechanical_arm": "Busy Hands!", "advancement.create.mechanical_arm.desc": "Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch as it does all the work for you.", "advancement.create.musical_arm": "Play Me My Theme Tune!", @@ -638,7 +682,7 @@ "advancement.create.crushing_wheel.desc": "Create some Crushing Wheels to break down more materials more effectively.", "advancement.create.blaze_cake": "Sugar Rush", "advancement.create.blaze_cake.desc": "Bake your blaze burner a special cake.", - "advancement.create.chromatic_compound": "Bipolar Minerals", + "advancement.create.chromatic_compound": "Mysterious Minerals", "advancement.create.chromatic_compound.desc": "Create a Bar of Chromatic Compound.", "advancement.create.shadow_steel": "Void Returner", "advancement.create.shadow_steel.desc": "Create Shadow Steel, a metal bar of nothingness.", @@ -650,6 +694,8 @@ "advancement.create.wand_of_symmetry.desc": "Craft a Staff of Symmetry.", "advancement.create.extendo_grip": "Boioioing!", "advancement.create.extendo_grip.desc": "Get hold of an Extendo Grip.", + "advancement.create.potato_cannon": "Fwoomp!", + "advancement.create.potato_cannon.desc": "Defeat an enemy with your Potato Cannon.", "advancement.create.dual_extendo_grip": "Ultimate Boing-age", "advancement.create.dual_extendo_grip.desc": "Dual wield Extendo Grips for super-human reach.", "advancement.create.eob": "End of Beta", @@ -662,15 +708,31 @@ "itemGroup.create.palettes": "Create Palettes", "death.attack.create.crush": "%1$s was processed by Crushing Wheels", - "death.attack.create.fan_fire": "%1$s was burned to death by hot air", - "death.attack.create.fan_lava": "%1$s was burned to death by lava fan", + "death.attack.create.crush.player": "%1$s was thrown into Crushing Wheels by %2$s", + "death.attack.create.fan_fire": "%1$s got smoked by an Encased Fan", + "death.attack.create.fan_fire.player": "%1$s was thrown into a smoker by %2$s", + "death.attack.create.fan_lava": "%1$s was incinerated by an Encased Fan", + "death.attack.create.fan_lava.player": "%1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "%1$s was impaled by a Mechanical Drill", + "death.attack.create.mechanical_drill.player": "%1$s was thrown in front of a Drill by %2$s", "death.attack.create.mechanical_saw": "%1$s got cut in half by a Mechanical Saw", + "death.attack.create.mechanical_saw.player": "%1$s was thrown into a Saw by %2$s", + "death.attack.create.potato_cannon": "%1$s was shot by %2$s's Potato Cannon", + "death.attack.create.potato_cannon.item": "%1$s was shot by %2$s using %3$s", "death.attack.create.cuckoo_clock_explosion": "%1$s was blown up by tampered cuckoo clock", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s was blown up by tampered cuckoo clock", "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.ponder_index": "Ponder Index", + "create.menu.only_ingame": "Available in the Pause Menu", + "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", @@ -695,7 +757,18 @@ "create.recipe.mystery_conversion": "Mysterious Conversion", "create.recipe.spout_filling": "Filling by Spout", "create.recipe.draining": "Item Draining", + "create.recipe.sequenced_assembly": "Sequenced Assembly", + "create.recipe.assembly.next": "Next: %1$s", + "create.recipe.assembly.step": "Step %1$s:", + "create.recipe.assembly.progress": "Progress: %1$s/%2$s", + "create.recipe.assembly.pressing": "Process in Press", + "create.recipe.assembly.spout_filling_fluid": "Spout %1$s", + "create.recipe.assembly.deploying_item": "Deploy %1$s", + "create.recipe.assembly.cutting": "Cut with Saw", + "create.recipe.assembly.repeat": "Repeat Sequence %1$s Times", + "create.recipe.assembly.junk": "Random salvage", "create.recipe.processing.chance": "%1$s%% Chance", + "create.recipe.deploying.not_consumed": "Not Consumed", "create.recipe.heat_requirement.none": "No Heating Required", "create.recipe.heat_requirement.heated": "Heated", "create.recipe.heat_requirement.superheated": "Super-Heated", @@ -723,7 +796,8 @@ "create.action.saveToFile": "Save", "create.action.discard": "Discard", - "create.keyinfo.toolmenu": "Focus Tool Menu", + "create.keyinfo.toolmenu": "Focus Schematic Overlay", + "create.keyinfo.toolbelt": "Access Nearby Toolboxes", "create.keyinfo.scrollup": "Simulate Mousewheel Up (inworld)", "create.keyinfo.scrolldown": "Simulate Mousewheel Down (inworld)", @@ -734,6 +808,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "Shift to Scroll Faster", "create.gui.toolmenu.focusKey": "Hold [%1$s] to Focus", "create.gui.toolmenu.cycle": "[SCROLL] to Cycle", + + "create.toolbox.unequip": "Unequip: %1$s", + "create.toolbox.outOfRange": "Toolbox of held item not in Range", + "create.toolbox.detach": "Stop tracking and keep item", + "create.toolbox.depositAll": "Return items to nearby Toolboxes", + "create.toolbox.depositBox": "Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Mirror", "create.gui.symmetryWand.orientation": "Orientation", @@ -980,18 +1061,14 @@ "create.item_attributes.placeable.inverted": "is not placeable", "create.item_attributes.consumable": "can be eaten", "create.item_attributes.consumable.inverted": "cannot be eaten", - "create.item_attributes.smeltable": "can be Smelted", - "create.item_attributes.smeltable.inverted": "cannot be Smelted", - "create.item_attributes.washable": "can be Washed", - "create.item_attributes.washable.inverted": "cannot be Washed", - "create.item_attributes.smokable": "can be Smoked", - "create.item_attributes.smokable.inverted": "cannot be Smoked", - "create.item_attributes.crushable": "can be Crushed", - "create.item_attributes.crushable.inverted": "cannot be Crushed", - "create.item_attributes.blastable": "is smeltable in Blast Furnace", - "create.item_attributes.blastable.inverted": "is not smeltable in Blast Furnace", + "create.item_attributes.fluid_container": "can store fluids", + "create.item_attributes.fluid_container.inverted": "cannot store fluids", "create.item_attributes.enchanted": "is enchanted", "create.item_attributes.enchanted.inverted": "is unenchanted", + "create.item_attributes.max_enchanted": "is enchanted at max level", + "create.item_attributes.max_enchanted.inverted": "is not enchanted at max level", + "create.item_attributes.renamed": "has a custom name", + "create.item_attributes.renamed.inverted": "does not have a custom name", "create.item_attributes.damaged": "is damaged", "create.item_attributes.damaged.inverted": "is not damaged", "create.item_attributes.badly_damaged": "is heavily damaged", @@ -1002,6 +1079,21 @@ "create.item_attributes.equipable.inverted": "cannot be equipped", "create.item_attributes.furnace_fuel": "is furnace fuel", "create.item_attributes.furnace_fuel.inverted": "is not furnace fuel", + "create.item_attributes.washable": "can be Washed", + "create.item_attributes.washable.inverted": "cannot be Washed", + "create.item_attributes.crushable": "can be Crushed", + "create.item_attributes.crushable.inverted": "cannot be Crushed", + "create.item_attributes.smeltable": "can be Smelted", + "create.item_attributes.smeltable.inverted": "cannot be Smelted", + "create.item_attributes.smokable": "can be Smoked", + "create.item_attributes.smokable.inverted": "cannot be Smoked", + "create.item_attributes.blastable": "is smeltable in Blast Furnace", + "create.item_attributes.blastable.inverted": "is not smeltable in Blast Furnace", + "create.item_attributes.shulker_level": "is shulker %1$s", + "create.item_attributes.shulker_level.inverted": "is shulker not %1$s", + "create.item_attributes.shulker_level.full": "full", + "create.item_attributes.shulker_level.empty": "empty", + "create.item_attributes.shulker_level.partial": "partially filled", "create.item_attributes.in_tag": "is tagged %1$s", "create.item_attributes.in_tag.inverted": "is not tagged %1$s", "create.item_attributes.in_item_group": "is in group '%1$s'", @@ -1012,8 +1104,6 @@ "create.item_attributes.has_enchant.inverted": "is not enchanted with %1$s", "create.item_attributes.color": "is dyed %1$s", "create.item_attributes.color.inverted": "is not dyed %1$s", - "create.item_attributes.max_enchanted": "is enchanted at max level", - "create.item_attributes.max_enchanted.inverted": "is not enchanted at max level", "create.item_attributes.has_fluid": "contains %1$s", "create.item_attributes.has_fluid.inverted": "does not contain %1$s", "create.item_attributes.has_name": "has the custom name %1$s", @@ -1028,14 +1118,14 @@ "create.item_attributes.book_copy_second.inverted": "is not a second-generation copy", "create.item_attributes.book_copy_tattered": "is a tattered mess", "create.item_attributes.book_copy_tattered.inverted": "is not a tattered mess", - "create.item_attributes.astralsorcery_crystal": "has crystal attribute %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "does not have crystal attribute %1$s", - "create.item_attributes.astralsorcery_constellation": "is attuned to %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "is not attuned to %1$s", - "create.item_attributes.astralsorcery_perk_gem": "has perk attribute %1$s", - "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.item_attributes.astralsorcery_constellation": "is attuned to %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "is not attuned to %1$s", + "create.item_attributes.astralsorcery_crystal": "has crystal attribute %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "does not have crystal attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem": "has perk attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "does not have perk attribute %1$s", "create.gui.attribute_filter.no_selected_attributes": "No attributes selected", "create.gui.attribute_filter.selected_attributes": "Selected attributes:", @@ -1103,6 +1193,27 @@ "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.tooltip.brass_tunnel.contains": "Currently distributing:", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "Right-Click to retrieve", + + "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.potato_cannon.ammo.attack_damage": "%1$s Attack Damage", + "create.potato_cannon.ammo.reload_ticks": "%1$s Reload Ticks", + "create.potato_cannon.ammo.knockback": "%1$s Knockback", "create.hint.hose_pulley.title": "Bottomless Supply", "create.hint.hose_pulley": "The targeted body of fluid is considered infinite.", @@ -1131,32 +1242,44 @@ "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.contraption_disassemble": "Contraption stops", + "create.subtitle.peculiar_bell_use": "Peculiar Bell tolls", + "create.subtitle.mixing": "Mixing noises", + "create.subtitle.mechanical_press_activation_belt": "Mechanical Press bonks", + "create.subtitle.fwoomp": "Potato Launcher fwoomps", + "create.subtitle.worldshaper_place": "Worldshaper zaps", + "create.subtitle.crushing_1": "Crushing noises", + "create.subtitle.depot_slide": "Item slides", + "create.subtitle.saw_activate_stone": "Mechanical Saw activates", + "create.subtitle.blaze_munch": "Blaze Burner munches", + "create.subtitle.funnel_flap": "Funnel flaps", + "create.subtitle.schematicannon_finish": "Schematicannon dings", + "create.subtitle.haunted_bell_use": "Haunted Bell tolls", + "create.subtitle.scroll_value": "Scroll-input clicks", + "create.subtitle.crafter_craft": "Crafter crafts", + "create.subtitle.controller_put": "Controller thumps", + "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.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.potato_hit": "Vegetable impacts", + "create.subtitle.saw_activate_wood": "Mechanical Saw activates", + "create.subtitle.haunted_bell_convert": "Haunted Bell awakens", "create.subtitle.deployer_polish": "Deployer applies polish", - "create.subtitle.depot_slide": "Item slides", "create.subtitle.deny": "Declining boop", - "create.subtitle.blaze_munch": "Blaze Burner munches", + "create.subtitle.controller_click": "Controller clicks", "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.controller_take": "Lectern empties", "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", @@ -1178,14 +1301,6 @@ "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", @@ -1194,65 +1309,6 @@ "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", - "block.create.hose_pulley.tooltip.behaviour1": "_Raises_ or _Lowers_ the hose, location of the hose determines up to which _height extraction_ or _filling_ will act.", - "block.create.hose_pulley.tooltip.condition2": "When Fluids pulled from Pulley", - "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.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.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.", - "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", @@ -1279,9 +1335,18 @@ "item.create.tree_fertilizer.tooltip.behaviour1": "Grows Trees _regardless_ of their _spacing conditions_", "item.create.extendo_grip.tooltip": "EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "Boioioing! Greatly _increases reach distance_ of the wielder.", + "item.create.extendo_grip.tooltip.summary": "Boioioing! Greatly _increases reach distance_ of the wielder. Can be powered with Air Pressure from a _Copper_ _Backtank_", "item.create.extendo_grip.tooltip.condition1": "When in Off-Hand", "item.create.extendo_grip.tooltip.behaviour1": "Increases _reach distance_ of items used in the _Main-Hand_.", + "item.create.extendo_grip.tooltip.condition2": "While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.behaviour2": "_No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", + + "item.create.potato_cannon.tooltip": "POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.condition1": "When R-Clicked", + "item.create.potato_cannon.tooltip.behaviour1": "_Shoots_ a suitable item from your _Inventory_.", + "item.create.potato_cannon.tooltip.condition2": "While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.behaviour2": "_No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.filter.tooltip": "FILTER", "item.create.filter.tooltip.summary": "_Controls outputs_ and _inputs_ of logistical devices with more _precision_, matching them against a _set of items_ or several _nested filters_.", @@ -1357,20 +1422,26 @@ "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.toolbox.tooltip": "TOOLBOX", + "block.create.toolbox.tooltip.summary": "Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "_Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "_Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "Opens the _Container Interface_.", "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.summary": "Toggles a Redstone signal based on the amount of _Stored Items_ or _Fluids_ 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_.", + "block.create.content_observer.tooltip.summary": "_Detects Items_ or _Fluids_ inside _containers_, _pipes_ or _conveyors_ matching a configured _filter_.", + "block.create.content_observer.tooltip.condition1": "When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "ADJUSTABLE CRATE", "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_.", @@ -1382,6 +1453,11 @@ "block.create.creative_crate.tooltip.condition1": "When Item in Filter Slot", "block.create.creative_crate.tooltip.behaviour1": "Anything _extracting_ from this container will provide an _endless supply_ of the item specified. Items _inserted_ into this crate will be _voided._", + "item.create.creative_blaze_cake.tooltip": "CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "_Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "CONTROLLER RAIL", "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", @@ -1397,26 +1473,61 @@ "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.linked_controller.tooltip.condition4": "R-Click on Lectern", + "item.create.linked_controller.tooltip.behaviour4": "Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", + + "item.create.diving_helmet.tooltip": "DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "Together with a _Copper_ _Backtank_, allows the wielder 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": "Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder 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.", + "block.create.peculiar_bell.tooltip": "PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + + "block.create.haunted_bell.tooltip": "HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "A _Cursed Bell_ haunted by lost souls of the Nether.", + "block.create.haunted_bell.tooltip.condition1": "When Held or Rang", + "block.create.haunted_bell.tooltip.behaviour1": "Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn.", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1433,41 +1544,46 @@ "create.ponder.replay": "Replay", "create.ponder.think_back": "Think Back", "create.ponder.slow_text": "Comfy Reading", - "create.ponder.shared.movement_anchors": "With the help of Chassis or Super Glue, larger structures can be moved.", - "create.ponder.shared.rpm32": "32 RPM", - "create.ponder.shared.sneak_and": "Sneak +", - "create.ponder.shared.storage_on_contraption": "Inventories attached to the Contraption will pick up their drops automatically", + "create.ponder.exit": "Exit", + "create.ponder.welcome": "Welcome to Ponder", + "create.ponder.categories": "Available Categories in Create", + "create.ponder.index_description": "Click one of the icons to learn about its associated Items and Blocks", + "create.ponder.index_title": "Ponder Index", + "create.ponder.shared.rpm16": "16 RPM", "create.ponder.shared.behaviour_modify_wrench": "This behaviour can be modified using a Wrench", + "create.ponder.shared.storage_on_contraption": "Inventories attached to the Contraption will pick up their drops automatically", + "create.ponder.shared.sneak_and": "Sneak +", "create.ponder.shared.rpm8": "8 RPM", "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm32": "32 RPM", "create.ponder.shared.rpm16_source": "Source: 16 RPM", - "create.ponder.shared.rpm16": "16 RPM", - "create.ponder.tag.kinetic_sources": "Kinetic Sources", - "create.ponder.tag.kinetic_sources.description": "Components which generate Rotational Force", - "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": "Targets for Mechanical Arms", - "create.ponder.tag.arm_targets.description": "Components which can be selected as inputs or outputs to the Mechanical Arm", - "create.ponder.tag.logistics": "Item Transportation", - "create.ponder.tag.logistics.description": "Components which help moving items around", - "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": "Creative Mode", - "create.ponder.tag.creative.description": "Components not usually available for Survival Mode", - "create.ponder.tag.kinetic_relays": "Kinetic Blocks", - "create.ponder.tag.kinetic_relays.description": "Components which help relaying Rotational Force elsewhere", - "create.ponder.tag.windmill_sails": "Sails for Windmill Bearings", - "create.ponder.tag.windmill_sails.description": "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": "Block Attachment Utility", - "create.ponder.tag.contraption_assembly.description": "Tools and Components used to assemble structures moved as an animated Contraption", - "create.ponder.tag.decoration": "Aesthetics", - "create.ponder.tag.decoration.description": "Components used mostly for decorative purposes", - "create.ponder.tag.kinetic_appliances": "Kinetic Appliances", - "create.ponder.tag.kinetic_appliances.description": "Components which make use of Rotational Force", + "create.ponder.shared.movement_anchors": "With the help of Chassis or Super Glue, larger structures can be moved.", "create.ponder.tag.redstone": "Logic Components", "create.ponder.tag.redstone.description": "Components which help with redstone engineering", + "create.ponder.tag.contraption_assembly": "Block Attachment Utility", + "create.ponder.tag.contraption_assembly.description": "Tools and Components used to assemble structures moved as an animated Contraption", "create.ponder.tag.fluids": "Fluid Manipulators", "create.ponder.tag.fluids.description": "Components which help relaying and making use of Fluids", + "create.ponder.tag.decoration": "Aesthetics", + "create.ponder.tag.decoration.description": "Components used mostly for decorative purposes", + "create.ponder.tag.windmill_sails": "Sails for Windmill Bearings", + "create.ponder.tag.windmill_sails.description": "Blocks that count towards the strength of a Windmill Contraption when assembled. Each of these have equal efficiency in doing so.", + "create.ponder.tag.arm_targets": "Targets for Mechanical Arms", + "create.ponder.tag.arm_targets.description": "Components which can be selected as inputs or outputs to the Mechanical Arm", + "create.ponder.tag.kinetic_appliances": "Kinetic Appliances", + "create.ponder.tag.kinetic_appliances.description": "Components which make use of Rotational Force", + "create.ponder.tag.kinetic_sources": "Kinetic Sources", + "create.ponder.tag.kinetic_sources.description": "Components which generate Rotational Force", + "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.kinetic_relays": "Kinetic Blocks", + "create.ponder.tag.kinetic_relays.description": "Components which help relaying Rotational Force elsewhere", + "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.creative": "Creative Mode", + "create.ponder.tag.creative.description": "Components not usually available for Survival Mode", + "create.ponder.tag.logistics": "Item Transportation", + "create.ponder.tag.logistics.description": "Components which help moving items around", "create.ponder.adjustable_pulse_repeater.header": "Controlling signals using Adjustable Pulse Repeaters", "create.ponder.adjustable_pulse_repeater.text_1": "Adjustable Pulse Repeaters emit a short pulse at a delay", @@ -1579,7 +1695,8 @@ "create.ponder.cart_assembler_modes.header": "Orientation Settings for Minecart Contraptions", "create.ponder.cart_assembler_modes.text_1": "Cart Contraptions will rotate to face towards their carts' motion", - "create.ponder.cart_assembler_modes.text_2": "If the Assembler is set to Lock Rotation, the contraptions' orientation will never change", + "create.ponder.cart_assembler_modes.text_2": "This Arrow indicates which side of the Structure will be considered the front", + "create.ponder.cart_assembler_modes.text_3": "If the Assembler is set to Lock Rotation, the contraptions' orientation will never change", "create.ponder.cart_assembler_rails.header": "Other types of Minecarts and Rails", "create.ponder.cart_assembler_rails.text_1": "Cart Assemblers on Regular Tracks will not affect the passing carts' motion", @@ -1593,7 +1710,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 +1750,12 @@ "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_fluid_tank.text_1": "Creative Fluid Tanks can be used to provide a bottomless supply of fluid", + "create.ponder.creative_fluid_tank.text_2": "Right-Click with a fluid containing item to configure it", + "create.ponder.creative_fluid_tank.text_3": "Pipe Networks can now endlessly draw the assigned fluid from the tank", + "create.ponder.creative_fluid_tank.text_4": "Any Fluids pushed back into a Creative Fluid Tank will be voided", + "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 +1792,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", @@ -1685,7 +1814,13 @@ "create.ponder.empty_blaze_burner.text_2": "Alternatively, Blazes can be collected from their Spawners directly", "create.ponder.empty_blaze_burner.text_3": "You now have an ideal heat source for various machines", "create.ponder.empty_blaze_burner.text_4": "For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", - "create.ponder.empty_blaze_burner.text_5": "However, these are not suitable for industrial heating", + "create.ponder.empty_blaze_burner.text_5": "The flame can be transformed using a soul-infused item", + "create.ponder.empty_blaze_burner.text_6": "However, without a blaze they 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", @@ -1705,6 +1840,35 @@ "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_sizes.text_1": "Fluid Tanks can be combined to increase the total capacity", + "create.ponder.fluid_tank_sizes.text_2": "Their base square can be up to 3 blocks wide...", + "create.ponder.fluid_tank_sizes.text_3": "...and grow in height by more than 30 additional layers", + "create.ponder.fluid_tank_sizes.text_4": "Using a Wrench, a tanks' window can be toggled", + + "create.ponder.fluid_tank_storage.header": "Storing Fluids in Fluid Tanks", + "create.ponder.fluid_tank_storage.text_1": "Fluid Tanks can be used to store large amounts of fluid", + "create.ponder.fluid_tank_storage.text_2": "Pipe networks can push and pull fluids from any side", + "create.ponder.fluid_tank_storage.text_3": "The contained fluid can be measured by a Comparator", + "create.ponder.fluid_tank_storage.text_4": "However, in Survival Mode Fluids cannot be added or taken manually", + "create.ponder.fluid_tank_storage.text_5": "You can use Basins, Item Drains and Spouts to drain or fill fluid containing items", + "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 +1942,34 @@ "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.text_1": "Hose Pulleys can be used to fill or drain large bodies of Fluid", + "create.ponder.hose_pulley.text_2": "With the Kinetic Input, the height of the pulleys' hose can be controlled", + "create.ponder.hose_pulley.text_3": "The Pulley retracts while the input rotation is inverted", + "create.ponder.hose_pulley.text_4": "On the opposite side, pipes can be connected", + "create.ponder.hose_pulley.text_5": "Attached pipe networks can either provide fluid to the hose...", + "create.ponder.hose_pulley.text_6": "...or pull from it, draining the pool instead", + "create.ponder.hose_pulley.text_7": "Fill and Drain speed of the pulley depends entirely on the fluid networks' throughput", + + "create.ponder.hose_pulley_infinite.header": "Passively Filling and Draining large bodies of Fluid", + "create.ponder.hose_pulley_infinite.text_1": "When deploying the Hose Pulley into a large enough ocean...", + "create.ponder.hose_pulley_infinite.text_2": "It will provide/dispose fluids without affecting the source", + "create.ponder.hose_pulley_infinite.text_3": "Pipe networks can limitlessly take fluids from/to such pulleys", + + "create.ponder.hose_pulley_level.header": "Fill and Drain level of Hose Pulleys", + "create.ponder.hose_pulley_level.text_1": "While fully retracted, the Hose Pulley cannot operate", + "create.ponder.hose_pulley_level.text_2": "Draining runs from top to bottom", + "create.ponder.hose_pulley_level.text_3": "The surface level will end up just below where the hose ends", + "create.ponder.hose_pulley_level.text_4": "Filling runs from bottom to top", + "create.ponder.hose_pulley_level.text_5": "The filled pool will not grow beyond the layer above the hose end", + + "create.ponder.item_drain.header": "Emptying Fluid Containers using Item Drains", + "create.ponder.item_drain.text_1": "Item Drains can extract fluids from items", + "create.ponder.item_drain.text_2": "Right-click it to pour fluids from your held item into it", + "create.ponder.item_drain.text_3": "When items are inserted from the side...", + "create.ponder.item_drain.text_4": "...they roll across, emptying out their contained fluid", + "create.ponder.item_drain.text_5": "Pipe Networks can now pull the fluid from the drains' internal buffer", + "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 +2092,21 @@ "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_flow.text_1": "Mechanical Pumps govern the flow of their attached pipe networks", + "create.ponder.mechanical_pump_flow.text_2": "When powered, their arrow indicates the direction of flow", + "create.ponder.mechanical_pump_flow.text_3": "The network behind is now pulling fluids...", + "create.ponder.mechanical_pump_flow.text_4": "...while the network in front is transferring it outward", + "create.ponder.mechanical_pump_flow.text_5": "Reversing the input rotation reverses the direction of flow", + "create.ponder.mechanical_pump_flow.text_6": "Use a Wrench to reverse the orientation of pumps manually", + + "create.ponder.mechanical_pump_speed.header": "Throughput of Mechanical Pumps", + "create.ponder.mechanical_pump_speed.text_1": "Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away", + "create.ponder.mechanical_pump_speed.text_2": "Speeding up the input rotation changes the speed of flow propagation...", + "create.ponder.mechanical_pump_speed.text_3": "...aswell as how quickly fluids are transferred", + "create.ponder.mechanical_pump_speed.text_4": "Pumps can combine their throughputs within shared pipe networks", + "create.ponder.mechanical_pump_speed.text_5": "Alternating their orientation can help align their flow directions", + "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", @@ -1925,11 +2132,22 @@ "create.ponder.nixie_tube.header": "Using Nixie Tubes", "create.ponder.nixie_tube.text_1": "When powered by Redstone, Nixie Tubes will display the redstone signals' strength", "create.ponder.nixie_tube.text_2": "Using name tags edited with an anvil, custom text can be displayed", + "create.ponder.nixie_tube.text_3": "Right-Click with Dye to change their display colour", "create.ponder.piston_pole.header": "Piston Extension Poles", "create.ponder.piston_pole.text_1": "Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "Contraption Fluid Exchange", + "create.ponder.portable_fluid_interface.text_1": "Fluid Tanks on moving contraptions cannot be accessed by any pipes", + "create.ponder.portable_fluid_interface.text_2": "This component can interact with fluid tanks without the need to stop the contraption", + "create.ponder.portable_fluid_interface.text_3": "Place a second one with a gap of 1 or 2 blocks inbetween", + "create.ponder.portable_fluid_interface.text_4": "Whenever they pass by each other, they will engage in a connection", + "create.ponder.portable_fluid_interface.text_5": "While engaged, the stationary interface will represent ALL Tanks on the contraption", + "create.ponder.portable_fluid_interface.text_6": "Fluid can now be inserted...", + "create.ponder.portable_fluid_interface.text_7": "...or extracted from the contraption", + "create.ponder.portable_fluid_interface.text_8": "After no contents have been exchanged for a while, the contraption will continue on its way", + "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 +2245,25 @@ "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.smart_pipe.text_1": "Smart pipes can help control flows by fluid type", + "create.ponder.smart_pipe.text_2": "When placed directly at the source, they can specify the type of fluid to extract", + "create.ponder.smart_pipe.text_3": "Simply Right-Click their filter slot with any item containing the desired fluid", + "create.ponder.smart_pipe.text_4": "When placed further down a pipe network, smart pipes will only let matching fluids continue", + "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_filling.header": "Filling Items using a Spout", + "create.ponder.spout_filling.text_1": "The Spout can fill fluid holding items provided beneath it", + "create.ponder.spout_filling.text_2": "The content of a Spout cannot be accessed manually", + "create.ponder.spout_filling.text_3": "Instead, Pipes can be used to supply it with fluids", + "create.ponder.spout_filling.text_4": "The Input items can be placed on a Depot under the Spout", + "create.ponder.spout_filling.text_5": "When items are provided on a belt...", + "create.ponder.spout_filling.text_6": "The Spout will hold and process them automatically", + "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 +2295,12 @@ "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.valve_pipe.text_1": "Valve pipes help control fluids propagating through pipe networks", + "create.ponder.valve_pipe.text_2": "Their shaft input controls whether fluid is currently allowed through", + "create.ponder.valve_pipe.text_3": "Given Rotational Force in the opening direction, the valve will open up", + "create.ponder.valve_pipe.text_4": "It can be closed again by reversing the input rotation", + "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..4f99e411c 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: 1173", "_": "->------------------------] Game Elements [------------------------<-", @@ -28,12 +28,16 @@ "block.create.belt": "Mechanischer Riemen", "block.create.birch_window": "Birkenholzfenster", "block.create.birch_window_pane": "Birkenholzfensterscheibe", + "block.create.black_nixie_tube": "UNLOCALIZED: Black Nixie Tube", "block.create.black_sail": "Schwarzes Segel", "block.create.black_seat": "Schwarzer Sitz", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "Schwarzer Ventilgriff", "block.create.blaze_burner": "Lohenbrenner", + "block.create.blue_nixie_tube": "UNLOCALIZED: Blue Nixie Tube", "block.create.blue_sail": "Blaues Segel", "block.create.blue_seat": "Blauer Sitz", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "Blauer Ventilgriff", "block.create.brass_belt_funnel": "Riementrichter aus Messing", "block.create.brass_block": "Messing Block", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "Messingummantelte Welle", "block.create.brass_funnel": "Messingtrichter", "block.create.brass_tunnel": "Messingtunnel", + "block.create.brown_nixie_tube": "UNLOCALIZED: Brown Nixie Tube", "block.create.brown_sail": "Braunes Segel", "block.create.brown_seat": "Brauner Sitz", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "Brauner Ventilgriff", "block.create.cart_assembler": "Lorenmonteur", "block.create.chiseled_dark_scoria": "Gemeißelte dunkle Schlacke", @@ -73,8 +79,10 @@ "block.create.crushing_wheel": "Mahlwerkrad", "block.create.crushing_wheel_controller": "Mahlwerkrad Steurung", "block.create.cuckoo_clock": "Kuckucksuhr", + "block.create.cyan_nixie_tube": "UNLOCALIZED: Cyan Nixie Tube", "block.create.cyan_sail": "Türkises Segel", "block.create.cyan_seat": "Türkiser Sitz", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "Türkiser Ventilgriff", "block.create.dark_oak_window": "Schwarzeichenholzfenster", "block.create.dark_oak_window_pane": "Schwarzeichenholzfensterscheibe", @@ -179,13 +187,18 @@ "block.create.granite_cobblestone_stairs": "Granitbruchtreppe", "block.create.granite_cobblestone_wall": "Granitbruchsteinmauer", "block.create.granite_pillar": "Granitsäule", + "block.create.gray_nixie_tube": "UNLOCALIZED: Gray Nixie Tube", "block.create.gray_sail": "Graues Segel", "block.create.gray_seat": "Grauer Sitz", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "Grauer Ventilgriff", + "block.create.green_nixie_tube": "UNLOCALIZED: Green Nixie Tube", "block.create.green_sail": "Grünes Segel", "block.create.green_seat": "Grüner Sitz", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "Grüner Ventilgriff", "block.create.hand_crank": "Handkurbel", + "block.create.haunted_bell": "UNLOCALIZED: Haunted Bell", "block.create.honey": "Honig", "block.create.horizontal_framed_glass": "Horizontal Gerahmtes Glas", "block.create.horizontal_framed_glass_pane": "Horizontal Gerahmte Glasscheibe", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "Geschichteter Kalkstein", "block.create.layered_scoria": "Geschichtete Schlacke", "block.create.layered_weathered_limestone": "Geschichteter Verwitterter Kalkstein", + "block.create.lectern_controller": "UNLOCALIZED: Lectern Controller", + "block.create.light_blue_nixie_tube": "UNLOCALIZED: Light Blue Nixie Tube", "block.create.light_blue_sail": "Hellblaues Segel", "block.create.light_blue_seat": "Hellblauer Sitz", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "Hellblauer Ventilgriff", + "block.create.light_gray_nixie_tube": "UNLOCALIZED: Light Gray Nixie Tube", "block.create.light_gray_sail": "Hellgraues Segel", "block.create.light_gray_seat": "Hellgrauer Sitz", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "Hellgrauer Ventilgriff", + "block.create.lime_nixie_tube": "UNLOCALIZED: Lime Nixie Tube", "block.create.lime_sail": "Hellgrünes Segel", "block.create.lime_seat": "Hellgrüner Sitz", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "Hellgrüner Ventilgriff", "block.create.limesand": "Kalksand", "block.create.limestone": "Kalkstein", @@ -225,8 +245,10 @@ "block.create.limestone_pillar": "Kalksteinsäule", "block.create.linear_chassis": "Schubgerüst", "block.create.lit_blaze_burner": "Aktiver Lohenbrenner", + "block.create.magenta_nixie_tube": "UNLOCALIZED: Magenta Nixie Tube", "block.create.magenta_sail": "Magenta Segel", "block.create.magenta_seat": "Magenta Sitz", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "Magenta Ventilgriff", "block.create.mechanical_arm": "Mechanischer Arm", "block.create.mechanical_bearing": "Mechanisches Lager", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "Eichenfensterscheibe", "block.create.orange_sail": "Oranges Segel", "block.create.orange_seat": "Oranger Sitz", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "Oranger Ventilgriff", "block.create.ornate_iron_window": "Kunstvolles Eisenfenster", "block.create.ornate_iron_window_pane": "Kunstvolle Eisenfensterscheibe", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "Gepflasterte Verwitterte Kalksteinstufe", "block.create.paved_weathered_limestone_stairs": "Gepflasterte Verwitterte Kalksteintreppe", "block.create.paved_weathered_limestone_wall": "Gepflasterte Verwitterte Kalksteinmauer", + "block.create.peculiar_bell": "UNLOCALIZED: Peculiar Bell", + "block.create.pink_nixie_tube": "UNLOCALIZED: Pink Nixie Tube", "block.create.pink_sail": "Rosa Segel", "block.create.pink_seat": "Rosa Sitz", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "Rosa Ventilgriff", "block.create.piston_extension_pole": "Kolben-Pleuelverlängerung", "block.create.polished_dark_scoria": "Polierte Dunkle Schlacke", @@ -342,12 +368,16 @@ "block.create.powered_toggle_latch": "T-Flipflop", "block.create.pulley_magnet": "Rollenmagnet", "block.create.pulse_repeater": "Pulsierender Verstärker", + "block.create.purple_nixie_tube": "UNLOCALIZED: Purple Nixie Tube", "block.create.purple_sail": "Lila Segel", "block.create.purple_seat": "Lila Sitz", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "Lila Ventilgriff", "block.create.radial_chassis": "Drehgerüst", + "block.create.red_nixie_tube": "UNLOCALIZED: Red Nixie Tube", "block.create.red_sail": "Rote Segel", "block.create.red_seat": "Roter Sitz", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "Roter Ventilgriff", "block.create.redstone_contact": "Redstone-Kontakt", "block.create.redstone_link": "Redstone-Verbindung", @@ -402,24 +432,32 @@ "block.create.weathered_limestone_cobblestone_wall": "Verwitterte Limestonepflastermauer", "block.create.weathered_limestone_pillar": "Verwitterte Kalksteinsäule", "block.create.weighted_ejector": "Gewichteter Werfer", + "block.create.white_nixie_tube": "UNLOCALIZED: White Nixie Tube", "block.create.white_sail": "Weiße Segel", "block.create.white_seat": "Weißer Sitz", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "Weißer Ventilgriff", "block.create.windmill_bearing": "Windmühlenlager", "block.create.wooden_bracket": "Holzhalterung", + "block.create.yellow_nixie_tube": "UNLOCALIZED: Yellow Nixie Tube", "block.create.yellow_sail": "Gelbes Segel", "block.create.yellow_seat": "Gelber Sitz", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "Gelber Ventilgriff", "block.create.zinc_block": "Zinkblock", "block.create.zinc_ore": "Zinkerz", + "enchantment.create.capacity": "UNLOCALIZED: Capacity", + "enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery", + "entity.create.contraption": "Vorrichtung", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "Portalkran Vorrichtung", + "entity.create.potato_projectile": "UNLOCALIZED: Potato Projectile", "entity.create.seat": "Sitz", "entity.create.stationary_contraption": "Stationäre Vorrichtung", "entity.create.super_glue": "Superkleber", - "fluid.create.milk": "Milch", "fluid.create.potion": "Trank", "fluid.create.tea": "Bauherrentee", @@ -444,6 +482,8 @@ "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.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "item.create.crushed_aluminum_ore": "Zerkleinertes Aluminiumerz", "item.create.crushed_brass": "Zerkleinertes Messing", "item.create.crushed_copper_ore": "Zerkleinertes Kupfererz", @@ -472,13 +512,17 @@ "item.create.handheld_worldshaper": "Geländeformer", "item.create.honey_bucket": "Honigeimer", "item.create.honeyed_apple": "Honigapfel", - "item.create.integrated_circuit": "Integrierter Schaltkreis", + "item.create.incomplete_cogwheel": "UNLOCALIZED: Incomplete Cogwheel", + "item.create.incomplete_large_cogwheel": "UNLOCALIZED: Incomplete Large Cogwheel", + "item.create.incomplete_precision_mechanism": "UNLOCALIZED: Incomplete Precision Mechanism", "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", + "item.create.potato_cannon": "UNLOCALIZED: Potato Cannon", "item.create.powdered_obsidian": "Pulverisierter Obsidian", + "item.create.precision_mechanism": "UNLOCALIZED: Precision Mechanism", "item.create.propeller": "Propeller", "item.create.red_sand_paper": "Rotes Schmirgelpapier", "item.create.refined_radiance": "Raffinierter Glanz", @@ -623,8 +667,8 @@ "advancement.create.flywheel.desc": "UNLOCALIZED: Successfully connect an engine to the Flywheel.", "advancement.create.overstress_flywheel": "UNLOCALIZED: High levels of Stress", "advancement.create.overstress_flywheel.desc": "UNLOCALIZED: Overstress a Furnace Engine.", - "advancement.create.integrated_circuit": "UNLOCALIZED: Complex Calculation", - "advancement.create.integrated_circuit.desc": "UNLOCALIZED: Assemble an Integrated Circuit.", + "advancement.create.precision_mechanism": "UNLOCALIZED: Complex Curiosities", + "advancement.create.precision_mechanism.desc": "UNLOCALIZED: Assemble a Precision Mechanism.", "advancement.create.mechanical_arm": "UNLOCALIZED: Busy Hands!", "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch as it does all the work for you.", "advancement.create.musical_arm": "UNLOCALIZED: Play Me My Theme Tune!", @@ -639,7 +683,7 @@ "advancement.create.crushing_wheel.desc": "UNLOCALIZED: Create some Crushing Wheels to break down more materials more effectively.", "advancement.create.blaze_cake": "UNLOCALIZED: Sugar Rush", "advancement.create.blaze_cake.desc": "UNLOCALIZED: Bake your blaze burner a special cake.", - "advancement.create.chromatic_compound": "UNLOCALIZED: Bipolar Minerals", + "advancement.create.chromatic_compound": "UNLOCALIZED: Mysterious Minerals", "advancement.create.chromatic_compound.desc": "UNLOCALIZED: Create a Bar of Chromatic Compound.", "advancement.create.shadow_steel": "UNLOCALIZED: Void Returner", "advancement.create.shadow_steel.desc": "UNLOCALIZED: Create Shadow Steel, a metal bar of nothingness.", @@ -651,6 +695,8 @@ "advancement.create.wand_of_symmetry.desc": "UNLOCALIZED: Craft a Staff of Symmetry.", "advancement.create.extendo_grip": "Boioioing!", "advancement.create.extendo_grip.desc": "Beschaffe einen Extendo Griff.", + "advancement.create.potato_cannon": "UNLOCALIZED: Fwoomp!", + "advancement.create.potato_cannon.desc": "UNLOCALIZED: Defeat an enemy with your Potato Cannon.", "advancement.create.dual_extendo_grip": "Ultimatives Boing-Zeitalter", "advancement.create.dual_extendo_grip.desc": "Schwinge zwei Extendo Griffe gleichzeitig für eine übermenschliche Reichweite.", "advancement.create.eob": "Ende der Beta", @@ -663,15 +709,31 @@ "itemGroup.create.palettes": "Create Paletten", "death.attack.create.crush": "%1$s stolperte in ein Mahlwerk", + "death.attack.create.crush.player": "UNLOCALIZED: %1$s was thrown into Crushing Wheels by %2$s", "death.attack.create.fan_fire": "%1$s hat heiße Luft eingeatmet", + "death.attack.create.fan_fire.player": "UNLOCALIZED: %1$s was thrown into a smoker by %2$s", "death.attack.create.fan_lava": "%1$s wurde von Lava verweht", + "death.attack.create.fan_lava.player": "UNLOCALIZED: %1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "%1$s wurde von einem Bohrer durchlöchert", + "death.attack.create.mechanical_drill.player": "UNLOCALIZED: %1$s was thrown in front of a Drill by %2$s", "death.attack.create.mechanical_saw": "%1$s wurde zersägt", + "death.attack.create.mechanical_saw.player": "UNLOCALIZED: %1$s was thrown into a Saw by %2$s", + "death.attack.create.potato_cannon": "UNLOCALIZED: %1$s was shot by %2$s's Potato Cannon", + "death.attack.create.potato_cannon.item": "UNLOCALIZED: %1$s was shot by %2$s using %3$s", "death.attack.create.cuckoo_clock_explosion": "%1$s wurde durch eine falsche Kuckucksuhr gesprengt", + "death.attack.create.cuckoo_clock_explosion.player": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", "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.ponder_index": "UNLOCALIZED: Ponder Index", + "create.menu.only_ingame": "UNLOCALIZED: Available in the Pause Menu", + "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", @@ -696,7 +758,18 @@ "create.recipe.mystery_conversion": "Mysteriöse Konvertierung", "create.recipe.spout_filling": "Befüllung per Ausguss", "create.recipe.draining": "Gegenstandsablassung", + "create.recipe.sequenced_assembly": "UNLOCALIZED: Sequenced Assembly", + "create.recipe.assembly.next": "UNLOCALIZED: Next: %1$s", + "create.recipe.assembly.step": "UNLOCALIZED: Step %1$s:", + "create.recipe.assembly.progress": "UNLOCALIZED: Progress: %1$s/%2$s", + "create.recipe.assembly.pressing": "UNLOCALIZED: Process in Press", + "create.recipe.assembly.spout_filling_fluid": "UNLOCALIZED: Spout %1$s", + "create.recipe.assembly.deploying_item": "UNLOCALIZED: Deploy %1$s", + "create.recipe.assembly.cutting": "UNLOCALIZED: Cut with Saw", + "create.recipe.assembly.repeat": "UNLOCALIZED: Repeat Sequence %1$s Times", + "create.recipe.assembly.junk": "UNLOCALIZED: Random salvage", "create.recipe.processing.chance": "Chance: %1$s%%", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "Keine Hitze benötigt", "create.recipe.heat_requirement.heated": "Wenig Hitze benötigt", "create.recipe.heat_requirement.superheated": "Viel Hitze benötigt", @@ -725,6 +798,7 @@ "create.action.discard": "Löschen", "create.keyinfo.toolmenu": "Werkzeugmenü", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "Simuliere Mausrad hoch (In der Welt)", "create.keyinfo.scrolldown": "Simuliere Mausrad runter (In der Welt)", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "Shift zum schnelleren Auswählen", "create.gui.toolmenu.focusKey": "Halte [%1$s] zum Fokussieren", "create.gui.toolmenu.cycle": "[Mausrad] zum Wechseln", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Spiegeln", "create.gui.symmetryWand.orientation": "Orientierung", @@ -981,18 +1062,14 @@ "create.item_attributes.placeable.inverted": "UNLOCALIZED: is not placeable", "create.item_attributes.consumable": "UNLOCALIZED: can be eaten", "create.item_attributes.consumable.inverted": "UNLOCALIZED: cannot be eaten", - "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", - "create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted", - "create.item_attributes.washable": "UNLOCALIZED: can be Washed", - "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", - "create.item_attributes.smokable": "UNLOCALIZED: can be Smoked", - "create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked", - "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", - "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", - "create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace", - "create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace", + "create.item_attributes.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "UNLOCALIZED: is enchanted", "create.item_attributes.enchanted.inverted": "UNLOCALIZED: is unenchanted", + "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.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "UNLOCALIZED: is damaged", "create.item_attributes.damaged.inverted": "UNLOCALIZED: is not damaged", "create.item_attributes.badly_damaged": "UNLOCALIZED: is heavily damaged", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "UNLOCALIZED: cannot be equipped", "create.item_attributes.furnace_fuel": "UNLOCALIZED: is furnace fuel", "create.item_attributes.furnace_fuel.inverted": "UNLOCALIZED: is not furnace fuel", + "create.item_attributes.washable": "UNLOCALIZED: can be Washed", + "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", + "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", + "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", + "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", + "create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted", + "create.item_attributes.smokable": "UNLOCALIZED: can be Smoked", + "create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked", + "create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace", + "create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace", + "create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s", + "create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s", + "create.item_attributes.shulker_level.full": "UNLOCALIZED: full", + "create.item_attributes.shulker_level.empty": "UNLOCALIZED: empty", + "create.item_attributes.shulker_level.partial": "UNLOCALIZED: partially filled", "create.item_attributes.in_tag": "UNLOCALIZED: is tagged %1$s", "create.item_attributes.in_tag.inverted": "UNLOCALIZED: is not tagged %1$s", "create.item_attributes.in_item_group": "UNLOCALIZED: is in group '%1$s'", @@ -1013,8 +1105,6 @@ "create.item_attributes.has_enchant.inverted": "UNLOCALIZED: is not enchanted with %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.has_fluid": "UNLOCALIZED: contains %1$s", "create.item_attributes.has_fluid.inverted": "UNLOCALIZED: does not contain %1$s", "create.item_attributes.has_name": "UNLOCALIZED: has the custom name %1$s", @@ -1029,14 +1119,14 @@ "create.item_attributes.book_copy_second.inverted": "UNLOCALIZED: is not a second-generation copy", "create.item_attributes.book_copy_tattered": "UNLOCALIZED: is a tattered mess", "create.item_attributes.book_copy_tattered.inverted": "UNLOCALIZED: is not a tattered mess", - "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", - "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", - "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", "create.item_attributes.astralsorcery_amulet": "UNLOCALIZED: improves %1$s", "create.item_attributes.astralsorcery_amulet.inverted": "UNLOCALIZED: does not improve %1$s", + "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", + "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", "create.gui.attribute_filter.no_selected_attributes": "Keine Attribute ausgewählt", "create.gui.attribute_filter.selected_attributes": "Ausgewählte Attribute:", @@ -1104,6 +1194,27 @@ "create.tooltip.chute.fans_pull_up": "Propeller ziehen von oberhalb", "create.tooltip.chute.fans_pull_down": "Propeller ziehen von unterhalb", "create.tooltip.chute.contains": "Enthält: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "UNLOCALIZED: Currently distributing:", + "create.tooltip.brass_tunnel.contains_entry": "UNLOCALIZED: > %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "UNLOCALIZED: Right-Click to retrieve", + + "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.potato_cannon.ammo.attack_damage": "UNLOCALIZED: %1$s Attack Damage", + "create.potato_cannon.ammo.reload_ticks": "UNLOCALIZED: %1$s Reload Ticks", + "create.potato_cannon.ammo.knockback": "UNLOCALIZED: %1$s Knockback", "create.hint.hose_pulley.title": "Endlose Versorgung", "create.hint.hose_pulley": "Das angewählte Gewässer wird als unendlich betrachtet.", @@ -1132,32 +1243,44 @@ "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.contraption_disassemble": "UNLOCALIZED: Contraption stops", + "create.subtitle.peculiar_bell_use": "UNLOCALIZED: Peculiar Bell tolls", + "create.subtitle.mixing": "UNLOCALIZED: Mixing noises", + "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", + "create.subtitle.fwoomp": "UNLOCALIZED: Potato Launcher fwoomps", + "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", + "create.subtitle.crushing_1": "UNLOCALIZED: Crushing noises", + "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.blaze_munch": "Lohe kaut glücklich", + "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel flaps", + "create.subtitle.schematicannon_finish": "Bauplankanone endet", + "create.subtitle.haunted_bell_use": "UNLOCALIZED: Haunted Bell tolls", + "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.controller_put": "UNLOCALIZED: Controller thumps", + "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.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.potato_hit": "UNLOCALIZED: Vegetable impacts", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens", "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", - "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", "create.subtitle.deny": "UNLOCALIZED: Declining boop", - "create.subtitle.blaze_munch": "Lohe kaut glücklich", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", "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.controller_take": "UNLOCALIZED: Lectern empties", "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", @@ -1179,14 +1302,6 @@ "block.create.metal_bracket.tooltip": "UNLOCALIZED: METAL BRACKET", "block.create.metal_bracket.tooltip.summary": "UNLOCALIZED: _Decorate_ your _Shafts, Cogwheels_ and _Pipes_ with an industrial and sturdy bit of reinforcement.", - "block.create.copper_casing.tooltip": "UNLOCALIZED: COPPER CASING", - "block.create.copper_casing.tooltip.summary": "UNLOCALIZED: Robust machine casing with a variety of uses. Safe for decoration.", - "block.create.copper_casing.tooltip.condition1": "UNLOCALIZED: When used on Fluid Pipe", - "block.create.copper_casing.tooltip.behaviour1": "UNLOCALIZED: _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": "UNLOCALIZED: ENCASED FLUID PIPE", - "block.create.encased_fluid_pipe.tooltip.summary": "UNLOCALIZED: A _Fluid Pipe_ encased with the _Copper Casing_.", - "block.create.seat.tooltip": "UNLOCALIZED: SEAT", "block.create.seat.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: Right click on Seat", @@ -1195,65 +1310,6 @@ "item.create.blaze_cake.tooltip": "UNLOCALIZED: BLAZE CAKE", "item.create.blaze_cake.tooltip.summary": "UNLOCALIZED: A Delicious treat for your hard-working _Blaze Burners_. Gets them all fired up!", - "block.create.fluid_pipe.tooltip": "UNLOCALIZED: FLUID PIPE", - "block.create.fluid_pipe.tooltip.summary": "UNLOCALIZED: Used for moving _fluids_ around. Needs a _Mechanical Pump_ to get the _fluid_ moving.", - "block.create.fluid_pipe.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.fluid_pipe.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Places a window on the pipe if available", - - "block.create.hose_pulley.tooltip": "UNLOCALIZED: HOSE PULLEY", - "block.create.hose_pulley.tooltip.summary": "UNLOCALIZED: Used for _placing_ or _draining_ large _fluid bodies_ in the world.", - "block.create.hose_pulley.tooltip.condition1": "UNLOCALIZED: When Powered by Kinetics", - "block.create.hose_pulley.tooltip.behaviour1": "UNLOCALIZED: _Raises_ or _Lowers_ the hose, location of the hose determines up to which _height extraction_ or _filling_ will act.", - "block.create.hose_pulley.tooltip.condition2": "UNLOCALIZED: When Fluids pulled from Pulley", - "block.create.hose_pulley.tooltip.behaviour2": "UNLOCALIZED: 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": "UNLOCALIZED: When Fluids pushed to Pulley", - "block.create.hose_pulley.tooltip.behaviour3": "UNLOCALIZED: Starts _filling fluid_ into the world _up to_ the _hose_ ends' _height_.", - - "block.create.fluid_tank.tooltip": "UNLOCALIZED: FLUID TANK", - "block.create.fluid_tank.tooltip.summary": "UNLOCALIZED: _Stores_ all your favourite _fluids_. Scales in width and height.", - "block.create.fluid_tank.tooltip.condition1": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_tank.tooltip.behaviour1": "UNLOCALIZED: Changes the optional window", - - "block.create.creative_fluid_tank.tooltip": "UNLOCALIZED: CREATIVE FLUID TANK", - "block.create.creative_fluid_tank.tooltip.summary": "UNLOCALIZED: This _Fluid Tank_ allows infinite replication of any Fluid. Scales in width and height.", - "block.create.creative_fluid_tank.tooltip.condition1": "UNLOCALIZED: When Fluid in Tank", - "block.create.creative_fluid_tank.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.creative_fluid_tank.tooltip.behaviour2": "UNLOCALIZED: Changes the optional window", - - "block.create.fluid_valve.tooltip": "UNLOCALIZED: FLUID VALVE", - "block.create.fluid_valve.tooltip.summary": "UNLOCALIZED: Halts the flow of fluid down a pipe.", - "block.create.fluid_valve.tooltip.condition1": "UNLOCALIZED: Controllable flow", - "block.create.fluid_valve.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: MECHANICAL PUMP", - "block.create.mechanical_pump.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: Fluid Flow", - "block.create.mechanical_pump.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.mechanical_pump.tooltip.action1": "UNLOCALIZED: Reverses the direction of the _pump_, switching the default direction of the flow", - - "block.create.smart_fluid_pipe.tooltip": "UNLOCALIZED: SMART FLUID PIPE", - "block.create.smart_fluid_pipe.tooltip.summary": "UNLOCALIZED: A _fluid pipe_ with a filter. Can specify which _fluids_ pass through.", - "block.create.smart_fluid_pipe.tooltip.condition1": "UNLOCALIZED: When Fluids are pushed into it", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "UNLOCALIZED: Smart pipes receiving fluid that does not match its filter will block the flow.", - "block.create.smart_fluid_pipe.tooltip.condition2": "UNLOCALIZED: When adjacent to fluid container", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Smart pipes _starting_ a _flow_ from any container will only extract fluids that _match_ its _filter._", - - "block.create.spout.tooltip": "UNLOCALIZED: SPOUT", - "block.create.spout.tooltip.summary": "UNLOCALIZED: An injector for refilling your _fluid items._", - "block.create.spout.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.spout.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Fluid Automation", - "block.create.spout.tooltip.behaviour2": "UNLOCALIZED: 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": "UNLOCALIZED: ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "UNLOCALIZED: A grated depot for emptying your _fluid items._", - "block.create.item_drain.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.item_drain.tooltip.behaviour1": "UNLOCALIZED: 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": "SYMMETRIESTAB", "item.create.wand_of_symmetry.tooltip.summary": "Spiegelt deine Blockplatzierung perfekt über die konfigurierten Ebenen.", "item.create.wand_of_symmetry.tooltip.condition1": "Wenn in der Schnellleiste", @@ -1280,9 +1336,18 @@ "item.create.tree_fertilizer.tooltip.behaviour1": "Lässt Bäume unabhängig vom Platz um sie herum wachsen", "item.create.extendo_grip.tooltip": "UNLOCALIZED: EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder.", + "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder. Can be powered with Air Pressure from a _Copper_ _Backtank_", "item.create.extendo_grip.tooltip.condition1": "UNLOCALIZED: When in Off-Hand", "item.create.extendo_grip.tooltip.behaviour1": "UNLOCALIZED: Increases _reach distance_ of items used in the _Main-Hand_.", + "item.create.extendo_grip.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", + + "item.create.potato_cannon.tooltip": "UNLOCALIZED: POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "UNLOCALIZED: Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", + "item.create.potato_cannon.tooltip.behaviour1": "UNLOCALIZED: _Shoots_ a suitable item from your _Inventory_.", + "item.create.potato_cannon.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.filter.tooltip": "UNLOCALIZED: FILTER", "item.create.filter.tooltip.summary": "UNLOCALIZED: _Controls outputs_ and _inputs_ of logistical devices with more _precision_, matching them against a _set of items_ or several _nested filters_.", @@ -1358,12 +1423,14 @@ "block.create.turntable.tooltip": "DREHTISCH", "block.create.turntable.tooltip.summary": "Wandelt _Rotationsenergie_ in starkes Schwindelgefühl um.", - "block.create.portable_fluid_interface.tooltip": "UNLOCALIZED: PORTABLE FLUID INTERFACE", - "block.create.portable_fluid_interface.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: While Moving", - "block.create.portable_fluid_interface.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: When Powered by Redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "UNLOCALIZED: _Disengages_ any active connection immediately.", + "block.create.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "VORRATSSENSOR", "block.create.stockpile_switch.tooltip.summary": "Schaltet ein Redstone-Signal ein oder aus, basierend auf der _Speichermenge_ im verbundenen Behälter.", @@ -1371,7 +1438,11 @@ "block.create.stockpile_switch.tooltip.behaviour1": "Wird das Redstone-Signal ausgeschaltet.", "block.create.content_observer.tooltip": "UNLOCALIZED: CONTENT OBSERVER", - "block.create.content_observer.tooltip.summary": "UNLOCALIZED: _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_.", + "block.create.content_observer.tooltip.summary": "UNLOCALIZED: _Detects Items_ or _Fluids_ inside _containers_, _pipes_ or _conveyors_ matching a configured _filter_.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "LAGERRAUM", "block.create.adjustable_crate.tooltip.summary": "Dieser _Speicherbehälter_ erlaubt manuelle Kontrolle über seine Kapazität. Er kann bis zu _16_ _Stacks_ von jeglichem Gegenstand beinhalten.", @@ -1383,6 +1454,11 @@ "block.create.creative_crate.tooltip.condition1": "Wenn Gegenstand in Filter Slot", "block.create.creative_crate.tooltip.behaviour1": "Alles _extrahierende_ von diesem Container wird einen _endlosen Vorrat_ des angegebenen Gegenstands zur Verfügung stellen. In diese Kiste _eingefügte_ Gegenstände werden _entsorgt_.", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "UNLOCALIZED: CONTROLLER RAIL", "block.create.controller_rail.tooltip.summary": "UNLOCALIZED: A _uni-directional powered rail_ capable of _fine control_ over a minecarts' _movement speed_.", "block.create.controller_rail.tooltip.condition1": "UNLOCALIZED: When Powered by Redstone", @@ -1398,26 +1474,61 @@ "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.linked_controller.tooltip.condition4": "UNLOCALIZED: R-Click on Lectern", + "item.create.linked_controller.tooltip.behaviour4": "UNLOCALIZED: Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the wielder 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: Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder 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.", + "block.create.peculiar_bell.tooltip": "UNLOCALIZED: PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "UNLOCALIZED: A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + + "block.create.haunted_bell.tooltip": "UNLOCALIZED: HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "UNLOCALIZED: A _Cursed Bell_ haunted by lost souls of the Nether.", + "block.create.haunted_bell.tooltip.condition1": "UNLOCALIZED: When Held or Rang", + "block.create.haunted_bell.tooltip.behaviour1": "UNLOCALIZED: Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn.", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1434,41 +1545,46 @@ "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.exit": "UNLOCALIZED: Exit", + "create.ponder.welcome": "UNLOCALIZED: Welcome to Ponder", + "create.ponder.categories": "UNLOCALIZED: Available Categories in Create", + "create.ponder.index_description": "UNLOCALIZED: Click one of the icons to learn about its associated Items and Blocks", + "create.ponder.index_title": "UNLOCALIZED: Ponder Index", + "create.ponder.shared.rpm16": "UNLOCALIZED: 16 RPM", "create.ponder.shared.behaviour_modify_wrench": "UNLOCALIZED: This behaviour can be modified using a Wrench", + "create.ponder.shared.storage_on_contraption": "UNLOCALIZED: Inventories attached to the Contraption will pick up their drops automatically", + "create.ponder.shared.sneak_and": "UNLOCALIZED: Sneak +", "create.ponder.shared.rpm8": "UNLOCALIZED: 8 RPM", "create.ponder.shared.ctrl_and": "UNLOCALIZED: Ctrl +", + "create.ponder.shared.rpm32": "UNLOCALIZED: 32 RPM", "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.shared.movement_anchors": "UNLOCALIZED: With the help of Chassis or Super Glue, larger structures can be moved.", "create.ponder.tag.redstone": "UNLOCALIZED: Logic Components", "create.ponder.tag.redstone.description": "UNLOCALIZED: Components which help with redstone engineering", + "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.fluids": "UNLOCALIZED: Fluid Manipulators", "create.ponder.tag.fluids.description": "UNLOCALIZED: Components which help relaying and making use of Fluids", + "create.ponder.tag.decoration": "UNLOCALIZED: Aesthetics", + "create.ponder.tag.decoration.description": "UNLOCALIZED: Components used mostly for decorative purposes", + "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.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.kinetic_appliances": "UNLOCALIZED: Kinetic Appliances", + "create.ponder.tag.kinetic_appliances.description": "UNLOCALIZED: Components which make use of Rotational Force", + "create.ponder.tag.kinetic_sources": "UNLOCALIZED: Kinetic Sources", + "create.ponder.tag.kinetic_sources.description": "UNLOCALIZED: Components which generate Rotational Force", + "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.kinetic_relays": "UNLOCALIZED: Kinetic Blocks", + "create.ponder.tag.kinetic_relays.description": "UNLOCALIZED: Components which help relaying Rotational Force elsewhere", + "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.creative": "UNLOCALIZED: Creative Mode", + "create.ponder.tag.creative.description": "UNLOCALIZED: Components not usually available for Survival Mode", + "create.ponder.tag.logistics": "UNLOCALIZED: Item Transportation", + "create.ponder.tag.logistics.description": "UNLOCALIZED: Components which help moving items around", "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", @@ -1580,7 +1696,8 @@ "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_modes.text_2": "UNLOCALIZED: This Arrow indicates which side of the Structure will be considered the front", + "create.ponder.cart_assembler_modes.text_3": "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", @@ -1594,7 +1711,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 +1751,12 @@ "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_fluid_tank.text_1": "UNLOCALIZED: Creative Fluid Tanks can be used to provide a bottomless supply of fluid", + "create.ponder.creative_fluid_tank.text_2": "UNLOCALIZED: Right-Click with a fluid containing item to configure it", + "create.ponder.creative_fluid_tank.text_3": "UNLOCALIZED: Pipe Networks can now endlessly draw the assigned fluid from the tank", + "create.ponder.creative_fluid_tank.text_4": "UNLOCALIZED: Any Fluids pushed back into a Creative Fluid Tank will be voided", + "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 +1793,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", @@ -1686,7 +1815,13 @@ "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.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item", + "create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they 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", @@ -1706,6 +1841,35 @@ "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_sizes.text_1": "UNLOCALIZED: Fluid Tanks can be combined to increase the total capacity", + "create.ponder.fluid_tank_sizes.text_2": "UNLOCALIZED: Their base square can be up to 3 blocks wide...", + "create.ponder.fluid_tank_sizes.text_3": "UNLOCALIZED: ...and grow in height by more than 30 additional layers", + "create.ponder.fluid_tank_sizes.text_4": "UNLOCALIZED: Using a Wrench, a tanks' window can be toggled", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.fluid_tank_storage.text_1": "UNLOCALIZED: Fluid Tanks can be used to store large amounts of fluid", + "create.ponder.fluid_tank_storage.text_2": "UNLOCALIZED: Pipe networks can push and pull fluids from any side", + "create.ponder.fluid_tank_storage.text_3": "UNLOCALIZED: The contained fluid can be measured by a Comparator", + "create.ponder.fluid_tank_storage.text_4": "UNLOCALIZED: However, in Survival Mode Fluids cannot be added or taken manually", + "create.ponder.fluid_tank_storage.text_5": "UNLOCALIZED: You can use Basins, Item Drains and Spouts to drain or fill fluid containing items", + "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 +1943,34 @@ "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.text_1": "UNLOCALIZED: Hose Pulleys can be used to fill or drain large bodies of Fluid", + "create.ponder.hose_pulley.text_2": "UNLOCALIZED: With the Kinetic Input, the height of the pulleys' hose can be controlled", + "create.ponder.hose_pulley.text_3": "UNLOCALIZED: The Pulley retracts while the input rotation is inverted", + "create.ponder.hose_pulley.text_4": "UNLOCALIZED: On the opposite side, pipes can be connected", + "create.ponder.hose_pulley.text_5": "UNLOCALIZED: Attached pipe networks can either provide fluid to the hose...", + "create.ponder.hose_pulley.text_6": "UNLOCALIZED: ...or pull from it, draining the pool instead", + "create.ponder.hose_pulley.text_7": "UNLOCALIZED: Fill and Drain speed of the pulley depends entirely on the fluid networks' throughput", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + "create.ponder.hose_pulley_infinite.text_1": "UNLOCALIZED: When deploying the Hose Pulley into a large enough ocean...", + "create.ponder.hose_pulley_infinite.text_2": "UNLOCALIZED: It will provide/dispose fluids without affecting the source", + "create.ponder.hose_pulley_infinite.text_3": "UNLOCALIZED: Pipe networks can limitlessly take fluids from/to such pulleys", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + "create.ponder.hose_pulley_level.text_1": "UNLOCALIZED: While fully retracted, the Hose Pulley cannot operate", + "create.ponder.hose_pulley_level.text_2": "UNLOCALIZED: Draining runs from top to bottom", + "create.ponder.hose_pulley_level.text_3": "UNLOCALIZED: The surface level will end up just below where the hose ends", + "create.ponder.hose_pulley_level.text_4": "UNLOCALIZED: Filling runs from bottom to top", + "create.ponder.hose_pulley_level.text_5": "UNLOCALIZED: The filled pool will not grow beyond the layer above the hose end", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.item_drain.text_1": "UNLOCALIZED: Item Drains can extract fluids from items", + "create.ponder.item_drain.text_2": "UNLOCALIZED: Right-click it to pour fluids from your held item into it", + "create.ponder.item_drain.text_3": "UNLOCALIZED: When items are inserted from the side...", + "create.ponder.item_drain.text_4": "UNLOCALIZED: ...they roll across, emptying out their contained fluid", + "create.ponder.item_drain.text_5": "UNLOCALIZED: Pipe Networks can now pull the fluid from the drains' internal buffer", + "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 +2093,21 @@ "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_flow.text_1": "UNLOCALIZED: Mechanical Pumps govern the flow of their attached pipe networks", + "create.ponder.mechanical_pump_flow.text_2": "UNLOCALIZED: When powered, their arrow indicates the direction of flow", + "create.ponder.mechanical_pump_flow.text_3": "UNLOCALIZED: The network behind is now pulling fluids...", + "create.ponder.mechanical_pump_flow.text_4": "UNLOCALIZED: ...while the network in front is transferring it outward", + "create.ponder.mechanical_pump_flow.text_5": "UNLOCALIZED: Reversing the input rotation reverses the direction of flow", + "create.ponder.mechanical_pump_flow.text_6": "UNLOCALIZED: Use a Wrench to reverse the orientation of pumps manually", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_pump_speed.text_1": "UNLOCALIZED: Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away", + "create.ponder.mechanical_pump_speed.text_2": "UNLOCALIZED: Speeding up the input rotation changes the speed of flow propagation...", + "create.ponder.mechanical_pump_speed.text_3": "UNLOCALIZED: ...aswell as how quickly fluids are transferred", + "create.ponder.mechanical_pump_speed.text_4": "UNLOCALIZED: Pumps can combine their throughputs within shared pipe networks", + "create.ponder.mechanical_pump_speed.text_5": "UNLOCALIZED: Alternating their orientation can help align their flow directions", + "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", @@ -1926,11 +2133,22 @@ "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.nixie_tube.text_3": "UNLOCALIZED: Right-Click with Dye to change their display colour", "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_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + "create.ponder.portable_fluid_interface.text_1": "UNLOCALIZED: Fluid Tanks on moving contraptions cannot be accessed by any pipes", + "create.ponder.portable_fluid_interface.text_2": "UNLOCALIZED: This component can interact with fluid tanks without the need to stop the contraption", + "create.ponder.portable_fluid_interface.text_3": "UNLOCALIZED: Place a second one with a gap of 1 or 2 blocks inbetween", + "create.ponder.portable_fluid_interface.text_4": "UNLOCALIZED: Whenever they pass by each other, they will engage in a connection", + "create.ponder.portable_fluid_interface.text_5": "UNLOCALIZED: While engaged, the stationary interface will represent ALL Tanks on the contraption", + "create.ponder.portable_fluid_interface.text_6": "UNLOCALIZED: Fluid can now be inserted...", + "create.ponder.portable_fluid_interface.text_7": "UNLOCALIZED: ...or extracted from the contraption", + "create.ponder.portable_fluid_interface.text_8": "UNLOCALIZED: After no contents have been exchanged for a while, the contraption will continue on its way", + "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 +2246,25 @@ "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.smart_pipe.text_1": "UNLOCALIZED: Smart pipes can help control flows by fluid type", + "create.ponder.smart_pipe.text_2": "UNLOCALIZED: When placed directly at the source, they can specify the type of fluid to extract", + "create.ponder.smart_pipe.text_3": "UNLOCALIZED: Simply Right-Click their filter slot with any item containing the desired fluid", + "create.ponder.smart_pipe.text_4": "UNLOCALIZED: When placed further down a pipe network, smart pipes will only let matching fluids continue", + "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_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.spout_filling.text_1": "UNLOCALIZED: The Spout can fill fluid holding items provided beneath it", + "create.ponder.spout_filling.text_2": "UNLOCALIZED: The content of a Spout cannot be accessed manually", + "create.ponder.spout_filling.text_3": "UNLOCALIZED: Instead, Pipes can be used to supply it with fluids", + "create.ponder.spout_filling.text_4": "UNLOCALIZED: The Input items can be placed on a Depot under the Spout", + "create.ponder.spout_filling.text_5": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.spout_filling.text_6": "UNLOCALIZED: The Spout will hold and process them automatically", + "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 +2296,12 @@ "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.valve_pipe.text_1": "UNLOCALIZED: Valve pipes help control fluids propagating through pipe networks", + "create.ponder.valve_pipe.text_2": "UNLOCALIZED: Their shaft input controls whether fluid is currently allowed through", + "create.ponder.valve_pipe.text_3": "UNLOCALIZED: Given Rotational Force in the opening direction, the valve will open up", + "create.ponder.valve_pipe.text_4": "UNLOCALIZED: It can be closed again by reversing the input rotation", + "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..183c73ff2 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: 39", "_": "->------------------------] Game Elements [------------------------<-", @@ -14,7 +14,7 @@ "block.create.andesite_bricks": "Ladrillos de andesita", "block.create.andesite_bricks_slab": "Losa de ladrillos de andesita", "block.create.andesite_bricks_stairs": "Escaleras de ladrillos de andesita", - "block.create.andesite_bricks_wall": "Pared de ladrillos de andesita", + "block.create.andesite_bricks_wall": "Muro de ladrillos de andesita", "block.create.andesite_casing": "Revestidor de andesita", "block.create.andesite_cobblestone": "Adoquín de andesita", "block.create.andesite_cobblestone_slab": "Losa de adoquín de andesita", @@ -28,12 +28,16 @@ "block.create.belt": "Cinta", "block.create.birch_window": "Ventana de abedul", "block.create.birch_window_pane": "Panel de ventana de abedul", + "block.create.black_nixie_tube": "Tubo Nixie negro", "block.create.black_sail": "Vela negra", "block.create.black_seat": "Asiento negro", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "Asa de válvula negra", "block.create.blaze_burner": "Quemador de Blaze", + "block.create.blue_nixie_tube": "Tubo Nixie azul", "block.create.blue_sail": "Vela azul", "block.create.blue_seat": "Asiento azul", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "Asa de válvula azul", "block.create.brass_belt_funnel": "Embudo de cinta de latón", "block.create.brass_block": "Bloque de latón", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "Eje revestido de latón", "block.create.brass_funnel": "Embudo de latón", "block.create.brass_tunnel": "Túnel de latón", + "block.create.brown_nixie_tube": "Tubo Nixie marrón", "block.create.brown_sail": "Vela marrón", "block.create.brown_seat": "Asiento marrón", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "Asa de válvula marrón", "block.create.cart_assembler": "Ensamblador de vagonetas", "block.create.chiseled_dark_scoria": "Escoria oscura cincelada", @@ -53,28 +59,30 @@ "block.create.chiseled_weathered_limestone": "Piedra caliza erosionada cincelada", "block.create.chocolate": "Chocolate", "block.create.chute": "Ducto", - "block.create.clockwork_bearing": "Rodamiento de reloj", + "block.create.clockwork_bearing": "Rodamiento tipo reloj", "block.create.clutch": "Embrague", - "block.create.cogwheel": "Rueda dentada", + "block.create.cogwheel": "Engranaje pequeño", "block.create.content_observer": "Observador de contenidos", "block.create.controller_rail": "Raíl de control", - "block.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "block.create.copper_backtank": "Depósito trasero de cobre", "block.create.copper_block": "Bloque de cobre", "block.create.copper_casing": "Revestidor de caliza", - "block.create.copper_ore": "Mineral de cobre", + "block.create.copper_ore": "Mena de cobre", "block.create.copper_shingles": "Bloque de tejas de cobre", "block.create.copper_tiles": "Bloque de baldosas de cobre", "block.create.copper_valve_handle": "Asa de válvula de cobre", "block.create.creative_crate": "Caja creativa", "block.create.creative_fluid_tank": "Tanque de fluidos creativo", "block.create.creative_motor": "Motor creativo", - "block.create.crimson_window": "UNLOCALIZED: Crimson Window", - "block.create.crimson_window_pane": "UNLOCALIZED: Crimson Window Pane", + "block.create.crimson_window": "Ventana carmesí", + "block.create.crimson_window_pane": "Panel de ventana carmesí", "block.create.crushing_wheel": "Rueda trituradora", "block.create.crushing_wheel_controller": "Controlador de Rueda trituradora", - "block.create.cuckoo_clock": "Reloj Cucú", + "block.create.cuckoo_clock": "Reloj de cuco", + "block.create.cyan_nixie_tube": "Tubo Nixie cian", "block.create.cyan_sail": "Vela cian", "block.create.cyan_seat": "Asiento cian", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "Asa de válvula cian", "block.create.dark_oak_window": "Ventana de roble oscuro", "block.create.dark_oak_window_pane": "Panel de ventana de roble oscuro", @@ -82,32 +90,32 @@ "block.create.dark_scoria_bricks": "Ladrillos de escoria oscura", "block.create.dark_scoria_bricks_slab": "Losa de ladrillos de escoria oscura", "block.create.dark_scoria_bricks_stairs": "Escaleras de ladrillos de escoria oscura", - "block.create.dark_scoria_bricks_wall": "Pared de ladrillos de escoria oscura", + "block.create.dark_scoria_bricks_wall": "Muro de ladrillos de escoria oscura", "block.create.dark_scoria_cobblestone": "Adoquines de escoria oscura", "block.create.dark_scoria_cobblestone_slab": "Losa de adoquines de escoria oscura", "block.create.dark_scoria_cobblestone_stairs": "Escaleras de adoquines de escoria oscura", - "block.create.dark_scoria_cobblestone_wall": "Pared de adoquines de escoria oscura", + "block.create.dark_scoria_cobblestone_wall": "Muro de adoquines de escoria oscura", "block.create.dark_scoria_pillar": "Pilar de escoria oscura", "block.create.deployer": "Desplegador", "block.create.depot": "Depósito", "block.create.diorite_bricks": "Ladrillos de diorita", "block.create.diorite_bricks_slab": "Losa de ladrillos de diorita", "block.create.diorite_bricks_stairs": "Escaleras de ladrillos de diorita", - "block.create.diorite_bricks_wall": "Pared de ladrillos de diorita", + "block.create.diorite_bricks_wall": "Muro de ladrillos de diorita", "block.create.diorite_cobblestone": "Adoquín de diorita", "block.create.diorite_cobblestone_slab": "Losa de adoquínes de diorita", "block.create.diorite_cobblestone_stairs": "Escaleras de adoquines de diorita", - "block.create.diorite_cobblestone_wall": "Pared de adoquines de diorita", + "block.create.diorite_cobblestone_wall": "Muro de adoquines de diorita", "block.create.diorite_pillar": "Pilar de diorita", "block.create.dolomite": "Dolomita", "block.create.dolomite_bricks": "Ladrillos de dolomita", "block.create.dolomite_bricks_slab": "Losa de ladrillos de dolomita", "block.create.dolomite_bricks_stairs": "Escaleras de ladrillos de dolomita", - "block.create.dolomite_bricks_wall": "Pared de ladrillos de dolomita", + "block.create.dolomite_bricks_wall": "Muro de ladrillos de dolomita", "block.create.dolomite_cobblestone": "Adoquín de dolomita", "block.create.dolomite_cobblestone_slab": "Losa de adoquín de dolomita", "block.create.dolomite_cobblestone_stairs": "Escaleras de adoquines de dolomita", - "block.create.dolomite_cobblestone_wall": "Pared de adoquines de dolomita", + "block.create.dolomite_cobblestone_wall": "Muro de adoquines de dolomita", "block.create.dolomite_pillar": "Pilar de dolomita", "block.create.encased_chain_drive": "Cadena de transmisión revestida", "block.create.encased_fan": "Ventilador revestido", @@ -115,39 +123,39 @@ "block.create.fancy_andesite_bricks": "Ladrillos de andesita elegantes", "block.create.fancy_andesite_bricks_slab": "Ladrillos de andesita elegantes", "block.create.fancy_andesite_bricks_stairs": "Escaleras de ladrillos de andesita elegantes", - "block.create.fancy_andesite_bricks_wall": "Pared de ladrillos de andesita elegantes", + "block.create.fancy_andesite_bricks_wall": "Muro de ladrillos de andesita elegantes", "block.create.fancy_dark_scoria_bricks": "Ladrillos de escoria oscura elegantes", "block.create.fancy_dark_scoria_bricks_slab": "Losa de ladrillos de escoria oscura elegantes", "block.create.fancy_dark_scoria_bricks_stairs": "Escalera de ladrillos de escoria oscura elegantes", - "block.create.fancy_dark_scoria_bricks_wall": "Pared de ladrillos de escoria oscura elegantes", + "block.create.fancy_dark_scoria_bricks_wall": "Muro de ladrillos de escoria oscura elegantes", "block.create.fancy_diorite_bricks": "Ladrillos de diorita elegantes", "block.create.fancy_diorite_bricks_slab": "Losa de ladrillos de diorita elegantes", "block.create.fancy_diorite_bricks_stairs": "Escaleras de ladrillos de diorita elegantes", - "block.create.fancy_diorite_bricks_wall": "Pared de ladrillos de diorita elegantes", + "block.create.fancy_diorite_bricks_wall": "Muro de ladrillos de diorita elegantes", "block.create.fancy_dolomite_bricks": "Ladrillos de dolomita elegantes", "block.create.fancy_dolomite_bricks_slab": "Losa de ladrillos de dolomita elegantes", "block.create.fancy_dolomite_bricks_stairs": "Escaleras de ladrillos de dolomita elegantes", - "block.create.fancy_dolomite_bricks_wall": "Pared de ladrillos de dolomita elegantes", + "block.create.fancy_dolomite_bricks_wall": "Muro de ladrillos de dolomita elegantes", "block.create.fancy_gabbro_bricks": "Ladrillos de gabro elegantes", "block.create.fancy_gabbro_bricks_slab": "Losa de ladrillos de gabro elegantes", "block.create.fancy_gabbro_bricks_stairs": "Escaleras de ladrillos de gabro elegantes", - "block.create.fancy_gabbro_bricks_wall": "Pared de ladrillos de gabro elegantes", + "block.create.fancy_gabbro_bricks_wall": "Muro de ladrillos de gabro elegantes", "block.create.fancy_granite_bricks": "Ladrillos de granito elegantes", "block.create.fancy_granite_bricks_slab": "Losa de ladrillos de granito elegantes", "block.create.fancy_granite_bricks_stairs": "Escaleras de ladrillos de granito elegantes", - "block.create.fancy_granite_bricks_wall": "Pared de ladrillos de granito elegantes", + "block.create.fancy_granite_bricks_wall": "Muro de ladrillos de granito elegantes", "block.create.fancy_limestone_bricks": "Ladrillos de piedra caliza elegantes", "block.create.fancy_limestone_bricks_slab": "Losa de ladrillos de piedra caliza elegantes", "block.create.fancy_limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza elegantes", - "block.create.fancy_limestone_bricks_wall": "Pared de ladrillos de piedra caliza elegantes", + "block.create.fancy_limestone_bricks_wall": "Muro de ladrillos de piedra caliza elegantes", "block.create.fancy_scoria_bricks": "Ladrillos de escoria elegantes", "block.create.fancy_scoria_bricks_slab": "Losa de ladrillos de escoria elegantes", "block.create.fancy_scoria_bricks_stairs": "Escaleras de ladrillos de escoria elegantes", - "block.create.fancy_scoria_bricks_wall": "Pared de ladrillos de escoria elegantes", + "block.create.fancy_scoria_bricks_wall": "Muro de ladrillos de escoria elegantes", "block.create.fancy_weathered_limestone_bricks": "Ladrillos de piedra de caliza erosionada elegantes", "block.create.fancy_weathered_limestone_bricks_slab": "Losa de ladrillos de caliza erosionada elegantes", "block.create.fancy_weathered_limestone_bricks_stairs": "Escaleras de ladrillos de caliza erosionada elegantes", - "block.create.fancy_weathered_limestone_bricks_wall": "Pared de ladrillos de caliza erosionada elegantes", + "block.create.fancy_weathered_limestone_bricks_wall": "Muro de ladrillos de caliza erosionada elegantes", "block.create.fluid_pipe": "Tubería de fluidos de cobre", "block.create.fluid_tank": "Depósito de fluidos", "block.create.fluid_valve": "Válvula de fluidos", @@ -159,13 +167,13 @@ "block.create.gabbro_bricks": "Ladrillos de gabro", "block.create.gabbro_bricks_slab": "Losa de ladrillos de gabro", "block.create.gabbro_bricks_stairs": "Escaleras de ladrillos de gabro", - "block.create.gabbro_bricks_wall": "Pared de ladrillos de gabro", + "block.create.gabbro_bricks_wall": "Muro de ladrillos de gabro", "block.create.gabbro_cobblestone": "Adoquín de gabro", "block.create.gabbro_cobblestone_slab": "Losa de adoquínes de gabro", "block.create.gabbro_cobblestone_stairs": "Escaleras de adoquínes de gabro", - "block.create.gabbro_cobblestone_wall": "Pared de adoquínes de gabro", + "block.create.gabbro_cobblestone_wall": "Muro de adoquínes de gabro", "block.create.gabbro_pillar": "Pilar de gabro", - "block.create.gantry_carriage": "UNLOCALIZED: Gantry Carriage", + "block.create.gantry_carriage": "Carro de grúa", "block.create.gantry_shaft": "Eje de grúa", "block.create.gearbox": "Caja de transmisión", "block.create.gearshift": "Caja de cambios", @@ -173,27 +181,32 @@ "block.create.granite_bricks": "Ladrillos de granito", "block.create.granite_bricks_slab": "Losa de ladrillos de granito", "block.create.granite_bricks_stairs": "Escaleras de ladrillos de granito", - "block.create.granite_bricks_wall": "Pared de ladrillos de granito", + "block.create.granite_bricks_wall": "Muro de ladrillos de granito", "block.create.granite_cobblestone": "Adoquín de granito", "block.create.granite_cobblestone_slab": "Losa de adoquínes de granito", "block.create.granite_cobblestone_stairs": "Escaleras de adoquínes de granito", - "block.create.granite_cobblestone_wall": "Pared de adoquínes de granito", + "block.create.granite_cobblestone_wall": "Muro de adoquínes de granito", "block.create.granite_pillar": "Pilar de granito", + "block.create.gray_nixie_tube": "Tubo Nixie gris", "block.create.gray_sail": "Vela gris", "block.create.gray_seat": "Asiento gris", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "Asa de válvula gris", + "block.create.green_nixie_tube": "Tubo Nixie verde", "block.create.green_sail": "Vela verde", "block.create.green_seat": "Asiento verde", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "Asa de válvula verde", "block.create.hand_crank": "Manivela", + "block.create.haunted_bell": "Campana encantada", "block.create.honey": "Miel", "block.create.horizontal_framed_glass": "Cristal con marco horizontal", "block.create.horizontal_framed_glass_pane": "Panel de cristal con marco horizontal", "block.create.hose_pulley": "Polea de manguera", - "block.create.item_drain": "Drenador de elementos", + "block.create.item_drain": "Drenador de objetos", "block.create.jungle_window": "Ventana de jungla", "block.create.jungle_window_pane": "Panel de ventana de jungla", - "block.create.large_cogwheel": "Rueda dentada grande", + "block.create.large_cogwheel": "Engranaje grande", "block.create.layered_andesite": "Andesita estratificada", "block.create.layered_dark_scoria": "Escoria oscura estratificada", "block.create.layered_diorite": "Diorita estratificada", @@ -203,34 +216,43 @@ "block.create.layered_limestone": "Piedra caliza estratificada", "block.create.layered_scoria": "Escoria estratificada", "block.create.layered_weathered_limestone": "Caliza erosionada estratificada", + "block.create.lectern_controller": "Controlador de atril", + "block.create.light_blue_nixie_tube": "Tubo Nixie azul claro", "block.create.light_blue_sail": "Vela azul claro", "block.create.light_blue_seat": "Asiento azul claro", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "Asa de válvula azul claro", + "block.create.light_gray_nixie_tube": "Tubo Nixie gris claro", "block.create.light_gray_sail": "Vela gris claro", "block.create.light_gray_seat": "Asiento gris claro", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "Asa de válvula gris claro", + "block.create.lime_nixie_tube": "Tubo Nixie lima", "block.create.lime_sail": "Vela lima", "block.create.lime_seat": "Asiento lima", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "Asa de válvula lima", "block.create.limesand": "Arena caliza", "block.create.limestone": "Piedra caliza", "block.create.limestone_bricks": "Ladrillos de piedra caliza", "block.create.limestone_bricks_slab": "Losa de ladrillos de piedra caliza", "block.create.limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza", - "block.create.limestone_bricks_wall": "Pared de ladrillos de piedra caliza", + "block.create.limestone_bricks_wall": "Muro de ladrillos de piedra caliza", "block.create.limestone_cobblestone": "Adoquínes de piedra caliza", "block.create.limestone_cobblestone_slab": "Losa de adoquines de piedra caliza", "block.create.limestone_cobblestone_stairs": "Escaleras de adoquines de piedra caliza", - "block.create.limestone_cobblestone_wall": "Pared de adoquines de piedra caliza", + "block.create.limestone_cobblestone_wall": "Muro de adoquines de piedra caliza", "block.create.limestone_pillar": "Pilar de piedra caliza", "block.create.linear_chassis": "Chasis lineal", "block.create.lit_blaze_burner": "Quemador de Blaze encendido", + "block.create.magenta_nixie_tube": "Tubo Nixie magenta", "block.create.magenta_sail": "Vela magenta", "block.create.magenta_seat": "Asiento magenta", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "Asa de válvula magenta", "block.create.mechanical_arm": "Brazo mecánico", "block.create.mechanical_bearing": "Rodamiento mecánico", - "block.create.mechanical_crafter": "Autoensamblador mecánico", + "block.create.mechanical_crafter": "Ensamblador mecánico", "block.create.mechanical_drill": "Taladro mecánico", "block.create.mechanical_harvester": "Cosechadora mecánica", "block.create.mechanical_mixer": "Mezcladora mecánica", @@ -252,7 +274,7 @@ "block.create.mossy_limestone": "Caliza musgosa", "block.create.mossy_scoria": "Escoria musgosa", "block.create.mossy_weathered_limestone": "Caliza erosionada musgosa", - "block.create.mysterious_cuckoo_clock": "Reloj cucú", + "block.create.mysterious_cuckoo_clock": "Reloj de cuco", "block.create.natural_scoria": "Escoria natural", "block.create.nixie_tube": "Tubo Nixie", "block.create.nozzle": "Boquilla", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "Panel de ventana de roble", "block.create.orange_sail": "Vela naranja", "block.create.orange_seat": "Asiento naranja", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "Asa de válvula naranja", "block.create.ornate_iron_window": "Ventana de hierro ornamentada", "block.create.ornate_iron_window_pane": "Panel de ventana de hierro ornamentada", @@ -275,102 +298,109 @@ "block.create.paved_andesite": "Andesita pavimentada", "block.create.paved_andesite_slab": "Losa de andesita pavimentada", "block.create.paved_andesite_stairs": "Escaleras de andesita pavimentada", - "block.create.paved_andesite_wall": "Pared de andesita pavimentada", + "block.create.paved_andesite_wall": "Muro de andesita pavimentada", "block.create.paved_dark_scoria": "Escoria oscura pavimentada", "block.create.paved_dark_scoria_slab": "Losa de escoria oscura pavimentada", "block.create.paved_dark_scoria_stairs": "Escaleras de escoria oscura pavimentada", - "block.create.paved_dark_scoria_wall": "Pared de escoria oscura pavimentad", + "block.create.paved_dark_scoria_wall": "Muro de escoria oscura pavimentad", "block.create.paved_diorite": "Diorita pavimentada", "block.create.paved_diorite_slab": "Losa de diorita pavimentada", "block.create.paved_diorite_stairs": "Escaleras de diorita pavimentada", - "block.create.paved_diorite_wall": "Pared de diorita pavimentad", + "block.create.paved_diorite_wall": "Muro de diorita pavimentad", "block.create.paved_dolomite": "Dolomita pavimentada", "block.create.paved_dolomite_slab": "Losa de dolomita pavimentada", "block.create.paved_dolomite_stairs": "Escaleras de dolomita pavimentada", - "block.create.paved_dolomite_wall": "Pared de dolomita pavimentada", + "block.create.paved_dolomite_wall": "Muro de dolomita pavimentada", "block.create.paved_gabbro": "Gabro pavimentado", "block.create.paved_gabbro_slab": "Losa de gabro pavimentado", "block.create.paved_gabbro_stairs": "Escaleras de gabro pavimentado", - "block.create.paved_gabbro_wall": "Pared de gabro pavimentado", + "block.create.paved_gabbro_wall": "Muro de gabro pavimentado", "block.create.paved_granite": "Granito pavimentado", "block.create.paved_granite_slab": "Losa de granito pavimentado", "block.create.paved_granite_stairs": "Escaleras de granito pavimentado", - "block.create.paved_granite_wall": "Pared de granito pavimentado", + "block.create.paved_granite_wall": "Muro de granito pavimentado", "block.create.paved_limestone": "Piedra caliza pavimentada", "block.create.paved_limestone_slab": "Losa de piedra caliza pavimentada", "block.create.paved_limestone_stairs": "Escaleras de piedra caliza pavimentada", - "block.create.paved_limestone_wall": "Pared de piedra caliza pavimentada", + "block.create.paved_limestone_wall": "Muro de piedra caliza pavimentada", "block.create.paved_scoria": "Escoria pavimentada", "block.create.paved_scoria_slab": "Losa de escoria pavimentada", "block.create.paved_scoria_stairs": "Escaleras de escoria pavimentada", - "block.create.paved_scoria_wall": "Pared de escoria pavimentada", + "block.create.paved_scoria_wall": "Muro de escoria pavimentada", "block.create.paved_weathered_limestone": "Piedra caliza erosionada pavimentada", "block.create.paved_weathered_limestone_slab": "Losa de piedra caliza erosionada pavimentada", "block.create.paved_weathered_limestone_stairs": "Escaleras de piedra caliza erosionada pavimentada", - "block.create.paved_weathered_limestone_wall": "Pared de piedra caliza erosionada pavimentada", + "block.create.paved_weathered_limestone_wall": "Muro de piedra caliza erosionada pavimentada", + "block.create.peculiar_bell": "Campana peculiar", + "block.create.pink_nixie_tube": "Tubo Nixie rosa", "block.create.pink_sail": "Vela rosa", "block.create.pink_seat": "Asiento rosa", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "Asa de válvula rosa", "block.create.piston_extension_pole": "Pértiga de extensión de pistón", "block.create.polished_dark_scoria": "Escoria oscura pulida", "block.create.polished_dark_scoria_slab": "Losa de escoria oscura pulida", "block.create.polished_dark_scoria_stairs": "Escaleras de escoria oscura pulida", - "block.create.polished_dark_scoria_wall": "Pared de escoria oscura pulida", + "block.create.polished_dark_scoria_wall": "Muro de escoria oscura pulida", "block.create.polished_dolomite": "Dolomita pulida", "block.create.polished_dolomite_slab": "Losa de dolomita pulida", "block.create.polished_dolomite_stairs": "Escaleras de dolomita pulidas", - "block.create.polished_dolomite_wall": "Pared de dolomita pulida", + "block.create.polished_dolomite_wall": "Muro de dolomita pulida", "block.create.polished_gabbro": "Gabro pulido", "block.create.polished_gabbro_slab": "Losa de gabro pulido", "block.create.polished_gabbro_stairs": "Escaleras de gabro pulido", - "block.create.polished_gabbro_wall": "Pared de gabro pulido", + "block.create.polished_gabbro_wall": "Muro de gabro pulido", "block.create.polished_limestone": "Piedra caliza pulida", "block.create.polished_limestone_slab": "Losa de piedra caliza pulida", "block.create.polished_limestone_stairs": "Escaleras de piedra caliza pulidas", - "block.create.polished_limestone_wall": "Pared de piedra caliza pulida", + "block.create.polished_limestone_wall": "Muro de piedra caliza pulida", "block.create.polished_scoria": "Escoria pulida", "block.create.polished_scoria_slab": "Losa de escoria pulida", "block.create.polished_scoria_stairs": "Escaleras de losa pulida", - "block.create.polished_scoria_wall": "Pared de escoria pulida", + "block.create.polished_scoria_wall": "Muro de escoria pulida", "block.create.polished_weathered_limestone": "Piedra caliza erosionada pulida", "block.create.polished_weathered_limestone_slab": "Losa de piedra caliza erosionada pulida", "block.create.polished_weathered_limestone_stairs": "Escaleras de piedra caliza erosionada pulida", - "block.create.polished_weathered_limestone_wall": "Pared de piedra caliza erosionada pulida", + "block.create.polished_weathered_limestone_wall": "Muro de piedra caliza erosionada pulida", "block.create.portable_fluid_interface": "Interfaz de fluidos portátil", "block.create.portable_storage_interface": "Interfaz de almacenamiento portátil", "block.create.powered_latch": "Palanca motorizada", "block.create.powered_toggle_latch": "Palanca de cierre motorizada", "block.create.pulley_magnet": "Imán de la polea", - "block.create.pulse_repeater": "Repetidor de pulsos de Redstone", + "block.create.pulse_repeater": "Repetidor de pulsos de redstone", + "block.create.purple_nixie_tube": "Tubo Nixie morado", "block.create.purple_sail": "Vela morada", "block.create.purple_seat": "Asiento morado", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "Asa de válvula morada", "block.create.radial_chassis": "Chasis radial", + "block.create.red_nixie_tube": "Tubo Nixie rojo", "block.create.red_sail": "Vela roja", "block.create.red_seat": "Asiento rojo", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "Asa de válvula roja", - "block.create.redstone_contact": "Contacto de Redstone", - "block.create.redstone_link": "Enlace de Redstone", - "block.create.refined_radiance_casing": "Revestidor de radiante", + "block.create.redstone_contact": "Contacto de redstone", + "block.create.redstone_link": "Enlace de redstone", + "block.create.refined_radiance_casing": "Revestidor radiante", "block.create.reinforced_rail": "Raíl reforzado", "block.create.rope": "Cuerda", "block.create.rope_pulley": "Polea de cuerda", - "block.create.rotation_speed_controller": "Controlador de velocidad de rotación", + "block.create.rotation_speed_controller": "Controlador de velocidad rotacional", "block.create.sail_frame": "Marco de vela", "block.create.schematic_table": "Tabla de esquemas", - "block.create.schematicannon": "Schematicannon", + "block.create.schematicannon": "Cañón de esquemas", "block.create.scoria": "Escoria", "block.create.scoria_bricks": "Ladrillos de escoria", "block.create.scoria_bricks_slab": "Losa de ladrillos de escoria", "block.create.scoria_bricks_stairs": "Escaleras de ladrillos de escoria", - "block.create.scoria_bricks_wall": "Pared de ladrillos de escoria", + "block.create.scoria_bricks_wall": "Muro de ladrillos de escoria", "block.create.scoria_cobblestone": "Adoquín de escoria", "block.create.scoria_cobblestone_slab": "Losa de adoquínes de escoria", "block.create.scoria_cobblestone_stairs": "Escaleras de adoquines de escoria", - "block.create.scoria_cobblestone_wall": "Pared de adoquines de escoria", + "block.create.scoria_cobblestone_wall": "Muro de adoquines de escoria", "block.create.scoria_pillar": "Pilar de escoria", "block.create.secondary_linear_chassis": "Chasis lineal secundario", - "block.create.sequenced_gearshift": "Palanca de cambios secuencial", + "block.create.sequenced_gearshift": "Caja de cambios secuencial", "block.create.shadow_steel_casing": "Revestidor sombrío", "block.create.shaft": "Eje", "block.create.smart_chute": "Ducto inteligente", @@ -379,7 +409,7 @@ "block.create.spout": "Surtidor", "block.create.spruce_window": "Ventana de abeto", "block.create.spruce_window_pane": "Panel de ventana de abeto", - "block.create.sticker": "UNLOCALIZED: Sticker", + "block.create.sticker": "Sticker", "block.create.sticky_mechanical_piston": "Pistón mecánico pegajoso", "block.create.stockpile_switch": "Interruptor de acopio", "block.create.stressometer": "Estresómetro", @@ -388,62 +418,72 @@ "block.create.turntable": "Plataforma giratoria mecánica", "block.create.vertical_framed_glass": "Vidrio esmaltado vertical", "block.create.vertical_framed_glass_pane": "Panel de vidrio esmaltado vertical", - "block.create.warped_window": "UNLOCALIZED: Warped Window", - "block.create.warped_window_pane": "UNLOCALIZED: Warped Window Pane", + "block.create.warped_window": "Ventana distorsionada", + "block.create.warped_window_pane": "Panel de ventana distorsionada", "block.create.water_wheel": "Rueda hidráulica mecánica", "block.create.weathered_limestone": "Piedra caliza erosionada", "block.create.weathered_limestone_bricks": "Ladrillos de piedra caliza erosionada", "block.create.weathered_limestone_bricks_slab": "Losa de piedra caliza erosionada", "block.create.weathered_limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza erosionada", - "block.create.weathered_limestone_bricks_wall": "Pared de ladrillos de piedra caliza erosionada", + "block.create.weathered_limestone_bricks_wall": "Muro de ladrillos de piedra caliza erosionada", "block.create.weathered_limestone_cobblestone": "Adoquín de piedra caliza erosionada", "block.create.weathered_limestone_cobblestone_slab": "Losa de adoquín de piedra caliza erosionada", "block.create.weathered_limestone_cobblestone_stairs": "Escaleras de adoquín de piedra caliza erosionada", - "block.create.weathered_limestone_cobblestone_wall": "Pared de adoquínes de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone_wall": "Muro de adoquínes de piedra caliza erosionada", "block.create.weathered_limestone_pillar": "Pilar de piedra caliza erosionada", - "block.create.weighted_ejector": "UNLOCALIZED: Weighted Ejector", + "block.create.weighted_ejector": "Eyector de peso", + "block.create.white_nixie_tube": "Tubo Nixie blanco", "block.create.white_sail": "Vela blanca", "block.create.white_seat": "Asiento blanco", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "Asa de válvula blanco", "block.create.windmill_bearing": "Rodamiento del molino de viento", "block.create.wooden_bracket": "Soporte de madera para ejes", + "block.create.yellow_nixie_tube": "Tubo Nixie amarillo", "block.create.yellow_sail": "Vela amarilla", "block.create.yellow_seat": "Asiento amarillo", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "Asa de válvula amarillo", "block.create.zinc_block": "Bloque de zinc", - "block.create.zinc_ore": "Mineral de zinc", + "block.create.zinc_ore": "Mena de zinc", + + "enchantment.create.capacity": "Capacidad", + "enchantment.create.potato_recovery": "Recuperación de patatas", "entity.create.contraption": "Artilugio", + "entity.create.crafting_blueprint": "Plano de elaboración", "entity.create.gantry_contraption": "Artilugio de grúa", + "entity.create.potato_projectile": "Proyectil de patata", "entity.create.seat": "Asiento", "entity.create.stationary_contraption": "Artilugio estacionario", - "entity.create.super_glue": "Super Pegamento", + "entity.create.super_glue": "Pegamento", - "fluid.create.milk": "Leche", "fluid.create.potion": "Poción", "fluid.create.tea": "Té del Constructor", "item.create.andesite_alloy": "Aleación de andesita", "item.create.attribute_filter": "Filtro de atributos", "item.create.bar_of_chocolate": "Barra de chocolate", - "item.create.belt_connector": "Correa", - "item.create.blaze_cake": "Pastel de Blaze", - "item.create.blaze_cake_base": "Base de Pastel de Blaze", + "item.create.belt_connector": "Correa mecánica", + "item.create.blaze_cake": "Pastel de blaze", + "item.create.blaze_cake_base": "Base de pastel de blaze", "item.create.brass_hand": "Mano de latón", "item.create.brass_ingot": "Lingote de latón", "item.create.brass_nugget": "Pepita de latón", "item.create.brass_sheet": "Lámina de latón", "item.create.builders_tea": "Té del Constructor", "item.create.chest_minecart_contraption": "Artilugio de vagoneta con cofre", - "item.create.chocolate_bucket": "Cubo de chocolate", - "item.create.chocolate_glazed_berries": "UNLOCALIZED: Chocolate Glazed Berries", + "item.create.chocolate_bucket": "Cubo con chocolate", + "item.create.chocolate_glazed_berries": "Bayas glaseadas con chocolate", "item.create.chromatic_compound": "Compuesto cromático", - "item.create.cinder_flour": "Harina de ceniza", - "item.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "item.create.cinder_flour": "Harina del Nether", + "item.create.copper_backtank": "Depósito trasero de cobre", "item.create.copper_ingot": "Lingote de cobre", "item.create.copper_nugget": "Pepita de cobre", "item.create.copper_sheet": "Lámina de cobre", - "item.create.crafter_slot_cover": "Tapa de ranura del Autoensamblador mecánico", + "item.create.crafter_slot_cover": "Tapa de ranura del ensamblador mecánico", + "item.create.crafting_blueprint": "Plano de elaboración", + "item.create.creative_blaze_cake": "´Pastel de blaze creativo", "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", @@ -458,38 +498,42 @@ "item.create.crushed_tin_ore": "Mineral de estaño molido", "item.create.crushed_uranium_ore": "Mineral de uranio molido", "item.create.crushed_zinc_ore": "Mineral de zinc molido", - "item.create.diving_boots": "UNLOCALIZED: Diving Boots", - "item.create.diving_helmet": "UNLOCALIZED: Diving Helmet", + "item.create.diving_boots": "Botas de buceo", + "item.create.diving_helmet": "Casco de buceo", "item.create.dough": "Masilla", "item.create.electron_tube": "Tubo de electrones", - "item.create.empty_blaze_burner": "Quemador de Blaze vacío", + "item.create.empty_blaze_burner": "Quemador de blaze vacío", "item.create.empty_schematic": "Esquema vacío", "item.create.extendo_grip": "Agarre extendido", "item.create.filter": "Filtro", "item.create.furnace_minecart_contraption": "Artilugio de vagoneta de horno", - "item.create.goggles": "Gafas del Ingeniero", + "item.create.goggles": "Gafas del constructor", "item.create.golden_sheet": "Lámina de oro", - "item.create.handheld_worldshaper": "Worldshaper", - "item.create.honey_bucket": "Cubo de miel", - "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", - "item.create.integrated_circuit": "Chip de circuito integrado", + "item.create.handheld_worldshaper": "Worldshaper Creativo", + "item.create.honey_bucket": "Cubo con miel", + "item.create.honeyed_apple": "Manzana con miel", + "item.create.incomplete_cogwheel": "Engranaje pequeño incompleto", + "item.create.incomplete_large_cogwheel": "Engranaje grande incompleto", + "item.create.incomplete_precision_mechanism": "Mecanismo de precisión incompleto", "item.create.iron_sheet": "Lámina de hierro", - "item.create.lapis_sheet": "Lámina de lapislázuli", + "item.create.linked_controller": "Controlador enlazado", "item.create.minecart_contraption": "Artilugio de vagoneta", "item.create.minecart_coupling": "Acoplamiento de vagoneta", "item.create.polished_rose_quartz": "Cuarzo rosado pulido", - "item.create.powdered_obsidian": "Obsidiana en polvo", + "item.create.potato_cannon": "Cañón de patatas", + "item.create.powdered_obsidian": "Polvo de obsidiana", + "item.create.precision_mechanism": "Mecanismo de precisión", "item.create.propeller": "Hélice", "item.create.red_sand_paper": "Papel de lija rojo", "item.create.refined_radiance": "Resplandor refinado", "item.create.rose_quartz": "Cuarzo rosado", "item.create.sand_paper": "Papel de lija", "item.create.schematic": "Esquema", - "item.create.schematic_and_quill": "Esquema y Pluma", + "item.create.schematic_and_quill": "Esquema y pluma", "item.create.shadow_steel": "Acero sombrío", - "item.create.super_glue": "Super Pegamento", - "item.create.sweet_roll": "UNLOCALIZED: Sweet Roll", - "item.create.tree_fertilizer": "Fertilizador de árboles", + "item.create.super_glue": "Pegamento", + "item.create.sweet_roll": "Pan dulce", + "item.create.tree_fertilizer": "Fertilizante para árboles", "item.create.vertical_gearbox": "Caja de transmisión vertical", "item.create.wand_of_symmetry": "Varita de simetría", "item.create.wheat_flour": "Harina de trigo", @@ -502,25 +546,25 @@ "_": "->------------------------] Advancements [------------------------<-", "advancement.create.root": "Bienvenido a Create", - "advancement.create.root.desc": "¡Es hora de empezar a construir increíbles Artilugios!", - "advancement.create.andesite_alloy": "Aliteraciones en abundancia", + "advancement.create.root.desc": "¡Es hora de empezar a construir increíbles artilugios!", + "advancement.create.andesite_alloy": "Aleaciones en abundancia", "advancement.create.andesite_alloy.desc": "Los materiales de Create tienen nombres extraños, la aleación de andesita es uno de ellos.", - "advancement.create.its_alive": "Está Vivo!", - "advancement.create.its_alive.desc": "Vea cómo gira su primer componente cinético.", + "advancement.create.its_alive": "¡Está vivo!", + "advancement.create.its_alive.desc": "Mira cómo gira tu primer componente cinético.", "advancement.create.shifting_gears": "Cambiando de marcha", - "advancement.create.shifting_gears.desc": "Conecta una rueda dentada grande a una pequeña, lo que te permitirá cambiar la velocidad de tu artilugio.", + "advancement.create.shifting_gears.desc": "Conecta un engranaje grande a uno pequeño, lo que te permitirá cambiar la velocidad de tu artilugio.", "advancement.create.overstressed": "Sobrecargado", "advancement.create.overstressed.desc": "Experimenta los límites del estrés.", "advancement.create.belt": "Paseo de algas", "advancement.create.belt.desc": "Conectar dos ejes con una correa.", - "advancement.create.tunnel": "Cúbrete!", - "advancement.create.tunnel.desc": "Embellece tu correa con un Túnel.", + "advancement.create.tunnel": "¡Cúbrete!", + "advancement.create.tunnel.desc": "Embellece tu correa con un túnel.", "advancement.create.splitter_tunnel": "Divide y vencerás", "advancement.create.splitter_tunnel.desc": "Crear un divisor con un grupo de túneles de latón.", "advancement.create.chute": "Caída en picado", "advancement.create.chute.desc": "Coloque un ducto, la contrapartida vertical de la cinta.", "advancement.create.upward_chute": "Abducción aérea", - "advancement.create.upward_chute.desc": "Observe cómo un objeto lanzado vuela hacia un paracaídas impulsado por un ventilador.", + "advancement.create.upward_chute.desc": "Observe cómo un objeto lanzado vuela dentro de un ducto impulsado por un ventilador.", "advancement.create.belt_funnel": "Colgantes con forma de embudo", "advancement.create.belt_funnel.desc": "Coloca un embudo lateral encima de una cinta o depósito para crear un tipo especial.", "advancement.create.belt_funnel_kiss": "Los loros y las aletas", @@ -528,81 +572,81 @@ "advancement.create.fan": "Maestro mecánico del aire", "advancement.create.fan.desc": "Monta la corriente de aire proporcionada por un ventilador revestido.", "advancement.create.fan_lava": "Calentador geotérmico", - "advancement.create.fan_lava.desc": "Quedar atrapado en una corriente de aire que funde las cosas.", + "advancement.create.fan_lava.desc": "Queda atrapado en una corriente de aire que funde las cosas.", "advancement.create.fan_water": "Lavado de la ropa", - "advancement.create.fan_water.desc": "Quedar atrapado en una corriente de aire que lava las cosas.", + "advancement.create.fan_water.desc": "Queda atrapado en una corriente de aire que lava las cosas.", "advancement.create.fan_smoke": "Fuelle mecánico", - "advancement.create.fan_smoke.desc": "Quedar atrapado en una corriente de aire que humea los artículos.", + "advancement.create.fan_smoke.desc": "Queda atrapado en una corriente de aire que humea los objetos.", "advancement.create.wrench": "Configurar convenientemente", "advancement.create.wrench.desc": "Crea una llave inglesa para ayudarte a construir tus artilugios.", - "advancement.create.goggles": "Stress-O-Vision", - "advancement.create.goggles.desc": "Crea unas Gafas del Ingeniero para ayudarte a obtener más información cinética de los componentes.", - "advancement.create.speedometer": "Pero, ¿con qué rapidez exactamente??", - "advancement.create.speedometer.desc": "Coloca y alimenta un Velocímetro. Míralo a través de las gafas para leer su valor exacto.", + "advancement.create.goggles": "Estresóvisión", + "advancement.create.goggles.desc": "Crea unas gafas del constructor para ayudarte a obtener más información cinética de los componentes.", + "advancement.create.speedometer": "Pero, ¿con qué rapidez exactamente?", + "advancement.create.speedometer.desc": "Coloca y alimenta un velocímetro. Míralo a través de las gafas para leer su valor exacto.", "advancement.create.stressometer": "Pero, ¿cuán estresado exactamente??", - "advancement.create.stressometer.desc": "Coloca y alimenta un Estresómetro. Míralo a través de las gafas para leer su valor exacto.", - "advancement.create.aesthetics": "Boom, Estética!", - "advancement.create.aesthetics.desc": "Colocar los soportes en un eje, tubo y rueda dentada.", - "advancement.create.reinforced": "Boom, Reforzado!", - "advancement.create.reinforced.desc": "Utilizar bloques de revestimiento en un eje, un tubo y una cinta.", + "advancement.create.stressometer.desc": "Coloca y alimenta un estresómetro. Míralo a través de las gafas para leer su valor exacto.", + "advancement.create.aesthetics": "Boom, ¡Estética!", + "advancement.create.aesthetics.desc": "Coloca soportes en ejes, ductos y engranajes.", + "advancement.create.reinforced": "Boom, ¡Reforzado!", + "advancement.create.reinforced.desc": "Utiliza bloques de revestimiento en un eje, un ducto y una cinta.", "advancement.create.water_wheel": "Aprovechar la hidráulica", - "advancement.create.water_wheel.desc": "Coloca una Rueda hidráulica e intenta hacerla girar.", + "advancement.create.water_wheel.desc": "Coloca una rueda hidráulica e intenta hacerla girar.", "advancement.create.chocolate_wheel": "Potencia de buen gusto", - "advancement.create.chocolate_wheel.desc": "Hacer funcionar una rueda de agua con chocolate fundido.", - "advancement.create.lava_wheel": "Rueda de Magma", + "advancement.create.chocolate_wheel.desc": "Haz funcionar una rueda de agua con chocolate fundido.", + "advancement.create.lava_wheel": "Rueda de magma", "advancement.create.lava_wheel.desc": "Esto no debió haber funcionado.", "advancement.create.cuckoo": "¿Es el momento?", - "advancement.create.cuckoo.desc": "Presenciar cómo un Reloj de cucú anuncia la hora de acostarse.", + "advancement.create.cuckoo.desc": "Presencia cómo un reloj de cuco anuncia la hora de acostarse.", "advancement.create.millstone": "Triturador de bolsillo", - "advancement.create.millstone.desc": "Colocar y alimentar una Piedra de molino.", + "advancement.create.millstone.desc": "Coloca y alimenta una piedra de molino.", "advancement.create.windmill": "Una suave brisa", - "advancement.create.windmill.desc": "Montar un molino de viento.", + "advancement.create.windmill.desc": "Monta un molino de viento.", "advancement.create.maxed_windmill": "Una fuerte brisa", - "advancement.create.maxed_windmill.desc": "Montar un molino de viento de máxima intensidad.", + "advancement.create.maxed_windmill.desc": "Monta un molino de viento con máxima intensidad.", "advancement.create.andesite_casing": "La edad de la andesita", "advancement.create.andesite_casing.desc": "Utiliza un poco de aleación de andesita y madera para crear un revestimiento básico.", "advancement.create.mechanical_drill": "Interruptores fijos", - "advancement.create.mechanical_drill.desc": "Colocar y alimentar un taladro mecánico.", + "advancement.create.mechanical_drill.desc": "Coloca y alimenta un taladro mecánico.", "advancement.create.press": "¡La prensa se pone en marcha!", "advancement.create.press.desc": "Activa una prensa mecánica y utilízala para crear algunas láminas.", "advancement.create.polished_rose_quartz": "Diamantes rosas", "advancement.create.polished_rose_quartz.desc": "Utiliza un trozo de papel de lija para pulir el cuarzo rosa hasta que se vuelva transparente.", "advancement.create.electron_tube": "Beep Boop", - "advancement.create.electron_tube.desc": "Haz algunos Tubos de Electrones, útiles en la fabricación de maquinaria menos primitiva.", + "advancement.create.electron_tube.desc": "Haz algunos tubos de electrones, útiles en la fabricación de maquinaria menos primitiva.", "advancement.create.mechanical_saw": "Picado estacionario", - "advancement.create.mechanical_saw.desc": "Colocar y alimentar una sierra mecánica.", + "advancement.create.mechanical_saw.desc": "Coloca y alimenta una sierra mecánica.", "advancement.create.basin": "Funcionamiento de la cuenca", - "advancement.create.basin.desc": "Coloca una Cuenca e intenta arrojar objetos en ella.", + "advancement.create.basin.desc": "Coloca una cuenca e intenta arrojar objetos en ella.", "advancement.create.mixer": "Mezcla de colores", - "advancement.create.mixer.desc": "Coloque una batidora mecánica sobre el lavabo, enciéndala y empiece a mezclar algunos ingredientes.", + "advancement.create.mixer.desc": "Coloca una batidora mecánica sobre el lavabo, enciéndala y empiece a mezclar algunos ingredientes.", "advancement.create.blaze_burner": "Una chimenea viva", - "advancement.create.blaze_burner.desc": "Obtener un Quemador de Blaze.", + "advancement.create.blaze_burner.desc": "Obtiene un quemador de blaze.", "advancement.create.compact": "Compactación automática", - "advancement.create.compact.desc": "Utiliza una prensa y una palangana para compactar algunos elementos.", + "advancement.create.compact.desc": "Utiliza una prensa y una cuenca para compactar algunos objetos.", "advancement.create.brass": "Aleaciones reales", - "advancement.create.brass.desc": "Utiliza Cobre molido y Zinc molido para crear algo de latón.", + "advancement.create.brass.desc": "Utiliza cobre molido y zinc molido para crear algo de latón.", "advancement.create.brass_casing": "La Edad de Latón", "advancement.create.brass_casing.desc": "Utiliza el latón recién obtenido y algo de madera para crear un revestimiento más avanzado.", "advancement.create.copper_casing": "La Edad de Cobre", "advancement.create.copper_casing.desc": "Utiliza algunas láminas de cobre y madera para crear algunos revestimientos de cobre.", "advancement.create.spout": "Sploosh", - "advancement.create.spout.desc": "Observar el llenado de un elemento fluido usando una boquilla.", + "advancement.create.spout.desc": "Observa el llenado de un fluido usando una boquilla.", "advancement.create.spout_potion": "Cervecera global", "advancement.create.spout_potion.desc": "Mira cómo un pico llena una botella con líquido de poción.", "advancement.create.chocolate": "Un mundo de imaginación", - "advancement.create.chocolate.desc": "Obtener un cubo de chocolate fundido.", + "advancement.create.chocolate.desc": "Obtiene un cubo con chocolate fundido.", "advancement.create.item_drain": "Drenaje de la ropa", - "advancement.create.item_drain.desc": "Ver cómo se vacía un elemento fluido mediante una drenadora de elementos.", - "advancement.create.chained_item_drain": "Déjalo rodar!", - "advancement.create.chained_item_drain.desc": "Observa cómo un objeto rueda por varios drenadores de elementos encadenados.", + "advancement.create.item_drain.desc": "Ve cómo se vacía un fluido mediante un drenador de objetos.", + "advancement.create.chained_item_drain": "¡Déjalo rodar!", + "advancement.create.chained_item_drain.desc": "Observa cómo un objeto rueda por varios drenadores de objetos encadenados.", "advancement.create.glass_pipe": "Espía del flujo", - "advancement.create.glass_pipe.desc": "Observe cómo se propaga el fluido a través de una tubería de fluidos con ventanas. Las tuberías de fluido rectas se convierten en ventanas cuando se utiliza una llave en ellas.", + "advancement.create.glass_pipe.desc": "Observa cómo se propaga el fluido a través de un tubo de fluidos con ventanas. Los tubos de fluido rectos se convierten en ventanas cuando se utiliza una llave inglesa en ellas.", "advancement.create.pipe_collision": "No cruzar nunca los arroyos", "advancement.create.pipe_collision.desc": "Vea cómo se unen dos fluidos en su red de tuberías.", "advancement.create.pipe_spill": "¡Hay una fuga!", "advancement.create.pipe_spill.desc": "Observe cómo un extremo abierto de una tubería toma o deposita fluidos en el mundo.", "advancement.create.hose_pulley": "Vertidos industriales", - "advancement.create.hose_pulley.desc": "Bajar una polea de manguera y ver cómo se vacía o se llena un cuerpo de líquido.", + "advancement.create.hose_pulley.desc": "Baja una polea de manguera y ve cómo se vacía o se llena un cuerpo de líquido.", "advancement.create.infinite_water": "Drenando el océano", "advancement.create.infinite_water.desc": "Bombea de una masa de agua lo suficientemente grande como para ser considerada infinita.", "advancement.create.infinite_lava": "Drenaje del núcleo de los planetas", @@ -610,49 +654,51 @@ "advancement.create.infinite_chocolate": "Ahogándose en la imaginación", "advancement.create.infinite_chocolate.desc": "Bombea desde una masa de chocolate fundido lo suficientemente grande como para ser considerado infinito.", "advancement.create.crafter": "Montaje automatizado", - "advancement.create.crafter.desc": "Coloca y alimenta algunos autoensambladores.", + "advancement.create.crafter.desc": "Coloca y alimenta algunos ensambladores.", "advancement.create.clockwork_bearing": "Artilugio a la hora", - "advancement.create.clockwork_bearing.desc": "Ensamblar una estructura montada sobre un rodamiento de relojería.", + "advancement.create.clockwork_bearing.desc": "Ensamblar una estructura montada sobre un rodamiento tipo reloj.", "advancement.create.nixie_tube": "Signos de estilo", - "advancement.create.nixie_tube.desc": "Obtener y colocar un par de Tubos Nixie.", + "advancement.create.nixie_tube.desc": "Obtener y colocar un par de tubos nixie.", "advancement.create.deployer": "Picar, colocar y atacar", - "advancement.create.deployer.desc": "Coloca y potencia un Desplegador, el reflejo perfecto de ti mismo.", + "advancement.create.deployer.desc": "Coloca y potencia un desplegador, el reflejo perfecto de ti mismo.", "advancement.create.speed_controller": "Los ingenieros lo odian!", - "advancement.create.speed_controller.desc": "Coloque un regulador de velocidad de rotación, el dispositivo definitivo para cambiar de marcha.", + "advancement.create.speed_controller.desc": "Coloca un controlador de velocidad rotacional, el dispositivo definitivo para cambiar de marcha.", "advancement.create.flywheel": "El corazón de la fábrica", - "advancement.create.flywheel.desc": "Conectar con éxito un motor a la rueda de inercia.", + "advancement.create.flywheel.desc": "Conecta con éxito un motor a la rueda de inercia.", "advancement.create.overstress_flywheel": "Altos niveles de estrés", - "advancement.create.overstress_flywheel.desc": "Sobrecargar un Motor de Horno.", - "advancement.create.integrated_circuit": "Cálculos complejos", - "advancement.create.integrated_circuit.desc": "Ensamblar un chip de circuito integrado.", - "advancement.create.mechanical_arm": "Manos ocupadas!", + "advancement.create.overstress_flywheel.desc": "Sobrecarga un motor de horno.", + "advancement.create.precision_mechanism": "Curiosidades complejas", + "advancement.create.precision_mechanism.desc": "Monta un mecanismo de precisión.", + "advancement.create.mechanical_arm": "¡Manos ocupadas!", "advancement.create.mechanical_arm.desc": "Crea un brazo mecánico, selecciona las entradas y salidas, colócalo en el suelo y dale energía; luego observa cómo hace todo el trabajo por ti.", - "advancement.create.musical_arm": "Tócame la melodía!", - "advancement.create.musical_arm.desc": "Vea cómo un brazo mecánico maneja su Jukebox.", + "advancement.create.musical_arm": "¡Tócame la melodía!", + "advancement.create.musical_arm.desc": "Vea cómo un brazo mecánico maneja su tocadiscos.", "advancement.create.arm_many_targets": "Organize-o-Tron", - "advancement.create.arm_many_targets.desc": "Programar un brazo mecánico con diez o más posiciones de salida.", + "advancement.create.arm_many_targets.desc": "Programa un brazo mecánico con diez o más posiciones de salida.", "advancement.create.arm_blaze_burner": "Combust-o-Tron", - "advancement.create.arm_blaze_burner.desc": "Instruya un brazo mecánico para alimentar su Quemador de Blaze.", + "advancement.create.arm_blaze_burner.desc": "Instruya un brazo mecánico para alimentar su quemador de blaze.", "advancement.create.fist_bump": "¡Pégale, hermano!", - "advancement.create.fist_bump.desc": "Hacer que dos Desplegadores se den un puñetazo.", + "advancement.create.fist_bump.desc": "Haz que dos desplegadores se den un puñetazo.", "advancement.create.crushing_wheel": "Un par de gigantes", - "advancement.create.crushing_wheel.desc": "Crea algunas Ruedas de trituración para descomponer más materiales de forma más eficaz.", + "advancement.create.crushing_wheel.desc": "Crea algunas ruedas de trituración para descomponer más materiales de forma más eficaz.", "advancement.create.blaze_cake": "Fiebre del azúcar", - "advancement.create.blaze_cake.desc": "Hornea en tu Quemador de Blaze un pastel especial.", - "advancement.create.chromatic_compound": "Minerales bipolares", - "advancement.create.chromatic_compound.desc": "Crea una Barra de Compuesto Cromático.", + "advancement.create.blaze_cake.desc": "Hornea en tu quemador de blaze un pastel especial.", + "advancement.create.chromatic_compound": "Minerales misteriosos", + "advancement.create.chromatic_compound.desc": "Crea una barra de compuesto cromático.", "advancement.create.shadow_steel": "Retorno del vacío", - "advancement.create.shadow_steel.desc": "Crea Acero Sombrío, una barra de metal de la nada.", + "advancement.create.shadow_steel.desc": "Crea acero sombrío, una barra de metal de la nada.", "advancement.create.refined_radiance": "Brillante e inspirador", - "advancement.create.refined_radiance.desc": "Crea un Resplandor refinado, una poderosa sustancia cromática.", + "advancement.create.refined_radiance.desc": "Crea un resplandor refinado, una poderosa sustancia cromática.", "advancement.create.chromatic_age": "La edad cromática", "advancement.create.chromatic_age.desc": "Crear bloques de revestimiento de la luz y la oscuridad.", "advancement.create.wand_of_symmetry": "Espejos radiantes", "advancement.create.wand_of_symmetry.desc": "Crear un bastón de simetría.", - "advancement.create.extendo_grip": "Boioioing!", - "advancement.create.extendo_grip.desc": "Hazte con un Agarre extentido.", + "advancement.create.extendo_grip": "¡Boioioing!", + "advancement.create.extendo_grip.desc": "Hazte con un agarre extentido.", + "advancement.create.potato_cannon": "Fwoomp!", + "advancement.create.potato_cannon.desc": "Derrota a un enemigo con tu cañón de patatas.", "advancement.create.dual_extendo_grip": "La última edad del boing", - "advancement.create.dual_extendo_grip.desc": "Doble Empuñadura extendida para un alcance sobrehumano.", + "advancement.create.dual_extendo_grip.desc": "Doble empuñadura extendida para un alcance sobrehumano.", "advancement.create.eob": "Fin de la beta", "advancement.create.eob.desc": "Espere más contenido aquí en el futuro. <3", @@ -662,16 +708,32 @@ "itemGroup.create.base": "Create", "itemGroup.create.palettes": "Paletas", - "death.attack.create.crush": "%1$s se procesó por las Ruedas de trituración", + "death.attack.create.crush": "%1$s se procesó en las ruedas de trituración", + "death.attack.create.crush.player": "%1$s fue arrojado a las ruedas de trituración por %2$s", "death.attack.create.fan_fire": "%1$s murió quemado por el aire caliente", + "death.attack.create.fan_fire.player": "%1$s fue arrojado a un ahumador por %2$s", "death.attack.create.fan_lava": "%1$s murió quemado por un abanico de lava", + "death.attack.create.fan_lava.player": "%1$s fue arrojado a una fundición por %2$s", "death.attack.create.mechanical_drill": "%1$s fue empalado por un taladro mecánico", + "death.attack.create.mechanical_drill.player": "%1$s fue lanzado frente a un taladro por %2$s", "death.attack.create.mechanical_saw": "%1$s fue cortado por la mitad por una sierra mecánica", - "death.attack.create.cuckoo_clock_explosion": "%1$s fue volado por los aires por un reloj cucú manipulado", + "death.attack.create.mechanical_saw.player": "%1$s fue arrojado a una sierra por %2$s", + "death.attack.create.potato_cannon": "%1$s fue disparado por el cañón de patatas de %2$s's", + "death.attack.create.potato_cannon.item": "%1$s fue disparado por %2$s utilizando %3$s", + "death.attack.create.cuckoo_clock_explosion": "%1$s fue volado por los aires por un reloj de cuco manipulado", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s fue volado por un reloj de cuco manipulado", - "create.block.deployer.damage_source_name": "un Desplegador rebelde", + "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": "Regresar al menú", + "create.menu.configure": "Configurar...", + "create.menu.ponder_index": "Índice", + "create.menu.only_ingame": "Disponible en el menú de pausa", + "create.menu.project_page": "Página del proyecto", + "create.menu.report_bugs": "Reportar problemas", + "create.menu.support": "Apóyenos", + "create.recipe.crushing": "Trituración", "create.recipe.milling": "Fresado", "create.recipe.fan_washing": "Lavado a granel", @@ -682,7 +744,7 @@ "create.recipe.fan_blasting.fan": "Ventilador detrás de la lava", "create.recipe.pressing": "Prensando", "create.recipe.mixing": "Mezclando", - "create.recipe.deploying": "UNLOCALIZED: Deploying", + "create.recipe.deploying": "Desplegando", "create.recipe.automatic_shapeless": "Elaboración automatizada de productos sin forma", "create.recipe.automatic_brewing": "Elaboración de cerveza automatizada", "create.recipe.packing": "Compactando", @@ -695,8 +757,19 @@ "create.recipe.sandpaper_polishing": "Pulido con papel de lija", "create.recipe.mystery_conversion": "Conversión misteriosa", "create.recipe.spout_filling": "Llenar por el pico", - "create.recipe.draining": "Drenador de elementos", + "create.recipe.draining": "Drenador de objetos", + "create.recipe.sequenced_assembly": "Montaje secuenciado", + "create.recipe.assembly.next": "Siguiente: %1$s", + "create.recipe.assembly.step": "Fase %1$s:", + "create.recipe.assembly.progress": "Progreso: %1$s/%2$s", + "create.recipe.assembly.pressing": "Proceso en prensa", + "create.recipe.assembly.spout_filling_fluid": "Pico %1$s", + "create.recipe.assembly.deploying_item": "Despliegue %1$s", + "create.recipe.assembly.cutting": "Corte con sierra", + "create.recipe.assembly.repeat": "Repetir la secuencia %1$s veces", + "create.recipe.assembly.junk": "Basura aleatoria", "create.recipe.processing.chance": "%1$s%% Chance", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "No es necesario calentar", "create.recipe.heat_requirement.heated": "Calentado", "create.recipe.heat_requirement.superheated": "Súper-Calentado", @@ -712,7 +785,7 @@ "create.generic.unit.seconds": "Segundos", "create.generic.unit.minutes": "Minutos", "create.generic.unit.rpm": "RPM", - "create.generic.unit.stress": "su", + "create.generic.unit.stress": "SU(unidades de estrés)", "create.generic.unit.degrees": "°", "create.generic.unit.millibuckets": "%1$smB", "create.generic.clockwise": "En el sentido de las agujas del reloj", @@ -725,16 +798,24 @@ "create.action.discard": "Descartar", "create.keyinfo.toolmenu": "Menú de la Herramienta de Enfoque", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "Simular usar la rueda del ratón hacia arriba (en el mundo)", "create.keyinfo.scrolldown": "Simular usar la rueda del ratón hacia abajo (en el mundo)", "create.gui.scrollInput.defaultTitle": "Seleccione una opción:", - "create.gui.scrollInput.scrollToModify": "Usa la rueda del ratón para Modificar", + "create.gui.scrollInput.scrollToModify": "Usa la rueda del ratón para modificar", "create.gui.scrollInput.scrollToAdjustAmount": "Usa la rueda del ratón para ajustar la cantidad", - "create.gui.scrollInput.scrollToSelect": "Usa la rueda del ratón para Seleccionar", - "create.gui.scrollInput.shiftScrollsFaster": "Shift para usar la rueda del ratón más rápido", - "create.gui.toolmenu.focusKey": "Mantenga [%1$s] para enfocar", + "create.gui.scrollInput.scrollToSelect": "Usa la rueda del ratón para seleccionar", + "create.gui.scrollInput.shiftScrollsFaster": "Mayús izdo para usar la rueda del ratón más rápido", + "create.gui.toolmenu.focusKey": "Mantén [%1$s] para enfocar", "create.gui.toolmenu.cycle": "[RUEDA DEL RATÓN] para el ciclo", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Espejado", "create.gui.symmetryWand.orientation": "Orientación", @@ -748,17 +829,17 @@ "create.orientation.alongZ": "A lo largo de Z", "create.orientation.alongX": "A lo largo de X", - "create.gui.terrainzapper.title": "Worldshaper", - "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.placement": "Colocación", + "create.gui.terrainzapper.title": "Blockzapper", + "create.gui.terrainzapper.searchDiagonal": "Seguir diagonales", + "create.gui.terrainzapper.searchFuzzy": "Ignorar los bordes del material", + "create.gui.terrainzapper.patternSection": "Patrón", + "create.gui.terrainzapper.pattern.solid": "Sólido", + "create.gui.terrainzapper.pattern.checkered": "Tablero de ajedrez", + "create.gui.terrainzapper.pattern.inversecheckered": "Tablero de ajedrez invertido", + "create.gui.terrainzapper.pattern.chance25": "25% Roll", + "create.gui.terrainzapper.pattern.chance50": "50% Roll", + "create.gui.terrainzapper.pattern.chance75": "75% Roll", + "create.gui.terrainzapper.placement": "Ubicación", "create.gui.terrainzapper.placement.merged": "Fusionado", "create.gui.terrainzapper.placement.attached": "Adjuntado", "create.gui.terrainzapper.placement.inserted": "Insertado", @@ -766,19 +847,19 @@ "create.gui.terrainzapper.brush.cuboid": "Cuboide", "create.gui.terrainzapper.brush.sphere": "Esfera", "create.gui.terrainzapper.brush.cylinder": "Cilindro", - "create.gui.terrainzapper.brush.surface": "UNLOCALIZED: Surface", - "create.gui.terrainzapper.brush.cluster": "UNLOCALIZED: Cluster", + "create.gui.terrainzapper.brush.surface": "Superficie", + "create.gui.terrainzapper.brush.cluster": "Grupo", "create.gui.terrainzapper.tool": "Herramienta", "create.gui.terrainzapper.tool.fill": "Llenar", - "create.gui.terrainzapper.tool.place": "Sitio", - "create.gui.terrainzapper.tool.replace": "Sustituir", - "create.gui.terrainzapper.tool.clear": "Borrar", - "create.gui.terrainzapper.tool.overlay": "Superposición", + "create.gui.terrainzapper.tool.place": "Ubicar", + "create.gui.terrainzapper.tool.replace": "Reemplazar", + "create.gui.terrainzapper.tool.clear": "Eliminar", + "create.gui.terrainzapper.tool.overlay": "Superponer", "create.gui.terrainzapper.tool.flatten": "Aplanar", - "create.terrainzapper.shiftRightClickToSet": "Shift+Clic con el botón derecho para seleccionar una forma", - "create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s", - "create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material", + "create.terrainzapper.shiftRightClickToSet": "Mayús izdo + clic derecho para seleccionar una forma", + "create.terrainzapper.usingBlock": "Usando: %1$s", + "create.terrainzapper.leftClickToSet": "Clic izquierdo a un bloque para establecer el material", "create.minecart_coupling.two_couplings_max": "Las vagonetas no pueden tener más de dos enganches cada una", "create.minecart_coupling.unloaded": "Algunas partes de su tren parecen estar en chunks no cargados", @@ -804,8 +885,8 @@ "create.contraptions.clockwork.hour_first_24": "La manecilla del día primero", "create.logistics.filter": "Filtro", - "create.logistics.recipe_filter": "Filtro de recetas", - "create.logistics.fluid_filter": "Filtro de fluidos", + "create.logistics.recipe_filter": "Filtro para recetas", + "create.logistics.fluid_filter": "Filtro para fluidos", "create.logistics.firstFrequency": "Freq. #1", "create.logistics.secondFrequency": "Freq. #2", "create.logistics.filter.apply": "Filtro aplicado a %1$s.", @@ -816,14 +897,14 @@ "create.gui.goggles.kinetic_stats": "Estadísticas cinéticas:", "create.gui.goggles.at_current_speed": "con la velocidad actual", "create.gui.goggles.pole_length": "Longitud del poste:", - "create.gui.goggles.fluid_container": "UNLOCALIZED: Fluid Container Info:", - "create.gui.goggles.fluid_container.capacity": "UNLOCALIZED: Capacity: ", + "create.gui.goggles.fluid_container": "Información sobre el contenedor de fluidos:", + "create.gui.goggles.fluid_container.capacity": "Capacidad: ", "create.gui.assembly.exception": "Este artilugio no se pudo montar:", "create.gui.assembly.exception.unmovableBlock": "Bloque inamovible (%4$s) en [%1$s,%2$s,%3$s]", "create.gui.assembly.exception.chunkNotLoaded": "El bloque en [%1$s,%2$s,%3$s] no estaba en un chunk cargado", "create.gui.assembly.exception.structureTooLarge": "Hay demasiados bloques incluídos en el artilugio.\nEl máximo configurado es: %1$s", "create.gui.assembly.exception.tooManyPistonPoles": "Hay demasiadas Pértigas de extensión conectadas a este Pistón.\nEl máximo configurado es: %1$s", - "create.gui.assembly.exception.noPistonPoles": "Faltan pértigas de extensión para el Pistón", + "create.gui.assembly.exception.noPistonPoles": "Faltan pértigas de extensión para el pistón", "create.gui.assembly.exception.not_enough_sails": "La estructura adjunta no incluye suficientes bloques tipo vela: %1$s\nSe requiere un mínimo de %2$s", "create.gui.gauge.info_header": "Información sobre el medidor:", "create.gui.speedometer.title": "Velocidad de rotación", @@ -832,7 +913,7 @@ "create.gui.stressometer.overstressed": "Sobrecargado", "create.gui.stressometer.no_rotation": "Sin rotación", "create.gui.contraptions.not_fast_enough": "Parece que este %1$s no está girando con _suficiente_ velocidad_.", - "create.gui.contraptions.network_overstressed": "Parece que este artilugio está _sobrecargado_. Añade más fuentes o _desacelera_ los componentes con un _impacto_ de alto estrés.", + "create.gui.contraptions.network_overstressed": "Parece que este artilugio está _sobrecargado_. Añade más fuentes o _desacelera_ los componentes con un _impacto de estrés alto_.", "create.gui.adjustable_crate.title": "Caja ajustable", "create.gui.adjustable_crate.storageSpace": "Espacio de almacenamiento", "create.gui.stockpile_switch.title": "Interruptor de acopio", @@ -852,7 +933,7 @@ "create.gui.sequenced_gearshift.instruction.delay.duration": "Duración", "create.gui.sequenced_gearshift.instruction.end.descriptive": "Fin", "create.gui.sequenced_gearshift.instruction.end": "Fin", - "create.gui.sequenced_gearshift.instruction.await.descriptive": "En espera de un Pulso de Redstone", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "En espera de un pulso de redstone", "create.gui.sequenced_gearshift.instruction.await": "En espera", "create.gui.sequenced_gearshift.speed": "Velocidad, Dirección", "create.gui.sequenced_gearshift.speed.forward": "Velocidad de entrada, hacia adelante", @@ -863,7 +944,7 @@ "create.schematicAndQuill.dimensions": "Tamaño del esquema: %1$sx%2$sx%3$s", "create.schematicAndQuill.firstPos": "Primera posición fijada.", "create.schematicAndQuill.secondPos": "Segunda posición fijada.", - "create.schematicAndQuill.noTarget": "Mantenga [Ctrl] para seleccionar los bloques del aire.", + "create.schematicAndQuill.noTarget": "Mantén [Ctrl] para seleccionar los bloques del aire.", "create.schematicAndQuill.abort": "Selección eliminada.", "create.schematicAndQuill.title": "Nombre del esquema:", "create.schematicAndQuill.convert": "Guardar y desplegar inmediatamente", @@ -879,7 +960,7 @@ "create.schematic.rotation.cw270": "En el sentido de las agujas del reloj 270", "create.schematic.mirror": "Espejado", "create.schematic.mirror.none": "Ninguno", - "create.schematic.mirror.frontBack": "Delante-detrás", + "create.schematic.mirror.frontBack": "Delante-Detrás", "create.schematic.mirror.leftRight": "Izquierda-Derecha", "create.schematic.tool.deploy": "Despliegue", "create.schematic.tool.move": "Mover XZ", @@ -888,27 +969,27 @@ "create.schematic.tool.print": "Imprimir", "create.schematic.tool.flip": "Voltear", "create.schematic.tool.deploy.description.0": "Mueve la estructura a un lugar.", - "create.schematic.tool.deploy.description.1": "Haga clic con el botón derecho del ratón en el suelo para colocar.", - "create.schematic.tool.deploy.description.2": "Mantenga [Ctrl] para seleccionar a una distancia fija.", - "create.schematic.tool.deploy.description.3": "[Ctrl]-Rueda del ratón para cambiar la distancia.", + "create.schematic.tool.deploy.description.1": "Haz clic con el botón derecho del ratón en el suelo para colocarla.", + "create.schematic.tool.deploy.description.2": "Mantén [Ctrl] para seleccionar a una distancia fija.", + "create.schematic.tool.deploy.description.3": "[Ctrl] + [RUEDA DEL RATÓN] para cambiar la distancia.", "create.schematic.tool.move.description.0": "Desplaza el esquema horizontalmente.", - "create.schematic.tool.move.description.1": "Apunta al Esquema y [CTRL]-Rueda del ratón para ponerlo.", + "create.schematic.tool.move.description.1": "Apunta al esquema y [Ctrl] + [RUEDA DEL RATÓN] para ponerlo.", "create.schematic.tool.move.description.2": "", "create.schematic.tool.move.description.3": "", "create.schematic.tool.movey.description.0": "Desplaza el esquema verticalmente..", - "create.schematic.tool.movey.description.1": "[CTRL]-Rueda del ratón para moverlo hacia arriba/abajo.", + "create.schematic.tool.movey.description.1": "[Ctrl] + [RUEDA DEL RATÓN] para moverlo hacia arriba/abajo.", "create.schematic.tool.movey.description.2": "", "create.schematic.tool.movey.description.3": "", "create.schematic.tool.rotate.description.0": "Gira el esquema alrededor de su centro.", - "create.schematic.tool.rotate.description.1": "[CTRL]-Rueda del ratón para girar 90 grados.", + "create.schematic.tool.rotate.description.1": "[Ctrl] + [RUEDA DEL RATÓN] para girar 90 grados.", "create.schematic.tool.rotate.description.2": "", "create.schematic.tool.rotate.description.3": "", "create.schematic.tool.print.description.0": "Sitúa instantáneamente la estructura en el mundo.", "create.schematic.tool.print.description.1": "[Clic derecho] para confirmar la colocación en el lugar actual.", "create.schematic.tool.print.description.2": "Esta herramienta es sólo para el Modo Creativo.", "create.schematic.tool.print.description.3": "", - "create.schematic.tool.flip.description.0": "Voltea el Esquema a lo largo de la cara que seleccione.", - "create.schematic.tool.flip.description.1": "Apunta al esquema y [CTRL]-Rueda del ratón para voltearlo.", + "create.schematic.tool.flip.description.0": "Voltea el esquema a lo largo de la cara que seleccione.", + "create.schematic.tool.flip.description.1": "Apunta al esquema y [Ctrl] + [RUEDA DEL RATÓN] para voltearlo.", "create.schematic.tool.flip.description.2": "", "create.schematic.tool.flip.description.3": "", @@ -922,8 +1003,8 @@ "create.gui.schematicTable.availableSchematics": "Esquemas disponibles", "create.gui.schematicTable.noSchematics": "No hay esquemas guardados", "create.gui.schematicTable.uploading": "Subiendo...", - "create.gui.schematicTable.finished": "Subida finalizada!", - "create.gui.schematicannon.title": "Schematicannon", + "create.gui.schematicTable.finished": "¡Subida finalizada!", + "create.gui.schematicannon.title": "Cañón de esquemas", "create.gui.schematicannon.listPrinter": "Lista de control de la impresora", "create.gui.schematicannon.gunpowderLevel": "Pólvora %1$s%%", "create.gui.schematicannon.shotsRemaining": "Disparos restantes: %1$s", @@ -941,16 +1022,16 @@ "create.gui.schematicannon.slot.listPrinter": "Coloque los libros aquí para imprimir una lista de comprobación para su esquema", "create.gui.schematicannon.slot.schematic": "Añada su esquema aquí. Asegúrese de que se despliega en un lugar específico.", "create.gui.schematicannon.option.skipMissing.description": "Si el cañón no encuentra un bloque necesario para su colocación, continuará en la siguiente ubicación.", - "create.gui.schematicannon.option.skipTileEntities.description": "El cañón evitará reemplazar los bloques que contienen datos, como los Cofres.", + "create.gui.schematicannon.option.skipTileEntities.description": "El cañón evitará reemplazar los bloques que contienen datos, como los cofres.", "create.gui.schematicannon.option.dontReplaceSolid.description": "El cañón nunca sustituirá ningún bloque sólido en su zona de trabajo, sólo los no sólidos y el aire.", "create.gui.schematicannon.option.replaceWithSolid.description": "El cañón sólo reemplazará los bloques sólidos en su área de trabajo si el esquema contiene un bloque sólido en la ubicación.", "create.gui.schematicannon.option.replaceWithAny.description": "El cañón reemplazará los bloques sólidos en su área de trabajo si el esquema contiene algún bloque en la ubicación.", - "create.gui.schematicannon.option.replaceWithEmpty.description": "El cañón eliminará todos los bloques de su zona de trabajo, incluidos los sustituidos por Aire.", + "create.gui.schematicannon.option.replaceWithEmpty.description": "El cañón eliminará todos los bloques de su zona de trabajo, incluidos los sustituidos por aire.", "create.schematicannon.status.idle": "Inactivo", "create.schematicannon.status.ready": "Listo", "create.schematicannon.status.running": "Funcionando", - "create.schematicannon.status.finished": "Finished", + "create.schematicannon.status.finished": "Finalizado", "create.schematicannon.status.paused": "Pausado", "create.schematicannon.status.stopped": "Detenido", "create.schematicannon.status.noGunpowder": "Sin pólvora", @@ -969,9 +1050,9 @@ "create.materialChecklist.blocksNotLoaded": "* Descargo de Responsabilidad *\n\nLa lista de materiales puede ser inexacta debido a que no se han cargado los chunks pertinentes.", "create.gui.filter.deny_list": "Lista de denegados", - "create.gui.filter.deny_list.description": "Los elementos pasan si NO coinciden con ninguno de los anteriores. Una lista de denegación vacía acepta todo.", + "create.gui.filter.deny_list.description": "Los objetos pasan si NO coinciden con ninguno de los anteriores. Una lista de denegación vacía acepta todo.", "create.gui.filter.allow_list": "Lista de permitidos", - "create.gui.filter.allow_list.description": "Los elementos pasan si coinciden con alguno de los anteriores. Una lista de permitidos vacía rechaza todo.", + "create.gui.filter.allow_list.description": "Los objetos pasan si coinciden con alguno de los anteriores. Una lista de permitidos vacía rechaza todo.", "create.gui.filter.respect_data": "Respetar datos", "create.gui.filter.respect_data.description": "Los objetos sólo coinciden si su durabilidad, encantos y otros atributos también coinciden.", "create.gui.filter.ignore_data": "Ignorar datos", @@ -981,18 +1062,14 @@ "create.item_attributes.placeable.inverted": "no se puede colocar", "create.item_attributes.consumable": "se puede comer", "create.item_attributes.consumable.inverted": "no se puede comer", - "create.item_attributes.smeltable": "se puede fundir", - "create.item_attributes.smeltable.inverted": "no se puede fundir", - "create.item_attributes.washable": "se puede lavar", - "create.item_attributes.washable.inverted": "no se puede lavar", - "create.item_attributes.smokable": "puede ser ahumado", - "create.item_attributes.smokable.inverted": "no puede ser ahumado", - "create.item_attributes.crushable": "puede ser molido", - "create.item_attributes.crushable.inverted": "no puede ser molido", - "create.item_attributes.blastable": "es fundible en el alto horno", - "create.item_attributes.blastable.inverted": "no es fundible en el alto horno", + "create.item_attributes.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "está encantado", "create.item_attributes.enchanted.inverted": "no está encantado", + "create.item_attributes.max_enchanted": "está encantado en el nivel máximo", + "create.item_attributes.max_enchanted.inverted": "no está encantado en el nivel máximo", + "create.item_attributes.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "está dañado", "create.item_attributes.damaged.inverted": "no está dañado", "create.item_attributes.badly_damaged": "está muy dañado", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "no se puede equipar", "create.item_attributes.furnace_fuel": "es combustible para hornos", "create.item_attributes.furnace_fuel.inverted": "no es combustible para hornos", + "create.item_attributes.washable": "se puede lavar", + "create.item_attributes.washable.inverted": "no se puede lavar", + "create.item_attributes.crushable": "puede ser molido", + "create.item_attributes.crushable.inverted": "no puede ser molido", + "create.item_attributes.smeltable": "se puede fundir", + "create.item_attributes.smeltable.inverted": "no se puede fundir", + "create.item_attributes.smokable": "puede ser ahumado", + "create.item_attributes.smokable.inverted": "no puede ser ahumado", + "create.item_attributes.blastable": "es fundible en el alto horno", + "create.item_attributes.blastable.inverted": "no es fundible en el alto horno", + "create.item_attributes.shulker_level": "es shulker %1$s", + "create.item_attributes.shulker_level.inverted": "no es shulker %1$s", + "create.item_attributes.shulker_level.full": "lleno", + "create.item_attributes.shulker_level.empty": "vacío", + "create.item_attributes.shulker_level.partial": "parcialmente lleno", "create.item_attributes.in_tag": "está etiquetado %1$s", "create.item_attributes.in_tag.inverted": "no está etiquetado %1$s", "create.item_attributes.in_item_group": "está en el grupo '%1$s'", @@ -1011,10 +1103,8 @@ "create.item_attributes.added_by.inverted": "no fue añadida por %1$s", "create.item_attributes.has_enchant": "está encantado con %1$s", "create.item_attributes.has_enchant.inverted": "no está encantado con %1$s", - "create.item_attributes.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": "Está teñido %1$s", + "create.item_attributes.color.inverted": "No está teñido %1$s", "create.item_attributes.has_fluid": "contiene %1$s", "create.item_attributes.has_fluid.inverted": "no contiene %1$s", "create.item_attributes.has_name": "tiene el nombre personalizado %1$s", @@ -1029,30 +1119,30 @@ "create.item_attributes.book_copy_second.inverted": "no es una copia de segunda generación", "create.item_attributes.book_copy_tattered": "es un desordenado desastre", "create.item_attributes.book_copy_tattered.inverted": "no es un desordenado desastre", - "create.item_attributes.astralsorcery_crystal": "tiene el atributo de cristal %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "no tiene atributo de cristal %1$s", - "create.item_attributes.astralsorcery_constellation": "está en sintonía con %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "no está en sintonía con %1$s", - "create.item_attributes.astralsorcery_perk_gem": "tiene el atributo ventaja %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "no tiene el atributo ventaja %1$s", "create.item_attributes.astralsorcery_amulet": "mejora %1$s", "create.item_attributes.astralsorcery_amulet.inverted": "no mejora %1$s", + "create.item_attributes.astralsorcery_constellation": "está en sintonía con %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "no está en sintonía con %1$s", + "create.item_attributes.astralsorcery_crystal": "tiene el atributo de cristal %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "no tiene atributo de cristal %1$s", + "create.item_attributes.astralsorcery_perk_gem": "tiene el atributo ventaja %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "no tiene el atributo ventaja %1$s", "create.gui.attribute_filter.no_selected_attributes": "No hay atributos seleccionados", "create.gui.attribute_filter.selected_attributes": "Atributos seleccionados:", "create.gui.attribute_filter.add_attribute": "Añadir atributo a la lista", "create.gui.attribute_filter.add_inverted_attribute": "Añadir atributo invertido a la Lista", "create.gui.attribute_filter.allow_list_disjunctive": "Lista de permitidos (Cualquiera)", - "create.gui.attribute_filter.allow_list_disjunctive.description": "Los elementos pasan si tienen alguno de los atributos seleccionados", + "create.gui.attribute_filter.allow_list_disjunctive.description": "Los objetos pasan si tienen alguno de los atributos seleccionados", "create.gui.attribute_filter.allow_list_conjunctive": "Lista de permitidos (Todos)", - "create.gui.attribute_filter.allow_list_conjunctive.description": "Los elementos pasan sólo si tienen TODOS los atributos seleccionados", + "create.gui.attribute_filter.allow_list_conjunctive.description": "Los objetos pasan sólo si tienen TODOS los atributos seleccionados", "create.gui.attribute_filter.deny_list": "Lista de denegados", - "create.gui.attribute_filter.deny_list.description": "Los elementos pasan si NO tienen ninguno de los atributos seleccionados", + "create.gui.attribute_filter.deny_list.description": "Los objetos pasan si NO tienen ninguno de los atributos seleccionados", "create.gui.attribute_filter.add_reference_item": "Añadir elemento de referencia", - "create.tooltip.holdForDescription": "UNLOCALIZED: Hold [%1$s] for Summary", - "create.tooltip.holdForControls": "UNLOCALIZED: Hold [%1$s] for Controls", - "create.tooltip.keyShift": "Shift", + "create.tooltip.holdForDescription": "Mantén [%1$s] para mas información", + "create.tooltip.holdForControls": "Mantén [%1$s] para ver los controles", + "create.tooltip.keyShift": "Mayús izdo.", "create.tooltip.keyCtrl": "Ctrl", "create.tooltip.speedRequirement": "Requisitos de velocidad: %1$s", "create.tooltip.speedRequirement.none": "Ninguno", @@ -1067,25 +1157,25 @@ "create.tooltip.capacityProvided.low": "Pequeña", "create.tooltip.capacityProvided.medium": "Media", "create.tooltip.capacityProvided.high": "Grande", - "create.tooltip.generationSpeed": "Genera en %1$s %2$s", + "create.tooltip.generationSpeed": "Generada en %1$s %2$s", "create.tooltip.analogStrength": "Fuerza analógica: %1$s/15", - "create.mechanical_arm.extract_from": "Extraer elementos de %1$s", - "create.mechanical_arm.deposit_to": "Depositar elementos en %1$s", + "create.mechanical_arm.extract_from": "Extraer objetos de %1$s", + "create.mechanical_arm.deposit_to": "Depositar objetos en %1$s", "create.mechanical_arm.summary": "El brazo mecánico tiene %1$s entrada(s) y %2$s salida(s)", "create.mechanical_arm.points_outside_range": "%1$s punto(s) de interacción seleccionado(s) eliminado(s) debido a las limitaciones de rango", - "create.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": "Objetivo seleccionado", + "create.weighted_ejector.target_not_valid": "Expulsión al bloque adyacente (el objetivo no era válido)", + "create.weighted_ejector.no_target": "Expulsión al bloque adyacente (no se ha seleccionado ningún objetivo)", + "create.weighted_ejector.targeting": "Expulsión a [%1$s,%2$s,%3$s]", + "create.weighted_ejector.stack_size": "Tamaño de la pila expulsada", "create.logistics.when_multiple_outputs_available": "Cuando hay múltiples salidas disponibles", "create.mechanical_arm.selection_mode.round_robin": "Round Robin", "create.mechanical_arm.selection_mode.forced_round_robin": "Round Robin forzado", - "create.mechanical_arm.selection_mode.prefer_first": "Preferir el primer objetivo", + "create.mechanical_arm.selection_mode.prefer_first": "Preferir el primero", "create.tunnel.selection_mode.split": "División", "create.tunnel.selection_mode.forced_split": "División forzada", @@ -1096,23 +1186,44 @@ "create.tunnel.selection_mode.synchronize": "Sincronizar entradas", "create.tooltip.chute.header": "Información del ducto", - "create.tooltip.chute.items_move_down": "Los elementos se mueven hacia abajo", - "create.tooltip.chute.items_move_up": "Los elementos se mueven hacia arriba", + "create.tooltip.chute.items_move_down": "Los objetos se mueven hacia abajo", + "create.tooltip.chute.items_move_up": "Los objetos se mueven hacia arriba", "create.tooltip.chute.no_fans_attached": "No hay ventiladores adjuntos", "create.tooltip.chute.fans_push_up": "Los ventiladores empujan desde abajo", "create.tooltip.chute.fans_push_down": "Los ventiladores empujan desde arriba", "create.tooltip.chute.fans_pull_up": "Los ventiladores tiran desde arriba", "create.tooltip.chute.fans_pull_down": "Los ventiladores tiran desde abajo", "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "Actualmente distribuye:", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "Haga clic derecho para recuperar", - "create.hint.hose_pulley.title": "Suministro sin fondo", - "create.hint.hose_pulley": "La masa de fluido objetivo se considera infinita", - "create.hint.mechanical_arm_no_targets.title": "No hay objetivos", - "create.hint.mechanical_arm_no_targets": "Parece que a este _brazo mecánico_ no se le ha asignado ningún _objetivo._ Selecciona correas, depósitos, embudos y otros bloques haciendo _clic derecho_ sobre ellos mientras _sostienes_ el _brazo mecánico_ en tu _mano_.", - "create.hint.empty_bearing.title": "Rodamiento de reloj", - "create.hint.empty_bearing": "_Haz clic con el botón derecho del ratón_ en el rodamiento con la _mano vacía_ para _adherir_ la estructura que acabas de construir delante de él", - "create.hint.full_deployer.title": "Desbordamiento de elementos del desplegador", - "create.hint.full_deployer": "Parece que este _Desplegador_ contiene _elementos_ en exceso que necesitan ser _extraídos._ Usa un _tolva,_embudo_ u otro medio para liberarlo de su desbordamiento.", + "create.linked_controller.bind_mode": "Modo de enlace activo", + "create.linked_controller.press_keybind": "Presiona %1$s, %2$s, %3$s, %4$s, %5$s o %6$s, para vincular esta frecuencia a la tecla correspondiente", + "create.linked_controller.key_bound": "Frecuencia ligada a %1$s", + "create.linked_controller.frequency_slot_1": "Enlace de teclas: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "Enlace de teclas: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "Ranura para ingredientes", + "create.crafting_blueprint.filter_items_viable": "Los objetos del filtro avanzado son viables", + "create.crafting_blueprint.display_slot": "Ranura de pantalla", + "create.crafting_blueprint.inferred": "A partir de la receta", + "create.crafting_blueprint.manually_assigned": "Asignado manualmente", + "create.crafting_blueprint.secondary_display_slot": "Ranura de pantalla secundaria", + "create.crafting_blueprint.optional": "Opcional", + + "create.potato_cannon.ammo.attack_damage": "%1$s Daño de ataque", + "create.potato_cannon.ammo.reload_ticks": "%1$s Recarga por Ticks", + "create.potato_cannon.ammo.knockback": "%1$s Golpe de efecto", + + "create.hint.hose_pulley.title": "Suministro ilimitado", + "create.hint.hose_pulley": "La masa de fluido objetivo se considera infinita.", + "create.hint.mechanical_arm_no_targets.title": "Sin objetivos", + "create.hint.mechanical_arm_no_targets": "Parece que a este _brazo mecánico_ no se le ha asignado ningún objetivo. Selecciona _correas_, _depósitos_, _embudos_ y otros bloques haciendo clic derecho sobre ellos mientras _sostienes_ el _brazo mecánico_ en tu mano..", + "create.hint.empty_bearing.title": "Actualización del rodamiento", + "create.hint.empty_bearing": "Haz clic derecho sobre el rodamiento con la _mano vacía_ para _adjuntar_ la estructura que acabas de construir delante de él.", + "create.hint.full_deployer.title": "Exceso de objetos en el desplegador", + "create.hint.full_deployer": "Parece que este _desplegador_ contiene _exceso_ de objetos que necesitan ser _extraídos._ Usa una _tolva_, _embudo_ u otro medio para liberarlo de su excedente.", "create.gui.config.overlay1": "Hola :)", "create.gui.config.overlay2": "Esta es una muestra de la superposición", @@ -1127,39 +1238,51 @@ "create.command.killTPSCommand.status.slowed_by.0": "[Crear]: El tick del servidor está actualmente ralentizado en %s ms :o", "create.command.killTPSCommand.status.slowed_by.1": "[Crear]: El tick del servidor está ralentizado en %s ms ahora >:)", "create.command.killTPSCommand.status.slowed_by.2": "[Create]: El tick del servidor ha vuelto a su velocidad normal :D", - "create.command.killTPSCommand.status.usage.0": "[Create]: usar /killtps stop para que el servidor vuelva a la velocidad normal", - "create.command.killTPSCommand.status.usage.1": "[Create]: usar /killtps start para ralentizar artificialmente el tick del servidor", + "create.command.killTPSCommand.status.usage.0": "[Create]: usa /killtps stop para que el servidor vuelva a la velocidad normal", + "create.command.killTPSCommand.status.usage.1": "[Create]: usa /killtps start para ralentizar artificialmente el tick del servidor", "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": "Este artilugio de vagoneta parece demasiado grande para recogerlo", + "create.contraption.minecart_contraption_illegal_pickup": "Una fuerza mística está atando este artilugio de vagoneta al mundo", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "Slime aplastado", - "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.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.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", + "create.subtitle.contraption_disassemble": "", + "create.subtitle.peculiar_bell_use": "", + "create.subtitle.mixing": "", + "create.subtitle.mechanical_press_activation_belt": "", + "create.subtitle.fwoomp": "", + "create.subtitle.worldshaper_place": "", + "create.subtitle.crushing_1": "", + "create.subtitle.depot_slide": "", + "create.subtitle.saw_activate_stone": "", + "create.subtitle.blaze_munch": "", + "create.subtitle.funnel_flap": "", + "create.subtitle.schematicannon_finish": "", + "create.subtitle.haunted_bell_use": "", + "create.subtitle.scroll_value": "", + "create.subtitle.crafter_craft": "", + "create.subtitle.controller_put": "", + "create.subtitle.cranking": "", + "create.subtitle.wrench_remove": "", + "create.subtitle.cogs": "", + "create.subtitle.slime_added": "", + "create.subtitle.wrench_rotate": "", + "create.subtitle.potato_hit": "", + "create.subtitle.saw_activate_wood": "", + "create.subtitle.haunted_bell_convert": "", + "create.subtitle.deployer_polish": "", + "create.subtitle.deny": "", + "create.subtitle.controller_click": "", + "create.subtitle.schematicannon_launch_block": "", + "create.subtitle.copper_armor_equip": "", + "create.subtitle.controller_take": "Lectern empties", + "create.subtitle.mechanical_press_activation": "", + "create.subtitle.contraption_assemble": "", + "create.subtitle.crafter_click": "", + "create.subtitle.depot_plop": "", + "create.subtitle.confirm": "", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1170,940 +1293,1055 @@ "item.create.example_item.tooltip.behaviour1": "Entonces este elemento hace esto. (los comportamientos se muestran en el turno)", "item.create.example_item.tooltip.condition2": "Y cuando esto", "item.create.example_item.tooltip.behaviour2": "Puedes añadir tantos comportamientos como quieras", - "item.create.example_item.tooltip.control1": "Cuando se pulsa Ctrl", + "item.create.example_item.tooltip.control1": "Cuando se pulsa [Ctrl]", "item.create.example_item.tooltip.action1": "Se muestran estos controles", "block.create.wooden_bracket.tooltip": "SOPORTE DE MADERA PARA EJES", - "block.create.wooden_bracket.tooltip.summary": "Decora tus _Ejes_, _Ruedas dentadas_ y _Ductos_ con un refuerzo acogedor y de madera.", + "block.create.wooden_bracket.tooltip.summary": "Decora tus _ejes_, _engranajes_ y _ductos_ con un acogedor refuerzo de madera.", "block.create.metal_bracket.tooltip": "SOPORTE DE METAL PARA EJES", - "block.create.metal_bracket.tooltip.summary": "Decora tus _Ejes_, _Ruedas dentadas_ y _Ductos_ con un poco de refuerzo industrial robusto.", - - "block.create.copper_casing.tooltip": "REVESTIDOR DE COBRE", - "block.create.copper_casing.tooltip.summary": "Robusta máquina de revestimientos con una gran variedad de usos. Seguro para la decoración.", - "block.create.copper_casing.tooltip.condition1": "Cuando se utiliza en una tubería de fluidos", - "block.create.copper_casing.tooltip.behaviour1": "_Reviste_ la _Tubería de fluidos_ con _Revestimiento de cobre_. Las tuberías de fluidos revestidas _bloquean sus conexiones_ en su lugar, dejando de reaccionar a los cambios en las tuberías vecinas.", - - "block.create.encased_fluid_pipe.tooltip": "TUBO DE FLUIDOS REFORZADO", - "block.create.encased_fluid_pipe.tooltip.summary": "Un tubo de fluidos reforzado con más cobre.", + "block.create.metal_bracket.tooltip.summary": "Decora tus _ejes_, _engranajes_ y _ductos_ con un poco de robusto refuerzo industrial.", "block.create.seat.tooltip": "ASIENTO", - "block.create.seat.tooltip.summary": "¡Siéntate y disfruta del viaje! Anclará a un jugador en un _contrafuerte_ en movimiento. También es ideal para los muebles estáticos. Viene en una variedad de colores.", - "block.create.seat.tooltip.condition1": "Click derecho en el asiento", - "block.create.seat.tooltip.behaviour1": "Sienta al jugador en el _Asiento_. Pulsa shift izquierdo para dejar el _Asiento_.", + "block.create.seat.tooltip.summary": "¡Siéntate y disfruta del viaje! Anclará a un jugador en un artilugio en movimiento. También es ideal para muebles estáticos. Viene en una variedad de colores.", + "block.create.seat.tooltip.condition1": "Cuando se hace clic derecho en el asiento", + "block.create.seat.tooltip.behaviour1": "Sienta al jugador en el _asiento_. Pulsa Mayús izdo para dejar el asiento.", "item.create.blaze_cake.tooltip": "PASTEL DE BLAZE", - "item.create.blaze_cake.tooltip.summary": "Un delicioso regalo para sus esforzados _Quemadores de blaze_. Los pone en marcha!.", - - "block.create.fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS DE COBRE", - "block.create.fluid_pipe.tooltip.summary": "Se utiliza para mover _fluidos_. Necesita una _bomba mecánica_ para que el _fluido_ se mueva.", - "block.create.fluid_pipe.tooltip.condition1": "Transferencia de fluidos", - "block.create.fluid_pipe.tooltip.behaviour1": "Puede conectarse a _contenedores de fluidos_ como _depósitos_ o _cuencas_. Los extremos expuestos de los _tubos_ también pueden drenar o colocar bloques de fluido. ¡Cuidado con las fugas!", - "block.create.fluid_pipe.tooltip.condition2": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Places a window on the pipe if available", - - "block.create.hose_pulley.tooltip": "POLEA DE MANGUERA", - "block.create.hose_pulley.tooltip.summary": "Se utiliza para _colocar_ o _drenar_ grandes _cuerpos fluidos_ en el mundo", - "block.create.hose_pulley.tooltip.condition1": "Cuando se alimenta por cinética", - "block.create.hose_pulley.tooltip.behaviour1": "_Sube_ o _baja_ la manguera, la ubicación de la manguera determina hasta qué _altura de extracción_ o _llenado_ actuará.", - "block.create.hose_pulley.tooltip.condition2": "Cuando los fluidos se extraen de la polea", - "block.create.hose_pulley.tooltip.behaviour2": "Comienza a _tomar bloques de fluidos_ del cuerpo al que se bajó el extremo de la manguera. Los cuerpos muy _grandes_ de fluidos se _considerarán infinitos_.", - "block.create.hose_pulley.tooltip.condition3": "Cuando los fluidos son empujados a la polea", - "block.create.hose_pulley.tooltip.behaviour3": "Comienza a _llenar de fluido_ el mundo hasta la _altura_ de los extremos de la _manguera_", - - "block.create.fluid_tank.tooltip": "TANQUE DE FLUIDOS", - "block.create.fluid_tank.tooltip.summary": "Almacena todos tus _líquidos_ favoritos. Escala en anchura y altura.", - "block.create.fluid_tank.tooltip.condition1": "Cuando se hace click derecho con la Llave Inglesa", - "block.create.fluid_tank.tooltip.behaviour1": "Cambia la ventana opcional", - - "block.create.creative_fluid_tank.tooltip": "TANQUE DE FLUIDOS CREATIVO", - "block.create.creative_fluid_tank.tooltip.summary": "Este _Tanque de Fluidos_ permite la replicación infinita de cualquier Fluido. Escala en anchura y altura.", - "block.create.creative_fluid_tank.tooltip.condition1": "Cuando hay fluido en el tanque", - "block.create.creative_fluid_tank.tooltip.behaviour1": "Todo lo que se _extraiga_ de este tanque proporcionará un _suministro ilimitado_ del fluido especificado. Los fluidos _insertados_ en este tanque serán _evitados._", - "block.create.creative_fluid_tank.tooltip.condition2": "Cuando se hace clic derecho con una Llave Inglesa", - "block.create.creative_fluid_tank.tooltip.behaviour2": "Cambia la ventana opcional", - - "block.create.fluid_valve.tooltip": "VALVULA DE FLUIDOS", - "block.create.fluid_valve.tooltip.summary": "Detiene el flujo de un fluido por una tubería", - "block.create.fluid_valve.tooltip.condition1": "Flujo controlable", - "block.create.fluid_valve.tooltip.behaviour1": "La _fuerza de rotación_ aplicada obligará a la _válvula_ a cerrarse, cesando el flujo de _fluidos_. Invierta la dirección de la _fuerza de rotación_ para volver a abrir la válvula", - - "block.create.mechanical_pump.tooltip": "BOMBA MECÁNICA", - "block.create.mechanical_pump.tooltip.summary": "Toma la _fuerza de rotación_ y la utiliza para mover el _fluido_ a lo largo de un _tubo_. Tiene un rango máximo de efecto en ambas direcciones. (16 bloques por defecto)", - "block.create.mechanical_pump.tooltip.condition1": "Flujo de fluido", - "block.create.mechanical_pump.tooltip.behaviour1": "La _fuerza de rotación_ aplicada crea una presión que obliga al _fluido_ a pasar por la red de _tuberías_. Invierte la dirección de la _fuerza de rotación_ para cambiar la dirección en la que fluye el _fluido_", - "block.create.mechanical_pump.tooltip.control1": "Pulsando con el botón derecho del ratón con la Llave Inglesa", - "block.create.mechanical_pump.tooltip.action1": "Invierte la dirección de la _bomba_, cambiando la dirección por defecto del flujo", - - "block.create.smart_fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS INTELIGENTE", - "block.create.smart_fluid_pipe.tooltip.summary": "Una _tubería de fluidos_ con un filtro. Puede especificar qué _fluidos_ pasan por ella", - "block.create.smart_fluid_pipe.tooltip.condition1": "Cuando se introducen fluidos en ella", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "Las tuberías inteligentes que reciban fluidos que no coincidan con su filtro bloquearán el flujo", - "block.create.smart_fluid_pipe.tooltip.condition2": "Cuando es adyacente a un contenedor de fluido", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "Las tuberías inteligentes que _inicien_ un _flujo_ desde cualquier contenedor sólo extraerán fluidos que _coincidan_ con su _filtro._", - - "block.create.spout.tooltip": "SURTIDOR", - "block.create.spout.tooltip.summary": "Un inyector para rellenar tus elementos de _fluidos._", - "block.create.spout.tooltip.condition1": "Transferencia de fluidos", - "block.create.spout.tooltip.behaviour1": "Cuando se coloca un _contenedor de fluidos_ como un _cubo_ o una _botella_ debajo, el caño intentará rellenarlo con su propio _fluido_ almacenado", - "block.create.spout.tooltip.condition2": "Automatización de fluidos", - "block.create.spout.tooltip.behaviour2": "El caño colocado encima de una _cinta_ o _depósito_ reaccionará automáticamente con un contenedor de fluidos_ que pase por debajo", - - "block.create.item_drain.tooltip": "DRENADOR DE ELEMENTOS", - "block.create.item_drain.tooltip.summary": "Un depósito rallado para vaciar tus _artículos fluidos._", - "block.create.item_drain.tooltip.condition1": "Transferencia de fluidos", - "block.create.item_drain.tooltip.behaviour1": "Cuando un _contenedor de fluidos_, como un _cubo_ o una _botella_, se inserta desde el lateral, el desagüe intentará vaciarlo en su propio _contenedor de fluidos_. El artículo será entonces expulsado por el lado opuesto", + "item.create.blaze_cake.tooltip.summary": "Un delicioso regalo para sus esforzados _quemadores de blaze_. ¡Los pone en marcha!.", "item.create.wand_of_symmetry.tooltip": "VARITA DE SIMETRÍA", - "item.create.wand_of_symmetry.tooltip.summary": "Refleja perfectamente la colocación de bloques en los planos configurados", + "item.create.wand_of_symmetry.tooltip.summary": "Refleja perfectamente la colocación de bloques en los planos configurados.", "item.create.wand_of_symmetry.tooltip.condition1": "Mientras está en el inventario rápido", - "item.create.wand_of_symmetry.tooltip.behaviour1": "Permanece activo", - "item.create.wand_of_symmetry.tooltip.control1": "Click derecho en el suelo", - "item.create.wand_of_symmetry.tooltip.action1": "_Crea_ o _Mueve_ el Espejo", - "item.create.wand_of_symmetry.tooltip.control2": "Click derecho en el aire", - "item.create.wand_of_symmetry.tooltip.action2": "_Quita_ el Espejo activo", - "item.create.wand_of_symmetry.tooltip.control3": "Click derecho mientras se agacha", - "item.create.wand_of_symmetry.tooltip.action3": "Abre la _Interfaz de Configuración_", + "item.create.wand_of_symmetry.tooltip.behaviour1": "Permanece activo.", + "item.create.wand_of_symmetry.tooltip.control1": "Cuando se hace clic derecho en el suelo", + "item.create.wand_of_symmetry.tooltip.action1": "_Crea_ o _mueve_ el espejo.", + "item.create.wand_of_symmetry.tooltip.control2": "Cuando se hace clic derecho en el aire", + "item.create.wand_of_symmetry.tooltip.action2": "_Quita_ el espejo activo.", + "item.create.wand_of_symmetry.tooltip.control3": "Mayús izdo + clic derecho", + "item.create.wand_of_symmetry.tooltip.action3": "Abre la interfaz de configuración.", "item.create.handheld_worldshaper.tooltip": "WORLDSHAPER", - "item.create.handheld_worldshaper.tooltip.summary": "Práctica herramienta para crear _paisajes_ y _características del terreno_", - "item.create.handheld_worldshaper.tooltip.control1": "Click izquierdo en un bloque", - "item.create.handheld_worldshaper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo", - "item.create.handheld_worldshaper.tooltip.control2": "Click derecho en un bloque", + "item.create.handheld_worldshaper.tooltip.summary": "Práctica herramienta para crear _paisajes_ y _características del terreno_.", + "item.create.handheld_worldshaper.tooltip.control1": "Cuando se hace clic izquierdo en un bloque", + "item.create.handheld_worldshaper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo.", + "item.create.handheld_worldshaper.tooltip.control2": "Cuando se hace clic derecho en un bloque", "item.create.handheld_worldshaper.tooltip.action2": "Aplica el _pincel_ y la _herramienta_ actualmente seleccionadas en el lugar deseado.", - "item.create.handheld_worldshaper.tooltip.control3": "Click derecho mientras se agacha", - "item.create.handheld_worldshaper.tooltip.action3": "Abre la _Interfaz de Configuración_", + "item.create.handheld_worldshaper.tooltip.control3": "Mayús izdo + clic derecho", + "item.create.handheld_worldshaper.tooltip.action3": "Abre la interfaz de configuración.", "item.create.tree_fertilizer.tooltip": "FERTILIZANTE PARA ÁRBOLES", - "item.create.tree_fertilizer.tooltip.summary": "Una potente combinación de minerales adecuada para acelerar el crecimiento de los tipos de árboles más comunes", + "item.create.tree_fertilizer.tooltip.summary": "Una potente combinación de minerales adecuada para acelerar el crecimiento de los tipos de árboles más comunes.", "item.create.tree_fertilizer.tooltip.condition1": "Cuando se utiliza en un árbol joven", - "item.create.tree_fertilizer.tooltip.behaviour1": "Hace crecer los árboles _independientemente_ de sus condiciones de _espacio_", + "item.create.tree_fertilizer.tooltip.behaviour1": "Hace crecer los árboles _independientemente_ de sus condiciones de _espacio_.", "item.create.extendo_grip.tooltip": "AGARRE EXTENDIDO", - "item.create.extendo_grip.tooltip.summary": "¡Boioioing! Aumenta enormemente la _distancia de alcance_ del portador", + "item.create.extendo_grip.tooltip.summary": "¡Boioioing! Aumenta enormemente la _distancia de alcance_ del portador. Se puede alimentar con la presión de aire de un _depósito trasero de cobre_", "item.create.extendo_grip.tooltip.condition1": "Cuando está fuera de la mano", - "item.create.extendo_grip.tooltip.behaviour1": "Aumenta la _distancia de alcance_ de los objetos usados en la _mano principal_", + "item.create.extendo_grip.tooltip.behaviour1": "Aumenta la _distancia de alcance_ de los objetos usados en la _mano principal_.", + "item.create.extendo_grip.tooltip.condition2": "Mientras se usa un depósito trasero de cobre", + "item.create.extendo_grip.tooltip.behaviour2": "No se utilizará _durabilidad_. En su lugar, la _presión del aire_ se drena desde el tanque", + + "item.create.potato_cannon.tooltip": "CANÓN DE PATATAS", + "item.create.potato_cannon.tooltip.summary": "Fwoomp! Lanza tus verduras caseras a tus enemigos. Se puede alimentar con la presión de aire de un _depósito trasero de cobre_", + "item.create.potato_cannon.tooltip.condition1": "Cuando se usa clic derecho", + "item.create.potato_cannon.tooltip.behaviour1": "_Dispara_ un objeto adecuado desde tu inventario_.", + "item.create.potato_cannon.tooltip.condition2": "Mientras se usa un depósito trasero de cobre", + "item.create.potato_cannon.tooltip.behaviour2": "No se utilizará _durabilidad_. En su lugar, la _presión del aire_ se drena desde el tanque", "item.create.filter.tooltip": "FILTRO", - "item.create.filter.tooltip.summary": "Controla las salidas_ y _entradas_ de los dispositivos logísticos con más _precisión_, comparándolas con un _conjunto de elementos_ o varios _filtros anidados_", - "item.create.filter.tooltip.condition1": "Cuando está en la ranura del filtro", - "item.create.filter.tooltip.behaviour1": "Controla_ el flujo del elemento según su _configuración_", + "item.create.filter.tooltip.summary": "Controla las _salidas_ y _entradas_ de los _dispositivos logísticos_ con más precisión, comparándolas con un _conjunto de objetos_ o varios _filtros anidados_.", + "item.create.filter.tooltip.condition1": "Cuando está en la ranura de filtros", + "item.create.filter.tooltip.behaviour1": "Controla el flujo de objetos según su _configuración_.", "item.create.filter.tooltip.condition2": "Cuando se hace clic derecho", - "item.create.filter.tooltip.behaviour2": "Abre la interfaz de _configuración_", + "item.create.filter.tooltip.behaviour2": "Abre la interfaz de configuración.", "item.create.attribute_filter.tooltip": "FILTRO DE ATRIBUTOS", - "item.create.attribute_filter.tooltip.summary": "Controla las salidas_ y las _entradas_ de los dispositivos logísticos con más _precisión_, comparándolas con un _conjunto de _atributos_ y _categorías_ de artículos", - "item.create.attribute_filter.tooltip.condition1": "Cuando está en la ranura del filtro", - "item.create.attribute_filter.tooltip.behaviour1": "Controla el flujo del elemento según su _configuración_", + "item.create.attribute_filter.tooltip.summary": "Controla las _salidas_ y las _entradas_ de los _dispositivos logísticos_ con más precisión, comparándolas con un _conjunto de atributos_ y _categorías_ de objetos.", + "item.create.attribute_filter.tooltip.condition1": "Cuando está en la ranura de filtros", + "item.create.attribute_filter.tooltip.behaviour1": "Controla el flujo de objetos según su _configuración_.", "item.create.attribute_filter.tooltip.condition2": "Cuando se hace clic derecho", - "item.create.attribute_filter.tooltip.behaviour2": "Abre la interfaz de _configuración_", + "item.create.attribute_filter.tooltip.behaviour2": "Abre la interfaz de configuración.", "item.create.empty_schematic.tooltip": "ESQUEMA VACÍO", - "item.create.empty_schematic.tooltip.summary": "Se utiliza como ingrediente de las recetas y para escribir en la _tabla de esquemas_", + "item.create.empty_schematic.tooltip.summary": "Se utiliza como 'ingrediente' de las recetas y para escribir en la _tabla de esquemas_.", "item.create.schematic.tooltip": "ESQUEMA", - "item.create.schematic.tooltip.summary": "Contiene una estructura para ser posicionada y colocada en el mundo. Posiciona el holograma como se desee y utiliza un _Esquematicannon_ para construirlo", - "item.create.schematic.tooltip.condition1": "Cuando se mantiene", - "item.create.schematic.tooltip.behaviour1": "Se puede posicionar utilizando las herramientas en pantalla", - "item.create.schematic.tooltip.control1": "Click derecho mientras se agacha", - "item.create.schematic.tooltip.action1": "Abre una _Interfaz_ para introducir las _Coordenadas_ exactas", + "item.create.schematic.tooltip.summary": "Contiene una estructura para ser posicionada y colocada en el mundo. Posiciona el holograma como desees y utiliza un _cañón de esquemas_ para construirla.", + "item.create.schematic.tooltip.condition1": "Cuando se sostiene en la mano", + "item.create.schematic.tooltip.behaviour1": "Se puede posicionar utilizando las herramientas en pantalla.", + "item.create.schematic.tooltip.control1": "Mayús izdo + clic derecho", + "item.create.schematic.tooltip.action1": "Abre una _interfaz_ para introducir las _coordenadas_ exactas.", "item.create.schematic_and_quill.tooltip": "ESQUEMA Y PLUMA", - "item.create.schematic_and_quill.tooltip.summary": "Se utiliza para guardar una estructura de tu mundo en un archivo .nbt", + "item.create.schematic_and_quill.tooltip.summary": "Se utiliza para guardar una estructura de tu mundo en un archivo .nbt.", "item.create.schematic_and_quill.tooltip.condition1": "Paso 1", - "item.create.schematic_and_quill.tooltip.behaviour1": "Selecciona dos puntos de esquina usando click derecho", + "item.create.schematic_and_quill.tooltip.behaviour1": "Selecciona dos puntos de esquina usando clic derecho.", "item.create.schematic_and_quill.tooltip.condition2": "Paso 2", - "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrl-Rueda del ratón_ en las caras para ajustar el tamaño. Click derecho de nuevo para guardar", - "item.create.schematic_and_quill.tooltip.control1": "Click derecho", - "item.create.schematic_and_quill.tooltip.action1": "Seleccionar un punto de esquina / confirmar guardar", - "item.create.schematic_and_quill.tooltip.control2": "Al mantener Ctrl", - "item.create.schematic_and_quill.tooltip.action2": "Seleccionar puntos en _medio del aire_. Rueda del ratón para ajustar la distancia", - "item.create.schematic_and_quill.tooltip.control3": "Click derecho mientras se agacha", - "item.create.schematic_and_quill.tooltip.action3": "Reinicia_ y elimina la selección", + "item.create.schematic_and_quill.tooltip.behaviour2": "[Ctrl] + [RUEDA DEL RATÓN] en las caras para ajustar el tamaño. Clic derecho de nuevo para guardar.", + "item.create.schematic_and_quill.tooltip.control1": "Cuando se hace clic derecho", + "item.create.schematic_and_quill.tooltip.action1": "Selecciona un punto de esquina / confirmar guardar.", + "item.create.schematic_and_quill.tooltip.control2": "Cuando mantiene [Ctrl]", + "item.create.schematic_and_quill.tooltip.action2": "Selecciona puntos en _medio del aire_. Rueda del ratón para ajustar la distancia.", + "item.create.schematic_and_quill.tooltip.control3": "Mayús izdo + clic derecho", + "item.create.schematic_and_quill.tooltip.action3": "_Reinicia_ y elimina la selección.", - "block.create.schematicannon.tooltip": "ESQUEMATICAÑÓN", - "block.create.schematicannon.tooltip.summary": "Dispara bloques para recrear un _Esquema_ desplegado en el Mundo. Utiliza elementos de los inventarios adyacentes y _Pólvora_ como combustible.", - "block.create.schematicannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", - "block.create.schematicannon.tooltip.behaviour1": "UNLOCALIZED: Opens the _Interface_", + "block.create.schematicannon.tooltip": "CAÑÓN DE ESQUEMAS", + "block.create.schematicannon.tooltip.summary": "Dispara bloques para recrear un _esquema_ desplegado en el mundo. Utiliza objetos de los inventarios adyacentes y _pólvora_ como combustible.", + "block.create.schematicannon.tooltip.condition1": "Cuando se hace clic derecho", + "block.create.schematicannon.tooltip.behaviour1": "Abre la interfaz.", "block.create.schematic_table.tooltip": "TABLA DE ESQUEMAS", - "block.create.schematic_table.tooltip.summary": "Escribe los esquemas guardados en un _esquema vacío_", + "block.create.schematic_table.tooltip.summary": "Escribe los esquemas guardados en un _esquema vacío_.", "block.create.schematic_table.tooltip.condition1": "Cuando se da un esquema vacío", - "block.create.schematic_table.tooltip.behaviour1": "Carga un archivo elegido de la carpeta de esquemas", + "block.create.schematic_table.tooltip.behaviour1": "Carga un archivo elegido de la carpeta de esquemas.", - "item.create.goggles.tooltip": "GAFAS DEL INGENIERO", - "item.create.goggles.tooltip.summary": "Un par de gafas para aumentar tu visión con útil información _cinética_", + "item.create.goggles.tooltip": "GAFAS DEL CONSTRUCTOR", + "item.create.goggles.tooltip.summary": "Un par de gafas para aumentar tu visión con útil información _cinética_.", "item.create.goggles.tooltip.condition1": "Cuando se llevan puestas", - "item.create.goggles.tooltip.behaviour1": "Muestra _indicadores de color_ correspondientes al _Nivel de velocidad_ de un componente cinético colocado, así como el _Impacto de estrés_ y la _Capacidad_ de los componentes individuales.", - "item.create.goggles.tooltip.condition2": "Al mirar el medidor", - "item.create.goggles.tooltip.behaviour2": "Muestra información detallada sobre _Velocidad_ o _Estrés_ de la red a la que está conectado el medidor", - "item.create.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.behaviour1": "Muestra _indicadores de color_ correspondientes al _nivel de velocidad_ de un componente cinético colocado, así como el _impacto de estrés_ y la _carga_ de los componentes individuales.", + "item.create.goggles.tooltip.condition2": "Al mirar un medidor", + "item.create.goggles.tooltip.behaviour2": "Muestra información detallada sobre _velocidad_ o _estrés_ de la red a la que está conectado el medidor.", + "item.create.goggles.tooltip.condition3": "Al mirar un contenedor de fluidos", + "item.create.goggles.tooltip.behaviour3": "Muestra información detallada sobre la _carga_ del bloque y los _líquidos_ almacenados en su interior.", "item.create.wrench.tooltip": "LLAVE INGLESA", - "item.create.wrench.tooltip.summary": "Una herramienta útil para trabajar en artilugios cinéticos. Se puede utilizar para _Rotar_, _Desmantelar_ y para _Configurar_ componentes", - "item.create.wrench.tooltip.control1": "Click con el botón derecho en un bloque cinético", - "item.create.wrench.tooltip.action1": "_Rota los componentes_ hacia o desde la cara con la que ha interactuado", - "item.create.wrench.tooltip.control2": "Click derecho mientras te agachas", - "item.create.wrench.tooltip.action2": "Desmonta los componentes cinéticos_ y los devuelve a _tu inventario_", + "item.create.wrench.tooltip.summary": "Una herramienta útil para trabajar en artilugios cinéticos. Se puede utilizar para _rotar_, _desmantelar_ y para _configurar_ componentes.", + "item.create.wrench.tooltip.control1": "Cuando se hace clic derecho en un bloque cinético", + "item.create.wrench.tooltip.action1": "Rota los componentes hacia o desde la cara con la que ha interactuado.", + "item.create.wrench.tooltip.control2": "Mayús izdo + clic derecho", + "item.create.wrench.tooltip.action2": "Desmonta los _componentes cinéticos_ y los devuelve a tu inventario_.", "block.create.nozzle.tooltip": "BOQUILLA", - "block.create.nozzle.tooltip.summary": "Se acopla a la parte delantera de un _ventilador revestido_ para distribuir su efecto sobre las entidades en _todas las direcciones_", + "block.create.nozzle.tooltip.summary": "Se acopla a la parte delantera de un _ventilador revestido_ para distribuir su efecto sobre las entidades en _todas las direcciones_.", "block.create.cuckoo_clock.tooltip": "RELOJ DE CUCO", - "block.create.cuckoo_clock.tooltip.summary": "Fina artesanía para _decorar_ un espacio y _contar el tiempo_", + "block.create.cuckoo_clock.tooltip.summary": "Fina artesanía para decorar un espacio y contar el tiempo.", "block.create.cuckoo_clock.tooltip.condition1": "Cuando es alimentado por cinética", - "block.create.cuckoo_clock.tooltip.behaviour1": "Muestra la _hora actual_ y toca una melodía dos veces al día. Se activa_ una vez al _mediodía_ y al anochecer, en cuanto _los jugadores pueden dormir_", + "block.create.cuckoo_clock.tooltip.behaviour1": "Muestra la _hora actual_ y toca una melodía dos veces al día. Se activa una vez al mediodía y al anochecer, _en cuanto los jugadores pueden dormir_.", "block.create.turntable.tooltip": "PLATAFORMA GIRATORIA", - "block.create.turntable.tooltip.summary": "Convierte la _fuerza de rotación_ en un refinado mareo", + "block.create.turntable.tooltip.summary": "Convierte la _fuerza rotacional_ en un refinado mareo.", - "block.create.portable_fluid_interface.tooltip": "INTERFAZ DE FLUIDO PORTÁTIL", - "block.create.portable_fluid_interface.tooltip.summary": "Punto de intercambio portátil para _mover fluidos_ hacia y desde una _estructura_ movida por un pistón, rodamiento, vagoneta o polea. Para cumplirse dos interfaces tienen que _enfrentarse_ y estar separadas _1-2 bloques_", - "block.create.portable_fluid_interface.tooltip.condition1": "Mientras se mueve", - "block.create.portable_fluid_interface.tooltip.behaviour1": "Interactúa con las _interfaces de almacenamiento portátiles_ estacionarias para transferir fluidos hacia o desde el artilugio. Las tuberías que se inserten en la _interfaz estacionaria_ o se extraigan de ella interactuarán con los depósitos del artilugio _directamente._ La estructura se paralizará brevemente mientras se intercambian fluidos.", - "block.create.portable_fluid_interface.tooltip.condition2": "Cuando se alimenta con Redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "_Desconecta_ cualquier conexión activa inmediatamente", + "block.create.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "INTERRUPTOR DE ACOPIO", - "block.create.stockpile_switch.tooltip.summary": "Activa una señal de Redstone en función de la cantidad de _Artículos almacenados_ en el Contenedor adjunto. Viene con un práctico filtro. A diferencia de un _Comparador,_ el _Interruptor de acopio_ permite la configuración de _Umbrales,_ a partir de los cuales se invierten las señales", - "block.create.stockpile_switch.tooltip.condition1": "Cuando haces click derecho", - "block.create.stockpile_switch.tooltip.behaviour1": "Abre la _Interfaz de Configuración_", + "block.create.stockpile_switch.tooltip.summary": "Activa una señal de redstone en función de la cantidad de _objetos almacenados_ en el _contenedor_ adjunto. Viene con un práctico filtro. A diferencia de un _comparador, el _interruptor de acopio_ permite la configuración de _umbrales_, a partir de los cuales se invierten las señales.", + "block.create.stockpile_switch.tooltip.condition1": "Cuando se hace clic derecho", + "block.create.stockpile_switch.tooltip.behaviour1": "Abre la interfaz de configuración.", "block.create.content_observer.tooltip": "OBSERVADOR DE CONTENIDO", - "block.create.content_observer.tooltip.summary": "_Detecta artículos_ dentro de _contenedores_ y _transportadores_ que coinciden con un _filtro_ configurado. Mientras el _inventario_, la _cinta_ o la _canaleta_ observados contengan_ un artículo que coincida, este componente emitirá una _señal de Redstone_. Cuando un _túnel observado transfiere_ un artículo coincidente, este componente emitirá un _Pulso de Redstone_", + "block.create.content_observer.tooltip.summary": "_Detecta objetos_ dentro de _contenedores_ y _transportadores_ que coincidan con un _filtro_ configurado. Mientras el _inventario_, la _cinta_ o la _canaleta_ observados _contengan_ un objeto que coincida, este componente emitirá una _señal de redstone_. Cuando un embudo observado _transfiere_ un objeto coincidente, este componente emitirá un _pulso de redstone_.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "CAJA AJUSTABLE", - "block.create.adjustable_crate.tooltip.summary": "Este _Contenedor de Artículos_ permite el control manual de su capacidad. Puede contener hasta _16 pilas_ de cualquier objeto. Soporta _Comparadores de Redstone_", - "block.create.adjustable_crate.tooltip.condition1": "UNLOCALIZED: When R-Clicked", - "block.create.adjustable_crate.tooltip.behaviour1": "UNLOCALIZED: Opens the _Interface_.", + "block.create.adjustable_crate.tooltip.summary": "Este _contenedor de objetos_ permite el control manual de su capacidad. Puede contener hasta _16 pilas_ de cualquier objeto. Soporta _comparadores de redstone_.", + "block.create.adjustable_crate.tooltip.condition1": "Cuando se hace clic derecho", + "block.create.adjustable_crate.tooltip.behaviour1": "Abre la interfaz.", "block.create.creative_crate.tooltip": "CAJA CREATIVA", - "block.create.creative_crate.tooltip.summary": "Este _Contenedor de Almacenamiento_ permite la replicación infinita de cualquier elemento. Colócalo junto a un _Schematicannon_ para eliminar cualquier requisito de material", - "block.create.creative_crate.tooltip.condition1": "Cuando el artículo está en la ranura del filtro", - "block.create.creative_crate.tooltip.behaviour1": "Todo lo que se _extraiga_ de este contenedor proporcionará un _suministro ilimitado_ del elemento especificado. Los elementos _insertados_ en esta caja serán _evitados._", + "block.create.creative_crate.tooltip.summary": "Este _contenedor de objetos_ permite la replicación infinita de cualquier elemento. Colócalo junto a un _cañón de esquemas_ para eliminar cualquier requisito de material.", + "block.create.creative_crate.tooltip.condition1": "Cuando el elemento está en la ranura para filtros", + "block.create.creative_crate.tooltip.behaviour1": "Todo lo que se _extraiga_ de este contenedor proporcionará un suministro _ilimitado_ del elemento especificado. Los objetos _insertados_ en esta caja serán _evitados_.", + + "item.create.creative_blaze_cake.tooltip": "PASTEL CREATIVO", + "item.create.creative_blaze_cake.tooltip.summary": "Un regalo muy especial para los _Quemadores de Blaze_ que permite _controlar su nivel de calor_. Después de comer este pastel, los Quemadores de blaze _nunca se quedarán sin combustible_.", + "item.create.creative_blaze_cake.tooltip.condition1": "Click derecho en un Quemador de blaze", + "item.create.creative_blaze_cake.tooltip.behaviour1": "Bloquea el nivel de calor del Quemador de blaze. Si se utiliza de nuevo, _cicla_ el nivel de calor del Quemador de blaze.", "block.create.controller_rail.tooltip": "RAÍL DE CONTROL", - "block.create.controller_rail.tooltip.summary": "Un _raíl energizado unidireccional_ capaz de _controlar con precisión_ la _velocidad de movimiento_ de una vagoneta", - "block.create.controller_rail.tooltip.condition1": "Cuando es impulsado por Redstone", - "block.create.controller_rail.tooltip.behaviour1": "_Acelera_ o _Desacelera_ pasando _vagonetas_ correspondientes a la _fuerza de la señal_. Propaga la energía de Redstone a los Raíles de control adyacentes. Al alimentar dos Raíles de control con diferentes intensidades, los carriles entre ellos interpolarán su señal", + "block.create.controller_rail.tooltip.summary": "Un raíl energizado _unidireccional_ capaz de _controlar con precisión_ la _velocidad de movimiento_ de una vagoneta.", + "block.create.controller_rail.tooltip.condition1": "Cuando es alimentado con redstone", + "block.create.controller_rail.tooltip.behaviour1": "_Acelera_ o _desacelera_ pasando _vagonetas_ correspondientes a la _fuerza de la señal_. Propaga la energía de redstone a los raíles de control adyacentes. Al alimentar dos raíles de control con diferentes intensidades, los carriles entre ellos interpolarán su señal.", "item.create.sand_paper.tooltip": "PAPEL DE LIJA", - "item.create.sand_paper.tooltip.summary": "Un papel rugoso que se puede utilizar para _pulir materiales_. Se puede aplicar automáticamente con el Desplegador", + "item.create.sand_paper.tooltip.summary": "Un papel rugoso que se puede utilizar para _pulir materiales_. Se puede aplicar automáticamente con el _desplegador_.", "item.create.sand_paper.tooltip.condition1": "Cuando se usa", - "item.create.sand_paper.tooltip.behaviour1": "Aplica el pulido a los objetos sostenidos en la _mano libre_ o tirados en el _suelo_ cuando se _miran_", + "item.create.sand_paper.tooltip.behaviour1": "Aplica un pulido a los objetos sostenidos en la _mano libre_ o tirados en el _suelo_ cuando se _miran_.", "item.create.builders_tea.tooltip": "TÉ DEL CONSTRUCTOR", - "item.create.builders_tea.tooltip.summary": "La bebida perfecta para empezar el día- _Motivante_ y _Saturante._", + "item.create.builders_tea.tooltip.summary": "La bebida perfecta para empezar el día. Motivante y saturante.", "item.create.refined_radiance.tooltip": "RESPLANDOR REFINADO", - "item.create.refined_radiance.tooltip.summary": "Material cromático forjado a partir de _luz absorbida_", + "item.create.refined_radiance.tooltip.summary": "Un material cromático forjado a partir de la _luz absorbida_.", + "item.create.refined_radiance.tooltip.condition1": "Trabajo en progreso", + "item.create.refined_radiance.tooltip.behaviour1": "Los usos para este material estarán disponibles en un próximo lanzamiento.", "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.summary": "Un material cromático forjado en el _vacío_.", + "item.create.shadow_steel.tooltip.condition1": "Trabajo en curso", + "item.create.shadow_steel.tooltip.behaviour1": "Los usos de este material estarán disponibles en una futura versión.", + + "item.create.linked_controller.tooltip": "CONTROLADOR ENLAZADO", + "item.create.linked_controller.tooltip.summary": "Permite el control manual de las frecuencias de _enlaces de redstone_ asignadas a sus seis botones.", + "item.create.linked_controller.tooltip.condition1": "Al hacer clic derecho", + "item.create.linked_controller.tooltip.behaviour1": "Activa el _controlador_. Los _controles de movimiento_ se adquieren mientras está activo.", + "item.create.linked_controller.tooltip.condition2": "Al usar Mayús izdo + clic derecho", + "item.create.linked_controller.tooltip.behaviour2": "Abre la interfaz de configuración manual.", + "item.create.linked_controller.tooltip.condition3": "Al usar clic derecho en un receptor de enlaces de redstone", + "item.create.linked_controller.tooltip.behaviour3": "Activa el _modo de vinculación_, pulsa uno de los _seis controles_ para vincularlo a la _frecuencia de los enlaces_.", + "item.create.linked_controller.tooltip.condition4": "Clic derecho en un atril", + "item.create.linked_controller.tooltip.behaviour4": "Coloca el controlador en el atril para facilitar su activación. (Clic derecho + mayús izq. para recuperarlo)", + + "item.create.diving_helmet.tooltip": "CASCO DE BUCEO", + "item.create.diving_helmet.tooltip.summary": "Junto con un _depósito trasero de cobre_, permite que el usuario pueda respirar bajo el agua durante un tiempo prolongado.", + "item.create.diving_helmet.tooltip.condition1": "Cuando se lleva puesto", + "item.create.diving_helmet.tooltip.behaviour1": "Proporciona el efecto de _respiración acuática_, drenando lentamente la presión de aire del _depósito trasero_.", + + "item.create.copper_backtank.tooltip": "DEPÓSITO TRASERO DE COBRE", + "item.create.copper_backtank.tooltip.summary": "Un tanque portátil para transportar _aire presurizado_.", + "item.create.copper_backtank.tooltip.condition1": "Cuando se lleva puesto", + "item.create.copper_backtank.tooltip.behaviour1": "Proporciona _aire presurizado_ a los equipos que lo requieran.", + "item.create.copper_backtank.tooltip.condition2": "Cuando se coloca y es alimentado por cinética", + "item.create.copper_backtank.tooltip.behaviour2": "Recoge _aire presurizado_ a un ritmo que depende de la velocidad rotacional.", + + "item.create.diving_boots.tooltip": "BOTAS DE BUCEO", + "item.create.diving_boots.tooltip.summary": "Un par de _botas_ pesadas, que permiten atravesar mejor el suelo del océano.", + "item.create.diving_boots.tooltip.condition1": "Cuando se llevan puestas", + "item.create.diving_boots.tooltip.behaviour1": "El portador se hunde rápido y no puede nadar. Concede la capacidad de caminar y saltar bajo el agua. Al portador no le afectarán las _correas mecánicas.", + + "item.create.crafting_blueprint.tooltip": "PLANO DE ELABORACIÓN", + "item.create.crafting_blueprint.tooltip.summary": "Colocado en una pared, puede utilizarse para especificar la disposición de los ingredientes para facilitar la elaboración manual. Cada ranura representa una receta", + "item.create.crafting_blueprint.condition1": "Al hacer clic derecho en una ranura vacía", + "item.create.crafting_blueprint.behaviour1": "Abre un menú que permite configurar una receta y los objetos a mostrar.", + "item.create.crafting_blueprint.condition2": "Al hacer clic derecho en una ranura configurada", + "item.create.crafting_blueprint.behaviour2": "Aplica la receta configurada con los ingredientes que se encuentran en tu inventario. Se puede utilizar para fabricar hasta una pila de objetos.", "item.create.minecart_coupling.tooltip": "ENSAMBLADOR DE VAGONETAS", - "item.create.minecart_coupling.tooltip.summary": "_Encadena_ todas tus _Vagonetas_ o _Artilugios de vagoneta_ para formar un majestuoso Tren", - "item.create.minecart_coupling.tooltip.condition1": "Cuando se utiliza en Vagonetas", - "item.create.minecart_coupling.tooltip.behaviour1": "_Acopla_ dos Vagonetas, intentando mantenerlas a una _distancia constante_ mientras se mueven", + "item.create.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", + "block.create.peculiar_bell.tooltip": "CAMPANA PECULIAR", + "block.create.peculiar_bell.tooltip.summary": "Una campana decorativa de latón. Al colocarla sobre un _Fuego del alma_ o una _Fogata del alma_ puede producirse una transformación espeluznante...", + + "block.create.haunted_bell.tooltip": "CAMPANA ENCANTADA", + "block.create.haunted_bell.tooltip.summary": "Una _campana maldita_ perseguida por las almas perdidas del Nether", + "block.create.haunted_bell.tooltip.condition1": "Cuando se sostiene o suena", + "block.create.haunted_bell.tooltip.behaviour1": "Resalta los _puntos sin luz_ cercanos en los que pueden aparecer las _criaturas hostiles_.", "_": "->------------------------] 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": "Mantén [%1$s] para considerar", + "create.ponder.subject": "Tema de esta escena", + "create.ponder.pondering": "Considerando sobre...", + "create.ponder.identify_mode": "Identificando modo activo.\nDespausea con [%1$s]", + "create.ponder.associated": "Entradas asociadas", + "create.ponder.close": "Cerrar", + "create.ponder.identify": "Identificar", + "create.ponder.next": "Escena siguiente", + "create.ponder.previous": "Escena previa", + "create.ponder.replay": "Repetición", + "create.ponder.think_back": "Volver atrás", + "create.ponder.slow_text": "Lectura cómoda", + "create.ponder.exit": "Salir", + "create.ponder.welcome": "Bienvenido al instructivo de Create", + "create.ponder.categories": "Categorías disponibles", + "create.ponder.index_description": "Haga clic en uno de los iconos para conocer sus objetos y bloques asociados", + "create.ponder.index_title": "Índice", + "create.ponder.shared.rpm16": "16 RPM", + "create.ponder.shared.behaviour_modify_wrench": "Este comportamiento puede modificarse mediante una llave inglesa", + "create.ponder.shared.storage_on_contraption": "Los inventarios unidos al artilugio recogerán sus producciones automáticamente", + "create.ponder.shared.sneak_and": "Mayús izdo. +", + "create.ponder.shared.rpm8": "8 RPM", + "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm32": "32 RPM", + "create.ponder.shared.rpm16_source": "Fuente: 16 RPM", + "create.ponder.shared.movement_anchors": "Con la ayuda de un chasis o pegamento, se pueden mover estructuras más grandes.", + "create.ponder.tag.redstone": "Componentes lógicos", + "create.ponder.tag.redstone.description": "Componentes que ayudan a la ingeniería de redstone", + "create.ponder.tag.contraption_assembly": "Utilidades para adjuntar bloques", + "create.ponder.tag.contraption_assembly.description": "Herramientas y componentes utilizados para montar estructuras con movimiento, como un artilugio animado", + "create.ponder.tag.fluids": "Manipuladores de fluidos", + "create.ponder.tag.fluids.description": "Componentes que ayudan a transportar y utilizar fluidos", + "create.ponder.tag.decoration": "Estética", + "create.ponder.tag.decoration.description": "Componentes utilizados principalmente con fines decorativos", + "create.ponder.tag.windmill_sails": "Velas para los rodamientos de los molinos de viento", + "create.ponder.tag.windmill_sails.description": "Bloques que cuentan para la fuerza de un artefacto de molino de viento cuando se ensamblan. Cada uno de ellos tiene la misma eficacia al hacerlo.", + "create.ponder.tag.arm_targets": "Objetivos para los brazos mecánicos", + "create.ponder.tag.arm_targets.description": "Componentes que pueden seleccionarse como entradas o salidas del brazo mecánico", + "create.ponder.tag.kinetic_appliances": "Dispositivos cinéticos", + "create.ponder.tag.kinetic_appliances.description": "Componentes que utilizan la fuerza rotacional", + "create.ponder.tag.kinetic_sources": "Fuentes cinéticas", + "create.ponder.tag.kinetic_sources.description": "Componentes que generan fuerza rotacional", + "create.ponder.tag.movement_anchor": "Anclas de movimiento", + "create.ponder.tag.movement_anchor.description": "Componentes que permiten crear artilugios en movimiento, animando una estructura anexa de diversas maneras", + "create.ponder.tag.kinetic_relays": "Transmisores cinéticos", + "create.ponder.tag.kinetic_relays.description": "Componentes que ayudan a transmitir la fuerza rotacional en otro lugar", + "create.ponder.tag.contraption_actor": "Actores del artilugio", + "create.ponder.tag.contraption_actor.description": "Componentes que exponen un comportamiento especial cuando están unidos a un artilugio en movimiento", + "create.ponder.tag.creative": "Modo creativo", + "create.ponder.tag.creative.description": "Componentes que no suelen estar disponibles para el Modo Supervivencia", + "create.ponder.tag.logistics": "Transporte de objetos", + "create.ponder.tag.logistics.description": "Componentes que ayudan a desplazar los objetos", + + "create.ponder.adjustable_pulse_repeater.header": "Controlar señales mediante repetidores de pulsos ajustables", + "create.ponder.adjustable_pulse_repeater.text_1": "Los repetidores de pulsos ajustables emiten un pulso corto con un retardo", + "create.ponder.adjustable_pulse_repeater.text_2": "Con la rueda del ratón se puede configurar el tiempo de carga", + "create.ponder.adjustable_pulse_repeater.text_3": "Los retrasos configurados pueden ser de hasta 30 minutos", + + "create.ponder.adjustable_repeater.header": "Controlar señales mediante repetidores ajustables", + "create.ponder.adjustable_repeater.text_1": "Los repetidores ajustables se comportan de forma similar a los repetidores normales", + "create.ponder.adjustable_repeater.text_2": "Se cargan durante un tiempo determinado...", + "create.ponder.adjustable_repeater.text_3": "...y se enfrían durante el mismo tiempo", + "create.ponder.adjustable_repeater.text_4": "Con la rueda del ratón se puede configurar el tiempo de carga", + "create.ponder.adjustable_repeater.text_5": "Los retrasos configurados pueden variar hasta 30 minutos", + + "create.ponder.analog_lever.header": "Controlar señales mediante la palanca analógica", + "create.ponder.analog_lever.text_1": "Las palancas analógicas son una fuente compacta y precisa de energía de redstone", + "create.ponder.analog_lever.text_2": "Haz clic derecho para aumentar su potencia analógica", + "create.ponder.analog_lever.text_3": "Usa Mayús izdo + clic derecho para volver a disminuir su potencia", + + "create.ponder.andesite_tunnel.header": "Usar túneles de andesita", + "create.ponder.andesite_tunnel.text_1": "Los túneles de andesita se pueden utilizar para tapar las correas", + "create.ponder.andesite_tunnel.text_2": "Siempre que un túnel de andesita tenga conexiones a los lados...", + "create.ponder.andesite_tunnel.text_3": "...dividirá exactamente un elemento de cualquier pila que pase", + "create.ponder.andesite_tunnel.text_4": "El resto continuará su camino", + + "create.ponder.basin.header": "Procesar objetos en la cuenca", + "create.ponder.basin.text_1": "Una cuenca puede contener objetos y fluidos para su procesamiento", + "create.ponder.basin.text_2": "Después de un paso de procesamamiento, las cuencas intentan descargar por debajo a un lado de ellas", + "create.ponder.basin.text_3": "Cuando un ingrediente válido está presente, la cuenca mostrará un conducto de salida", + "create.ponder.basin.text_4": "Aquí se pueden aplicar varias opciones", + "create.ponder.basin.text_5": "Las salidas serán capturadas por el inventario que está por debajo", + "create.ponder.basin.text_6": "Sin conducto de salida, la cuenca retendrá los objetos creados en su procesamiento", + "create.ponder.basin.text_7": "Esto puede ser útil si las salidas deben ser reutilizadas como ingredientes", + "create.ponder.basin.text_8": "Las salidas deseadas tendrán que ser extraídas de la cuenca", + "create.ponder.basin.text_9": "Podría ser necesario un filtro para evitar sacar los objetos no procesados", + + "create.ponder.bearing_modes.header": "Modos de movimiento del rodamiento mecánico", + "create.ponder.bearing_modes.text_1": "Cuando se detenga, el rodamiento mecánico colocará la estructura en el ángulo más cercano alineado con la cuadrícula", + "create.ponder.bearing_modes.text_2": "Se puede configurar para que nunca vuelva a los bloques sólidos, o sólo cerca del ángulo en el que comenzó", + + "create.ponder.belt_casing.header": "Correas revestidas", + "create.ponder.belt_casing.text_1": "Se puede utilizar revestidor de latón o andesita para decorar las correas", + "create.ponder.belt_casing.text_2": "Se puede utilizar una llave inglesa para quitar el revestimiento", + + "create.ponder.belt_connector.header": "El uso de las correas mecánicas", + "create.ponder.belt_connector.text_1": "Al hacer clic derecho en dos ejes con una correa mecánica se conectarán entre sí", + "create.ponder.belt_connector.text_2": "Las selecciones accidentales pueden ser canceladas con Mayús izdo + clic derecho", + "create.ponder.belt_connector.text_3": "Se pueden añadir ejes adicionales en toda la correa", + "create.ponder.belt_connector.text_4": "Los ejes conectados a través de correas girarán con velocidad y dirección idénticas", + "create.ponder.belt_connector.text_5": "Los ejes añadidos se pueden quitar con la llave inglesa", + "create.ponder.belt_connector.text_6": "Las correas mecánicas se pueden teñir con fines estéticos", + + "create.ponder.belt_directions.header": "Orientaciones válidas para las correas mecánicas", + "create.ponder.belt_directions.text_1": "Las correas mecánicas no pueden conectarse en direcciones arbitrarias", + "create.ponder.belt_directions.text_2": "1. Pueden conectarse horizontalmente", + "create.ponder.belt_directions.text_3": "2. Pueden conectarse en diagonal", + "create.ponder.belt_directions.text_4": "3. Pueden conectarse verticalmente", + "create.ponder.belt_directions.text_5": "4. Y pueden conectar ejes verticales horizontalmente", + "create.ponder.belt_directions.text_6": "Estas son todas las direcciones posibles. Pueden abarcar cualquier longitud entre 2 y 20 bloques", + + "create.ponder.belt_transport.header": "El uso de las correas mecánicas para la logística", + "create.ponder.belt_transport.text_1": "Las correas mecánicas transportan objetos y otras entidades", + "create.ponder.belt_transport.text_2": "Haz clic derecho con la mano vacía para sacar objetos de una 'cinta'", + + "create.ponder.blaze_burner.header": "Alimentar quemadores de blaze", + "create.ponder.blaze_burner.text_1": "Los quemadores de blaze pueden proporcionar calor a los objetos procesados en una cuenca", + "create.ponder.blaze_burner.text_2": "Para ello, el blaze tiene que ser alimentado con objetos inflamables", + "create.ponder.blaze_burner.text_3": "Con un pastel de blaze, el quemador puede alcanzar un mayor nivel de calor", + "create.ponder.blaze_burner.text_4": "El proceso de alimentación puede automatizarse utilizando desplegadores o brazos mecánicos", + + "create.ponder.brass_funnel.header": "El embudo de latón", + "create.ponder.brass_funnel.text_1": "Los embudos de andesita sólo pueden extraer objetos individuales", + "create.ponder.brass_funnel.text_2": "Los embudos de latón pueden extraer hasta una pila completa", + "create.ponder.brass_funnel.text_3": "Usar la rueda de desplazamiento del ratón en la ranura para filtros permite un control preciso del tamaño de la pila extraída.", + "create.ponder.brass_funnel.text_4": "El uso de objetos en la ranura de filtrado restringirá el embudo para transferir sólo las pilas que coincidan.", + + "create.ponder.brass_tunnel.header": "Usar túneles de latón", + "create.ponder.brass_tunnel.text_1": "Los túneles de latón pueden utilizarse para tapar las correas", + "create.ponder.brass_tunnel.text_2": "Tienen ranuras de filtro en cada lado abierto", + "create.ponder.brass_tunnel.text_3": "Los filtros en las conexiones de entrada simplemente bloquean los objetos que no coincidan", + "create.ponder.brass_tunnel.text_4": "Los filtros en las conexiones de salida pueden utilizarse para ordenar los objetos por tipo", + "create.ponder.brass_tunnel.text_5": "Siempre que un objeto de paso tenga múltiples salidas válidas, el modo de distribución decidirá cómo manejarlo", + "create.ponder.brass_tunnel.text_6": "Los túneles de latón en bandas paralelas formarán un grupo", + "create.ponder.brass_tunnel.text_7": "Los objetos entrantes se distribuirán ahora por todas las salidas conectadas", + "create.ponder.brass_tunnel.text_8": "Para ello, los objetos también pueden insertarse en el bloque del túnel directamente", + + "create.ponder.brass_tunnel_modes.header": "Modos de distribución del túnel de latón", + "create.ponder.brass_tunnel_modes.text_1": "Mediante una llave inglesa se puede configurar el comportamiento de distribución de los túneles de latón", + "create.ponder.brass_tunnel_modes.text_10": "'Sincronizar entradas' es una configuración única de los túneles de latón", + "create.ponder.brass_tunnel_modes.text_11": "Las entradas sólo pueden pasar si cada túnel del grupo tiene una en espera", + "create.ponder.brass_tunnel_modes.text_12": "Esto asegura que todas las correas afectadas suministren objetos al mismo tiempo", + "create.ponder.brass_tunnel_modes.text_2": "El modo División intentará distribuir la pila uniformemente entre las salidas disponibles", + "create.ponder.brass_tunnel_modes.text_3": "Si una salida no puede tomar más objetos, se saltará", + "create.ponder.brass_tunnel_modes.text_4": "El modo División forzada nunca saltará las salidas, y en su lugar esperará hasta que estén libres", + "create.ponder.brass_tunnel_modes.text_5": "El modo Round Robin mantiene las pilas enteras, y recorre las salidas de forma iterativa", + "create.ponder.brass_tunnel_modes.text_6": "Una vez más, si una salida no puede aceptar más objetos, se saltará", + "create.ponder.brass_tunnel_modes.text_7": "El modo Round Robin forzado nunca omite salidas", + "create.ponder.brass_tunnel_modes.text_8": "El modo Preferir el más cercano prioriza las salidas más cercanas a la ubicación de entrada de los objetos", + "create.ponder.brass_tunnel_modes.text_9": "El modo Aleatorizar distribuirá pilas enteras a salidas elegidas al azar", + + "create.ponder.cart_assembler.header": "Mover estructuras usando ensambladores de vagonetas", + "create.ponder.cart_assembler.text_1": "Los ensambladores de vagonetas montan estructuras adjuntas a las vagonetas que pasan", + "create.ponder.cart_assembler.text_2": "Sin una señal de redstone, desmonta los artilugios de vagoneta que pasan de nuevo en bloques", + "create.ponder.cart_assembler.text_3": "El uso de una llave inglesa en una vagoneta te permitirá llevar el artilugio a otro lugar", + + "create.ponder.cart_assembler_dual.header": "Ensamblajes de artilugios de vagoneta", + "create.ponder.cart_assembler_dual.text_1": "Siempre que dos ensambladores de vagoneta compartan una estructura adjunta...", + "create.ponder.cart_assembler_dual.text_2": "...al alimentar a cualquiera de ellos se creará un artilugio de vagoneta", + "create.ponder.cart_assembler_dual.text_3": "Las vagonetas se comportarán como las conectadas a través del acoplamiento de vagoneta", + + "create.ponder.cart_assembler_modes.header": "Configurar la orientación de los artilugios de vagonetas", + "create.ponder.cart_assembler_modes.text_1": "Los artilugios de vagonetas girarán para orientarse hacia el movimiento de sus vagonetas", + "create.ponder.cart_assembler_modes.text_2": "Esta flecha indica qué lado de la estructura se considerará la parte delantera", + "create.ponder.cart_assembler_modes.text_3": "Si el ensamblador está configurado para bloquear la rotación, la orientación de los artilugios nunca cambiará", + + "create.ponder.cart_assembler_rails.header": "Otros tipos de vagonetas y raíles", + "create.ponder.cart_assembler_rails.text_1": "Los ensambladores de vagonetas en raíles normales no afectarán el movimiento de las vagonetas que pasen", + "create.ponder.cart_assembler_rails.text_2": "Cuando se encuentre en un raíl motorizado o en un raíl de control, las vagonetas se mantendrán en su sitio hasta que sea motorizado", + "create.ponder.cart_assembler_rails.text_3": "Se pueden utilizar otros tipos de vagonetas como anclaje", + "create.ponder.cart_assembler_rails.text_4": "Los artilugios de vagonetas de horno se mantendrán alimentados a sí mismos, sacando combustible de cualquier inventario adjunto", + + "create.ponder.chain_drive.header": "Transmitir fuerza rotacional con las cadenas de transmisión", + "create.ponder.chain_drive.text_1": "Las cadenas de transmisión transmiten la rotación entre sí en fila", + "create.ponder.chain_drive.text_2": "Todos los ejes conectados así girarán en la misma dirección", + "create.ponder.chain_drive.text_3": "Cualquier parte de la fila puede girar 90 grados usando una llave inglesa", + + "create.ponder.chain_gearshift.header": "Controlar la velocidad de rotación con la cadena de transmisión ajustable", + "create.ponder.chain_gearshift.text_1": "Las cadenas de transmisión ajustables sin alimentación se comportan exactamente como las cadenas de transmisión", + "create.ponder.chain_gearshift.text_2": "Cuando están alimentadas, la velocidad transmitida a las demás cadenas de transmisión de la fila se duplica", + "create.ponder.chain_gearshift.text_3": "Siempre que la cadena de transmisión alimentada no esté en el origen, su velocidad se reducirá a la mitad", + "create.ponder.chain_gearshift.text_4": "En ambos casos, las cadenas de transmisión de la fila siempre funcionan a 2 veces la velocidad de la cadena de transmisión alimentada", + "create.ponder.chain_gearshift.text_5": "Utilizando señales analógicas, la relación puede ajustarse con mayor precisión, entre 1 y 2", + "create.ponder.chain_gearshift.text_6": "12 RPM", + + "create.ponder.chute.header": "Transportar objetos hacia abajo a través de ductos", + "create.ponder.chute.text_1": "Los ductos pueden transportar objetos verticalmente desde y hacia los inventarios", + "create.ponder.chute.text_2": "Usando la llave inglesa, se puede crear una ventana", + "create.ponder.chute.text_3": "Colocar ductos apuntando a las caras laterales de otro lo hará en diagonal", + + "create.ponder.chute_upward.header": "Transportar objetos hacia arriba mediante ductos", + "create.ponder.chute_upward.text_1": "Usando ventiladores revestidos en la parte superior o inferior, un ducto puede transportar objetos hacia arriba", + "create.ponder.chute_upward.text_2": "Al inspeccionar los ductos con las gafas del constructor, se revela información sobre la dirección del movimiento", + "create.ponder.chute_upward.text_3": "En el extremo 'bloqueado', los objetos tendrán que ser insertados/tomados de los lados", + + "create.ponder.clockwork_bearing.header": "Animar estructuras con rodamientos tipo reloj", + "create.ponder.clockwork_bearing.text_1": "Los rodamientos tipo reloj se fijan a los bloques que tienen delante", + "create.ponder.clockwork_bearing.text_2": "Al recibir fuerza rotacional, la estructura girará según la hora del día", + "create.ponder.clockwork_bearing.text_3": "3:00", + "create.ponder.clockwork_bearing.text_4": "4:00", + "create.ponder.clockwork_bearing.text_5": "Haz clic derecho en el rodamiento para iniciar o detener la animación de la estructura", + "create.ponder.clockwork_bearing.text_6": "Delante de la manecilla de las horas se puede añadir una segunda estructura", + "create.ponder.clockwork_bearing.text_7": "Asegúrese de que las dos estructuras no están unidas entre sí con pegamento o algo similar", + "create.ponder.clockwork_bearing.text_8": "La segunda estructura ahora girará como el minutero", + + "create.ponder.clutch.header": "Controlar la fuerza rotacional mediante un embrague", + "create.ponder.clutch.text_1": "Los embragues transmitirán la rotación en línea recta", + "create.ponder.clutch.text_2": "Cuando se alimentan con redstone, rompen la conexión", + + "create.ponder.cog_speedup.header": "Cambiar de marchas con engranajes", + "create.ponder.cog_speedup.text_1": "Los engranajes grandes y pequeños pueden conectarse en diagonal", + "create.ponder.cog_speedup.text_2": "Al cambiar de engranajes grandes a pequeños, la velocidad rotacional se duplicará", + "create.ponder.cog_speedup.text_3": "Inversamente, la velocidad rotacional se reducirá a la mitad", + + "create.ponder.cogwheel.header": "Transmitir fuerza rotacional mediante engranajes", + "create.ponder.cogwheel.text_1": "Los engranajes transmitirán la rotación a otros engranajes adyacentes", + "create.ponder.cogwheel.text_2": "Los ejes adyacentes conectados así, girarán en direcciones opuestas", + + "create.ponder.creative_fluid_tank.header": "Tanque de fluídos creativo", + "create.ponder.creative_fluid_tank.text_1": "Los depósitos de fluidos creativos pueden utilizarse para proporcionar un suministro de fluidos sin fondo", + "create.ponder.creative_fluid_tank.text_2": "Haga clic con el botón derecho en un elemento que contenga fluido para configurarlo", + "create.ponder.creative_fluid_tank.text_3": "Las redes de tuberías pueden ahora extraer sin cesar el fluido asignado del depósito", + "create.ponder.creative_fluid_tank.text_4": "Cualquier fluido empujado de vuelta a un tanque de fluido creativo será anulado", + + "create.ponder.creative_motor.header": "Generar fuerza rotacional con motores creativos", + "create.ponder.creative_motor.text_1": "Los motores creativos son una fuente compacta y configurable de fuerza rotacional", + "create.ponder.creative_motor.text_2": "Usar la rueda de desplazamiento del ratón en su parte trasera cambia las RPM de la salida rotacional", + + "create.ponder.crushing_wheels.header": "Procesar objetos con las ruedas trituradoras", + "create.ponder.crushing_wheels.text_1": "Un par de ruedas trituradoras pueden moler objetos de forma muy eficaz", + "create.ponder.crushing_wheels.text_2": "Su fuerza rotacional tiene que hacerlas girar una contra otra", + "create.ponder.crushing_wheels.text_3": "Los objetos lanzados o insertados en la parte superior serán procesados", + "create.ponder.crushing_wheels.text_4": "Los objetos también pueden ser insertados y recogidos a través de medios automatizados", + + "create.ponder.deployer.header": "Usar el desplegador", + "create.ponder.deployer.text_1": "Dada la fuerza rotacional, un desplegador puede imitar las interacciones de los jugadores", + "create.ponder.deployer.text_10": "Haz clic derecho en el frente para darle un objeto a utilizar", + "create.ponder.deployer.text_11": "Los objetos también pueden ser insertados automáticamente", + "create.ponder.deployer.text_12": "Los desplegadores llevan una ranura de filtro", + "create.ponder.deployer.text_13": "Cuando se establece un filtro, sólo se activa mientras se mantiene un elemento coincidente", + "create.ponder.deployer.text_14": "Ahora sólo se pueden insertar los objetos que coincidan con el filtro...", + "create.ponder.deployer.text_15": "...y sólo se extraerán los objetos que no coincidan", + "create.ponder.deployer.text_2": "Siempre interactuará con la posición 2 bloques delante de sí mismo", + "create.ponder.deployer.text_3": "Los bloques situados directamente delante no lo obstruirán", + "create.ponder.deployer.text_4": "Los desplegadores pueden:", + "create.ponder.deployer.text_5": "Colocar bloques,", + "create.ponder.deployer.text_6": "Usar objetos,", + "create.ponder.deployer.text_7": "Activar bloques,", + "create.ponder.deployer.text_8": "Cosechar bloques", + "create.ponder.deployer.text_9": "Y atacar criaturas", + + "create.ponder.deployer_contraption.header": "Usar desplegadores en artilugios", + "create.ponder.deployer_contraption.text_1": "Siempre que los desplegadores se muevan como parte de un artilugio animado...", + "create.ponder.deployer_contraption.text_2": "Se activan en cada ubicación visitada, utilizando objetos de los inventarios de cualquier parte del artilugio", + "create.ponder.deployer_contraption.text_3": "La ranura para filtros se puede utilizar para especificar qué objetos tirar", + + "create.ponder.deployer_modes.header": "Modos del desplegador", + "create.ponder.deployer_modes.text_1": "Por defecto, un desplegador imita la interacción del clic derecho del ratón", + "create.ponder.deployer_modes.text_2": "Usando una llave inglesa, se puede configurar para imitar un clic izquierdo en su lugar", + + "create.ponder.deployer_processing.header": "Procesar objetos mediante desplegadores", + "create.ponder.deployer_processing.text_1": "Con un objeto de sujeción ajustado, los desplegadores pueden procesar los objetos proporcionados por debajo de ellos", + "create.ponder.deployer_processing.text_2": "Los objetos de entrada pueden soltarse o colocarse en un depósito bajo el desplegador", + "create.ponder.deployer_processing.text_3": "Cuando los objetos se proporcionan en una 'cinta'...", + "create.ponder.deployer_processing.text_4": "El desplegador los retendrá y procesará automáticamente", + + "create.ponder.deployer_redstone.header": "Controlar desplegadores con redstone", + "create.ponder.deployer_redstone.text_1": "Al controlar los desplegadores con redstone, éstos no se activarán", + "create.ponder.deployer_redstone.text_2": "Antes de detenerse, el desplegador terminará cualquier ciclo iniciado", + "create.ponder.deployer_redstone.text_3": "Por lo tanto, un pulso negativo puede ser utilizado para desencadenar exactamente un ciclo de activación", + + "create.ponder.depot.header": "Usar depósitos", + "create.ponder.depot.text_1": "Los depósitos pueden servir como objetos 'fijos' de la correa", + "create.ponder.depot.text_2": "Haz clic derecho para colocar o eliminar manualmente objetos del mismo", + "create.ponder.depot.text_3": "Al igual que las correas mecánicas, pueden proporcionar objetos para su procesamiento", + "create.ponder.depot.text_4": "...así como proporcionar objetos a los brazos mecánicos", + + "create.ponder.empty_blaze_burner.header": "Usar quemadores de blaze vacíos", + "create.ponder.empty_blaze_burner.text_1": "Haz clic derecho en un blaze con el quemador vacío para capturarlo", + "create.ponder.empty_blaze_burner.text_2": "Alternativamente, los blaze pueden ser recogidos de sus spawners directamente", + "create.ponder.empty_blaze_burner.text_3": "Ahora tienes una fuente de calor ideal para varias máquinas", + "create.ponder.empty_blaze_burner.text_4": "Por motivos estéticos, los quemadores de blaze vacíos también se pueden encender con pedernal y acero", + "create.ponder.empty_blaze_burner.text_5": "La llama puede transformarse utilizando un objeto con alma", + "create.ponder.empty_blaze_burner.text_6": "Sin embargo, no son adecuados para la calefacción industrial", + + "create.ponder.encased_fluid_pipe.header": "Revestir tuberías de fluídos", + "create.ponder.encased_fluid_pipe.text_1": "El revestidor de cobre puede utilizarse para decorar las tuberías de fluidos", + "create.ponder.encased_fluid_pipe.text_2": "Además de estar ocultas, las tuberías revestidas están bloqueadas en su estado de conectividad", + "create.ponder.encased_fluid_pipe.text_3": "Ya no reaccionará a los bloques vecinos que se añadan o eliminen", + + "create.ponder.fan_direction.header": "El flujo de aire de los ventiladores revestidos", + "create.ponder.fan_direction.text_1": "Los ventiladores revestidos utilizan la fuerza rotacional para crear una corriente de aire", + "create.ponder.fan_direction.text_2": "La fuerza y la dirección del flujo dependen de la fuerza rotacional suministrada", + + "create.ponder.fan_processing.header": "Procesar objetos mediante ventiladores revestidos", + "create.ponder.fan_processing.text_1": "Al pasar por lava, el flujo de aire se calienta", + "create.ponder.fan_processing.text_2": "Los objetos capturados en la zona serán fundidos", + "create.ponder.fan_processing.text_3": "Los artículos de comida arrojados aquí serán incinerados", + "create.ponder.fan_processing.text_4": "En su lugar, se debería utilizar una instalación de ahumado, usando fuego", + "create.ponder.fan_processing.text_5": "Los flujos de aire que pasan por el agua crean una instalación de lavado", + "create.ponder.fan_processing.text_6": "Se puede hacer un nuevo e interesante procesamiento con él", + "create.ponder.fan_processing.text_7": "La velocidad del ventilador NO afecta a la velocidad de procesamiento, sólo a su rango", + "create.ponder.fan_processing.text_8": "El procesamiento del ventilador también puede aplicarse a los objetos de los depósitos y las correas", + + "create.ponder.fan_source.header": "Generar fuerza rotacional mediante ventiladores revestidos", + "create.ponder.fan_source.text_1": "Los ventiladores orientados hacia una fuente de calor pueden proporcionar fuerza rotacional", + "create.ponder.fan_source.text_2": "Cuando se les da una señal de redstone, los ventiladores comenzarán a proporcionar fuerza", + + "create.ponder.fluid_pipe_flow.header": "Transportar fluidos mediante tuberías de cobre", + "create.ponder.fluid_pipe_flow.text_1": "Las tuberías de fluidos pueden conectar dos o más fuentes y objetivos de fluidos", + "create.ponder.fluid_pipe_flow.text_2": "Utilizando una llave, se puede dar a un segmento de tubo recto una ventana", + "create.ponder.fluid_pipe_flow.text_3": "Las tuberías con ventanas no se conectarán a ningún otro segmento de tubería adyacente", + "create.ponder.fluid_pipe_flow.text_4": "Accionadas por bombas mecánicas, las tuberías pueden transportar fluidos", + "create.ponder.fluid_pipe_flow.text_5": "Al principio no se extrae ningún líquido", + "create.ponder.fluid_pipe_flow.text_6": "Una vez que el flujo los conecta, los puntos finales transfieren gradualmente su contenido", + "create.ponder.fluid_pipe_flow.text_7": "Así, los bloques de tuberías nunca contienen 'físicamente' ningún fluido", + + "create.ponder.fluid_pipe_interaction.header": "Drenaje y llenado de contenedores de fluidos", + "create.ponder.fluid_pipe_interaction.text_1": "Los puntos finales de una red de tuberías pueden interactuar con una variedad de bloques", + "create.ponder.fluid_pipe_interaction.text_2": "Cualquier bloque con capacidad para almacenar fluidos puede ser llenado o vaciado", + "create.ponder.fluid_pipe_interaction.text_3": "Los bloques de origen justo delante de un extremo abierto pueden ser recogidos...", + "create.ponder.fluid_pipe_interaction.text_4": "...mientras que el derrame en espacios vacíos puede crear fuentes de fluidos", + "create.ponder.fluid_pipe_interaction.text_5": "Las tuberías también pueden extraer fluidos de un puñado de otros bloques directamente", + + "create.ponder.fluid_tank_sizes.header": "Dimensiones de un depósito de fluidos", + "create.ponder.fluid_tank_sizes.text_1": "Los depósitos de fluidos pueden combinarse para aumentar la capacidad total", + "create.ponder.fluid_tank_sizes.text_2": "Su cuadrado base puede tener hasta 3 bloques de ancho...", + "create.ponder.fluid_tank_sizes.text_3": "...y crecen en altura en más de 30 capas adicionales", + "create.ponder.fluid_tank_sizes.text_4": "Con una llave inglesa, se puede cambiar la ventana de un tanque", + + "create.ponder.fluid_tank_storage.header": "Almacenar fluidos en depósitos de fluidos", + "create.ponder.fluid_tank_storage.text_1": "Los depósitos de fluidos pueden utilizarse para almacenar grandes cantidades de fluidos", + "create.ponder.fluid_tank_storage.text_2": "Las redes de tuberías pueden empujar y arrastrar fluidos desde cualquier lado", + "create.ponder.fluid_tank_storage.text_3": "El fluido contenido puede ser medido por un Comparador", + "create.ponder.fluid_tank_storage.text_4": "Sin embargo, en el Modo Supervivencia no se pueden añadir o tomar fluidos manualmente", + "create.ponder.fluid_tank_storage.text_5": "Puede utilizar cuencas, drenadores de objetos y tuberías para vaciar o llenar objetos que contengan líquido", + + "create.ponder.flywheel.header": "Generar fuerza rotacional con la rueda de inercia", + "create.ponder.flywheel.text_1": "Las ruedas de inercia son necesarias para generar fuerza rotacional con el motor de horno", + "create.ponder.flywheel.text_2": "La fuerza rotacional proporcionada tiene una capacidad de estrés muy grande", + "create.ponder.flywheel.text_3": "El uso de un alto horno duplicará la eficiencia del motor", + + "create.ponder.funnel_compat.header": "Compatibilidades con el embudo", + "create.ponder.funnel_compat.text_1": "Los embudos deberían interactuar bien con un puñado de otros componentes", + "create.ponder.funnel_compat.text_2": "Sierras verticales", + "create.ponder.funnel_compat.text_3": "Depósitos", + "create.ponder.funnel_compat.text_4": "Drenadores de objetos", + + "create.ponder.funnel_direction.header": "Dirección de la transferencia", + "create.ponder.funnel_direction.text_1": "Colocado normalmente, extrae objetos del inventario", + "create.ponder.funnel_direction.text_2": "Colocado mientras pulsa Mayús izdo, pone objetos en el inventario", + "create.ponder.funnel_direction.text_3": "Usando una llave inglesa, el embudo puede ser volteado después de su colocación", + "create.ponder.funnel_direction.text_4": "Se aplicarán las mismas reglas para la mayoría de las orientaciones", + "create.ponder.funnel_direction.text_5": "Los embudos en las correas extraerán/insertarán dependiendo de su dirección de movimiento", + + "create.ponder.funnel_intro.header": "Usar embudos", + "create.ponder.funnel_intro.text_1": "Los embudos son ideales para transferir objetos desde y hacia los inventarios", + + "create.ponder.funnel_redstone.header": "Embudos alimentados con redstone", + "create.ponder.funnel_redstone.text_1": "La energía de redstone impedirá la actuación de cualquier embudo", + + "create.ponder.funnel_transfer.header": "Transferencia directa", + "create.ponder.funnel_transfer.text_1": "Los embudos no pueden transferir nunca entre inventarios cerrados directamente", + "create.ponder.funnel_transfer.text_2": "Los ductos o los ductos inteligentes podrían ser más adecuados para estos fines", + "create.ponder.funnel_transfer.text_3": "Lo mismo se aplica para el movimiento horizontal. Una correa mecánica debería ayudar aquí", + + "create.ponder.furnace_engine.header": "Generar fuerza rotacional con el motor de horno", + "create.ponder.furnace_engine.text_1": "Los motores de horno generan fuerza rotacional mientras su horno adjunto está funcionando", + "create.ponder.furnace_engine.text_2": "La fuerza rotacional proporcionada tiene una capacidad de estrés muy grande", + "create.ponder.furnace_engine.text_3": "El uso de un alto horno duplicará la eficiencia del motor", + + "create.ponder.gantry_carriage.header": "Usar carros de grúa", + "create.ponder.gantry_carriage.text_1": "Los carros de grúa pueden montarse y deslizarse a lo largo de un eje de grúa", + "create.ponder.gantry_carriage.text_2": "Las instalaciones de grúa pueden mover bloques adjuntos", + + "create.ponder.gantry_cascaded.header": "Grúas en cascada", + "create.ponder.gantry_cascaded.text_1": "Los ejes de grúas se unen a un carro de grúa sin necesidad de pegamento", + "create.ponder.gantry_cascaded.text_2": "Lo mismo se aplica a los carros de grúa en los ejes de grúas desplazados", + "create.ponder.gantry_cascaded.text_3": "Así, un sistema de grúas puede estar en cascada para cubrir múltiples ejes de movimiento", + + "create.ponder.gantry_direction.header": "Dirección del movimiento de la grúa", + "create.ponder.gantry_direction.text_1": "Los ejes de grúa pueden tener orientaciones opuestas", + "create.ponder.gantry_direction.text_2": "La dirección de movimiento de los carros de grúa depende de la orientación de sus ejes", + "create.ponder.gantry_direction.text_3": "...así como de su sentido de rotación", + "create.ponder.gantry_direction.text_4": "Se aplican las mismas reglas para la rotación propagada", + + "create.ponder.gantry_redstone.header": "Propagación de la potencia de la grúa", + "create.ponder.gantry_redstone.text_1": "Los ejes de grúa alimentados con redstone dejan de mover sus carros", + "create.ponder.gantry_redstone.text_2": "En su lugar, su fuerza rotacional se transmite al eje de salida de los carros", + + "create.ponder.gantry_shaft.header": "Usar ejes de grúa", + "create.ponder.gantry_shaft.text_1": "Los ejes de grúa forman la base de una instalación de grúas. Los carros adjuntos se moverán a lo largo de ellos", + "create.ponder.gantry_shaft.text_2": "Las instalaciones de grúas pueden mover los bloques adjuntos", + + "create.ponder.gearbox.header": "Transmitir fuerza rotacional mediante cajas de transmisión", + "create.ponder.gearbox.text_1": "Saltar entre ejes de rotación puede volverse voluminoso rápidamente", + "create.ponder.gearbox.text_2": "Una caja de transmisión es el equivalente más compacto de esta configuración", + "create.ponder.gearbox.text_3": "Los ejes giran en las direcciones reflejadas...", + "create.ponder.gearbox.text_4": "...esto quiere decir que las conexiones rectas se invierten", + + "create.ponder.gearshift.header": "Controlar la dirección rotacional mediante una caja de cambios", + "create.ponder.gearshift.text_1": "La caja de cambios transmitirá la rotación en línea recta", + "create.ponder.gearshift.text_2": "Cuando es alimentada con redstone, invierte la transmisión", + + "create.ponder.hand_crank.header": "Generar fuerza rotacional mediante manivelas", + "create.ponder.hand_crank.text_1": "Las manivelas pueden ser utilizadas para aplicar fuerza rotacional manualmente", + "create.ponder.hand_crank.text_2": "Mantén pulsado clic derecho para girar en sentido antihorario", + "create.ponder.hand_crank.text_3": "Su velocidad de transmisión es relativamente alta", + "create.ponder.hand_crank.text_4": "Mayús izdo + clic derecho pulsado para girar en sentido horario", + + "create.ponder.hose_pulley.header": "Llenado y vaciado de fuentes mediante poleas de manguera", + "create.ponder.hose_pulley.text_1": "Las poleas para mangueras pueden utilizarse para llenar o drenar grandes masas de fluido", + "create.ponder.hose_pulley.text_2": "Con entrada cinética, se puede controlar la altura de la manguera de las poleas", + "create.ponder.hose_pulley.text_3": "La polea se retrae mientras la rotación de entrada se invierte", + "create.ponder.hose_pulley.text_4": "En el lado opuesto, se pueden conectar las tuberías", + "create.ponder.hose_pulley.text_5": "Las redes de tuberías conectadas pueden proporcionar fluido a la manguera...", + "create.ponder.hose_pulley.text_6": "...o tirar de él, vaciando la piscina en su lugar", + "create.ponder.hose_pulley.text_7": "La velocidad de llenado y vaciado de la polea depende totalmente del caudal de las redes de fluidos", + + "create.ponder.hose_pulley_infinite.header": "Llenado y drenaje pasivo de grandes masas de fluido", + "create.ponder.hose_pulley_infinite.text_1": "Al desplegar la polea de manguera en un océano lo suficientemente grande...", + "create.ponder.hose_pulley_infinite.text_2": "Proporcionará/eliminará fluidos sin afectar a la fuente", + "create.ponder.hose_pulley_infinite.text_3": "Las redes de tuberías pueden llevar fluidos de forma ilimitada desde/hacia dichas poleas", + + "create.ponder.hose_pulley_level.header": "Nivel de llenado y vaciado de las poleas de las mangueras", + "create.ponder.hose_pulley_level.text_1": "Mientras esté totalmente retraída, la polea de la manguera no puede funcionar", + "create.ponder.hose_pulley_level.text_2": "El drenaje va de arriba a abajo", + "create.ponder.hose_pulley_level.text_3": "El nivel de la superficie terminará justo debajo de donde termina la manguera", + "create.ponder.hose_pulley_level.text_4": "El llenado va de abajo a arriba", + "create.ponder.hose_pulley_level.text_5": "La piscina llena no crecerá más allá de la capa por encima del extremo de la manguera", + + "create.ponder.item_drain.header": "Vaciar contenedores de fluidos mediante drenajes de objetos", + "create.ponder.item_drain.text_1": "Los drenajes de objetos pueden extraer los fluidos de los objetos", + "create.ponder.item_drain.text_2": "Haz clic derecho para verter los fluidos de tu objeto retenido en él", + "create.ponder.item_drain.text_3": "Cuando los artículos se insertan desde el lado...", + "create.ponder.item_drain.text_4": "...ruedan a través, vaciando su líquido contenido", + "create.ponder.item_drain.text_5": "Las redes de tuberías pueden ahora extraer el fluido del buffer interno de los desagües", + + "create.ponder.large_cogwheel.header": "Transmitir fuerza rotacional mediante engranajes grandes", + "create.ponder.large_cogwheel.text_1": "Los engranajes grandes pueden conectarse entre sí en ángulo recto", + "create.ponder.large_cogwheel.text_2": "Ayudarán a transmitir la velocidad transportada a otros ejes de rotación.", + + "create.ponder.linear_chassis_attachment.header": "Fijar bloques mediante el chasis lineal", + "create.ponder.linear_chassis_attachment.text_1": "Las caras abiertas de un chasis lineal pueden hacerse pegajosas", + "create.ponder.linear_chassis_attachment.text_2": "Haz clic de nuevo para que se pegue el lado opuesto", + "create.ponder.linear_chassis_attachment.text_3": "Mayús izdo + clic derecho con la mano vacía para eliminar el pegamento", + "create.ponder.linear_chassis_attachment.text_4": "Las caras pegadas del chasis lineal fijarán una línea de bloques delante de él", + "create.ponder.linear_chassis_attachment.text_5": "Utilizando una llave inglesa, se puede especificar un rango preciso", + "create.ponder.linear_chassis_attachment.text_6": "Manteniendo pulsada la tecla [Ctrl] y usando la rueda central del ratón, se ajusta el rango de todos los bloques de chasis adjuntos", + "create.ponder.linear_chassis_attachment.text_7": "Para fijar los bloques a cualquier otro lado es necesario utilizar pegamento", + "create.ponder.linear_chassis_attachment.text_8": "Utilizando esta mecánica, las estructuras de cualquier forma pueden moverse como un artilugio", + + "create.ponder.linear_chassis_group.header": "Mover chasis lineales en grupos", + "create.ponder.linear_chassis_group.text_1": "Los chasis lineales se conectan a los bloques de chasis idénticos que se encuentren a su lado", + "create.ponder.linear_chassis_group.text_2": "Cuando uno es movido por un artilugio, los otros son arrastrados con él", + "create.ponder.linear_chassis_group.text_3": "Los chasis de otro tipo u orientados en otra dirección no se fijan", + + "create.ponder.mechanical_arm.header": "Configurar los brazos mecánicos", + "create.ponder.mechanical_arm.text_1": "A los brazos mecánicos hay que asignarles sus entradas y salidas antes de colocarlos", + "create.ponder.mechanical_arm.text_2": "Clic derecho en los inventarios mientras mantiene el brazo mecánico para asignarlos como objetivos", + "create.ponder.mechanical_arm.text_3": "Clic derecho denuevo para alternar entre la entrada (azul) y la salida (naranja)", + "create.ponder.mechanical_arm.text_4": "Clic izquierdo en los componentes para eliminar su selección", + "create.ponder.mechanical_arm.text_5": "Una vez colocado, el brazo mecánico apuntará a los bloques seleccionados previamente", + "create.ponder.mechanical_arm.text_6": "Pueden tener cualquier cantidad de entradas y salidas dentro de su rango", + "create.ponder.mechanical_arm.text_7": "Sin embargo, no se puede interactuar directamente con todos los tipos de inventario", + "create.ponder.mechanical_arm.text_8": "Los embudos y depósitos pueden ayudar a salvar esa distancia", + + "create.ponder.mechanical_arm_filtering.header": "Filtrar salidas del brazo mecánico", + "create.ponder.mechanical_arm_filtering.text_1": "Entradas", + "create.ponder.mechanical_arm_filtering.text_2": "Salidas", + "create.ponder.mechanical_arm_filtering.text_3": "A veces es conveniente restringir los objetivos del brazo mecánico haciendo coincidir un filtro", + "create.ponder.mechanical_arm_filtering.text_4": "Por sí mismos no ofrecen ninguna opción de filtrado", + "create.ponder.mechanical_arm_filtering.text_5": "Sin embargo, los embudos de latón como objetivos comunican su propio filtro al brazo", + "create.ponder.mechanical_arm_filtering.text_6": "El brazo mecánico es lo suficientemente inteligente como para no recoger objetos que no podría distribuir", + + "create.ponder.mechanical_arm_modes.header": "Modos de distribución del brazo mecánico", + "create.ponder.mechanical_arm_modes.text_1": "Entradas", + "create.ponder.mechanical_arm_modes.text_2": "Salidas", + "create.ponder.mechanical_arm_modes.text_3": "Siempre que un brazo tenga que elegir entre varias salidas válidas...", + "create.ponder.mechanical_arm_modes.text_4": "...funcionará según su configuración", + "create.ponder.mechanical_arm_modes.text_5": "Usando la rueda del ratón con una llave inglesa te permitirá configurarlo", + "create.ponder.mechanical_arm_modes.text_6": "El modo Round Robin simplemente hace un ciclo a través de todas las salidas que están disponibles", + "create.ponder.mechanical_arm_modes.text_7": "Si una salida no puede admitir más objetos, se omitirá", + "create.ponder.mechanical_arm_modes.text_8": "El modo Round Robin forzado nunca omitirá las salidas, sino que esperará a que estén libres", + "create.ponder.mechanical_arm_modes.text_9": "Preferir el primero da prioridad a las salidas seleccionadas anteriormente al configurar este brazo", + + "create.ponder.mechanical_arm_redstone.header": "Controlar brazos mecánicos con redstone", + "create.ponder.mechanical_arm_redstone.text_1": "Cuando se alimentan con redstone, los brazos mecánicos no se activan", + "create.ponder.mechanical_arm_redstone.text_2": "Antes de detenerse, terminará los ciclos iniciados", + "create.ponder.mechanical_arm_redstone.text_3": "Así, un pulso negativo puede utilizarse para activar exactamente un ciclo de activación", + + "create.ponder.mechanical_bearing.header": "Mover estructuras mediante el rodamiento mecánico", + "create.ponder.mechanical_bearing.text_1": "Los rodamientos mecánicos se fijan al bloque que tienen delante", + "create.ponder.mechanical_bearing.text_2": "Al recibir fuerza rotacional, la ensamblará en un artilugio giratorio", + + "create.ponder.mechanical_crafter.header": "Configurar ensambladores mecánicos", + "create.ponder.mechanical_crafter.text_1": "Se puede utilizar una serie de ensambladores mecánicos para automatizar cualquier receta de elaboración.", + "create.ponder.mechanical_crafter.text_2": "Usando una llave inglesa, puedes establecer los caminos de los ensambladores ", + "create.ponder.mechanical_crafter.text_3": "Para que la configuración sea válida, todos los caminos tienen que converger en una salida, en cualquiera de los lados", + "create.ponder.mechanical_crafter.text_4": "Los puertos de salida de objetos se colocarán en un inventario a la salida", + "create.ponder.mechanical_crafter.text_5": "Los ensambladores mecánicos requieren fuerza rotacional para funcionar", + "create.ponder.mechanical_crafter.text_6": "Haga clic derecho en la parte delantera para insertar objetos manualmente", + "create.ponder.mechanical_crafter.text_7": "Una vez que cada ranura de una ruta contenga un objeto, comenzará el proceso de elaboración", + "create.ponder.mechanical_crafter.text_8": "Para las recetas que no ocupen totalmente la instalación del ensamblador, se puede forzar el arranque utilizando un pulso de redstone", + + "create.ponder.mechanical_crafter_connect.header": "Conectar inventarios a los ensambladores mecánicos", + "create.ponder.mechanical_crafter_connect.text_1": "Los objetos pueden ser insertados a los ensambladores mecánicos automáticamente", + "create.ponder.mechanical_crafter_connect.text_2": "Utilizando la llave inglesa a sus espaldas, las entradas pueden combinarse", + "create.ponder.mechanical_crafter_connect.text_3": "Ahora se puede acceder a todos los ensambladores mecánicos conectados por la misma ubicación de entrada", + + "create.ponder.mechanical_crafter_covers.header": "Cubrir las ranuras de los ensambladores mecánicos", + "create.ponder.mechanical_crafter_covers.text_1": "Algunas recetas requerirán ensambladores mecánicos adicionales para salvar las brechas en el camino", + "create.ponder.mechanical_crafter_covers.text_2": "Utilizando las tapas de ranuras del ensamblador mecánico, pueden actuar como una ranura vacía a su disposición", + "create.ponder.mechanical_crafter_covers.text_3": "Las entradas compartidas creadas con la llave inglesa en la parte posterior también pueden llegar a través de los ensambladores revestidos", + + "create.ponder.mechanical_drill.header": "Romper bloques con el taladro mecánico", + "create.ponder.mechanical_drill.text_1": "Cuando se le aplica fuerza rotacional, el taladro mecánico rompe los bloques que tiene delante.", + "create.ponder.mechanical_drill.text_2": "Su velocidad de trabajo depende de la fuerza rotacional suministrada", + + "create.ponder.mechanical_drill_contraption.header": "Usar taladros mecánicos en artilugios", + "create.ponder.mechanical_drill_contraption.text_1": "Siempre que los taladros mecánicos se muevan como parte de un artilugio animado...", + "create.ponder.mechanical_drill_contraption.text_2": "...romperán los bloques por los que artilugio los hace pasar", + + "create.ponder.mechanical_harvester.header": "Utilizar cosechadoras mecánicas en artilugios", + "create.ponder.mechanical_harvester.text_1": "Siempre que las cosechadoras mecánicas se muevan como parte de un artilugio animado...", + "create.ponder.mechanical_harvester.text_2": "...recogerán y repondrán los cultivos maduros en su camino", + + "create.ponder.mechanical_mixer.header": "Procesar objetos con la mezcladora mecánica", + "create.ponder.mechanical_mixer.text_1": "Con una mezcladora mecánica y una cuenca, se pueden automatizar algunas recetas", + "create.ponder.mechanical_mixer.text_2": "Las recetas disponibles incluyen cualquier receta de elaboración amorfa, además de un par de recetas adicionales", + "create.ponder.mechanical_mixer.text_3": "Algunas de esas recetas pueden requerir el calor de un quemador de blaze", + "create.ponder.mechanical_mixer.text_4": "La ranura para filtros se puede utilizar en caso de que dos recetas sean conflictivas.", + + "create.ponder.mechanical_piston.header": "Mover estructuras mediante pistones mecánicos", + "create.ponder.mechanical_piston.text_1": "Los pistones mecánicos pueden mover los bloques que tienen delante", + "create.ponder.mechanical_piston.text_2": "La velocidad y la dirección del movimiento dependen de la fuerza rotacional suministrada", + "create.ponder.mechanical_piston.text_3": "Los pistones mecánicos pegajosos pueden tirar de los bloques unidos hacia atrás", + + "create.ponder.mechanical_piston_modes.header": "Modos de movimiento del pistón mecánico", + "create.ponder.mechanical_piston_modes.text_1": "Cuando los pistones mecánicos dejan de moverse, la estructura movida vuelve a los bloques", + "create.ponder.mechanical_piston_modes.text_2": "Puede configurarse para que no vuelva nunca a los bloques sólidos, o sólo en la ubicación en la que comenzó", + + "create.ponder.mechanical_plough.header": "Utilizar arados mecánicos en los artilugios", + "create.ponder.mechanical_plough.text_1": "Cuando los arados mecánicos se mueven como parte de un artilugio animado...", + "create.ponder.mechanical_plough.text_2": "...romperán los bloques sin un hitbox de colisión sólido", + "create.ponder.mechanical_plough.text_3": "Además, pueden crear tierras de cultivo", + "create.ponder.mechanical_plough.text_4": "...también pueden lanzar entidades sin dañarlas", + + "create.ponder.mechanical_press.header": "Procesar objetos con la prensa mecánica", + "create.ponder.mechanical_press.text_1": "La prensa mecánica puede procesar los objetos proporcionados por debajo de ella", + "create.ponder.mechanical_press.text_2": "Los objetos de entrada pueden soltarse o colocarse en un depósito bajo la prensa", + "create.ponder.mechanical_press.text_3": "Cuando los objetos se proporcionan en una 'cinta'...", + "create.ponder.mechanical_press.text_4": "...la prensa mecánica los retendrá y procesará automáticamente", + + "create.ponder.mechanical_press_compacting.header": "Compactar objetos con la prensa mecánica", + "create.ponder.mechanical_press_compacting.text_1": "Al presionar los objetos que se encuentran en una cuenca, éstos se compactan.", + "create.ponder.mechanical_press_compacting.text_2": "La compactación incluye cualquier receta de elaboración de 2x2 o 3x3 rellena, además de un par extra", + "create.ponder.mechanical_press_compacting.text_3": "Algunas de esas recetas pueden requerir el calor de un quemador de blaze", + "create.ponder.mechanical_press_compacting.text_4": "La ranura para filtros se puede utilizar en caso de que dos recetas sean conflictivas.", + + "create.ponder.mechanical_pump_flow.header": "Transportar fluidos mediante bombas mecánicas", + "create.ponder.mechanical_pump_flow.text_1": "Las bombas mecánicas gobiernan el flujo de sus redes de tuberías anexas", + "create.ponder.mechanical_pump_flow.text_2": "Cuando están alimentadas, su flecha indica la dirección del flujo", + "create.ponder.mechanical_pump_flow.text_3": "La red de atrás está ahora tirando de fluidos...", + "create.ponder.mechanical_pump_flow.text_4": "...mientras la red de enfrente la transfiere hacia el exterior", + "create.ponder.mechanical_pump_flow.text_5": "Al invertir la rotación de la entrada se invierte el sentido del flujo", + "create.ponder.mechanical_pump_flow.text_6": "Utilice una llave inglesa para invertir la orientación de las bombas manualmente", + + "create.ponder.mechanical_pump_speed.header": "Rendimiento de las bombas mecánicas", + "create.ponder.mechanical_pump_speed.text_1": "Independientemente de la velocidad, las bombas mecánicas afectan a las tuberías conectadas hasta 16 bloques de distancia", + "create.ponder.mechanical_pump_speed.text_2": "Acelerar la rotación de entrada cambia la velocidad de propagación del flujo...", + "create.ponder.mechanical_pump_speed.text_3": "...así como la rapidez con la que se transfieren los fluidos", + "create.ponder.mechanical_pump_speed.text_4": "Las bombas pueden combinar sus rendimientos en redes de tuberías compartidas", + "create.ponder.mechanical_pump_speed.text_5": "Alternar su orientación puede ayudar a alinear sus direcciones de flujo", + + "create.ponder.mechanical_saw_breaker.header": "Cortar árboles con la sierra mecánica", + "create.ponder.mechanical_saw_breaker.text_1": "Cuando se le da una fuerza rotacional, la sierra mecánica cortará los árboles que estén directamente frente a ella", + "create.ponder.mechanical_saw_breaker.text_2": "Para poder cortar el árbol por completo, la sierra tiene que romper el último bloque que lo une al suelo", + + "create.ponder.mechanical_saw_contraption.header": "Utilizar sierras mecánicas en artilugios", + "create.ponder.mechanical_saw_contraption.text_1": "Cuando las sierras mecánicas se mueven como parte de un artilugio animado...", + "create.ponder.mechanical_saw_contraption.text_2": "...cortarán cualquier árbol con el que el artilugio se tope", + + "create.ponder.mechanical_saw_processing.header": "Procesar objetos en la sierra mecánica", + "create.ponder.mechanical_saw_processing.text_1": "Las sierras mecánicas orientadas hacia arriba pueden procesar una variedad de objetos", + "create.ponder.mechanical_saw_processing.text_2": "El objeto procesado siempre se mueve en contra de la fuerza rotacional de la sierra", + "create.ponder.mechanical_saw_processing.text_3": "Las sierras mecánicas pueden trabajar en línea con las correas mecánicas", + "create.ponder.mechanical_saw_processing.text_4": "Cuando un ingrediente tiene varios resultados posibles, la ranura para filtros puede especificarlo", + "create.ponder.mechanical_saw_processing.text_5": "Sin filtro, al contrario, la sierra mecánica pasaría por todos los resultados", + + "create.ponder.millstone.header": "Procesar objetos en la piedra de molino", + "create.ponder.millstone.text_1": "Las piedras de molino procesan los objetos mediante la molienda", + "create.ponder.millstone.text_2": "Se pueden accionar lateralmente mediante engranajes...", + "create.ponder.millstone.text_3": "... y tirar o insertar objetos en la parte superior", + "create.ponder.millstone.text_4": "Después de un tiempo, el resultado se puede obtener usando el clic derecho del ratón", + "create.ponder.millstone.text_5": "Las salidas también pueden extraerse mediante la automatización", + + "create.ponder.nixie_tube.header": "Usar los tubos Nixie", + "create.ponder.nixie_tube.text_1": "Cuando son alimentados con redstone, los tubos nixie mostrarán la fuerza de las señales de redstone", + "create.ponder.nixie_tube.text_2": "Con las etiquetas editadas en un yunque, pueden mostar un texto personalizado", + "create.ponder.nixie_tube.text_3": "Haga clic derecho con un tinte para cambiar su color de visualización", + + "create.ponder.piston_pole.header": "Pértigas de extensión de pistones", + "create.ponder.piston_pole.text_1": "Sin las pértigas de extensión unidas, un pistón mecánico no puede moverse", + "create.ponder.piston_pole.text_2": "La longitud de la pértiga añadida en su parte posterior determina el rango de alcance", + + "create.ponder.portable_fluid_interface.header": "Interfaz de fluidos portátil", + "create.ponder.portable_fluid_interface.text_1": "No se puede acceder a los depósitos de fluidos de los artilugios en movimiento por ninguna tubería", + "create.ponder.portable_fluid_interface.text_2": "Este componente puede interactuar con los depósitos de fluidos sin necesidad de detener el artilugio", + "create.ponder.portable_fluid_interface.text_3": "Coloca una segunda con un espacio de 1 o 2 bloques entre ellas", + "create.ponder.portable_fluid_interface.text_4": "Cada vez que pasen por delante de la otra, entablarán una conexión", + "create.ponder.portable_fluid_interface.text_5": "Mientras esté activada, la interfaz estacionaria representará TODOS los tanques del artilugio", + "create.ponder.portable_fluid_interface.text_6": "Ahora se puede introducir el fluido...", + "create.ponder.portable_fluid_interface.text_7": "...o extraerlo del artilugio", + "create.ponder.portable_fluid_interface.text_8": "Cuando no se intercambien contenidos durante un tiempo, el artilugio seguirá su camino", + + "create.ponder.portable_storage_interface.header": "Interfaz de almacenamiento portátil", + "create.ponder.portable_storage_interface.text_1": "Los jugadores no pueden acceder a los inventarios de los artilugios en movimiento.", + "create.ponder.portable_storage_interface.text_2": "Este componente puede interactuar con el almacenamiento sin necesidad de detener el artilugio.", + "create.ponder.portable_storage_interface.text_3": "Coloca una segunda unidad con un espacio de 1 o 2 bloques entre ellas", + "create.ponder.portable_storage_interface.text_4": "Cada vez que pasen por delante del otro, entablarán una conexión", + "create.ponder.portable_storage_interface.text_5": "Mientras esté conectada, la interfaz fija representará TODOS los inventarios del artilugio", + "create.ponder.portable_storage_interface.text_6": "Ahora pueden insertarse objetos...", + "create.ponder.portable_storage_interface.text_7": "...o extraerse", + "create.ponder.portable_storage_interface.text_8": "Cuando no se hayan intercambiado objetos durante un tiempo, el artilugio seguirá su camino", + + "create.ponder.portable_storage_interface_redstone.header": "Interfaz de almacenamiento portátil controlada por redstone", + "create.ponder.portable_storage_interface_redstone.text_1": "La energía de redstone impedirá que las interfaces de almacenamiento portátil se conecten", + + "create.ponder.powered_latch.header": "Controlar señales mediante la palanca motorizada", + "create.ponder.powered_latch.text_1": "Las palancas motorizadas son palancas controlables por redstone", + "create.ponder.powered_latch.text_2": "Las señales en la parte trasera la encienden", + "create.ponder.powered_latch.text_3": "Las señales sobre un lateral la vuelven a apagar", + "create.ponder.powered_latch.text_4": "Las palancas motorizadas también se pueden accionar manualmente", + + "create.ponder.powered_toggle_latch.header": "Controlar señales mediante la palanca de cierre motorizada", + "create.ponder.powered_toggle_latch.text_1": "Las palancas de cierre motorizadas son palancas controlables por redstone", + "create.ponder.powered_toggle_latch.text_2": "Las señales en la parte trasera cambiarán su estado...", + "create.ponder.powered_toggle_latch.text_3": "...encender y apagar", + "create.ponder.powered_toggle_latch.text_4": "Las palancas de cierre motorizadas también se pueden accionar manualmente", + + "create.ponder.pulse_repeater.header": "Controlar señales mediante repetidores de pulsos", + "create.ponder.pulse_repeater.text_1": "Los repetidores de pulsos acortan cualquier señal de redstone a un solo pulso", + + "create.ponder.radial_chassis.header": "Fijar bloques mediante chasis radiales", + "create.ponder.radial_chassis.text_1": "Los chasis radiales se conectan a bloques de chasis idénticos en una fila", + "create.ponder.radial_chassis.text_2": "Cuando uno es movido por un artilugio, los otros son arrastrados con él", + "create.ponder.radial_chassis.text_3": "Las caras laterales de un chasis radial pueden hacerse adhesivas", + "create.ponder.radial_chassis.text_4": "Haga clic de nuevo para que todos los demás lados sean pegajosos", + "create.ponder.radial_chassis.text_5": "Mayús izdo + clic derecho con la mano vacía para eliminar el pegamento", + "create.ponder.radial_chassis.text_6": "Cada vez que un bloque está junto a una cara pegajosa...", + "create.ponder.radial_chassis.text_7": "...adjuntará todos los bloques alcanzables dentro de un radio en esa capa", + "create.ponder.radial_chassis.text_8": "Con una llave inglesa y usando la rueda de desplazamiento del ratón se puede especificar un radio preciso", + "create.ponder.radial_chassis.text_9": "Los bloques no alcanzables por ninguna cara adhesiva no se fijarán", + + "create.ponder.redstone_contact.header": "Contactos de redstone", + "create.ponder.redstone_contact.text_1": "Los contactos de redstone enfrentados emitirán una señal de redstone", + "create.ponder.redstone_contact.text_2": "Esto sigue siendo válido cuando uno de ellos forma parte de un artilugio en movimiento", + + "create.ponder.redstone_link.header": "Usar los enlaces de redstone", + "create.ponder.redstone_link.text_1": "Los enlaces de redstone pueden transmitir señales redstone de forma inalámbrica", + "create.ponder.redstone_link.text_2": "Mayús izdo + clic derecho para cambiar el modo de recepción", + "create.ponder.redstone_link.text_3": "Un simple clic derecho con una llave inglesa puede hacer lo mismo", + "create.ponder.redstone_link.text_4": "Los receptores emiten la potencia de redstone de los transmisores en 128 bloques", + "create.ponder.redstone_link.text_5": "Colocando objetos en las dos ranuras puede especificar una frecuencia", + "create.ponder.redstone_link.text_6": "Sólo se comunicarán los enlaces con frecuencias coincidentes", + + "create.ponder.rope_pulley.header": "Mover estructuras con poleas de cuerda", + "create.ponder.rope_pulley.text_1": "Las poleas de cuerda pueden mover los bloques verticalmente cuando se les aplica una fuerza rotacional", + "create.ponder.rope_pulley.text_2": "La dirección y la velocidad del movimiento dependen de la fuerza rotacional suministrada", + + "create.ponder.rope_pulley_attachment.header": "Mover poleas como parte de un artilugio", + "create.ponder.rope_pulley_attachment.text_1": "Siempre que las poleas de cuerda sean movidas por un artilugio...", + "create.ponder.rope_pulley_attachment.text_2": "...su estructura adjunta será arrastrada con ella", + "create.ponder.rope_pulley_attachment.text_3": "Tenga en cuenta que las poleas de cuerda sólo se mueven cuando están paradas", + + "create.ponder.rope_pulley_modes.header": "Modos de movimiento de la polea de cuerda", + "create.ponder.rope_pulley_modes.text_1": "Cuando las poleas de cuerda dejan de moverse, la estructura movida vuelve a los bloques", + "create.ponder.rope_pulley_modes.text_2": "Puede configurarse para que no vuelva nunca a los bloques sólidos, o sólo en la ubicación en la que comenzó", + + "create.ponder.rotation_speed_controller.header": "Usar el controlador de velocidad rotacional", + "create.ponder.rotation_speed_controller.text_1": "Los controladores de velocidad rotacional transmiten la rotación de su eje a un engranaje grande situado encima.", + "create.ponder.rotation_speed_controller.text_2": "Utilizando la rueda de desplazamiento del ratón, puede configurarse la velocidad rotacional", + + "create.ponder.sail.header": "Montar molinos de viento usando velas", + "create.ponder.sail.text_1": "Las velas son bloques muy útiles para crear molinos de viento", + "create.ponder.sail.text_2": "Se fijarán a los bloques y entre sí sin necesidad de pegamento o bloques de chasis", + "create.ponder.sail.text_3": "Clic derecho con un tinte para pintarlas", + "create.ponder.sail.text_4": "Clic derecho con una tijera para volver a convertirlas en marcos", + + "create.ponder.sail_frame.header": "Montar molinos de viento con marcos de vela", + "create.ponder.sail_frame.text_1": "Los marcos de vela son prácticos bloques para crear molinos de viento", + "create.ponder.sail_frame.text_2": "Se fijarán a los bloques y entre sí sin necesidad de pegamento o bloques de chasis", + + "create.ponder.sequenced_gearshift.header": "Controlar la velocidad de rotación mediante la caja de cambios secuenciales", + "create.ponder.sequenced_gearshift.text_1": "La caja de cambios secuencial retransmite la rotación siguiendo una lista cronometrada de instrucciones", + "create.ponder.sequenced_gearshift.text_2": "Haga clic con el botón derecho para abrir la interfaz de configuración", + "create.ponder.sequenced_gearshift.text_3": "Al recibir una señal de redstone, comenzará a ejecutar su secuencia configurada", + "create.ponder.sequenced_gearshift.text_4": "Una vez terminado, espera la siguiente señal de redstone y vuelve a empezar", + "create.ponder.sequenced_gearshift.text_5": "Se puede utilizar un comparador de redstone para leer el progreso actual", + + "create.ponder.shaft.header": "Transmitir fuerza rotacional mediante ejes", + "create.ponder.shaft.text_1": "Los ejes transmiten la rotación en línea recta.", + + "create.ponder.shaft_casing.header": "Ejes revestidos", + "create.ponder.shaft_casing.text_1": "Puedes utilizar el revestidor de latón o de andesita para decorar tus ejes", + + "create.ponder.smart_chute.header": "Filtrar objetos mediante ductos inteligentes", + "create.ponder.smart_chute.text_1": "Los ductos inteligentes son ductos verticales con control adicional", + "create.ponder.smart_chute.text_2": "Los objetos en la ranura para filtros especifican lo que pueden extraer y transferir exactamente", + "create.ponder.smart_chute.text_3": "Usa la rueda del ratón para especificar el tamaño de la pila extraída", + "create.ponder.smart_chute.text_4": "La energía de redstone impedirá que funcionen.", + + "create.ponder.smart_pipe.header": "Controlar el flujo de fluidos mediante tuberías inteligentes", + "create.ponder.smart_pipe.text_1": "Las tuberías inteligentes pueden ayudar a controlar los flujos por tipo de fluido", + "create.ponder.smart_pipe.text_2": "Cuando se colocan directamente en la fuente, pueden especificar el tipo de fluido a extraer", + "create.ponder.smart_pipe.text_3": "Simplemente haga clic derecho en su ranura de filtro con cualquier elemento que contenga el fluido deseado", + "create.ponder.smart_pipe.text_4": "Cuando se colocan detrás de una red de tuberías, las tuberías inteligentes sólo dejan que los fluidos coincidentes continúen", + + "create.ponder.speedometer.header": "Controlar la información cinética mediante el velocímetro", + "create.ponder.speedometer.text_1": "El velocímetro muestra la velocidad actual de los componentes conectados", + "create.ponder.speedometer.text_2": "Cuando se usan las gafas del constructor, el jugador puede obtener información más detallada del medidor", + "create.ponder.speedometer.text_3": "Los comparadores pueden emitir señales analógicas de redstone en relación con las mediciones del velocímetro", + + "create.ponder.spout_filling.header": "Llenar objetos con un surtidor", + "create.ponder.spout_filling.text_1": "El surtidor puede llenar los elementos de retención de fluidos que se encuentran debajo de él", + "create.ponder.spout_filling.text_2": "No se puede acceder manualmente al contenido de un surtidor", + "create.ponder.spout_filling.text_3": "En su lugar, se pueden utilizar tuberías para suministrarle fluidos", + "create.ponder.spout_filling.text_4": "Los objetos de entrada pueden colocarse en un depósito bajo el surtidor", + "create.ponder.spout_filling.text_5": "Cuando los artículos se proporcionan en una cinta...", + "create.ponder.spout_filling.text_6": "El surtidor los retendrá y procesará automáticamente", + + "create.ponder.stabilized_bearings.header": "Estabilizar artilugios", + "create.ponder.stabilized_bearings.text_1": "Siempre que los rodamientos mecánicos formen parte de una estructura móvil...", + "create.ponder.stabilized_bearings.text_2": "...intentarán mantenerse derechos", + "create.ponder.stabilized_bearings.text_3": "Una vez más, el rodamiento se unirá al bloque de enfrente", + "create.ponder.stabilized_bearings.text_4": "Como resultado, todo el sub-artilugio se mantendrá en posición vertical", + + "create.ponder.sticker.header": "Fijar bloques con stickers", + "create.ponder.sticker.text_1": "Los stickers son ideales para la fijación de bloques controlados por redstone", + "create.ponder.sticker.text_2": "Al recibir una señal, cambiarán su estado", + "create.ponder.sticker.text_3": "Si ahora se mueve en un artilugio, el bloque se moverá con él", + "create.ponder.sticker.text_4": "Si se vuelve a activar, el bloque dejará de estar fijado", + + "create.ponder.stressometer.header": "Supervisar la información cinética con el estresómetro", + "create.ponder.stressometer.text_1": "El estresómetro muestra la capacidad de estrés actual de la red cinética conectada", + "create.ponder.stressometer.text_2": "Cuando se usan las gafas del constructor, el jugador puede obtener información más detallada del medidor", + "create.ponder.stressometer.text_3": "Los comparadores pueden emitir señales analógicas de redstone en relación con las mediciones del estresómetro", + + "create.ponder.super_glue.header": "Fijar bloques con pegamento", + "create.ponder.super_glue.text_1": "Se puede utilizar pegamento entre dos bloques cualquiera", + "create.ponder.super_glue.text_2": "Los bloques fijados se moverán juntos cuando se ensamblen en un artilugio", + "create.ponder.super_glue.text_3": "Cada vez que el pegamento es sostenido en la mano...", + "create.ponder.super_glue.text_4": "...los bloques añadidos se pegarán a la cara en la que fueron colocados automáticamente", + "create.ponder.super_glue.text_5": "El pegamento se puede quitar con un clic izquierdo", + + "create.ponder.valve_handle.header": "Generar fuerza rotacional mediante asas de válvula", + "create.ponder.valve_handle.text_1": "Los jugadores pueden utilizar las asas de válvulas para aplicar fuerza rotacional manualmente", + "create.ponder.valve_handle.text_2": "Mantén pulsado el clic derecho para rotar en sentido contrario a las agujas del reloj", + "create.ponder.valve_handle.text_3": "Su velocidad de transmisión es lenta y precisa", + "create.ponder.valve_handle.text_4": "Mayús izdo + clic derecho para rotar en el sentido de las agujas del reloj", + "create.ponder.valve_handle.text_5": "Las asas de las válvulas pueden teñirse con fines estéticos", + + "create.ponder.valve_pipe.header": "Controlar el flujo de fluidos mediante válvulas", + "create.ponder.valve_pipe.text_1": "Las tuberías con válvulas ayudan a controlar los fluidos que se propagan por las redes de tuberías", + "create.ponder.valve_pipe.text_2": "Su entrada en el eje controla si el fluido puede pasar por", + "create.ponder.valve_pipe.text_3": "Dada la fuerza de rotación en la dirección de apertura, la válvula se abrirá", + "create.ponder.valve_pipe.text_4": "Se puede volver a cerrar invirtiendo el giro de entrada", + + "create.ponder.water_wheel.header": "Generar fuerza rotacional mediante ruedas hidráulicas", + "create.ponder.water_wheel.text_1": "Las ruedas hidráulicas extraen la fuerza de las corrientes de agua adyacentes", + "create.ponder.water_wheel.text_2": "Cuantas más caras se alimenten, más rápido girará", + "create.ponder.water_wheel.text_3": "Las paletas de las ruedas deben estar orientadas en contra del flujo", + "create.ponder.water_wheel.text_4": "Orientadas hacia el lado contrario, no serán tan eficaces", + + "create.ponder.weighted_ejector.header": "Usar eyectores de peso", + "create.ponder.weighted_ejector.text_1": "Mayús izdo + clic derecho sosteniendo un eyector de peso para seleccionar la ubicación de destino", + "create.ponder.weighted_ejector.text_10": "Ahora estára limitado a este tamaño de pila, y sólo se activara cuando su pila retenida alcance esta cantidad", + "create.ponder.weighted_ejector.text_11": "Otras entidades activarán el eyector al pisarlos", + "create.ponder.weighted_ejector.text_2": "El eyector colocado lanzará ahora los objetos al lugar marcado", + "create.ponder.weighted_ejector.text_3": "Un objetivo válido puede estar a cualquier altura o distancia dentro del alcance", + "create.ponder.weighted_ejector.text_4": "Sin embargo, no pueden estar a un costado", + "create.ponder.weighted_ejector.text_5": "Si no se ha seleccionado ningún objetivo válido, simplemente se dirigirá al bloque que se encuentra justo delante", + "create.ponder.weighted_ejector.text_6": "Suministrale fuerza rotacional para cargarlo", + "create.ponder.weighted_ejector.text_7": "Los objetos colocados en el eyector hacen que se dispare", + "create.ponder.weighted_ejector.text_8": "Si se dirigen a un inventario, el eyector esperará hasta que haya espacio", + "create.ponder.weighted_ejector.text_9": "Con la llave inglesa se puede configurar el tamaño de pila requerido", + + "create.ponder.weighted_ejector_redstone.header": "Controlar los eyectores de peso con redstone", + "create.ponder.weighted_ejector_redstone.text_1": "Cuando se alimentan con redstone, los eyectores no se activan", + "create.ponder.weighted_ejector_redstone.text_2": "Además, los observadores de contenido pueden detectar cuando los eyectores se activan", + + "create.ponder.weighted_ejector_tunnel.header": "Dividir pilas de objetos mediante eyectores de peso", + "create.ponder.weighted_ejector_tunnel.text_1": "En combinación con los túneles de latón, los eyectores de peso pueden dividir las pilas de objetos en cantidades específicas", + "create.ponder.weighted_ejector_tunnel.text_2": "En primer lugar, configure el túnel de latón en 'Preferir lo más cercano', para dar prioridad a su salida lateral", + "create.ponder.weighted_ejector_tunnel.text_3": "El tamaño de la pila fijado en el eyector determina ahora la cantidad que se va a dividir", + "create.ponder.weighted_ejector_tunnel.text_4": "Mientras una nueva pila del tamaño configurado se expulse por la salida lateral...", + "create.ponder.weighted_ejector_tunnel.text_5": "...el resto seguirá su camino", + + "create.ponder.windmill_source.header": "Generar fuerza rotacional mediante rodamientos del molino de viento", + "create.ponder.windmill_source.text_1": "Los rodamientos del molino de viento se fijan al bloque que tienen delante", + "create.ponder.windmill_source.text_2": "Si se unen suficientes bloques tipo vela al bloque, éste puede actuar como un molino de viento", + "create.ponder.windmill_source.text_3": "Activado con un clic derecho, el rodamiento del molino de viento comenzará a proporcionar fuerza rotacional", + "create.ponder.windmill_source.text_4": "La cantidad de bloques de vela determina su velocidad de rotación", + "create.ponder.windmill_source.text_5": "Utiliza una llave inglesa para configurar su sentido de rotación", + "create.ponder.windmill_source.text_6": "Haga clic derecho sobre el rodamiento del molino en cualquier momento para detener y editar la estructura de nuevo", + + "create.ponder.windmill_structure.header": "Artilugios para molinos de viento", + "create.ponder.windmill_structure.text_1": "Cualquier estructura puede contar como un molino de viento válido, siempre que contenga al menos 8 bloques tipo vela.", "_": "Thank you for translating Create!" diff --git a/src/generated/resources/assets/create/lang/unfinished/es_mx.json b/src/generated/resources/assets/create/lang/unfinished/es_mx.json deleted file mode 100644 index f3de8dd15..000000000 --- a/src/generated/resources/assets/create/lang/unfinished/es_mx.json +++ /dev/null @@ -1,2110 +0,0 @@ -{ - "_": "Missing Localizations: 1266", - - "_": "->------------------------] Game Elements [------------------------<-", - - "block.create.acacia_window": "Ventana de Acacia", - "block.create.acacia_window_pane": "Panel de Ventana de Acacia", - "block.create.adjustable_chain_gearshift": "Cambio Ajustable de Velocidad de Cadena", - "block.create.adjustable_crate": "Caja Ajustable", - "block.create.adjustable_pulse_repeater": "Repetidor de Pulso Ajustable", - "block.create.adjustable_repeater": "Repetidor Ajustable", - "block.create.analog_lever": "Palanca Analogica", - "block.create.andesite_belt_funnel": "UNLOCALIZED: Andesite Belt Funnel", - "block.create.andesite_bricks": "Ladrillos de Andesita", - "block.create.andesite_bricks_slab": "Losa de Ladrillos de Andesita", - "block.create.andesite_bricks_stairs": "Escaleras de Ladrillos de Andesita", - "block.create.andesite_bricks_wall": "Pared de Ladrillos de Andesita", - "block.create.andesite_casing": "Carcasa de Andesita", - "block.create.andesite_cobblestone": "Piedra Labrada de Andesita", - "block.create.andesite_cobblestone_slab": "Losa de Piedra Labrada de Andesita", - "block.create.andesite_cobblestone_stairs": "Escaleras de Piedra Labrada de Andesita", - "block.create.andesite_cobblestone_wall": "Pared de Piedra Labrada de Andesita", - "block.create.andesite_encased_shaft": "Eje empotrado de Andesita", - "block.create.andesite_funnel": "Embudo de Andesita", - "block.create.andesite_pillar": "Pilar de Andesita", - "block.create.andesite_tunnel": "Túnel de Andesita", - "block.create.basin": "Cuenco", - "block.create.belt": "Correa", - "block.create.birch_window": "Ventana de Abedul", - "block.create.birch_window_pane": "Panel de Ventana de Abedul", - "block.create.black_sail": "Vela Negra", - "block.create.black_seat": "Asiento Negro", - "block.create.black_valve_handle": "Manija de Válvula Negra", - "block.create.blaze_burner": "Quemador de Blaze", - "block.create.blue_sail": "Vela Azul", - "block.create.blue_seat": "Asiento Azul", - "block.create.blue_valve_handle": "Manija de Válvula Azul", - "block.create.brass_belt_funnel": "UNLOCALIZED:Brass Belt Funnel", - "block.create.brass_block": "Bloque de Latón", - "block.create.brass_casing": "Carcasa de Latón", - "block.create.brass_encased_shaft": "Eje empotrado de Latón", - "block.create.brass_funnel": "Embudo de Latón", - "block.create.brass_tunnel": "Túnel de Latón", - "block.create.brown_sail": "Vela Café", - "block.create.brown_seat": "Asiento Café ", - "block.create.brown_valve_handle": "Manija de Válvula Café", - "block.create.cart_assembler": "Ensamblador de Vagonetas", - "block.create.chiseled_dark_scoria": "Escoria Oscura Grabada", - "block.create.chiseled_dolomite": "Dolomita Grabada", - "block.create.chiseled_gabbro": "Gabro Grabado", - "block.create.chiseled_limestone": "Caliza Grabada", - "block.create.chiseled_scoria": "Escoria Grabada", - "block.create.chiseled_weathered_limestone": "Caliza Meteorizada Grabada", - "block.create.chocolate": "Chocolate", - "block.create.chute": "Vertedor", - "block.create.clockwork_bearing": "Rodamiento de Reloj", - "block.create.clutch": "Embrague", - "block.create.cogwheel": "Rueda Dentada", - "block.create.content_observer": "Observador de Contenido", - "block.create.controller_rail": "Vía de Control", - "block.create.copper_backtank": "UNLOCALIZED: Copper Backtank", - "block.create.copper_block": "Bloque de Cobre", - "block.create.copper_casing": "Carcasa de Cobre", - "block.create.copper_ore": "Mineral de Cobre", - "block.create.copper_shingles": "Techado de Cobre", - "block.create.copper_tiles": "Baldosas de Cobre", - "block.create.copper_valve_handle": "Manija de Válvula de Cobre", - "block.create.creative_crate": "Caja del Creativo", - "block.create.creative_fluid_tank": "Tanque de Fluido del Creativo", - "block.create.creative_motor": "Motor del Creativo", - "block.create.crimson_window": "Ventana Carmesí", - "block.create.crimson_window_pane": "Panel de Ventana Carmesí", - "block.create.crushing_wheel": "Rueda Trituradora", - "block.create.crushing_wheel_controller": "UNLOCALIZED:Crushing Wheel Controller", - "block.create.cuckoo_clock": "Reloj Cuco", - "block.create.cyan_sail": "Vela Cian", - "block.create.cyan_seat": "Asiento Cian", - "block.create.cyan_valve_handle": "Manija de Válvula Cian", - "block.create.dark_oak_window": "Ventana de Roble Oscuro", - "block.create.dark_oak_window_pane": "Panel de Ventana de Roble Oscuro", - "block.create.dark_scoria": "Escoria Oscura", - "block.create.dark_scoria_bricks": "Ladrillos de Escoria Oscura", - "block.create.dark_scoria_bricks_slab": "Losa de Ladrillos de Escoria Oscura", - "block.create.dark_scoria_bricks_stairs": "Escaleras de Ladrillos de Escoria Oscura", - "block.create.dark_scoria_bricks_wall": "Pared de Ladrillos de Escoria Oscura", - "block.create.dark_scoria_cobblestone": "Piedra Labrada de Escoria Oscura", - "block.create.dark_scoria_cobblestone_slab": "Losa de Piedra Labrada de Escoria Oscura", - "block.create.dark_scoria_cobblestone_stairs": "Escaleras de Piedra Labrada de Escoria Oscura", - "block.create.dark_scoria_cobblestone_wall": "Pared de Piedra Labrada de Escoria Oscura", - "block.create.dark_scoria_pillar": "Pilar de Escoria Oscura", - "block.create.deployer": "Desplegador", - "block.create.depot": "Depósito", - "block.create.diorite_bricks": "Ladrillos de Diorita", - "block.create.diorite_bricks_slab": "Losa de Ladrillos de Diorita", - "block.create.diorite_bricks_stairs": "Escaleras de Ladrillos de Diorita", - "block.create.diorite_bricks_wall": "Pared de Ladrillos de Diorita", - "block.create.diorite_cobblestone": "Piedra Labrada de Diorita", - "block.create.diorite_cobblestone_slab": "Losa de Piedra Labrada de Diorita", - "block.create.diorite_cobblestone_stairs": "Escaleras de Piedra Labrada de Diorita", - "block.create.diorite_cobblestone_wall": "Pared de Piedra Labrada de Diorita", - "block.create.diorite_pillar": "Pared de Diorita", - "block.create.dolomite": "Dolomita", - "block.create.dolomite_bricks": "Ladrillos de Dolomita", - "block.create.dolomite_bricks_slab": "Losa de Ladrillos de Dolomita", - "block.create.dolomite_bricks_stairs": "Escaleras de Ladrillos de Dolomita", - "block.create.dolomite_bricks_wall": "Pared de Ladrillos de Dolomita", - "block.create.dolomite_cobblestone": "Piedra Labrada de Dolomita", - "block.create.dolomite_cobblestone_slab": "Losa de Piedra Labrada de Dolomita", - "block.create.dolomite_cobblestone_stairs": "Escaleras de Piedra Labrada de Dolomita", - "block.create.dolomite_cobblestone_wall": "Pared de Piedra Labrada de Dolomita", - "block.create.dolomite_pillar": "Pilar de Dolomita", - "block.create.encased_chain_drive": "Transmisión de Cadena Empotrada", - "block.create.encased_fan": "Ventilador Acoplado", - "block.create.encased_fluid_pipe": "Tubería de Fluidos Recubierta", - "block.create.fancy_andesite_bricks": "Ladrillos de Andesita Elegantes", - "block.create.fancy_andesite_bricks_slab": "Losa de Ladrillos de Andesita Elegantes", - "block.create.fancy_andesite_bricks_stairs": "Escaleras de Ladrillos de Andesita Elegantes", - "block.create.fancy_andesite_bricks_wall": "Pared de Ladrillos de Andesita Elegantes", - "block.create.fancy_dark_scoria_bricks": "Ladrillos de Escoria Oscura Elegantes", - "block.create.fancy_dark_scoria_bricks_slab": "Losa de Ladrillos de Escoria Oscura Elegantes", - "block.create.fancy_dark_scoria_bricks_stairs": "Escaleras de Ladrillos de Escoria Oscura Elegantes", - "block.create.fancy_dark_scoria_bricks_wall": "Pared de Ladrillos de Escoria Oscura Elegantes", - "block.create.fancy_diorite_bricks": "Ladrillos de Diorita Elegantes", - "block.create.fancy_diorite_bricks_slab": "Losa de Ladrillos de Diorita Elegantes", - "block.create.fancy_diorite_bricks_stairs": "Escaleras de Ladrillos de Diorita Elegantes", - "block.create.fancy_diorite_bricks_wall": "Pared de Ladrillos de Diorita Elegantes", - "block.create.fancy_dolomite_bricks": "Ladrillos de Dolomita Elegantes", - "block.create.fancy_dolomite_bricks_slab": "Losa de Ladrillos de Dolomita Elegantes", - "block.create.fancy_dolomite_bricks_stairs": "Escaleras de Ladrillos de Dolomita Elegantes", - "block.create.fancy_dolomite_bricks_wall": "Pared de Ladrillos de Dolomita Elegantes", - "block.create.fancy_gabbro_bricks": "Ladrillos de Gabro Elegantes", - "block.create.fancy_gabbro_bricks_slab": "Losa Ladrillos de Gabro Elegantes", - "block.create.fancy_gabbro_bricks_stairs": "Escaleras Ladrillos de Gabro Elegantes", - "block.create.fancy_gabbro_bricks_wall": "Pared de Ladrillos de Gabro Elegantes", - "block.create.fancy_granite_bricks": "Ladrillos de Granito Elegantes", - "block.create.fancy_granite_bricks_slab": "Losa de Ladrillos de Granito Elegantes", - "block.create.fancy_granite_bricks_stairs": "Escaleras de Ladrillos de Granito Elegantes", - "block.create.fancy_granite_bricks_wall": "Pared de Ladrillos de Granito Elegantes", - "block.create.fancy_limestone_bricks": "Ladrillos de Caliza Elegantes", - "block.create.fancy_limestone_bricks_slab": "Losa de Ladrillos de Caliza Elegantes", - "block.create.fancy_limestone_bricks_stairs": "Escaleras de Ladrillos de Caliza Elegantes", - "block.create.fancy_limestone_bricks_wall": "Pared de Ladrillos de Caliza Elegantes", - "block.create.fancy_scoria_bricks": "Ladrillos de Escoria Elegantes", - "block.create.fancy_scoria_bricks_slab": "Losa de Ladrillos de Escoria Elegantes", - "block.create.fancy_scoria_bricks_stairs": "Escaleras de Ladrillos de Escoria Elegantes", - "block.create.fancy_scoria_bricks_wall": "Pared de Ladrillos de Escoria Elegantes", - "block.create.fancy_weathered_limestone_bricks": "Ladrillos de Caliza Meteorizada Elegantes", - "block.create.fancy_weathered_limestone_bricks_slab": "Losa de Ladrillos de Caliza Meteorizada Elegantes", - "block.create.fancy_weathered_limestone_bricks_stairs": "Escaleras de Ladrillos de Caliza Meteorizada Elegantes", - "block.create.fancy_weathered_limestone_bricks_wall": "Pared de Ladrillos de Caliza Meteorizada Elegantes", - "block.create.fluid_pipe": "Tubería de Fluidos", - "block.create.fluid_tank": "Tanque de Fluidos", - "block.create.fluid_valve": "Válvula de Fluidos", - "block.create.flywheel": "Rueda de Inercia", - "block.create.framed_glass": "Vidrio Enmarcado", - "block.create.framed_glass_pane": "Panel de Vidrio Enmarcado", - "block.create.furnace_engine": "Motor de Horno", - "block.create.gabbro": "Gabro", - "block.create.gabbro_bricks": "Ladrillos de Gabro", - "block.create.gabbro_bricks_slab": "Losa de Ladrillos de Gabro", - "block.create.gabbro_bricks_stairs": "Escaleras de Ladrillos de Gabro", - "block.create.gabbro_bricks_wall": "Pared de Ladrillos de Gabro", - "block.create.gabbro_cobblestone": "Piedra Labrada de Gabro", - "block.create.gabbro_cobblestone_slab": "Losa de Piedra Labrada de Gabro", - "block.create.gabbro_cobblestone_stairs": "Escaleras de Piedra Labrada de Gabro", - "block.create.gabbro_cobblestone_wall": "Pared de Piedra Labrada de Gabro", - "block.create.gabbro_pillar": "Pilar de Gabro", - "block.create.gantry_carriage": "UNLOCALIZED: Gantry Carriage", - "block.create.gantry_shaft": "UNLOCALIZED: Gantry Shaft", - "block.create.gearbox": "Transmisión", - "block.create.gearshift": "Cambio de Marcha", - "block.create.glass_fluid_pipe": "Tubería de Fluidos de Vidrio", - "block.create.granite_bricks": "Ladrillos de Granito", - "block.create.granite_bricks_slab": "Losa de Ladrillos de Granito", - "block.create.granite_bricks_stairs": "Escaleras de Ladrillos de Granito", - "block.create.granite_bricks_wall": "Pared de Ladrillos de Granito", - "block.create.granite_cobblestone": "Piedra Labrada de Granito", - "block.create.granite_cobblestone_slab": "Losa de Piedra Labrada de Granito", - "block.create.granite_cobblestone_stairs": "Escaleras de Piedra Labrada de Granito", - "block.create.granite_cobblestone_wall": "Pared de Piedra Labrada de Granito", - "block.create.granite_pillar": "Pilar de Granito", - "block.create.gray_sail": "Vela Gris", - "block.create.gray_seat": "Asiento Gris", - "block.create.gray_valve_handle": "Manija de Válvula Gris", - "block.create.green_sail": "Vela Verde", - "block.create.green_seat": "Asiento Verde", - "block.create.green_valve_handle": "Manija de Válvula Verde", - "block.create.hand_crank": "Manivela", - "block.create.honey": "Miel", - "block.create.horizontal_framed_glass": "Vidrio Enmarcado Horizontal", - "block.create.horizontal_framed_glass_pane": "Panel de Vidrio Enmarcado Horizontal", - "block.create.hose_pulley": "Polea con Manguera", - "block.create.item_drain": "Extractor de Fluidos", - "block.create.jungle_window": "Ventana de Jungla", - "block.create.jungle_window_pane": "Panel de Ventana de Jungla", - "block.create.large_cogwheel": "Rueda Dentada Grande", - "block.create.layered_andesite": "Andesita en Capas", - "block.create.layered_dark_scoria": "Escoria Oscura en Capas", - "block.create.layered_diorite": "Diorita en Capas", - "block.create.layered_dolomite": "Dolomita en Capas", - "block.create.layered_gabbro": "Gabro en Capas", - "block.create.layered_granite": "Granito en Capas", - "block.create.layered_limestone": "Caliza en Capas", - "block.create.layered_scoria": "Escoria en Capas", - "block.create.layered_weathered_limestone": "Caliza Meteorizada en Capas", - "block.create.light_blue_sail": "Vela Azul Claro", - "block.create.light_blue_seat": "Asiento Azul Claro", - "block.create.light_blue_valve_handle": "Manija de Válvula Azul Claro", - "block.create.light_gray_sail": "Vela Gris Claro", - "block.create.light_gray_seat": "Asiento Gris Claro", - "block.create.light_gray_valve_handle": "Manija de Válvula Gris Claro", - "block.create.lime_sail": "Vela Verde Lima", - "block.create.lime_seat": "Asiento Verde Lima", - "block.create.lime_valve_handle": "Manija de Válvula Verde Lima", - "block.create.limesand": "Arena de Caliza", - "block.create.limestone": "Caliza", - "block.create.limestone_bricks": "Ladrillos de Caliza", - "block.create.limestone_bricks_slab": "Losa de Ladrillos de Caliza", - "block.create.limestone_bricks_stairs": "Escaleras de Ladrillos de Caliza", - "block.create.limestone_bricks_wall": "Pared de Ladrillos de Caliza", - "block.create.limestone_cobblestone": "Piedra Labrada de Caliza", - "block.create.limestone_cobblestone_slab": "Losa de Piedra Labrada de Caliza", - "block.create.limestone_cobblestone_stairs": "Escaleras de Piedra Labrada de Caliza", - "block.create.limestone_cobblestone_wall": "Pared de Piedra Labrada de Caliza", - "block.create.limestone_pillar": "Pilar de Caliza", - "block.create.linear_chassis": "Chasis Lineal", - "block.create.lit_blaze_burner": "Quemador de Blaze Iluminado", - "block.create.magenta_sail": "Vela Magenta", - "block.create.magenta_seat": "Asiento Magenta", - "block.create.magenta_valve_handle": "Manija de Válvula Magenta", - "block.create.mechanical_arm": "Brazo Mecánico", - "block.create.mechanical_bearing": "Rodamiento Mecánico", - "block.create.mechanical_crafter": "Crafter Mecánico", - "block.create.mechanical_drill": "Taladro Mecánico", - "block.create.mechanical_harvester": "Cosechador Mecánico", - "block.create.mechanical_mixer": "Mezcladora Mecánica", - "block.create.mechanical_piston": "Pistón Mecánico", - "block.create.mechanical_piston_head": "Cabeza de Pistón Mecánico", - "block.create.mechanical_plough": "Arado Mecánico", - "block.create.mechanical_press": "Prensa Mecánica", - "block.create.mechanical_pump": "Bomba Mecánica", - "block.create.mechanical_saw": "Sierra Mecánica", - "block.create.metal_bracket": "Soporte de Metal", - "block.create.millstone": "Molino", - "block.create.minecart_anchor": "Ancla de Vagonetas", - "block.create.mossy_andesite": "Andesita Musgosa", - "block.create.mossy_dark_scoria": "Escoria Oscura Musgosa", - "block.create.mossy_diorite": "Diorita Musgosa", - "block.create.mossy_dolomite": "Dolomita Musgosa", - "block.create.mossy_gabbro": "Gabro Musgoso", - "block.create.mossy_granite": "Granito Musgoso", - "block.create.mossy_limestone": "Caliza Musgosa", - "block.create.mossy_scoria": "Escoria Musgosa", - "block.create.mossy_weathered_limestone": "Caliza Meteorizada Musgosa", - "block.create.mysterious_cuckoo_clock": "Reloj Cuco", - "block.create.natural_scoria": "Escoria Natural", - "block.create.nixie_tube": "Tubo Nixie", - "block.create.nozzle": "Boquilla", - "block.create.oak_window": "Ventana de Roble", - "block.create.oak_window_pane": "Panel de Ventana de Roble", - "block.create.orange_sail": "Vela Naranja", - "block.create.orange_seat": "Asiento Naranja", - "block.create.orange_valve_handle": "Manija de Válvula Naranja", - "block.create.ornate_iron_window": "Ventana Ornamentada", - "block.create.ornate_iron_window_pane": "Panel de Ventana Ornamentada", - "block.create.overgrown_andesite": "Andesita Descuidada", - "block.create.overgrown_dark_scoria": "Escoria Oscura Descuidada", - "block.create.overgrown_diorite": "Diorita Descuidada", - "block.create.overgrown_dolomite": "Dolomita Descuidada", - "block.create.overgrown_gabbro": "Gabro Descuidado", - "block.create.overgrown_granite": "Granito Descuidado", - "block.create.overgrown_limestone": "Caliza Descuidada", - "block.create.overgrown_scoria": "Escoria Descuidada", - "block.create.overgrown_weathered_limestone": "Caliza Meteorizada Descuidada", - "block.create.paved_andesite": "Andesita Pavimentada", - "block.create.paved_andesite_slab": "Losa de Andesita Pavimentada", - "block.create.paved_andesite_stairs": "Escaleras de Andesita Pavimentada", - "block.create.paved_andesite_wall": "Pared de Andesita Pavimentada", - "block.create.paved_dark_scoria": "Escoria Oscura Pavimentada", - "block.create.paved_dark_scoria_slab": "Losa de Escoria Oscura Pavimentada", - "block.create.paved_dark_scoria_stairs": "Escaleras de Escoria Oscura Pavimentada", - "block.create.paved_dark_scoria_wall": "Pared de Escoria Oscura Pavimentada", - "block.create.paved_diorite": "Diorita Pavimentada", - "block.create.paved_diorite_slab": "Losa de Diorita Pavimentada", - "block.create.paved_diorite_stairs": "Escaleras de Diorita Pavimentada", - "block.create.paved_diorite_wall": "Pared de Diorita Pavimentada", - "block.create.paved_dolomite": "Dolomita Pavimentada", - "block.create.paved_dolomite_slab": "Losa de Dolomita Pavimentada", - "block.create.paved_dolomite_stairs": "Escaleras de Dolomita Pavimentada", - "block.create.paved_dolomite_wall": "Pared de Dolomita Pavimentada", - "block.create.paved_gabbro": "Gabro Pavimentado", - "block.create.paved_gabbro_slab": "Losa de Gabro Pavimentado", - "block.create.paved_gabbro_stairs": "Escaleras de Gabro Pavimentado", - "block.create.paved_gabbro_wall": "Pared de Gabro Pavimentado", - "block.create.paved_granite": "Granito Pavimentado", - "block.create.paved_granite_slab": "Losa de Granito Pavimentado", - "block.create.paved_granite_stairs": "Escaleras de Granito Pavimentado", - "block.create.paved_granite_wall": "Pared de Granito Pavimentado", - "block.create.paved_limestone": "Caliza Pavimentada", - "block.create.paved_limestone_slab": "Losa de Caliza Pavimentada", - "block.create.paved_limestone_stairs": "Escaleras de Caliza Pavimentada", - "block.create.paved_limestone_wall": "Pared de Caliza Pavimentada", - "block.create.paved_scoria": "Escoria Pavimentada", - "block.create.paved_scoria_slab": "Losa de Escoria Pavimentada", - "block.create.paved_scoria_stairs": "Escaleras de Escoria Pavimentada", - "block.create.paved_scoria_wall": "Pared de Escoria Pavimentada", - "block.create.paved_weathered_limestone": "Caliza Meteorizada Pavimentada", - "block.create.paved_weathered_limestone_slab": "Losa de Caliza Meteorizada Pavimentada", - "block.create.paved_weathered_limestone_stairs": "Escaleras de Caliza Meteorizada Pavimentada", - "block.create.paved_weathered_limestone_wall": "Pared de Caliza Meteorizada Pavimentada", - "block.create.pink_sail": "Vela Rosa", - "block.create.pink_seat": "Asiento Rosa", - "block.create.pink_valve_handle": "Manija de Válvula Rosa", - "block.create.piston_extension_pole": "Poste de Extensión de Pistón", - "block.create.polished_dark_scoria": "Escoria Oscura Pulida", - "block.create.polished_dark_scoria_slab": "Losa de Escoria Oscura Pulida", - "block.create.polished_dark_scoria_stairs": "Escaleras de Escoria Oscura Pulida", - "block.create.polished_dark_scoria_wall": "Pared de Escoria Oscura Pulida", - "block.create.polished_dolomite": "Dolomita Pulida", - "block.create.polished_dolomite_slab": "Losa de Dolomita Pulida", - "block.create.polished_dolomite_stairs": "Escaleras de Dolomita Pulida", - "block.create.polished_dolomite_wall": "Pared de Dolomita Pulida", - "block.create.polished_gabbro": "Gabro Pulido", - "block.create.polished_gabbro_slab": "Losa de Gabro Pulido", - "block.create.polished_gabbro_stairs": "Escaleras de Gabro Pulido", - "block.create.polished_gabbro_wall": "Pared de Gabro Pulido", - "block.create.polished_limestone": "Caliza Pulida", - "block.create.polished_limestone_slab": "Losa de Caliza Pulida", - "block.create.polished_limestone_stairs": "Escaleras de Caliza Pulida", - "block.create.polished_limestone_wall": "Pared de Caliza Pulida", - "block.create.polished_scoria": "Escoria Pulida", - "block.create.polished_scoria_slab": "Losa de Escoria Pulida", - "block.create.polished_scoria_stairs": "Escaleras de Escoria Pulida", - "block.create.polished_scoria_wall": "Pared de Escoria Pulida", - "block.create.polished_weathered_limestone": "Caliza Meteorizada Pulida", - "block.create.polished_weathered_limestone_slab": "Losa de Escoria Pulida", - "block.create.polished_weathered_limestone_stairs": "Escaleras de Escoria Pulida", - "block.create.polished_weathered_limestone_wall": "Pared de Escoria Pulida", - "block.create.portable_fluid_interface": "Interfaz de Fluidos Portable", - "block.create.portable_storage_interface": "Interfaz de Almacenamiento Portable", - "block.create.powered_latch": "Cerradura Electrica", - "block.create.powered_toggle_latch": "Cerradura Electrica de Palanca", - "block.create.pulley_magnet": "Polea con Imán", - "block.create.pulse_repeater": "Repetidor de Pulso", - "block.create.purple_sail": "Vela Morada", - "block.create.purple_seat": "Asiento Morado", - "block.create.purple_valve_handle": "Manija de Válvula Morada", - "block.create.radial_chassis": "Chasis Radial", - "block.create.red_sail": "Vela Roja", - "block.create.red_seat": "Asiento Rojo", - "block.create.red_valve_handle": "Manija de Válvula Roja", - "block.create.redstone_contact": "Contacto de Redstone", - "block.create.redstone_link": "Enlace de Redstone", - "block.create.refined_radiance_casing": "Carcasa Radiante", - "block.create.reinforced_rail": "Vía Reforzada", - "block.create.rope": "Cuerda", - "block.create.rope_pulley": "Polea con Cuerda", - "block.create.rotation_speed_controller": "Controlador de Velocidad de Rotación", - "block.create.sail_frame": "Marco de Vela", - "block.create.schematic_table": "Mesa de Esquemas", - "block.create.schematicannon": "Esquemacañon", - "block.create.scoria": "Escoria", - "block.create.scoria_bricks": "Ladrillos de Escoria", - "block.create.scoria_bricks_slab": "Losa de Ladrillos de Escoria", - "block.create.scoria_bricks_stairs": "Escaleras de Ladrillos de Escoria", - "block.create.scoria_bricks_wall": "Pared de Ladrillos de Escoria", - "block.create.scoria_cobblestone": "Piedra Labrada de Escoria", - "block.create.scoria_cobblestone_slab": "Losa de Piedra Labrada de Escoria", - "block.create.scoria_cobblestone_stairs": "Escaleras de Piedra Labrada de Escoria", - "block.create.scoria_cobblestone_wall": "Pared de Piedra Labrada de Escoria", - "block.create.scoria_pillar": "Pilar de Escoria", - "block.create.secondary_linear_chassis": "Chasis Lineal Secundario", - "block.create.sequenced_gearshift": "Cambio de Marcha Secuenciado", - "block.create.shadow_steel_casing": "Carcasa Sombría", - "block.create.shaft": "Eje", - "block.create.smart_chute": "UNLOCALIZED: Smart Chute", - "block.create.smart_fluid_pipe": "Tubería de Fluidos Inteligente", - "block.create.speedometer": "Velocímetro", - "block.create.spout": "Canaleta", - "block.create.spruce_window": "Ventana de Abeto", - "block.create.spruce_window_pane": "Panel de Ventana de Abeto", - "block.create.sticker": "UNLOCALIZED: Sticker", - "block.create.sticky_mechanical_piston": "Pistón Mecánico Pegajoso", - "block.create.stockpile_switch": "Interruptor de Pila", - "block.create.stressometer": "Estresómetro", - "block.create.tiled_glass": "Vidrio de Azulejos", - "block.create.tiled_glass_pane": "Panel de Vidrio de Azulejos", - "block.create.turntable": "Mesa Giratoria", - "block.create.vertical_framed_glass": "Vidrio Enmarcado Vertical", - "block.create.vertical_framed_glass_pane": "Panel de Vidrio Enmarcado Vertical", - "block.create.warped_window": "Ventana Distorsionada", - "block.create.warped_window_pane": "Panel de ventana Distorsionada", - "block.create.water_wheel": "Rueda Hidráulica", - "block.create.weathered_limestone": "Caliza Meteorizada", - "block.create.weathered_limestone_bricks": "Ladrillos de Caliza Meteorizada", - "block.create.weathered_limestone_bricks_slab": "Losa de Caliza Meteorizada", - "block.create.weathered_limestone_bricks_stairs": "Escaleras de Caliza Meteorizada", - "block.create.weathered_limestone_bricks_wall": "Pared de Caliza Meteorizada", - "block.create.weathered_limestone_cobblestone": "Piedra Labrada de Caliza Meteorizada", - "block.create.weathered_limestone_cobblestone_slab": "Losa de Piedra Labrada de Caliza Meteorizada", - "block.create.weathered_limestone_cobblestone_stairs": "Escaleras de Piedra Labrada de Caliza Meteorizada", - "block.create.weathered_limestone_cobblestone_wall": "Pared de Piedra Labrada de Caliza Meteorizada", - "block.create.weathered_limestone_pillar": "Pilar de Caliza Meteorizada", - "block.create.weighted_ejector": "UNLOCALIZED: Weighted Ejector", - "block.create.white_sail": "Vela Blanca", - "block.create.white_seat": "Asiento Blanco", - "block.create.white_valve_handle": "Manija de Válvula Blanca", - "block.create.windmill_bearing": "Rodamiento de Molino de Viento", - "block.create.wooden_bracket": "Soporte de Madera", - "block.create.yellow_sail": "Vela Amarilla", - "block.create.yellow_seat": "Asiento Amarillo", - "block.create.yellow_valve_handle": "Manija de Válvula Amarilla", - "block.create.zinc_block": "Bloque de Zinc", - "block.create.zinc_ore": "Mineral de Zinc", - - "entity.create.contraption": "Artefacto", - "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", - "entity.create.seat": "Asiento", - "entity.create.stationary_contraption": "Artefacto Estacionario", - "entity.create.super_glue": "Super Pegamento", - - "fluid.create.milk": "Leche", - "fluid.create.potion": "Poción", - "fluid.create.tea": "Té del Constructor", - - "item.create.andesite_alloy": "Aleación de Andesita", - "item.create.attribute_filter": "Filtro por Atributos", - "item.create.bar_of_chocolate": "Barra de Chocolate", - "item.create.belt_connector": "Conector de Correa", - "item.create.blaze_cake": "Pastel de Blaze", - "item.create.blaze_cake_base": "Base de Pastel de Blaze", - "item.create.brass_hand": "Mano de Latón", - "item.create.brass_ingot": "Lingote de Latón", - "item.create.brass_nugget": "Pepita de Latón", - "item.create.brass_sheet": "Lámina de Latón", - "item.create.builders_tea": "Té del Constructor", - "item.create.chest_minecart_contraption": "Artefacto de Vagón con Cofre", - "item.create.chocolate_bucket": "Cubeta de Chocolate", - "item.create.chocolate_glazed_berries": "UNLOCALIZED: Chocolate Glazed Berries", - "item.create.chromatic_compound": "Compuesto Cromático", - "item.create.cinder_flour": "Ceniza Molida", - "item.create.copper_backtank": "UNLOCALIZED: Copper Backtank", - "item.create.copper_ingot": "Lingote de Cobre", - "item.create.copper_nugget": "Pepita de Cobre", - "item.create.copper_sheet": "Lámina de Cobre", - "item.create.crafter_slot_cover": "Cubierta de Ranura del Crafter", - "item.create.crushed_aluminum_ore": "Mineral de Aluminio Molido", - "item.create.crushed_brass": "Latón Molido", - "item.create.crushed_copper_ore": "Mineral de Cobre Molido", - "item.create.crushed_gold_ore": "Mineral de Oro Molido", - "item.create.crushed_iron_ore": "Mineral de Hierro Molido", - "item.create.crushed_lead_ore": "Mineral de Plomo Molido", - "item.create.crushed_nickel_ore": "Mineral de Nickel Molido", - "item.create.crushed_osmium_ore": "Mineral de Osmio Molido", - "item.create.crushed_platinum_ore": "Mineral de Platino Molido", - "item.create.crushed_quicksilver_ore": "Mineral de Mercurio Molido", - "item.create.crushed_silver_ore": "Mineral de Plata Molido", - "item.create.crushed_tin_ore": "Mineral de Estaño Molido", - "item.create.crushed_uranium_ore": "Mineral de Uranio Molido", - "item.create.crushed_zinc_ore": "Mineral de Zinc Molido", - "item.create.diving_boots": "UNLOCALIZED: Diving Boots", - "item.create.diving_helmet": "UNLOCALIZED: Diving Helmet", - "item.create.dough": "Masa", - "item.create.electron_tube": "Válvula Electrónica", - "item.create.empty_blaze_burner": "Quemador de Blaze Vacío", - "item.create.empty_schematic": "Esquema Vacío", - "item.create.extendo_grip": "Brazo Extensor", - "item.create.filter": "Filtro", - "item.create.furnace_minecart_contraption": "Artefacto de Vagón con Horno", - "item.create.goggles": "Gafas de Protección para Ingenieros", - "item.create.golden_sheet": "Lámina de Oro", - "item.create.handheld_worldshaper": "Pistola de Manipulación de Mundo", - "item.create.honey_bucket": "Cubeta de Miel", - "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", - "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.minecart_contraption": "Artefacto de Vagón", - "item.create.minecart_coupling": "Acoplamiento de Vagonetas", - "item.create.polished_rose_quartz": "Cuarzo Rosa Pulido", - "item.create.powdered_obsidian": "Polvo de Obsidiana", - "item.create.propeller": "Hélice", - "item.create.red_sand_paper": "Papel de Arena Roja", - "item.create.refined_radiance": "Radiancia Refinada", - "item.create.rose_quartz": "Cuarzo Rosa", - "item.create.sand_paper": "Papel de Arena", - "item.create.schematic": "Esquema", - "item.create.schematic_and_quill": "Esquema y Pluma", - "item.create.shadow_steel": "Acero Sombrío", - "item.create.super_glue": "Super Pegamento", - "item.create.sweet_roll": "UNLOCALIZED: Sweet Roll", - "item.create.tree_fertilizer": "Fertilizador de Árboles", - "item.create.vertical_gearbox": "Transmisión Vertical", - "item.create.wand_of_symmetry": "Vara de la Simetria", - "item.create.wheat_flour": "Harina de Trigo", - "item.create.whisk": "Batidor", - "item.create.wrench": "Llave Inglesa", - "item.create.zinc_ingot": "Lingote de Zinc", - "item.create.zinc_nugget": "Pepita de Zinc", - - - "_": "->------------------------] Advancements [------------------------<-", - - "advancement.create.root": "UNLOCALIZED: Welcome to Create", - "advancement.create.root.desc": "UNLOCALIZED: It's time to start building some amazing Contraptions!", - "advancement.create.andesite_alloy": "UNLOCALIZED: Alliterations Aplenty", - "advancement.create.andesite_alloy.desc": "UNLOCALIZED: Create's materials have weird names, Andesite Alloy is one of them.", - "advancement.create.its_alive": "UNLOCALIZED: It's Alive!", - "advancement.create.its_alive.desc": "UNLOCALIZED: Watch your first kinetic component spin.", - "advancement.create.shifting_gears": "UNLOCALIZED: Shifting Gears", - "advancement.create.shifting_gears.desc": "UNLOCALIZED: Connect a Large Cogwheel to a Small Cogwheel, allowing you to change the speed of your contraption.", - "advancement.create.overstressed": "UNLOCALIZED: Overstressed", - "advancement.create.overstressed.desc": "UNLOCALIZED: Experience the limits of stress firsthand.", - "advancement.create.belt": "UNLOCALIZED: Kelp Drive", - "advancement.create.belt.desc": "UNLOCALIZED: Connect two shafts with a Mechanical Belt.", - "advancement.create.tunnel": "UNLOCALIZED: Take cover!", - "advancement.create.tunnel.desc": "UNLOCALIZED: Embellish your mechanical belt with a Tunnel.", - "advancement.create.splitter_tunnel": "UNLOCALIZED: Divide and Conquer", - "advancement.create.splitter_tunnel.desc": "UNLOCALIZED: Create a splitter with a group of Brass Tunnels.", - "advancement.create.chute": "UNLOCALIZED: Tumbling down", - "advancement.create.chute.desc": "UNLOCALIZED: Place a chute, the vertical counterpart of the belt.", - "advancement.create.upward_chute": "UNLOCALIZED: Aerial Abduction", - "advancement.create.upward_chute.desc": "UNLOCALIZED: Watch a thrown item fly up into a fan-powered chute.", - "advancement.create.belt_funnel": "UNLOCALIZED: Funnels' Flappy Danglers", - "advancement.create.belt_funnel.desc": "UNLOCALIZED: Place a sideways funnel on top of a belt or depot to create a special type.", - "advancement.create.belt_funnel_kiss": "UNLOCALIZED: The Parrots and the Flaps", - "advancement.create.belt_funnel_kiss.desc": "UNLOCALIZED: Make two belt mounted funnels kiss.", - "advancement.create.fan": "UNLOCALIZED: Mechanical Airbender", - "advancement.create.fan.desc": "UNLOCALIZED: Ride the stream of air provided by an Encased Fan.", - "advancement.create.fan_lava": "UNLOCALIZED: Geothermal Space Heater", - "advancement.create.fan_lava.desc": "UNLOCALIZED: Get caught in a stream of air that smelts things.", - "advancement.create.fan_water": "UNLOCALIZED: Wacky Washing", - "advancement.create.fan_water.desc": "UNLOCALIZED: Get caught in a stream of air that washes things.", - "advancement.create.fan_smoke": "UNLOCALIZED: Mechanical Bellows", - "advancement.create.fan_smoke.desc": "UNLOCALIZED: Get caught in a stream of air that smokes items.", - "advancement.create.wrench": "UNLOCALIZED: Configure Conveniently", - "advancement.create.wrench.desc": "UNLOCALIZED: Create a Wrench to aid you in building your contraptions.", - "advancement.create.goggles": "UNLOCALIZED: Stress-O-Vision", - "advancement.create.goggles.desc": "UNLOCALIZED: Create some Engineer's Goggles to aid you in getting more kinetic information from components.", - "advancement.create.speedometer": "UNLOCALIZED: But How Fast Exactly?", - "advancement.create.speedometer.desc": "UNLOCALIZED: Place and power a Speedometer. Look at it through your goggles to read its exact value.", - "advancement.create.stressometer": "UNLOCALIZED: But How Stressed Exactly?", - "advancement.create.stressometer.desc": "UNLOCALIZED: Place and power a Stressometer. Look at it through your goggles to read its exact value.", - "advancement.create.aesthetics": "UNLOCALIZED: Boom, Aesthetics!", - "advancement.create.aesthetics.desc": "UNLOCALIZED: Place brackets on a shaft, pipe and cogwheel.", - "advancement.create.reinforced": "UNLOCALIZED: Boom, Reinforced!", - "advancement.create.reinforced.desc": "UNLOCALIZED: Use fitting casing blocks on a shaft, pipe and mechanical belt.", - "advancement.create.water_wheel": "UNLOCALIZED: Harnessing Hydraulics", - "advancement.create.water_wheel.desc": "UNLOCALIZED: Place a Water Wheel and try getting it to spin!", - "advancement.create.chocolate_wheel": "UNLOCALIZED: Tasteful power", - "advancement.create.chocolate_wheel.desc": "UNLOCALIZED: Run a Water Wheel with molten Chocolate.", - "advancement.create.lava_wheel": "UNLOCALIZED: Magma Wheel", - "advancement.create.lava_wheel.desc": "UNLOCALIZED: This shouldn't have worked.", - "advancement.create.cuckoo": "UNLOCALIZED: Is it time?", - "advancement.create.cuckoo.desc": "UNLOCALIZED: Witness a cuckhoo clock announce bedtime.", - "advancement.create.millstone": "UNLOCALIZED: Pocket Crusher", - "advancement.create.millstone.desc": "UNLOCALIZED: Place and power a Millstone.", - "advancement.create.windmill": "UNLOCALIZED: A mild Breeze", - "advancement.create.windmill.desc": "UNLOCALIZED: Assemble a windmill.", - "advancement.create.maxed_windmill": "UNLOCALIZED: A strong breeze", - "advancement.create.maxed_windmill.desc": "UNLOCALIZED: Assemble a windmill of maximum strength.", - "advancement.create.andesite_casing": "UNLOCALIZED: The Andesite Age", - "advancement.create.andesite_casing.desc": "UNLOCALIZED: Use some Andesite Alloy and Wood to create a basic Casing.", - "advancement.create.mechanical_drill": "UNLOCALIZED: Stationary Breakers", - "advancement.create.mechanical_drill.desc": "UNLOCALIZED: Place and power a Mechanical Drill.", - "advancement.create.press": "UNLOCALIZED: Press Goes 'Bonk!'", - "advancement.create.press.desc": "UNLOCALIZED: Power a Mechanical Press and use it to create some Sheets.", - "advancement.create.polished_rose_quartz": "UNLOCALIZED: Pink Diamonds", - "advancement.create.polished_rose_quartz.desc": "UNLOCALIZED: Use a piece of Sand Paper to polish Rose Quartz until it becomes transparent.", - "advancement.create.electron_tube": "UNLOCALIZED: Beep Boop", - "advancement.create.electron_tube.desc": "UNLOCALIZED: Make some Electron Tubes, useful in crafting less primitive machinery.", - "advancement.create.mechanical_saw": "UNLOCALIZED: Stationary Chopping", - "advancement.create.mechanical_saw.desc": "UNLOCALIZED: Place and power a Mechanical Saw.", - "advancement.create.basin": "UNLOCALIZED: Basin Operation", - "advancement.create.basin.desc": "UNLOCALIZED: Place a Basin and try throwing items into it.", - "advancement.create.mixer": "UNLOCALIZED: Mixin' It Up", - "advancement.create.mixer.desc": "UNLOCALIZED: Place a Mechanical Mixer above the Basin, power it, and start mixing some ingredients.", - "advancement.create.blaze_burner": "UNLOCALIZED: A living Fireplace", - "advancement.create.blaze_burner.desc": "UNLOCALIZED: Obtain a Blaze Burner.", - "advancement.create.compact": "UNLOCALIZED: Automated Compacting", - "advancement.create.compact.desc": "UNLOCALIZED: Use a Press and a Basin to compact some items.", - "advancement.create.brass": "UNLOCALIZED: Actual Alloys", - "advancement.create.brass.desc": "UNLOCALIZED: Use Crushed Copper and Crushed Zinc to create some Brass.", - "advancement.create.brass_casing": "UNLOCALIZED: The Brass Age", - "advancement.create.brass_casing.desc": "UNLOCALIZED: Use newly obtained Brass and some Wood to create a more advanced Casing.", - "advancement.create.copper_casing": "UNLOCALIZED: The Copper Age", - "advancement.create.copper_casing.desc": "UNLOCALIZED: Use some Copper Sheets and Wood to create some Copper Casings.", - "advancement.create.spout": "UNLOCALIZED: Sploosh", - "advancement.create.spout.desc": "UNLOCALIZED: Watch a fluid item being filled using a spout.", - "advancement.create.spout_potion": "UNLOCALIZED: Global Brewery", - "advancement.create.spout_potion.desc": "UNLOCALIZED: Watch a spout fill a bottle with potion fluid.", - "advancement.create.chocolate": "UNLOCALIZED: A world of Imagination", - "advancement.create.chocolate.desc": "UNLOCALIZED: Obtain a bucket of Molten Chocolate.", - "advancement.create.item_drain": "UNLOCALIZED: Tumble Draining", - "advancement.create.item_drain.desc": "UNLOCALIZED: Watch a fluid item being emptied by an item drain.", - "advancement.create.chained_item_drain": "UNLOCALIZED: Let it roll!", - "advancement.create.chained_item_drain.desc": "UNLOCALIZED: Watch an item roll across several chained item drains.", - "advancement.create.glass_pipe": "UNLOCALIZED: Flow Spy", - "advancement.create.glass_pipe.desc": "UNLOCALIZED: Watch fluid propagate through a windowed fluid pipe. Straight fluid pipes become windowed when a wrench is used on them.", - "advancement.create.pipe_collision": "UNLOCALIZED: Never cross the Streams!", - "advancement.create.pipe_collision.desc": "UNLOCALIZED: Watch two fluids meet in your pipe network.", - "advancement.create.pipe_spill": "UNLOCALIZED: There's a leak!", - "advancement.create.pipe_spill.desc": "UNLOCALIZED: Watch an open end of a pipe take or place fluids into the world.", - "advancement.create.hose_pulley": "UNLOCALIZED: Industrial Spillage", - "advancement.create.hose_pulley.desc": "UNLOCALIZED: Lower a hose pulley and watch it drain or fill a body of fluid.", - "advancement.create.infinite_water": "UNLOCALIZED: Draining the Ocean", - "advancement.create.infinite_water.desc": "UNLOCALIZED: Pump from a body of Water large enough to be considered Infinite.", - "advancement.create.infinite_lava": "UNLOCALIZED: Draining the Planets' Core", - "advancement.create.infinite_lava.desc": "UNLOCALIZED: Pump from a body of Lava large enough to be considered Infinite.", - "advancement.create.infinite_chocolate": "UNLOCALIZED: Drowning in Imagination", - "advancement.create.infinite_chocolate.desc": "UNLOCALIZED: Pump from a body of Molten Chocolate large enough to be considered Infinite.", - "advancement.create.crafter": "UNLOCALIZED: Automated Assembly", - "advancement.create.crafter.desc": "UNLOCALIZED: Place and power some Mechanical Crafters.", - "advancement.create.clockwork_bearing": "UNLOCALIZED: Contraption o'clock", - "advancement.create.clockwork_bearing.desc": "UNLOCALIZED: Assemble a Structure mounted on a Clockwork Bearing.", - "advancement.create.nixie_tube": "UNLOCALIZED: Signs of Style", - "advancement.create.nixie_tube.desc": "UNLOCALIZED: Obtain and place down a pair of Nixie Tubes.", - "advancement.create.deployer": "UNLOCALIZED: Poke, Place, and Attack", - "advancement.create.deployer.desc": "UNLOCALIZED: Place and power a Deployer, the perfect reflection of yourself.", - "advancement.create.speed_controller": "UNLOCALIZED: Engineers hate him!", - "advancement.create.speed_controller.desc": "UNLOCALIZED: Place a Rotation Speed Controller, the ultimate device for changing gear.", - "advancement.create.flywheel": "UNLOCALIZED: Heart of the Factory", - "advancement.create.flywheel.desc": "UNLOCALIZED: Successfully connect an engine to the Flywheel.", - "advancement.create.overstress_flywheel": "UNLOCALIZED: High levels of Stress", - "advancement.create.overstress_flywheel.desc": "UNLOCALIZED: Overstress a Furnace Engine.", - "advancement.create.integrated_circuit": "UNLOCALIZED: Complex Calculation", - "advancement.create.integrated_circuit.desc": "UNLOCALIZED: Assemble an Integrated Circuit.", - "advancement.create.mechanical_arm": "UNLOCALIZED: Busy Hands!", - "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch as it does all the work for you.", - "advancement.create.musical_arm": "UNLOCALIZED: Play Me My Theme Tune!", - "advancement.create.musical_arm.desc": "UNLOCALIZED: Watch a Mechanical Arm operate your Jukebox.", - "advancement.create.arm_many_targets": "UNLOCALIZED: Organize-o-Tron", - "advancement.create.arm_many_targets.desc": "UNLOCALIZED: Program a Mechanical Arm with ten or more output locations.", - "advancement.create.arm_blaze_burner": "UNLOCALIZED: Combust-o-Tron", - "advancement.create.arm_blaze_burner.desc": "UNLOCALIZED: Instruct a Mechanical Arm to feed your Blaze Burner.", - "advancement.create.fist_bump": "UNLOCALIZED: Pound It, Bro!", - "advancement.create.fist_bump.desc": "UNLOCALIZED: Make two Deployers fist-bump.", - "advancement.create.crushing_wheel": "UNLOCALIZED: A Pair of Giants", - "advancement.create.crushing_wheel.desc": "UNLOCALIZED: Create some Crushing Wheels to break down more materials more effectively.", - "advancement.create.blaze_cake": "UNLOCALIZED: Sugar Rush", - "advancement.create.blaze_cake.desc": "UNLOCALIZED: Bake your blaze burner a special cake.", - "advancement.create.chromatic_compound": "UNLOCALIZED: Bipolar Minerals", - "advancement.create.chromatic_compound.desc": "UNLOCALIZED: Create a Bar of Chromatic Compound.", - "advancement.create.shadow_steel": "UNLOCALIZED: Void Returner", - "advancement.create.shadow_steel.desc": "UNLOCALIZED: Create Shadow Steel, a metal bar of nothingness.", - "advancement.create.refined_radiance": "UNLOCALIZED: Bright and Inspiring", - "advancement.create.refined_radiance.desc": "UNLOCALIZED: Create Refined Radiance, a powerful chromatic substance.", - "advancement.create.chromatic_age": "UNLOCALIZED: The Chromatic Age", - "advancement.create.chromatic_age.desc": "UNLOCALIZED: Create casing blocks of the light and dark.", - "advancement.create.wand_of_symmetry": "UNLOCALIZED: Radiant Mirrors", - "advancement.create.wand_of_symmetry.desc": "UNLOCALIZED: Craft a Staff of Symmetry.", - "advancement.create.extendo_grip": "UNLOCALIZED: Boioioing!", - "advancement.create.extendo_grip.desc": "UNLOCALIZED: Get hold of an Extendo Grip.", - "advancement.create.dual_extendo_grip": "UNLOCALIZED: Ultimate Boing-age", - "advancement.create.dual_extendo_grip.desc": "UNLOCALIZED: Dual wield Extendo Grips for super-human reach.", - "advancement.create.eob": "UNLOCALIZED: End of Beta", - "advancement.create.eob.desc": "UNLOCALIZED: Expect more content here in the future. <3", - - - "_": "->------------------------] UI & Messages [------------------------<-", - - "itemGroup.create.base": "UNLOCALIZED: Create", - "itemGroup.create.palettes": "UNLOCALIZED: Create Palettes", - - "death.attack.create.crush": "UNLOCALIZED: %1$s was processed by Crushing Wheels", - "death.attack.create.fan_fire": "UNLOCALIZED: %1$s was burned to death by hot air", - "death.attack.create.fan_lava": "UNLOCALIZED: %1$s was burned to death by lava fan", - "death.attack.create.mechanical_drill": "UNLOCALIZED: %1$s was impaled by a Mechanical Drill", - "death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by a Mechanical Saw", - "death.attack.create.cuckoo_clock_explosion": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", - - "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.recipe.crushing": "UNLOCALIZED: Crushing", - "create.recipe.milling": "UNLOCALIZED: Milling", - "create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing", - "create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water", - "create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking", - "create.recipe.fan_smoking.fan": "UNLOCALIZED: Fan behind Fire", - "create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting", - "create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava", - "create.recipe.pressing": "UNLOCALIZED: Pressing", - "create.recipe.mixing": "UNLOCALIZED: Mixing", - "create.recipe.deploying": "UNLOCALIZED: Deploying", - "create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting", - "create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing", - "create.recipe.packing": "UNLOCALIZED: Compacting", - "create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing", - "create.recipe.sawing": "UNLOCALIZED: Sawing", - "create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting", - "create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting", - "create.recipe.block_cutting": "UNLOCALIZED: Block Cutting", - "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", - "create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing", - "create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion", - "create.recipe.spout_filling": "UNLOCALIZED: Filling by Spout", - "create.recipe.draining": "UNLOCALIZED: Item Draining", - "create.recipe.processing.chance": "UNLOCALIZED: %1$s%% Chance", - "create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required", - "create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated", - "create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated", - - "create.generic.range": "UNLOCALIZED: Range", - "create.generic.radius": "UNLOCALIZED: Radius", - "create.generic.width": "UNLOCALIZED: Width", - "create.generic.height": "UNLOCALIZED: Height", - "create.generic.length": "UNLOCALIZED: Length", - "create.generic.speed": "UNLOCALIZED: Speed", - "create.generic.delay": "UNLOCALIZED: Delay", - "create.generic.unit.ticks": "UNLOCALIZED: Ticks", - "create.generic.unit.seconds": "UNLOCALIZED: Seconds", - "create.generic.unit.minutes": "UNLOCALIZED: Minutes", - "create.generic.unit.rpm": "UNLOCALIZED: RPM", - "create.generic.unit.stress": "UNLOCALIZED: su", - "create.generic.unit.degrees": "UNLOCALIZED: °", - "create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB", - "create.generic.clockwise": "UNLOCALIZED: Clockwise", - "create.generic.counter_clockwise": "UNLOCALIZED: Counter-Clockwise", - - "create.action.scroll": "UNLOCALIZED: Scroll", - "create.action.confirm": "UNLOCALIZED: Confirm", - "create.action.abort": "UNLOCALIZED: Abort", - "create.action.saveToFile": "UNLOCALIZED: Save", - "create.action.discard": "UNLOCALIZED: Discard", - - "create.keyinfo.toolmenu": "UNLOCALIZED: Focus Tool Menu", - "create.keyinfo.scrollup": "UNLOCALIZED: Simulate Mousewheel Up (inworld)", - "create.keyinfo.scrolldown": "UNLOCALIZED: Simulate Mousewheel Down (inworld)", - - "create.gui.scrollInput.defaultTitle": "UNLOCALIZED: Choose an Option:", - "create.gui.scrollInput.scrollToModify": "UNLOCALIZED: Scroll to Modify", - "create.gui.scrollInput.scrollToAdjustAmount": "UNLOCALIZED: Scroll to Adjust Amount", - "create.gui.scrollInput.scrollToSelect": "UNLOCALIZED: Scroll to Select", - "create.gui.scrollInput.shiftScrollsFaster": "UNLOCALIZED: Shift to Scroll Faster", - "create.gui.toolmenu.focusKey": "UNLOCALIZED: Hold [%1$s] to Focus", - "create.gui.toolmenu.cycle": "UNLOCALIZED: [SCROLL] to Cycle", - "create.gui.symmetryWand.mirrorType": "UNLOCALIZED: Mirror", - "create.gui.symmetryWand.orientation": "UNLOCALIZED: Orientation", - - "create.symmetry.mirror.plane": "UNLOCALIZED: Mirror Once", - "create.symmetry.mirror.doublePlane": "UNLOCALIZED: Rectangular", - "create.symmetry.mirror.triplePlane": "UNLOCALIZED: Octagonal", - - "create.orientation.orthogonal": "UNLOCALIZED: Orthogonal", - "create.orientation.diagonal": "UNLOCALIZED: Diagonal", - "create.orientation.horizontal": "UNLOCALIZED: Horizontal", - "create.orientation.alongZ": "UNLOCALIZED: Along Z", - "create.orientation.alongX": "UNLOCALIZED: Along X", - - "create.gui.terrainzapper.title": "UNLOCALIZED: Handheld Blockzapper", - "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.placement": "UNLOCALIZED: Placement", - "create.gui.terrainzapper.placement.merged": "UNLOCALIZED: Merged", - "create.gui.terrainzapper.placement.attached": "UNLOCALIZED: Attached", - "create.gui.terrainzapper.placement.inserted": "UNLOCALIZED: Inserted", - "create.gui.terrainzapper.brush": "UNLOCALIZED: Brush", - "create.gui.terrainzapper.brush.cuboid": "UNLOCALIZED: Cuboid", - "create.gui.terrainzapper.brush.sphere": "UNLOCALIZED: Sphere", - "create.gui.terrainzapper.brush.cylinder": "UNLOCALIZED: Cylinder", - "create.gui.terrainzapper.brush.surface": "UNLOCALIZED: Surface", - "create.gui.terrainzapper.brush.cluster": "UNLOCALIZED: Cluster", - "create.gui.terrainzapper.tool": "UNLOCALIZED: Tool", - "create.gui.terrainzapper.tool.fill": "UNLOCALIZED: Fill", - "create.gui.terrainzapper.tool.place": "UNLOCALIZED: Place", - "create.gui.terrainzapper.tool.replace": "UNLOCALIZED: Replace", - "create.gui.terrainzapper.tool.clear": "UNLOCALIZED: Clear", - "create.gui.terrainzapper.tool.overlay": "UNLOCALIZED: Overlay", - "create.gui.terrainzapper.tool.flatten": "UNLOCALIZED: Flatten", - - "create.terrainzapper.shiftRightClickToSet": "UNLOCALIZED: Shift-Right-Click to Select a Shape", - "create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s", - "create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material", - - "create.minecart_coupling.two_couplings_max": "UNLOCALIZED: Minecarts cannot have more than two couplings each", - "create.minecart_coupling.unloaded": "UNLOCALIZED: Parts of your train seem to be in unloaded chunks", - "create.minecart_coupling.no_loops": "UNLOCALIZED: Couplings cannot form a loop", - "create.minecart_coupling.removed": "UNLOCALIZED: Removed all couplings from minecart", - "create.minecart_coupling.too_far": "UNLOCALIZED: Minecarts are too far apart", - - "create.contraptions.movement_mode": "UNLOCALIZED: Movement Mode", - "create.contraptions.movement_mode.move_place": "UNLOCALIZED: Always Place when Stopped", - "create.contraptions.movement_mode.move_place_returned": "UNLOCALIZED: Place only in Starting Position", - "create.contraptions.movement_mode.move_never_place": "UNLOCALIZED: Place only when Anchor Destroyed", - "create.contraptions.movement_mode.rotate_place": "UNLOCALIZED: Always Place when Stopped", - "create.contraptions.movement_mode.rotate_place_returned": "UNLOCALIZED: Only Place near Initial Angle", - "create.contraptions.movement_mode.rotate_never_place": "UNLOCALIZED: Only Place when Anchor Destroyed", - "create.contraptions.cart_movement_mode": "UNLOCALIZED: Cart Movement Mode", - "create.contraptions.cart_movement_mode.rotate": "UNLOCALIZED: Always face toward motion", - "create.contraptions.cart_movement_mode.rotate_paused": "UNLOCALIZED: Pause actors while rotating", - "create.contraptions.cart_movement_mode.rotation_locked": "UNLOCALIZED: Lock rotation", - "create.contraptions.windmill.rotation_direction": "UNLOCALIZED: Rotation Direction", - "create.contraptions.clockwork.clock_hands": "UNLOCALIZED: Clock Hands", - "create.contraptions.clockwork.hour_first": "UNLOCALIZED: Hour hand first", - "create.contraptions.clockwork.minute_first": "UNLOCALIZED: Minute hand first", - "create.contraptions.clockwork.hour_first_24": "UNLOCALIZED: 24-Hour hand first", - - "create.logistics.filter": "UNLOCALIZED: Filter", - "create.logistics.recipe_filter": "UNLOCALIZED: Recipe Filter", - "create.logistics.fluid_filter": "UNLOCALIZED: Fluid Filter", - "create.logistics.firstFrequency": "UNLOCALIZED: Freq. #1", - "create.logistics.secondFrequency": "UNLOCALIZED: Freq. #2", - "create.logistics.filter.apply": "UNLOCALIZED: Applied filter to %1$s.", - "create.logistics.filter.apply_click_again": "UNLOCALIZED: Applied filter to %1$s, click again to copy the amount.", - "create.logistics.filter.apply_count": "UNLOCALIZED: Applied extraction count to filter.", - - "create.gui.goggles.generator_stats": "UNLOCALIZED: Generator Stats:", - "create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:", - "create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed", - "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", - "create.gui.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.gauge.info_header": "UNLOCALIZED: Gauge Information:", - "create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed", - "create.gui.stressometer.title": "UNLOCALIZED: Network Stress", - "create.gui.stressometer.capacity": "UNLOCALIZED: Remaining Capacity", - "create.gui.stressometer.overstressed": "UNLOCALIZED: Overstressed", - "create.gui.stressometer.no_rotation": "UNLOCALIZED: No Rotation", - "create.gui.contraptions.not_fast_enough": "UNLOCALIZED: It appears that this %1$s is _not_ rotating with _enough_ _speed_.", - "create.gui.contraptions.network_overstressed": "UNLOCALIZED: It appears that this contraption is _overstressed_. Add more sources or _slow_ _down_ the components with a high _stress_ _impact_.", - "create.gui.adjustable_crate.title": "UNLOCALIZED: Adjustable Crate", - "create.gui.adjustable_crate.storageSpace": "UNLOCALIZED: Storage Space", - "create.gui.stockpile_switch.title": "UNLOCALIZED: Stockpile Switch", - "create.gui.stockpile_switch.invert_signal": "UNLOCALIZED: Invert Signal", - "create.gui.stockpile_switch.move_to_lower_at": "UNLOCALIZED: Move to lower lane at %1$s%%", - "create.gui.stockpile_switch.move_to_upper_at": "UNLOCALIZED: Move to upper lane at %1$s%%", - "create.gui.sequenced_gearshift.title": "UNLOCALIZED: Sequenced Gearshift", - "create.gui.sequenced_gearshift.instruction": "UNLOCALIZED: Instruction", - "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", - "create.gui.sequenced_gearshift.instruction.turn_angle": "UNLOCALIZED: Turn", - "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "UNLOCALIZED: Angle", - "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", - "create.gui.sequenced_gearshift.instruction.turn_distance": "UNLOCALIZED: Piston", - "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "UNLOCALIZED: Distance", - "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", - "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", - "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", - "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", - "create.gui.sequenced_gearshift.instruction.end": "UNLOCALIZED: End", - "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", - "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", - "create.gui.sequenced_gearshift.speed": "UNLOCALIZED: Speed, Direction", - "create.gui.sequenced_gearshift.speed.forward": "UNLOCALIZED: Input speed, Forwards", - "create.gui.sequenced_gearshift.speed.forward_fast": "UNLOCALIZED: Double speed, Forwards", - "create.gui.sequenced_gearshift.speed.back": "UNLOCALIZED: Input speed, Reversed", - "create.gui.sequenced_gearshift.speed.back_fast": "UNLOCALIZED: Double speed, Reversed", - - "create.schematicAndQuill.dimensions": "UNLOCALIZED: Schematic Size: %1$sx%2$sx%3$s", - "create.schematicAndQuill.firstPos": "UNLOCALIZED: First position set.", - "create.schematicAndQuill.secondPos": "UNLOCALIZED: Second position set.", - "create.schematicAndQuill.noTarget": "UNLOCALIZED: Hold [Ctrl] to select Air blocks.", - "create.schematicAndQuill.abort": "UNLOCALIZED: Removed selection.", - "create.schematicAndQuill.title": "UNLOCALIZED: Schematic Name:", - "create.schematicAndQuill.convert": "UNLOCALIZED: Save and Upload Immediately", - "create.schematicAndQuill.fallbackName": "UNLOCALIZED: My Schematic", - "create.schematicAndQuill.saved": "UNLOCALIZED: Saved as %1$s", - - "create.schematic.invalid": "UNLOCALIZED: [!] Invalid Item - Use the Schematic Table instead", - "create.schematic.position": "UNLOCALIZED: Position", - "create.schematic.rotation": "UNLOCALIZED: Rotation", - "create.schematic.rotation.none": "UNLOCALIZED: None", - "create.schematic.rotation.cw90": "UNLOCALIZED: Clockwise 90", - "create.schematic.rotation.cw180": "UNLOCALIZED: Clockwise 180", - "create.schematic.rotation.cw270": "UNLOCALIZED: Clockwise 270", - "create.schematic.mirror": "UNLOCALIZED: Mirror", - "create.schematic.mirror.none": "UNLOCALIZED: None", - "create.schematic.mirror.frontBack": "UNLOCALIZED: Front-Back", - "create.schematic.mirror.leftRight": "UNLOCALIZED: Left-Right", - "create.schematic.tool.deploy": "UNLOCALIZED: Position", - "create.schematic.tool.move": "UNLOCALIZED: Move XZ", - "create.schematic.tool.movey": "UNLOCALIZED: Move Y", - "create.schematic.tool.rotate": "UNLOCALIZED: Rotate", - "create.schematic.tool.print": "UNLOCALIZED: Print", - "create.schematic.tool.flip": "UNLOCALIZED: Mirror", - "create.schematic.tool.deploy.description.0": "UNLOCALIZED: Moves the structure to a location.", - "create.schematic.tool.deploy.description.1": "UNLOCALIZED: Right-Click on the ground to place.", - "create.schematic.tool.deploy.description.2": "UNLOCALIZED: Hold [Ctrl] to select at a fixed distance.", - "create.schematic.tool.deploy.description.3": "UNLOCALIZED: [Ctrl]-Scroll to change the distance.", - "create.schematic.tool.move.description.0": "UNLOCALIZED: Shifts the Schematic Horizontally.", - "create.schematic.tool.move.description.1": "UNLOCALIZED: Point at the Schematic and [CTRL]-Scroll to push it.", - "create.schematic.tool.move.description.2": "UNLOCALIZED: ", - "create.schematic.tool.move.description.3": "UNLOCALIZED: ", - "create.schematic.tool.movey.description.0": "UNLOCALIZED: Shifts the Schematic Vertically.", - "create.schematic.tool.movey.description.1": "UNLOCALIZED: [CTRL]-Scroll to move it up/down.", - "create.schematic.tool.movey.description.2": "UNLOCALIZED: ", - "create.schematic.tool.movey.description.3": "UNLOCALIZED: ", - "create.schematic.tool.rotate.description.0": "UNLOCALIZED: Rotates the Schematic around its center.", - "create.schematic.tool.rotate.description.1": "UNLOCALIZED: [CTRL]-Scroll to rotate by 90 Degrees.", - "create.schematic.tool.rotate.description.2": "UNLOCALIZED: ", - "create.schematic.tool.rotate.description.3": "UNLOCALIZED: ", - "create.schematic.tool.print.description.0": "UNLOCALIZED: Instantly places the structure in the world.", - "create.schematic.tool.print.description.1": "UNLOCALIZED: [Right-Click] to confirm placement at the current location.", - "create.schematic.tool.print.description.2": "UNLOCALIZED: This tool is for Creative Mode only.", - "create.schematic.tool.print.description.3": "UNLOCALIZED: ", - "create.schematic.tool.flip.description.0": "UNLOCALIZED: Flips the Schematic along the face you select.", - "create.schematic.tool.flip.description.1": "UNLOCALIZED: Point at the Schematic and [CTRL]-Scroll to flip it.", - "create.schematic.tool.flip.description.2": "UNLOCALIZED: ", - "create.schematic.tool.flip.description.3": "UNLOCALIZED: ", - - "create.schematics.synchronizing": "UNLOCALIZED: Syncing...", - "create.schematics.uploadTooLarge": "UNLOCALIZED: Your schematic exceeds limitations specified by the server.", - "create.schematics.maxAllowedSize": "UNLOCALIZED: The maximum allowed schematic file size is:", - - "create.gui.schematicTable.refresh": "UNLOCALIZED: Refresh Files", - "create.gui.schematicTable.open_folder": "UNLOCALIZED: Open Folder", - "create.gui.schematicTable.title": "UNLOCALIZED: Schematic Table", - "create.gui.schematicTable.availableSchematics": "UNLOCALIZED: Available Schematics", - "create.gui.schematicTable.noSchematics": "UNLOCALIZED: No Schematics Saved", - "create.gui.schematicTable.uploading": "UNLOCALIZED: Uploading...", - "create.gui.schematicTable.finished": "UNLOCALIZED: Upload Finished!", - "create.gui.schematicannon.title": "UNLOCALIZED: Schematicannon", - "create.gui.schematicannon.listPrinter": "UNLOCALIZED: Checklist Printer", - "create.gui.schematicannon.gunpowderLevel": "UNLOCALIZED: Gunpowder at %1$s%%", - "create.gui.schematicannon.shotsRemaining": "UNLOCALIZED: Shots left: %1$s", - "create.gui.schematicannon.shotsRemainingWithBackup": "UNLOCALIZED: With backup: %1$s", - "create.gui.schematicannon.optionEnabled": "UNLOCALIZED: Currently Enabled", - "create.gui.schematicannon.optionDisabled": "UNLOCALIZED: Currently Disabled", - "create.gui.schematicannon.showOptions": "UNLOCALIZED: Show Printer Settings", - "create.gui.schematicannon.option.dontReplaceSolid": "UNLOCALIZED: Don't Replace Solid Blocks", - "create.gui.schematicannon.option.replaceWithSolid": "UNLOCALIZED: Replace Solid with Solid", - "create.gui.schematicannon.option.replaceWithAny": "UNLOCALIZED: Replace Solid with Any", - "create.gui.schematicannon.option.replaceWithEmpty": "UNLOCALIZED: Replace Solid with Empty", - "create.gui.schematicannon.option.skipMissing": "UNLOCALIZED: Skip missing Blocks", - "create.gui.schematicannon.option.skipTileEntities": "UNLOCALIZED: Protect Tile Entities", - "create.gui.schematicannon.slot.gunpowder": "UNLOCALIZED: Add gunpowder to fuel the cannon", - "create.gui.schematicannon.slot.listPrinter": "UNLOCALIZED: Place books here to print a Checklist for your Schematic", - "create.gui.schematicannon.slot.schematic": "UNLOCALIZED: Add your Schematic here. Make sure it is deployed at a specific location.", - "create.gui.schematicannon.option.skipMissing.description": "UNLOCALIZED: If the cannon cannot find a required Block for placement, it will continue at the next Location.", - "create.gui.schematicannon.option.skipTileEntities.description": "UNLOCALIZED: The cannon will avoid replacing data holding blocks such as Chests.", - "create.gui.schematicannon.option.dontReplaceSolid.description": "UNLOCALIZED: The cannon will never replace any Solid blocks in its working area, only non-Solid and Air.", - "create.gui.schematicannon.option.replaceWithSolid.description": "UNLOCALIZED: The cannon will only replace Solid blocks in its working area if the Schematic contains a solid Block at the Location.", - "create.gui.schematicannon.option.replaceWithAny.description": "UNLOCALIZED: The cannon will replace Solid blocks in its working area if the Schematic contains any Block at the Location.", - "create.gui.schematicannon.option.replaceWithEmpty.description": "UNLOCALIZED: The cannon will clear out all blocks in its working area, including those replaced by Air.", - - "create.schematicannon.status.idle": "UNLOCALIZED: Idle", - "create.schematicannon.status.ready": "UNLOCALIZED: Ready", - "create.schematicannon.status.running": "UNLOCALIZED: Running", - "create.schematicannon.status.finished": "UNLOCALIZED: Finished", - "create.schematicannon.status.paused": "UNLOCALIZED: Paused", - "create.schematicannon.status.stopped": "UNLOCALIZED: Stopped", - "create.schematicannon.status.noGunpowder": "UNLOCALIZED: Out of Gunpowder", - "create.schematicannon.status.targetNotLoaded": "UNLOCALIZED: Target is not loaded", - "create.schematicannon.status.targetOutsideRange": "UNLOCALIZED: Target too far away", - "create.schematicannon.status.searching": "UNLOCALIZED: Searching", - "create.schematicannon.status.skipping": "UNLOCALIZED: Skipping", - "create.schematicannon.status.missingBlock": "UNLOCALIZED: Missing Item:", - "create.schematicannon.status.placing": "UNLOCALIZED: Placing", - "create.schematicannon.status.clearing": "UNLOCALIZED: Clearing Blocks", - "create.schematicannon.status.schematicInvalid": "UNLOCALIZED: Schematic Invalid", - "create.schematicannon.status.schematicNotPlaced": "UNLOCALIZED: Schematic not Positioned", - "create.schematicannon.status.schematicExpired": "UNLOCALIZED: Schematic File Expired", - - "create.materialChecklist": "UNLOCALIZED: Material Checklist", - "create.materialChecklist.blocksNotLoaded": "UNLOCALIZED: * Disclaimer *\n\nMaterial List may be inaccurate due to relevant chunks not being loaded.", - - "create.gui.filter.deny_list": "UNLOCALIZED: Deny-List", - "create.gui.filter.deny_list.description": "UNLOCALIZED: Items pass if they do NOT match any of the above. An empty Deny-List accepts everything.", - "create.gui.filter.allow_list": "UNLOCALIZED: Allow-List", - "create.gui.filter.allow_list.description": "UNLOCALIZED: Items pass if they match any of the above. An empty Allow-List rejects everything.", - "create.gui.filter.respect_data": "UNLOCALIZED: Respect Data", - "create.gui.filter.respect_data.description": "UNLOCALIZED: Items only match if their durability, enchantments, and other attributes match as well.", - "create.gui.filter.ignore_data": "UNLOCALIZED: Ignore Data", - "create.gui.filter.ignore_data.description": "UNLOCALIZED: Items match regardless of their attributes.", - - "create.item_attributes.placeable": "UNLOCALIZED: is placeable", - "create.item_attributes.placeable.inverted": "UNLOCALIZED: is not placeable", - "create.item_attributes.consumable": "UNLOCALIZED: can be eaten", - "create.item_attributes.consumable.inverted": "UNLOCALIZED: cannot be eaten", - "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", - "create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted", - "create.item_attributes.washable": "UNLOCALIZED: can be Washed", - "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", - "create.item_attributes.smokable": "UNLOCALIZED: can be Smoked", - "create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked", - "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", - "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", - "create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace", - "create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace", - "create.item_attributes.enchanted": "UNLOCALIZED: is enchanted", - "create.item_attributes.enchanted.inverted": "UNLOCALIZED: is unenchanted", - "create.item_attributes.damaged": "UNLOCALIZED: is damaged", - "create.item_attributes.damaged.inverted": "UNLOCALIZED: is not damaged", - "create.item_attributes.badly_damaged": "UNLOCALIZED: is heavily damaged", - "create.item_attributes.badly_damaged.inverted": "UNLOCALIZED: is not heavily damaged", - "create.item_attributes.not_stackable": "UNLOCALIZED: cannot stack", - "create.item_attributes.not_stackable.inverted": "UNLOCALIZED: can be stacked", - "create.item_attributes.equipable": "UNLOCALIZED: can be equipped", - "create.item_attributes.equipable.inverted": "UNLOCALIZED: cannot be equipped", - "create.item_attributes.furnace_fuel": "UNLOCALIZED: is furnace fuel", - "create.item_attributes.furnace_fuel.inverted": "UNLOCALIZED: is not furnace fuel", - "create.item_attributes.in_tag": "UNLOCALIZED: is tagged %1$s", - "create.item_attributes.in_tag.inverted": "UNLOCALIZED: is not tagged %1$s", - "create.item_attributes.in_item_group": "UNLOCALIZED: is in group '%1$s'", - "create.item_attributes.in_item_group.inverted": "UNLOCALIZED: is not in group '%1$s'", - "create.item_attributes.added_by": "UNLOCALIZED: was added by %1$s", - "create.item_attributes.added_by.inverted": "UNLOCALIZED: was not added by %1$s", - "create.item_attributes.has_enchant": "UNLOCALIZED: is enchanted with %1$s", - "create.item_attributes.has_enchant.inverted": "UNLOCALIZED: is not enchanted with %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.has_fluid": "UNLOCALIZED: contains %1$s", - "create.item_attributes.has_fluid.inverted": "UNLOCALIZED: does not contain %1$s", - "create.item_attributes.has_name": "UNLOCALIZED: has the custom name %1$s", - "create.item_attributes.has_name.inverted": "UNLOCALIZED: does not have the custom name %1$s", - "create.item_attributes.book_author": "UNLOCALIZED: was authored by %1$s", - "create.item_attributes.book_author.inverted": "UNLOCALIZED: was not authored by %1$s", - "create.item_attributes.book_copy_original": "UNLOCALIZED: is an original", - "create.item_attributes.book_copy_original.inverted": "UNLOCALIZED: is not an original", - "create.item_attributes.book_copy_first": "UNLOCALIZED: is a first-generation copy", - "create.item_attributes.book_copy_first.inverted": "UNLOCALIZED: is not a first-generation copy", - "create.item_attributes.book_copy_second": "UNLOCALIZED: is a second-generation copy", - "create.item_attributes.book_copy_second.inverted": "UNLOCALIZED: is not a second-generation copy", - "create.item_attributes.book_copy_tattered": "UNLOCALIZED: is a tattered mess", - "create.item_attributes.book_copy_tattered.inverted": "UNLOCALIZED: is not a tattered mess", - "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", - "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", - "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", - "create.item_attributes.astralsorcery_amulet": "UNLOCALIZED: improves %1$s", - "create.item_attributes.astralsorcery_amulet.inverted": "UNLOCALIZED: does not improve %1$s", - - "create.gui.attribute_filter.no_selected_attributes": "UNLOCALIZED: No attributes selected", - "create.gui.attribute_filter.selected_attributes": "UNLOCALIZED: Selected attributes:", - "create.gui.attribute_filter.add_attribute": "UNLOCALIZED: Add attribute to List", - "create.gui.attribute_filter.add_inverted_attribute": "UNLOCALIZED: Add opposite attribute to List", - "create.gui.attribute_filter.allow_list_disjunctive": "UNLOCALIZED: Allow-List (Any)", - "create.gui.attribute_filter.allow_list_disjunctive.description": "UNLOCALIZED: Items pass if they have any of the selected attributes.", - "create.gui.attribute_filter.allow_list_conjunctive": "UNLOCALIZED: Allow-List (All)", - "create.gui.attribute_filter.allow_list_conjunctive.description": "UNLOCALIZED: Items pass only if they have ALL of the selected attributes.", - "create.gui.attribute_filter.deny_list": "UNLOCALIZED: Deny-List", - "create.gui.attribute_filter.deny_list.description": "UNLOCALIZED: Items pass if they do NOT have any of the selected attributes.", - "create.gui.attribute_filter.add_reference_item": "UNLOCALIZED: Add Reference Item", - - "create.tooltip.holdForDescription": "UNLOCALIZED: Hold [%1$s] for Summary", - "create.tooltip.holdForControls": "UNLOCALIZED: Hold [%1$s] for Controls", - "create.tooltip.keyShift": "UNLOCALIZED: Shift", - "create.tooltip.keyCtrl": "UNLOCALIZED: Ctrl", - "create.tooltip.speedRequirement": "UNLOCALIZED: Speed Requirement: %1$s", - "create.tooltip.speedRequirement.none": "UNLOCALIZED: None", - "create.tooltip.speedRequirement.medium": "UNLOCALIZED: Moderate", - "create.tooltip.speedRequirement.high": "UNLOCALIZED: Fast", - "create.tooltip.stressImpact": "UNLOCALIZED: Kinetic Stress Impact: %1$s", - "create.tooltip.stressImpact.low": "UNLOCALIZED: Low", - "create.tooltip.stressImpact.medium": "UNLOCALIZED: Moderate", - "create.tooltip.stressImpact.high": "UNLOCALIZED: High", - "create.tooltip.stressImpact.overstressed": "UNLOCALIZED: Overstressed", - "create.tooltip.capacityProvided": "UNLOCALIZED: Kinetic Stress Capacity: %1$s", - "create.tooltip.capacityProvided.low": "UNLOCALIZED: Small", - "create.tooltip.capacityProvided.medium": "UNLOCALIZED: Medium", - "create.tooltip.capacityProvided.high": "UNLOCALIZED: Large", - "create.tooltip.generationSpeed": "UNLOCALIZED: Generates at %1$s %2$s", - "create.tooltip.analogStrength": "UNLOCALIZED: Analog Strength: %1$s/15", - - "create.mechanical_arm.extract_from": "UNLOCALIZED: Take items from %1$s", - "create.mechanical_arm.deposit_to": "UNLOCALIZED: Deposit items to %1$s", - "create.mechanical_arm.summary": "UNLOCALIZED: Mechanical Arm has %1$s input(s) and %2$s output(s).", - "create.mechanical_arm.points_outside_range": "UNLOCALIZED: %1$s selected interaction point(s) removed due to range limitations.", - - "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.logistics.when_multiple_outputs_available": "UNLOCALIZED: When Multiple Outputs Available", - - "create.mechanical_arm.selection_mode.round_robin": "UNLOCALIZED: Round Robin", - "create.mechanical_arm.selection_mode.forced_round_robin": "UNLOCALIZED: Forced Round Robin", - "create.mechanical_arm.selection_mode.prefer_first": "UNLOCALIZED: Prefer First Target", - - "create.tunnel.selection_mode.split": "UNLOCALIZED: Split", - "create.tunnel.selection_mode.forced_split": "UNLOCALIZED: Forced Split", - "create.tunnel.selection_mode.round_robin": "UNLOCALIZED: Round Robin", - "create.tunnel.selection_mode.forced_round_robin": "UNLOCALIZED: Forced Round Robin", - "create.tunnel.selection_mode.prefer_nearest": "UNLOCALIZED: Prefer Nearest", - "create.tunnel.selection_mode.randomize": "UNLOCALIZED: Randomize", - "create.tunnel.selection_mode.synchronize": "UNLOCALIZED: Synchronize Inputs", - - "create.tooltip.chute.header": "UNLOCALIZED: Chute Information", - "create.tooltip.chute.items_move_down": "UNLOCALIZED: Items move Downward", - "create.tooltip.chute.items_move_up": "UNLOCALIZED: Items move Upward", - "create.tooltip.chute.no_fans_attached": "UNLOCALIZED: No attached fans", - "create.tooltip.chute.fans_push_up": "UNLOCALIZED: Fans push from Below", - "create.tooltip.chute.fans_push_down": "UNLOCALIZED: Fans push from Above", - "create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above", - "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", - "create.tooltip.chute.contains": "UNLOCALIZED: 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.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", - "create.hint.mechanical_arm_no_targets": "UNLOCALIZED: It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.", - "create.hint.empty_bearing.title": "UNLOCALIZED: Update Bearing", - "create.hint.empty_bearing": "UNLOCALIZED: _Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.", - "create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow", - "create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", - - "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", - "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", - "create.gui.config.overlay3": "UNLOCALIZED: Click or drag with your mouse", - "create.gui.config.overlay4": "UNLOCALIZED: to move this preview", - "create.gui.config.overlay5": "UNLOCALIZED: Press ESC to exit this screen", - "create.gui.config.overlay6": "UNLOCALIZED: and save the new position", - "create.gui.config.overlay7": "UNLOCALIZED: Run /create overlay reset", - "create.gui.config.overlay8": "UNLOCALIZED: to reset to the default position", - - "create.command.killTPSCommand": "UNLOCALIZED: killtps", - "create.command.killTPSCommand.status.slowed_by.0": "UNLOCALIZED: [Create]: Server tick is currently slowed by %s ms :o", - "create.command.killTPSCommand.status.slowed_by.1": "UNLOCALIZED: [Create]: Server tick is slowed by %s ms now >:)", - "create.command.killTPSCommand.status.slowed_by.2": "UNLOCALIZED: [Create]: Server tick is back to regular speed :D", - "create.command.killTPSCommand.status.usage.0": "UNLOCALIZED: [Create]: use /killtps stop to bring back server tick to regular speed", - "create.command.killTPSCommand.status.usage.1": "UNLOCALIZED: [Create]: use /killtps start to artificially slow down the server tick", - "create.command.killTPSCommand.argument.tickTime": "UNLOCALIZED: tickTime", - - "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", - - - "_": "->------------------------] Subtitles [------------------------<-", - - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "UNLOCALIZED: Slime squishes", - "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.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.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", - - - "_": "->------------------------] 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": "SOPORTE DE MADERA", - "block.create.wooden_bracket.tooltip.summary": "_Decora_ tus _ejes,_ _ruedas_ _dentadas_ y _tuberías_ con un pequeño y acogedor refuerzo de madera", - - "block.create.metal_bracket.tooltip": "SOPORTE DE METAL", - "block.create.metal_bracket.tooltip.summary": "_Decora_ tus _ejes,_ _ruedas_ _dentadas_ y _tuberías_ con un robusto refuerzo industrial de metal", - - "block.create.copper_casing.tooltip": "CARCASA DE COBRE", - "block.create.copper_casing.tooltip.summary": "Una simple carcasa para máquinas con una variedad de usos. Segura para la decoración.", - "block.create.copper_casing.tooltip.condition1": "Cuando se usa en una Tubería de Fluidos", - "block.create.copper_casing.tooltip.behaviour1": "Recubre la _Tubería_ _de_ _Fluidos_ con la _Carcasa_ _de_ _Cobre._ Las tuberías recubiertas _bloquearán_ _sus_ _conexiones_ en su lugar, ya no reaccionarán a los cambios de las tuberías vecinas.", - - "block.create.encased_fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS RECUBIERTA", - "block.create.encased_fluid_pipe.tooltip.summary": "Una _Tubería_ _de_ _Fluidos_ recubierta con una _Carcasa_ _de_ _Cobre_", - - "block.create.seat.tooltip": "ASIENTO", - "block.create.seat.tooltip.summary": "¡Siéntese y disfrute del paseo! Anclará a un jugador en una _artefacto_ en movimiento. ¡También es Grandioso para las construcciones estáticas! Viene en una variedad de colores.", - "block.create.seat.tooltip.condition1": "Click Derecho en el asiento", - "block.create.seat.tooltip.behaviour1": "Sienta al jugador en el _asiento_ . Presiona el shift izquierdo para salir del _asiento._", - - "item.create.blaze_cake.tooltip": "PASTEL DE BLAZE", - "item.create.blaze_cake.tooltip.summary": "Un delicioso regalo para tus grandiosos _quemadores_ _de_ _blaze._ ¡Los enciende a todos!", - - "block.create.fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS", - "block.create.fluid_pipe.tooltip.summary": "Se usa para mover _fluidos._ Necesita una _bomba_ _mecánica_ para mover el fluido.", - "block.create.fluid_pipe.tooltip.condition1": "Transferencia de fluidos", - "block.create.fluid_pipe.tooltip.behaviour1": "Puede conectarse a _contenedores_ _de_ _fluidos_ como _tanques_ o _cuencas._ Los extremos expuestos de las _tuberías_ también pueden drenar o colocar bloques de fluido. ¡Ten cuidado con las fugas!", - "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.hose_pulley.tooltip": "POLEA CON MANGUERA", - "block.create.hose_pulley.tooltip.summary": "Se utiliza para _colocar_ o _drenar_ grandes _cuerpos_ _de_ _fluido_ en el mundo.", - "block.create.hose_pulley.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.hose_pulley.tooltip.behaviour1": "_Sube_ o _baja_ la manguera, La ubicación de la manguera determina hasta qué _altura_ actuará la _extracción_ o el _llenado_ .", - "block.create.hose_pulley.tooltip.condition2": "Cuando los fluidos son extraídos de la polea", - "block.create.hose_pulley.tooltip.behaviour2": "Empieza a _extraer_ bloques de _líquido_ del cuerpo en el que se bajó la punta de la manguera. Los cuerpos de fluido _muy_ _grandes_ serán _considerados_ _infinitos_ .", - "block.create.hose_pulley.tooltip.condition3": "Cuando los fluidos son empujados a la polea", - "block.create.hose_pulley.tooltip.behaviour3": "Comienza a _llenar_ con _fluido_ en el mundo _hasta_ _arriba_ a la _altura_ de la _punta_ _de_ _la_ _manguera_ .", - - "block.create.fluid_tank.tooltip": "TANQUE DE FLUIDOS", - "block.create.fluid_tank.tooltip.summary": "Almacena todos tus _fluidos_ favoritos. Escala en anchura y altura.", - "block.create.fluid_tank.tooltip.condition1": "Click Derecho con una Llave Inglesa", - "block.create.fluid_tank.tooltip.behaviour1": "Cambia la ventana opcional", - - "block.create.creative_fluid_tank.tooltip": "TANQUE DE FLUIDOS DEL CREATIVO", - "block.create.creative_fluid_tank.tooltip.summary": "Este _Tanque_ _de_ _Fluidos_ permite la replicación infinita de cualquier Fluido. Escala en anchura y altura.", - "block.create.creative_fluid_tank.tooltip.condition1": "Cuando hay fluido en el tanque", - "block.create.creative_fluid_tank.tooltip.behaviour1": "Cualquier cosa que _extraiga_ de este tanque proporcionará un _suministro_ _ilimitado_ del fluido especificado. Los fluidos _insertados_ en este tanque serán _eliminados._", - "block.create.creative_fluid_tank.tooltip.condition2": "Click Derecho con una Llave Inglesa", - "block.create.creative_fluid_tank.tooltip.behaviour2": "Cambia la ventana opcional", - - "block.create.fluid_valve.tooltip": "VÁLVULAL DE FLUIDOS", - "block.create.fluid_valve.tooltip.summary": "Detiene el flujo de fluido por una tubería.", - "block.create.fluid_valve.tooltip.condition1": "Flujo controlable", - "block.create.fluid_valve.tooltip.behaviour1": "Aplicando una _fuerza_ _de_ _rotación_ forzará a la _válvula_ a cerrarse, cesando el flujo de _fluidos._ Invierte la dirección de la _fuerza_ _de_ _rotación_ para reabrir la válvula.", - - "block.create.mechanical_pump.tooltip": "BOMBA MECÁNICA", - "block.create.mechanical_pump.tooltip.summary": "Toma la _fuerza_ _de_ _rotación_ y la usa para mover el _fluido_ a lo largo de un _tubo._ Tiene un rango de efecto máximo en ambas direcciones. (16 bloques por defecto)", - "block.create.mechanical_pump.tooltip.condition1": "Flujo de fluidos", - "block.create.mechanical_pump.tooltip.behaviour1": "La _fuerza_ _de_ _rotación_ aplicada crea una presión que fuerza el _fluido_ a través de la red de _tuberías._ Invierte la dirección de la fuerza de rotación para cambiar la dirección en la que fluye el _fluido._", - "block.create.mechanical_pump.tooltip.control1": "Click Derecho con una Llave Inglesa", - "block.create.mechanical_pump.tooltip.action1": "Invierte la dirección de la _bomba,_ cambiando la dirección por defecto del flujo", - - "block.create.smart_fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS INTELIGENTE", - "block.create.smart_fluid_pipe.tooltip.summary": "Una _tubería_ _de_ _fluidos_ con un filtro. Puede especificar que _fluidos_ pasan por ella.", - "block.create.smart_fluid_pipe.tooltip.condition1": "Cuando los fluidos son empujados hacia ella", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "Las tuberías inteligentes que reciben un fluido que no coincide con su filtro bloquearán el flujo.", - "block.create.smart_fluid_pipe.tooltip.condition2": "Cuando está adyacente a un recipiente de fluido", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "Las tuberías inteligentes que _inicien_ un _flujo_ desde cualquier contenedor sólo extraerán los fluidos que _coincidan_ con su _filtro._", - - "block.create.spout.tooltip": "CANALETA", - "block.create.spout.tooltip.summary": "Un inyector para rellenar sus _objetos_ con _fluidos._", - "block.create.spout.tooltip.condition1": "Transferencia de fluidos", - "block.create.spout.tooltip.behaviour1": "Cuando se coloca un _objeto_ que puede _contener_ _fluidos_ como una _cubeta_ o _botella_ debajo, la canaleta intentará rellenarlo con su propio _fluido_ almacenado.", - "block.create.spout.tooltip.condition2": "Automatización de fluidos", - "block.create.spout.tooltip.behaviour2": "La canaleta colocada sobre una _correa_ o _depósito_ reaccionará automáticamente con un _contenedor_ _de_ _líquido_ que pase por debajo de él.", - - "block.create.item_drain.tooltip": "ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "Un depósito con rejilla para vaciar sus _objetos_ _con_ _fluidos._", - "block.create.item_drain.tooltip.condition1": "Transferencia de fluidos", - "block.create.item_drain.tooltip.behaviour1": "Cuando se inserta un _contenedor_ _de_ _fluidos_ como una _cubeta_ o _botella_ desde el lado, el extractor intentará vaciarlo en su propio _contenedor_ de _fluidos._ El objeto será entonces expulsado por el lado opuesto.", - - "item.create.wand_of_symmetry.tooltip": "SYMMETRY WAND", - "item.create.wand_of_symmetry.tooltip.summary": "Crea un 'espejo' que refleja perfectamente la colocación de bloques a través de los planos configurados.", - "item.create.wand_of_symmetry.tooltip.condition1": "Cuando esta en la barra de ítems", - "item.create.wand_of_symmetry.tooltip.behaviour1": "Se mantiene activo", - "item.create.wand_of_symmetry.tooltip.control1": "Click Derecho en el suelo", - "item.create.wand_of_symmetry.tooltip.action1": "_Crea_ o _mueve_ el 'espejo'.", - "item.create.wand_of_symmetry.tooltip.control2": "Click Derecho en el aire", - "item.create.wand_of_symmetry.tooltip.action2": "_Remueve_ el 'espejo' activo", - "item.create.wand_of_symmetry.tooltip.control3": "Click Derecho cuando se esta agachado", - "item.create.wand_of_symmetry.tooltip.action3": "Abre la _Interfaz_ _de_ _Configuración_", - - "item.create.handheld_worldshaper.tooltip": "HANDHELD WORLDSHAPER", - "item.create.handheld_worldshaper.tooltip.summary": "Una herramienta útil para crear _paisajes_ y _características_ en el _terreno._", - "item.create.handheld_worldshaper.tooltip.control1": "Click Izquierdo a un bloque", - "item.create.handheld_worldshaper.tooltip.action1": "Establece los bloques que serán colocados por la herramienta en el bloque objetivo.", - "item.create.handheld_worldshaper.tooltip.control2": "Click Derecho en un bloque", - "item.create.handheld_worldshaper.tooltip.action2": "Aplica el _Pincel_ y la _Herramienta_ actualmente seleccionados en el lugar objetivo.", - "item.create.handheld_worldshaper.tooltip.control3": "Click Derecho mientras se está agachado", - "item.create.handheld_worldshaper.tooltip.action3": "Abre la _Interfaz_ _de_ _Configuración._", - - "item.create.tree_fertilizer.tooltip": "TREE FERTILIZER", - "item.create.tree_fertilizer.tooltip.summary": "Una poderosa combinación de minerales adecuados para acelerar el crecimiento de los tipos de árboles comunes.", - "item.create.tree_fertilizer.tooltip.condition1": "Cuando se usa en un retoño de árbol", - "item.create.tree_fertilizer.tooltip.behaviour1": "Hace crecer los árboles, sin importar el espacio entre ellos.", - - "item.create.extendo_grip.tooltip": "EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "Boioioing! En gran medida, _aumenta_ _la_ _distancia_ _de_ _alcance_ del portador.", - "item.create.extendo_grip.tooltip.condition1": "Cuando está en la mano secundaria", - "item.create.extendo_grip.tooltip.behaviour1": "Aumenta el rango de alcance de los objetos usados en la _mano_ _principal._", - - "item.create.filter.tooltip": "FILTER", - "item.create.filter.tooltip.summary": "_Controla_ las _salidas_ y _entradas_ de los dispositivos logísticos con más _precisión,_ comparándolas con un _conjunto_ _de_ _objetos_ o varios _filtros_ _anidados._", - "item.create.filter.tooltip.condition1": "Cuando está en la ranura del filtro", - "item.create.filter.tooltip.behaviour1": "_Controla_ el flujo de objetos según su _configuración._", - "item.create.filter.tooltip.condition2": "Con Click Derecho", - "item.create.filter.tooltip.behaviour2": "Abre la _Interfaz_ _de_ _Configuración._", - - "item.create.attribute_filter.tooltip": "ATTRIBUTE FILTER", - "item.create.attribute_filter.tooltip.summary": "_Controla_ las _salidas_ y _entradas_ de los dispositivos logísticos con más _precisión,_ comparándolas con un _conjunto_ _de_ _atributos_ _de_ _objetos_ y _categorias._", - "item.create.attribute_filter.tooltip.condition1": "Cuando está en la ranura del filtro", - "item.create.attribute_filter.tooltip.behaviour1": "_Controla_ el flujo de objetos según su _configuración._", - "item.create.attribute_filter.tooltip.condition2": "Con Click Derecho", - "item.create.attribute_filter.tooltip.behaviour2": "Abre la _Interfaz_ _de_ _Configuración._", - - "item.create.empty_schematic.tooltip": "EMPTY SCHEMATIC", - "item.create.empty_schematic.tooltip.summary": "Se usa como ingrediente en una receta y para escribir en la _Mesa_ _de_ _Esquemas._", - - "item.create.schematic.tooltip": "SCHEMATIC", - "item.create.schematic.tooltip.summary": "Sostiene una estructura para ser posicionada y colocada en el mundo. Posiciona el Holograma como se desee y usa un _Esquemacañon_ para construirlo.", - "item.create.schematic.tooltip.condition1": "Cuando es sostenido", - "item.create.schematic.tooltip.behaviour1": "Se puede posicionar usando las Herramientas en Pantalla.", - "item.create.schematic.tooltip.control1": "Click Derecho mientras se está agachado", - "item.create.schematic.tooltip.action1": "Abre una _interfaz_ para introducir las _coordenadas_ exactas.", - - "item.create.schematic_and_quill.tooltip": "SCHEMATIC AND QUILL", - "item.create.schematic_and_quill.tooltip.summary": "Se usa para guardar una estructura de tu mundo en un archivo .nbt", - "item.create.schematic_and_quill.tooltip.condition1": "Paso 1", - "item.create.schematic_and_quill.tooltip.behaviour1": "Selecciona dos esquinas con Click Derecho.", - "item.create.schematic_and_quill.tooltip.condition2": "Paso 2", - "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrl_ _+_ _girar_ _rueda_ _del_ _ratón_ en las caras para ajustar el tamaño. Click Derecho de nuevo para Guardar.", - "item.create.schematic_and_quill.tooltip.control1": "Click Derecho", - "item.create.schematic_and_quill.tooltip.action1": "Selecciona una esquina / confirma el guardado.", - "item.create.schematic_and_quill.tooltip.control2": "Manteniendo la tecla Ctrl", - "item.create.schematic_and_quill.tooltip.action2": "Selecciona los puntos en _medio_ _del_ _aire._ _Girar_ _rueda_ _del_ _ratón_ para ajustar la distancia.", - "item.create.schematic_and_quill.tooltip.control3": "Click Derecho mientras se está agachado", - "item.create.schematic_and_quill.tooltip.action3": "_Reinicia_ y quita la selección.", - - "block.create.schematicannon.tooltip": "SCHEMATICANNON", - "block.create.schematicannon.tooltip.summary": "Dispara bloques para recrear un _esquema_ ya desplegado en el mundo. Utiliza objetos de los inventarios adyacentes y _Pólvora_ como combustible.", - "block.create.schematicannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", - "block.create.schematicannon.tooltip.behaviour1": "UNLOCALIZED: Opens the _Interface_", - - "block.create.schematic_table.tooltip": "SCHEMATIC TABLE", - "block.create.schematic_table.tooltip.summary": "Escribe los esquemas guardados en un _Esquema_ _Vacío._", - "block.create.schematic_table.tooltip.condition1": "Cuando se le da un esquema vacío", - "block.create.schematic_table.tooltip.behaviour1": "Carga un archivo elegido de su carpeta de esquemas.", - - "item.create.goggles.tooltip": "GOGGLES", - "item.create.goggles.tooltip.summary": "Un par de gafas para aumentar la visión con _información_ _cinética_ útil.", - "item.create.goggles.tooltip.condition1": "Cuando se usan", - "item.create.goggles.tooltip.behaviour1": "Muestra _indicadores_ _con_ _colores_ correspondientes al _Nivel_ _de_ _Velocidad_ de un componente cinético colocado, así como _Impacto_ _de_ _Estrés_ y _Capacidad_ de los componentes individuales.", - "item.create.goggles.tooltip.condition2": "Al mirar el medidor", - "item.create.goggles.tooltip.behaviour2": "Muestra información detallada sobre la _velocidad_ o el _estrés_ de la red a la que está conectado el medidor.", - "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.wrench.tooltip": "WRENCH", - "item.create.wrench.tooltip.summary": "Una herramienta útil para trabajar en artefactos cinéticos. Se puede utilizar para _Rotar,_ _Desmantelar_ y _Configurar_ componentes.", - "item.create.wrench.tooltip.control1": "Click Derecho en un bloqueo cinético", - "item.create.wrench.tooltip.action1": "_Gira_ los componentes hacia o en contra de la cara con la que interactuó.", - "item.create.wrench.tooltip.control2": "Click Derecho mientras se está agachado", - "item.create.wrench.tooltip.action2": "_Desmonta_ los _componentes_ _cinéticos_ y los coloca de nuevo en _tú_ _inventario._", - - "block.create.nozzle.tooltip": "UNLOCALIZED: NOZZLE", - "block.create.nozzle.tooltip.summary": "UNLOCALIZED: Attach to the front of an _Encased Fan_ to distribute its effect on Entities in _all directions_.", - - "block.create.cuckoo_clock.tooltip": "UNLOCALIZED: CUCKOO CLOCK", - "block.create.cuckoo_clock.tooltip.summary": "UNLOCALIZED: Fine craftsmanship for _decorating_ a space and _keeping track of time_.", - "block.create.cuckoo_clock.tooltip.condition1": "UNLOCALIZED: When Powered by Kinetics", - "block.create.cuckoo_clock.tooltip.behaviour1": "UNLOCALIZED: Shows the _current time_ and plays a tune twice a day. _Activates_ once at _noon_ and at dusk, as soon as _players can sleep_.", - - "block.create.turntable.tooltip": "UNLOCALIZED: TURNTABLE", - "block.create.turntable.tooltip.summary": "UNLOCALIZED: Turns _Rotational Force_ into refined Motion Sickness.", - - "block.create.portable_fluid_interface.tooltip": "UNLOCALIZED: PORTABLE FLUID INTERFACE", - "block.create.portable_fluid_interface.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: While Moving", - "block.create.portable_fluid_interface.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: When Powered by Redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "UNLOCALIZED: _Disengages_ any active connection immediately.", - - "block.create.stockpile_switch.tooltip": "UNLOCALIZED: STOCKPILE SWITCH", - "block.create.stockpile_switch.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: When R-Clicked", - "block.create.stockpile_switch.tooltip.behaviour1": "UNLOCALIZED: Opens the _Configuration Interface_.", - - "block.create.content_observer.tooltip": "UNLOCALIZED: CONTENT OBSERVER", - "block.create.content_observer.tooltip.summary": "UNLOCALIZED: _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_.", - - "block.create.adjustable_crate.tooltip": "UNLOCALIZED: ADJUSTABLE CRATE", - "block.create.adjustable_crate.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: When R-Clicked", - "block.create.adjustable_crate.tooltip.behaviour1": "UNLOCALIZED: Opens the _Interface_.", - - "block.create.creative_crate.tooltip": "UNLOCALIZED: THE ENDLESS CRATE", - "block.create.creative_crate.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: When Item in Filter Slot", - "block.create.creative_crate.tooltip.behaviour1": "UNLOCALIZED: Anything _extracting_ from this container will provide an _endless supply_ of the item specified. Items _inserted_ into this crate will be _voided._", - - "block.create.controller_rail.tooltip": "UNLOCALIZED: CONTROLLER RAIL", - "block.create.controller_rail.tooltip.summary": "UNLOCALIZED: A _uni-directional powered rail_ capable of _fine control_ over a minecarts' _movement speed_.", - "block.create.controller_rail.tooltip.condition1": "UNLOCALIZED: When Powered by Redstone", - "block.create.controller_rail.tooltip.behaviour1": "UNLOCALIZED: _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": "UNLOCALIZED: SAND PAPER", - "item.create.sand_paper.tooltip.summary": "UNLOCALIZED: A rough paper that can be used to _polish materials_. Can be automatically applied using the Deployer.", - "item.create.sand_paper.tooltip.condition1": "UNLOCALIZED: When Used", - "item.create.sand_paper.tooltip.behaviour1": "UNLOCALIZED: Applies polish to items held in the _offhand_ or lying on the _floor_ when _looking at them_", - - "item.create.builders_tea.tooltip": "UNLOCALIZED: BUILDERS TEA", - "item.create.builders_tea.tooltip.summary": "UNLOCALIZED: The perfect drink to get the day started- _Motivating_ and _Saturating._", - - "item.create.refined_radiance.tooltip": "UNLOCALIZED: REFINED RADIANCE", - "item.create.refined_radiance.tooltip.summary": "UNLOCALIZED: A Chromatic material forged from _absorbed light_.", - - "item.create.shadow_steel.tooltip": "UNLOCALIZED: SHADOW STEEL", - "item.create.shadow_steel.tooltip.summary": "UNLOCALIZED: A Chromatic material forged _in the void_.", - - "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 [------------------------<-", - - "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.", - - "_": "Thank you for translating Create!" - -} \ No newline at end of file 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..edd754860 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: 1425", "_": "->------------------------] Game Elements [------------------------<-", @@ -28,12 +28,16 @@ "block.create.belt": "Tapis roulant", "block.create.birch_window": "Fenêtre en bouleau", "block.create.birch_window_pane": "Vitre en bouleau", + "block.create.black_nixie_tube": "UNLOCALIZED: Black Nixie Tube", "block.create.black_sail": "Voile noire", "block.create.black_seat": "Siège noir", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "Vanne noire", "block.create.blaze_burner": "Brûleur à blaze", + "block.create.blue_nixie_tube": "UNLOCALIZED: Blue Nixie Tube", "block.create.blue_sail": "Voile bleue", "block.create.blue_seat": "Siège bleu", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "Vanne bleue", "block.create.brass_belt_funnel": "Entonnoir en laiton pour tapis roulant", "block.create.brass_block": "Bloc de laiton", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "Rotor dans un revêtement en laiton", "block.create.brass_funnel": "Entonnoir en laiton", "block.create.brass_tunnel": "Tunnel en laiton", + "block.create.brown_nixie_tube": "UNLOCALIZED: Brown Nixie Tube", "block.create.brown_sail": "Voile brune", "block.create.brown_seat": "Siège brun", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "Vanne brune", "block.create.cart_assembler": "Assembleur de wagon", "block.create.chiseled_dark_scoria": "Scoria sombre taillé", @@ -73,8 +79,10 @@ "block.create.crushing_wheel": "Roue de concassage", "block.create.crushing_wheel_controller": "Contrôleur de roue de concassage", "block.create.cuckoo_clock": "Horloge à coucou", + "block.create.cyan_nixie_tube": "UNLOCALIZED: Cyan Nixie Tube", "block.create.cyan_sail": "Voile cyan", "block.create.cyan_seat": "Siège cyan", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "Vanne cyan", "block.create.dark_oak_window": "fenêtre en chêne sombre", "block.create.dark_oak_window_pane": "Vitre en chêne sombre", @@ -179,13 +187,18 @@ "block.create.granite_cobblestone_stairs": "UNLOCALIZED: Granite Cobblestone Stairs", "block.create.granite_cobblestone_wall": "UNLOCALIZED: Granite Cobblestone Wall", "block.create.granite_pillar": "UNLOCALIZED: Granite Pillar", + "block.create.gray_nixie_tube": "UNLOCALIZED: Gray Nixie Tube", "block.create.gray_sail": "UNLOCALIZED: Gray Sail", "block.create.gray_seat": "UNLOCALIZED: Gray Seat", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "UNLOCALIZED: Gray Valve Handle", + "block.create.green_nixie_tube": "UNLOCALIZED: Green Nixie Tube", "block.create.green_sail": "UNLOCALIZED: Green Sail", "block.create.green_seat": "UNLOCALIZED: Green Seat", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "UNLOCALIZED: Green Valve Handle", "block.create.hand_crank": "Manivelle", + "block.create.haunted_bell": "UNLOCALIZED: Haunted Bell", "block.create.honey": "UNLOCALIZED: Honey", "block.create.horizontal_framed_glass": "Fenêtre en verre horizontale", "block.create.horizontal_framed_glass_pane": "Vitre encadrée horizontale", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "UNLOCALIZED: Layered Limestone", "block.create.layered_scoria": "UNLOCALIZED: Layered Scoria", "block.create.layered_weathered_limestone": "UNLOCALIZED: Layered Weathered Limestone", + "block.create.lectern_controller": "UNLOCALIZED: Lectern Controller", + "block.create.light_blue_nixie_tube": "UNLOCALIZED: Light Blue Nixie Tube", "block.create.light_blue_sail": "UNLOCALIZED: Light Blue Sail", "block.create.light_blue_seat": "UNLOCALIZED: Light Blue Seat", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "UNLOCALIZED: Light Blue Valve Handle", + "block.create.light_gray_nixie_tube": "UNLOCALIZED: Light Gray Nixie Tube", "block.create.light_gray_sail": "UNLOCALIZED: Light Gray Sail", "block.create.light_gray_seat": "UNLOCALIZED: Light Gray Seat", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "UNLOCALIZED: Light Gray Valve Handle", + "block.create.lime_nixie_tube": "UNLOCALIZED: Lime Nixie Tube", "block.create.lime_sail": "UNLOCALIZED: Lime Sail", "block.create.lime_seat": "UNLOCALIZED: Lime Seat", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "UNLOCALIZED: Lime Valve Handle", "block.create.limesand": "Chaux", "block.create.limestone": "Calcaire", @@ -225,8 +245,10 @@ "block.create.limestone_pillar": "Pillier de calcaire", "block.create.linear_chassis": "Châssis linéaire", "block.create.lit_blaze_burner": "UNLOCALIZED: Lit Blaze Burner", + "block.create.magenta_nixie_tube": "UNLOCALIZED: Magenta Nixie Tube", "block.create.magenta_sail": "UNLOCALIZED: Magenta Sail", "block.create.magenta_seat": "UNLOCALIZED: Magenta Seat", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "UNLOCALIZED: Magenta Valve Handle", "block.create.mechanical_arm": "UNLOCALIZED: Mechanical Arm", "block.create.mechanical_bearing": "Roulement mécanique", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "UNLOCALIZED: Oak Window Pane", "block.create.orange_sail": "UNLOCALIZED: Orange Sail", "block.create.orange_seat": "UNLOCALIZED: Orange Seat", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "UNLOCALIZED: Orange Valve Handle", "block.create.ornate_iron_window": "UNLOCALIZED: Ornate Iron Window", "block.create.ornate_iron_window_pane": "UNLOCALIZED: Ornate Iron Window Pane", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "UNLOCALIZED: Paved Weathered Limestone Slab", "block.create.paved_weathered_limestone_stairs": "UNLOCALIZED: Paved Weathered Limestone Stairs", "block.create.paved_weathered_limestone_wall": "UNLOCALIZED: Paved Weathered Limestone Wall", + "block.create.peculiar_bell": "UNLOCALIZED: Peculiar Bell", + "block.create.pink_nixie_tube": "UNLOCALIZED: Pink Nixie Tube", "block.create.pink_sail": "UNLOCALIZED: Pink Sail", "block.create.pink_seat": "UNLOCALIZED: Pink Seat", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "UNLOCALIZED: Pink Valve Handle", "block.create.piston_extension_pole": "Barre d'extension de piston", "block.create.polished_dark_scoria": "Scorie sombre polie", @@ -342,12 +368,16 @@ "block.create.powered_toggle_latch": "Verrou alimenté à bascule", "block.create.pulley_magnet": "Aimant de poulie", "block.create.pulse_repeater": "Répéteur d'impulsions", + "block.create.purple_nixie_tube": "UNLOCALIZED: Purple Nixie Tube", "block.create.purple_sail": "UNLOCALIZED: Purple Sail", "block.create.purple_seat": "UNLOCALIZED: Purple Seat", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "UNLOCALIZED: Purple Valve Handle", "block.create.radial_chassis": "Châssis radial", + "block.create.red_nixie_tube": "UNLOCALIZED: Red Nixie Tube", "block.create.red_sail": "UNLOCALIZED: Red Sail", "block.create.red_seat": "UNLOCALIZED: Red Seat", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "UNLOCALIZED: Red Valve Handle", "block.create.redstone_contact": "Contact de redstone", "block.create.redstone_link": "Liaison Redstone", @@ -402,24 +432,32 @@ "block.create.weathered_limestone_cobblestone_wall": "UNLOCALIZED: Weathered Limestone Cobblestone Wall", "block.create.weathered_limestone_pillar": "Pillier de Calcaire altéré", "block.create.weighted_ejector": "UNLOCALIZED: Weighted Ejector", + "block.create.white_nixie_tube": "UNLOCALIZED: White Nixie Tube", "block.create.white_sail": "UNLOCALIZED: White Sail", "block.create.white_seat": "UNLOCALIZED: White Seat", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle", "block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing", "block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket", + "block.create.yellow_nixie_tube": "UNLOCALIZED: Yellow Nixie Tube", "block.create.yellow_sail": "UNLOCALIZED: Yellow Sail", "block.create.yellow_seat": "UNLOCALIZED: Yellow Seat", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle", "block.create.zinc_block": "Bloc de zinc", "block.create.zinc_ore": "Minerai de zinc", + "enchantment.create.capacity": "UNLOCALIZED: Capacity", + "enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery", + "entity.create.contraption": "Engin", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "entity.create.potato_projectile": "UNLOCALIZED: Potato Projectile", "entity.create.seat": "Siège", "entity.create.stationary_contraption": "Engin stationnaire", "entity.create.super_glue": "Colle extra-forte", - "fluid.create.milk": "Lait", "fluid.create.potion": "Potion", "fluid.create.tea": "Thé du constructeur", @@ -444,6 +482,8 @@ "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.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "item.create.crushed_aluminum_ore": "Aluminium concassé", "item.create.crushed_brass": "Laiton concassé", "item.create.crushed_copper_ore": "Cuivre concassé", @@ -472,13 +512,17 @@ "item.create.handheld_worldshaper": "Térraformeur portable", "item.create.honey_bucket": "Seau de miel", "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", - "item.create.integrated_circuit": "Circuit intégré", + "item.create.incomplete_cogwheel": "UNLOCALIZED: Incomplete Cogwheel", + "item.create.incomplete_large_cogwheel": "UNLOCALIZED: Incomplete Large Cogwheel", + "item.create.incomplete_precision_mechanism": "UNLOCALIZED: Incomplete Precision Mechanism", "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", + "item.create.potato_cannon": "UNLOCALIZED: Potato Cannon", "item.create.powdered_obsidian": "Obsidienne concassée", + "item.create.precision_mechanism": "UNLOCALIZED: Precision Mechanism", "item.create.propeller": "Hélice", "item.create.red_sand_paper": "Papier de verre rouge", "item.create.refined_radiance": "Éclat raffiné", @@ -623,8 +667,8 @@ "advancement.create.flywheel.desc": "UNLOCALIZED: Successfully connect an engine to the Flywheel.", "advancement.create.overstress_flywheel": "UNLOCALIZED: High levels of Stress", "advancement.create.overstress_flywheel.desc": "UNLOCALIZED: Overstress a Furnace Engine.", - "advancement.create.integrated_circuit": "UNLOCALIZED: Complex Calculation", - "advancement.create.integrated_circuit.desc": "UNLOCALIZED: Assemble an Integrated Circuit.", + "advancement.create.precision_mechanism": "UNLOCALIZED: Complex Curiosities", + "advancement.create.precision_mechanism.desc": "UNLOCALIZED: Assemble a Precision Mechanism.", "advancement.create.mechanical_arm": "UNLOCALIZED: Busy Hands!", "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch as it does all the work for you.", "advancement.create.musical_arm": "UNLOCALIZED: Play Me My Theme Tune!", @@ -639,7 +683,7 @@ "advancement.create.crushing_wheel.desc": "UNLOCALIZED: Create some Crushing Wheels to break down more materials more effectively.", "advancement.create.blaze_cake": "UNLOCALIZED: Sugar Rush", "advancement.create.blaze_cake.desc": "UNLOCALIZED: Bake your blaze burner a special cake.", - "advancement.create.chromatic_compound": "UNLOCALIZED: Bipolar Minerals", + "advancement.create.chromatic_compound": "UNLOCALIZED: Mysterious Minerals", "advancement.create.chromatic_compound.desc": "UNLOCALIZED: Create a Bar of Chromatic Compound.", "advancement.create.shadow_steel": "UNLOCALIZED: Void Returner", "advancement.create.shadow_steel.desc": "UNLOCALIZED: Create Shadow Steel, a metal bar of nothingness.", @@ -651,6 +695,8 @@ "advancement.create.wand_of_symmetry.desc": "UNLOCALIZED: Craft a Staff of Symmetry.", "advancement.create.extendo_grip": "UNLOCALIZED: Boioioing!", "advancement.create.extendo_grip.desc": "UNLOCALIZED: Get hold of an Extendo Grip.", + "advancement.create.potato_cannon": "UNLOCALIZED: Fwoomp!", + "advancement.create.potato_cannon.desc": "UNLOCALIZED: Defeat an enemy with your Potato Cannon.", "advancement.create.dual_extendo_grip": "UNLOCALIZED: Ultimate Boing-age", "advancement.create.dual_extendo_grip.desc": "UNLOCALIZED: Dual wield Extendo Grips for super-human reach.", "advancement.create.eob": "UNLOCALIZED: End of Beta", @@ -663,15 +709,31 @@ "itemGroup.create.palettes": "Create Palettes", "death.attack.create.crush": "%1$s a été concassé.e", + "death.attack.create.crush.player": "UNLOCALIZED: %1$s was thrown into Crushing Wheels by %2$s", "death.attack.create.fan_fire": "%1$s a été brûlé à mort par l'air chaud", + "death.attack.create.fan_fire.player": "UNLOCALIZED: %1$s was thrown into a smoker by %2$s", "death.attack.create.fan_lava": "%1$s a été brûlé à mort par un ventilateur de lave", + "death.attack.create.fan_lava.player": "UNLOCALIZED: %1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "%1$s a été empalé par une perceuse mécanique", + "death.attack.create.mechanical_drill.player": "UNLOCALIZED: %1$s was thrown in front of a Drill by %2$s", "death.attack.create.mechanical_saw": "%1$s a été coupé en deux par une scie mécanique", + "death.attack.create.mechanical_saw.player": "UNLOCALIZED: %1$s was thrown into a Saw by %2$s", + "death.attack.create.potato_cannon": "UNLOCALIZED: %1$s was shot by %2$s's Potato Cannon", + "death.attack.create.potato_cannon.item": "UNLOCALIZED: %1$s was shot by %2$s using %3$s", "death.attack.create.cuckoo_clock_explosion": "%1$s a été explosé par un coucou trafiquée", + "death.attack.create.cuckoo_clock_explosion.player": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", "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.ponder_index": "UNLOCALIZED: Ponder Index", + "create.menu.only_ingame": "UNLOCALIZED: Available in the Pause Menu", + "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", @@ -696,7 +758,18 @@ "create.recipe.mystery_conversion": "Métamorphose chromatique", "create.recipe.spout_filling": "Remplissage par un bec verseur", "create.recipe.draining": "UNLOCALIZED: Item Draining", + "create.recipe.sequenced_assembly": "UNLOCALIZED: Sequenced Assembly", + "create.recipe.assembly.next": "UNLOCALIZED: Next: %1$s", + "create.recipe.assembly.step": "UNLOCALIZED: Step %1$s:", + "create.recipe.assembly.progress": "UNLOCALIZED: Progress: %1$s/%2$s", + "create.recipe.assembly.pressing": "UNLOCALIZED: Process in Press", + "create.recipe.assembly.spout_filling_fluid": "UNLOCALIZED: Spout %1$s", + "create.recipe.assembly.deploying_item": "UNLOCALIZED: Deploy %1$s", + "create.recipe.assembly.cutting": "UNLOCALIZED: Cut with Saw", + "create.recipe.assembly.repeat": "UNLOCALIZED: Repeat Sequence %1$s Times", + "create.recipe.assembly.junk": "UNLOCALIZED: Random salvage", "create.recipe.processing.chance": "%1$s%% de chance", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "Pas de chauffage requis", "create.recipe.heat_requirement.heated": "Chauffé", "create.recipe.heat_requirement.superheated": "Surchauffé", @@ -725,6 +798,7 @@ "create.action.discard": "Annuler", "create.keyinfo.toolmenu": "Focus sur le menu de l'outil", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "UNLOCALIZED: Simulate Mousewheel Up (inworld)", "create.keyinfo.scrolldown": "UNLOCALIZED: Simulate Mousewheel Down (inworld)", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "Maj pour défiler plus rapidement", "create.gui.toolmenu.focusKey": "Enfoncez [%1$s] pour focus", "create.gui.toolmenu.cycle": "[SCROLL] pour cycler", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Mirroir", "create.gui.symmetryWand.orientation": "Orientation", @@ -981,18 +1062,14 @@ "create.item_attributes.placeable.inverted": "n'est pas plaçable", "create.item_attributes.consumable": "peut être mangé", "create.item_attributes.consumable.inverted": "ne peut pas être mangé", - "create.item_attributes.smeltable": "peut être fondu", - "create.item_attributes.smeltable.inverted": "ne peut pas être fondu", - "create.item_attributes.washable": "peut être lavé", - "create.item_attributes.washable.inverted": "ne peut pas être lavé", - "create.item_attributes.smokable": "peut être fumé", - "create.item_attributes.smokable.inverted": "ne peut pas être fumé", - "create.item_attributes.crushable": "peut être concassé", - "create.item_attributes.crushable.inverted": "ne peut pas être concassé", - "create.item_attributes.blastable": "est fondable dans un Haut fourneau", - "create.item_attributes.blastable.inverted": "n'est pas fondable dans un Haut fourneau", + "create.item_attributes.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "est enchanté", "create.item_attributes.enchanted.inverted": "n'est pas enchanté", + "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.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "est endommagé", "create.item_attributes.damaged.inverted": "n'est pas endomagé", "create.item_attributes.badly_damaged": "est fortement damaged", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "ne peut pas être équipé", "create.item_attributes.furnace_fuel": "est du combustible", "create.item_attributes.furnace_fuel.inverted": "n'est pas un combustible", + "create.item_attributes.washable": "peut être lavé", + "create.item_attributes.washable.inverted": "ne peut pas être lavé", + "create.item_attributes.crushable": "peut être concassé", + "create.item_attributes.crushable.inverted": "ne peut pas être concassé", + "create.item_attributes.smeltable": "peut être fondu", + "create.item_attributes.smeltable.inverted": "ne peut pas être fondu", + "create.item_attributes.smokable": "peut être fumé", + "create.item_attributes.smokable.inverted": "ne peut pas être fumé", + "create.item_attributes.blastable": "est fondable dans un Haut fourneau", + "create.item_attributes.blastable.inverted": "n'est pas fondable dans un Haut fourneau", + "create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s", + "create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s", + "create.item_attributes.shulker_level.full": "UNLOCALIZED: full", + "create.item_attributes.shulker_level.empty": "UNLOCALIZED: empty", + "create.item_attributes.shulker_level.partial": "UNLOCALIZED: partially filled", "create.item_attributes.in_tag": "est étiqueté %1$s", "create.item_attributes.in_tag.inverted": "n'est pas étiqueté", "create.item_attributes.in_item_group": "appartient à %1$s", @@ -1013,8 +1105,6 @@ "create.item_attributes.has_enchant.inverted": "n'est pas enchenté %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.has_fluid": "contient %1$s", "create.item_attributes.has_fluid.inverted": "ne contient pas %1$s", "create.item_attributes.has_name": "est renommé %1$s", @@ -1029,14 +1119,14 @@ "create.item_attributes.book_copy_second.inverted": "UNLOCALIZED: is not a second-generation copy", "create.item_attributes.book_copy_tattered": "UNLOCALIZED: is a tattered mess", "create.item_attributes.book_copy_tattered.inverted": "UNLOCALIZED: is not a tattered mess", - "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", - "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", - "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", "create.item_attributes.astralsorcery_amulet": "UNLOCALIZED: improves %1$s", "create.item_attributes.astralsorcery_amulet.inverted": "UNLOCALIZED: does not improve %1$s", + "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", + "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", "create.gui.attribute_filter.no_selected_attributes": "Aucun attribut sélectionné", "create.gui.attribute_filter.selected_attributes": "Attributs sélectionnés:", @@ -1104,6 +1194,27 @@ "create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above", "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "UNLOCALIZED: Currently distributing:", + "create.tooltip.brass_tunnel.contains_entry": "UNLOCALIZED: > %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "UNLOCALIZED: Right-Click to retrieve", + + "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.potato_cannon.ammo.attack_damage": "UNLOCALIZED: %1$s Attack Damage", + "create.potato_cannon.ammo.reload_ticks": "UNLOCALIZED: %1$s Reload Ticks", + "create.potato_cannon.ammo.knockback": "UNLOCALIZED: %1$s Knockback", "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", @@ -1132,32 +1243,44 @@ "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.contraption_disassemble": "UNLOCALIZED: Contraption stops", + "create.subtitle.peculiar_bell_use": "UNLOCALIZED: Peculiar Bell tolls", + "create.subtitle.mixing": "UNLOCALIZED: Mixing noises", + "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", + "create.subtitle.fwoomp": "UNLOCALIZED: Potato Launcher fwoomps", + "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", + "create.subtitle.crushing_1": "UNLOCALIZED: Crushing noises", + "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", + "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel flaps", + "create.subtitle.schematicannon_finish": "Fin de schémacanon", + "create.subtitle.haunted_bell_use": "UNLOCALIZED: Haunted Bell tolls", + "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.controller_put": "UNLOCALIZED: Controller thumps", + "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.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.potato_hit": "UNLOCALIZED: Vegetable impacts", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens", "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", - "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", "create.subtitle.deny": "UNLOCALIZED: Declining boop", - "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", "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.controller_take": "UNLOCALIZED: Lectern empties", "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", @@ -1179,14 +1302,6 @@ "block.create.metal_bracket.tooltip": "UNLOCALIZED: METAL BRACKET", "block.create.metal_bracket.tooltip.summary": "UNLOCALIZED: _Decorate_ your _Shafts, Cogwheels_ and _Pipes_ with an industrial and sturdy bit of reinforcement.", - "block.create.copper_casing.tooltip": "UNLOCALIZED: COPPER CASING", - "block.create.copper_casing.tooltip.summary": "UNLOCALIZED: Robust machine casing with a variety of uses. Safe for decoration.", - "block.create.copper_casing.tooltip.condition1": "UNLOCALIZED: When used on Fluid Pipe", - "block.create.copper_casing.tooltip.behaviour1": "UNLOCALIZED: _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": "UNLOCALIZED: ENCASED FLUID PIPE", - "block.create.encased_fluid_pipe.tooltip.summary": "UNLOCALIZED: A _Fluid Pipe_ encased with the _Copper Casing_.", - "block.create.seat.tooltip": "UNLOCALIZED: SEAT", "block.create.seat.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: Right click on Seat", @@ -1195,65 +1310,6 @@ "item.create.blaze_cake.tooltip": "UNLOCALIZED: BLAZE CAKE", "item.create.blaze_cake.tooltip.summary": "UNLOCALIZED: A Delicious treat for your hard-working _Blaze Burners_. Gets them all fired up!", - "block.create.fluid_pipe.tooltip": "UNLOCALIZED: FLUID PIPE", - "block.create.fluid_pipe.tooltip.summary": "UNLOCALIZED: Used for moving _fluids_ around. Needs a _Mechanical Pump_ to get the _fluid_ moving.", - "block.create.fluid_pipe.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.fluid_pipe.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Places a window on the pipe if available", - - "block.create.hose_pulley.tooltip": "UNLOCALIZED: HOSE PULLEY", - "block.create.hose_pulley.tooltip.summary": "UNLOCALIZED: Used for _placing_ or _draining_ large _fluid bodies_ in the world.", - "block.create.hose_pulley.tooltip.condition1": "UNLOCALIZED: When Powered by Kinetics", - "block.create.hose_pulley.tooltip.behaviour1": "UNLOCALIZED: _Raises_ or _Lowers_ the hose, location of the hose determines up to which _height extraction_ or _filling_ will act.", - "block.create.hose_pulley.tooltip.condition2": "UNLOCALIZED: When Fluids pulled from Pulley", - "block.create.hose_pulley.tooltip.behaviour2": "UNLOCALIZED: 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": "UNLOCALIZED: When Fluids pushed to Pulley", - "block.create.hose_pulley.tooltip.behaviour3": "UNLOCALIZED: Starts _filling fluid_ into the world _up to_ the _hose_ ends' _height_.", - - "block.create.fluid_tank.tooltip": "UNLOCALIZED: FLUID TANK", - "block.create.fluid_tank.tooltip.summary": "UNLOCALIZED: _Stores_ all your favourite _fluids_. Scales in width and height.", - "block.create.fluid_tank.tooltip.condition1": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_tank.tooltip.behaviour1": "UNLOCALIZED: Changes the optional window", - - "block.create.creative_fluid_tank.tooltip": "UNLOCALIZED: CREATIVE FLUID TANK", - "block.create.creative_fluid_tank.tooltip.summary": "UNLOCALIZED: This _Fluid Tank_ allows infinite replication of any Fluid. Scales in width and height.", - "block.create.creative_fluid_tank.tooltip.condition1": "UNLOCALIZED: When Fluid in Tank", - "block.create.creative_fluid_tank.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.creative_fluid_tank.tooltip.behaviour2": "UNLOCALIZED: Changes the optional window", - - "block.create.fluid_valve.tooltip": "UNLOCALIZED: FLUID VALVE", - "block.create.fluid_valve.tooltip.summary": "UNLOCALIZED: Halts the flow of fluid down a pipe.", - "block.create.fluid_valve.tooltip.condition1": "UNLOCALIZED: Controllable flow", - "block.create.fluid_valve.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: MECHANICAL PUMP", - "block.create.mechanical_pump.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: Fluid Flow", - "block.create.mechanical_pump.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.mechanical_pump.tooltip.action1": "UNLOCALIZED: Reverses the direction of the _pump_, switching the default direction of the flow", - - "block.create.smart_fluid_pipe.tooltip": "UNLOCALIZED: SMART FLUID PIPE", - "block.create.smart_fluid_pipe.tooltip.summary": "UNLOCALIZED: A _fluid pipe_ with a filter. Can specify which _fluids_ pass through.", - "block.create.smart_fluid_pipe.tooltip.condition1": "UNLOCALIZED: When Fluids are pushed into it", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "UNLOCALIZED: Smart pipes receiving fluid that does not match its filter will block the flow.", - "block.create.smart_fluid_pipe.tooltip.condition2": "UNLOCALIZED: When adjacent to fluid container", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Smart pipes _starting_ a _flow_ from any container will only extract fluids that _match_ its _filter._", - - "block.create.spout.tooltip": "UNLOCALIZED: SPOUT", - "block.create.spout.tooltip.summary": "UNLOCALIZED: An injector for refilling your _fluid items._", - "block.create.spout.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.spout.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Fluid Automation", - "block.create.spout.tooltip.behaviour2": "UNLOCALIZED: 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": "UNLOCALIZED: ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "UNLOCALIZED: A grated depot for emptying your _fluid items._", - "block.create.item_drain.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.item_drain.tooltip.behaviour1": "UNLOCALIZED: 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": "BÂTON DE SYMÉTRIE", "item.create.wand_of_symmetry.tooltip.summary": "Reflète parfaitement le placement des blocs sur les plans configurés.", "item.create.wand_of_symmetry.tooltip.condition1": "Quand positionné dans la barre active", @@ -1280,9 +1336,18 @@ "item.create.tree_fertilizer.tooltip.behaviour1": "Fait pousser des rotors _indépendamment_ de leurs _conditions_ _d'emplacement_", "item.create.extendo_grip.tooltip": "UNLOCALIZED: EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder.", + "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder. Can be powered with Air Pressure from a _Copper_ _Backtank_", "item.create.extendo_grip.tooltip.condition1": "UNLOCALIZED: When in Off-Hand", "item.create.extendo_grip.tooltip.behaviour1": "UNLOCALIZED: Increases _reach distance_ of items used in the _Main-Hand_.", + "item.create.extendo_grip.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", + + "item.create.potato_cannon.tooltip": "UNLOCALIZED: POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "UNLOCALIZED: Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", + "item.create.potato_cannon.tooltip.behaviour1": "UNLOCALIZED: _Shoots_ a suitable item from your _Inventory_.", + "item.create.potato_cannon.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.filter.tooltip": "FILTRE", "item.create.filter.tooltip.summary": "_Contrôle_ les _sorties_ et _entrées_ de dispositifs logistiques avec plus de _précision_, en les comparant à un _ensemble_ _d'objets_ ou à plusieurs _filtres_ _imbriqués_.", @@ -1358,12 +1423,14 @@ "block.create.turntable.tooltip": "PLAQUE TOURNANTE", "block.create.turntable.tooltip.summary": "Transforme la _force_ _de_ _rotation_ en énergie cinétique.", - "block.create.portable_fluid_interface.tooltip": "UNLOCALIZED: PORTABLE FLUID INTERFACE", - "block.create.portable_fluid_interface.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: While Moving", - "block.create.portable_fluid_interface.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: When Powered by Redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "UNLOCALIZED: _Disengages_ any active connection immediately.", + "block.create.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "DÉTÉCTEUR DE STOCKAGE", "block.create.stockpile_switch.tooltip.summary": "Bascule un signal Redstone basé sur _l'espace_ _de_ _stockage_ dans le conteneur attaché.", @@ -1372,6 +1439,10 @@ "block.create.content_observer.tooltip": "OBSERVATEUR DE CONTENU", "block.create.content_observer.tooltip.summary": "_Détecte les objets_ à l'intérieur des _conteneurs_ et des _transporteurs_ correspondant à un _filtre_ configuré. Tant que l'_inventaire_, le _tapis roulant_ ou la _glissière_ observé _contient_ un objet correspondant, ce composant émet un _signal de redstone_. Quand un _entonnoir_ observé _transfère_ un objet correspondant, ce composant émet une _impulsion de redstone_.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "CAISSE AJUSTABLE", "block.create.adjustable_crate.tooltip.summary": "Ce _conteneur_ _de_ _stockage_ permet un contrôle manuel de sa capacité. Il peut contenir jusqu'à _16_ _piles_ de n'importe quel objet. Prend en charge les _comparateurs_ _de_ _redstone_.", @@ -1383,6 +1454,11 @@ "block.create.creative_crate.tooltip.condition1": "Quand un objet se trouve dans l'emplacement de filtrage", "block.create.creative_crate.tooltip.behaviour1": "Tout ce qui _extrait_ de ce conteneur aura une _alimentation illimitée_ de l'objet spécifié. Les objets _insérés_ dans cette caisse seront _éliminés_.", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "UNLOCALIZED: CONTROLLER RAIL", "block.create.controller_rail.tooltip.summary": "UNLOCALIZED: A _uni-directional powered rail_ capable of _fine control_ over a minecarts' _movement speed_.", "block.create.controller_rail.tooltip.condition1": "UNLOCALIZED: When Powered by Redstone", @@ -1398,26 +1474,61 @@ "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.linked_controller.tooltip.condition4": "UNLOCALIZED: R-Click on Lectern", + "item.create.linked_controller.tooltip.behaviour4": "UNLOCALIZED: Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the wielder 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: Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder 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.", + "block.create.peculiar_bell.tooltip": "UNLOCALIZED: PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "UNLOCALIZED: A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + + "block.create.haunted_bell.tooltip": "UNLOCALIZED: HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "UNLOCALIZED: A _Cursed Bell_ haunted by lost souls of the Nether.", + "block.create.haunted_bell.tooltip.condition1": "UNLOCALIZED: When Held or Rang", + "block.create.haunted_bell.tooltip.behaviour1": "UNLOCALIZED: Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn.", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1434,41 +1545,46 @@ "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.exit": "UNLOCALIZED: Exit", + "create.ponder.welcome": "UNLOCALIZED: Welcome to Ponder", + "create.ponder.categories": "UNLOCALIZED: Available Categories in Create", + "create.ponder.index_description": "UNLOCALIZED: Click one of the icons to learn about its associated Items and Blocks", + "create.ponder.index_title": "UNLOCALIZED: Ponder Index", + "create.ponder.shared.rpm16": "UNLOCALIZED: 16 RPM", "create.ponder.shared.behaviour_modify_wrench": "UNLOCALIZED: This behaviour can be modified using a Wrench", + "create.ponder.shared.storage_on_contraption": "UNLOCALIZED: Inventories attached to the Contraption will pick up their drops automatically", + "create.ponder.shared.sneak_and": "UNLOCALIZED: Sneak +", "create.ponder.shared.rpm8": "UNLOCALIZED: 8 RPM", "create.ponder.shared.ctrl_and": "UNLOCALIZED: Ctrl +", + "create.ponder.shared.rpm32": "UNLOCALIZED: 32 RPM", "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.shared.movement_anchors": "UNLOCALIZED: With the help of Chassis or Super Glue, larger structures can be moved.", "create.ponder.tag.redstone": "UNLOCALIZED: Logic Components", "create.ponder.tag.redstone.description": "UNLOCALIZED: Components which help with redstone engineering", + "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.fluids": "UNLOCALIZED: Fluid Manipulators", "create.ponder.tag.fluids.description": "UNLOCALIZED: Components which help relaying and making use of Fluids", + "create.ponder.tag.decoration": "UNLOCALIZED: Aesthetics", + "create.ponder.tag.decoration.description": "UNLOCALIZED: Components used mostly for decorative purposes", + "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.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.kinetic_appliances": "UNLOCALIZED: Kinetic Appliances", + "create.ponder.tag.kinetic_appliances.description": "UNLOCALIZED: Components which make use of Rotational Force", + "create.ponder.tag.kinetic_sources": "UNLOCALIZED: Kinetic Sources", + "create.ponder.tag.kinetic_sources.description": "UNLOCALIZED: Components which generate Rotational Force", + "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.kinetic_relays": "UNLOCALIZED: Kinetic Blocks", + "create.ponder.tag.kinetic_relays.description": "UNLOCALIZED: Components which help relaying Rotational Force elsewhere", + "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.creative": "UNLOCALIZED: Creative Mode", + "create.ponder.tag.creative.description": "UNLOCALIZED: Components not usually available for Survival Mode", + "create.ponder.tag.logistics": "UNLOCALIZED: Item Transportation", + "create.ponder.tag.logistics.description": "UNLOCALIZED: Components which help moving items around", "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", @@ -1580,7 +1696,8 @@ "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_modes.text_2": "UNLOCALIZED: This Arrow indicates which side of the Structure will be considered the front", + "create.ponder.cart_assembler_modes.text_3": "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", @@ -1594,7 +1711,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 +1751,12 @@ "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_fluid_tank.text_1": "UNLOCALIZED: Creative Fluid Tanks can be used to provide a bottomless supply of fluid", + "create.ponder.creative_fluid_tank.text_2": "UNLOCALIZED: Right-Click with a fluid containing item to configure it", + "create.ponder.creative_fluid_tank.text_3": "UNLOCALIZED: Pipe Networks can now endlessly draw the assigned fluid from the tank", + "create.ponder.creative_fluid_tank.text_4": "UNLOCALIZED: Any Fluids pushed back into a Creative Fluid Tank will be voided", + "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 +1793,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", @@ -1686,7 +1815,13 @@ "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.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item", + "create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they 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", @@ -1706,6 +1841,35 @@ "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_sizes.text_1": "UNLOCALIZED: Fluid Tanks can be combined to increase the total capacity", + "create.ponder.fluid_tank_sizes.text_2": "UNLOCALIZED: Their base square can be up to 3 blocks wide...", + "create.ponder.fluid_tank_sizes.text_3": "UNLOCALIZED: ...and grow in height by more than 30 additional layers", + "create.ponder.fluid_tank_sizes.text_4": "UNLOCALIZED: Using a Wrench, a tanks' window can be toggled", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.fluid_tank_storage.text_1": "UNLOCALIZED: Fluid Tanks can be used to store large amounts of fluid", + "create.ponder.fluid_tank_storage.text_2": "UNLOCALIZED: Pipe networks can push and pull fluids from any side", + "create.ponder.fluid_tank_storage.text_3": "UNLOCALIZED: The contained fluid can be measured by a Comparator", + "create.ponder.fluid_tank_storage.text_4": "UNLOCALIZED: However, in Survival Mode Fluids cannot be added or taken manually", + "create.ponder.fluid_tank_storage.text_5": "UNLOCALIZED: You can use Basins, Item Drains and Spouts to drain or fill fluid containing items", + "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 +1943,34 @@ "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.text_1": "UNLOCALIZED: Hose Pulleys can be used to fill or drain large bodies of Fluid", + "create.ponder.hose_pulley.text_2": "UNLOCALIZED: With the Kinetic Input, the height of the pulleys' hose can be controlled", + "create.ponder.hose_pulley.text_3": "UNLOCALIZED: The Pulley retracts while the input rotation is inverted", + "create.ponder.hose_pulley.text_4": "UNLOCALIZED: On the opposite side, pipes can be connected", + "create.ponder.hose_pulley.text_5": "UNLOCALIZED: Attached pipe networks can either provide fluid to the hose...", + "create.ponder.hose_pulley.text_6": "UNLOCALIZED: ...or pull from it, draining the pool instead", + "create.ponder.hose_pulley.text_7": "UNLOCALIZED: Fill and Drain speed of the pulley depends entirely on the fluid networks' throughput", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + "create.ponder.hose_pulley_infinite.text_1": "UNLOCALIZED: When deploying the Hose Pulley into a large enough ocean...", + "create.ponder.hose_pulley_infinite.text_2": "UNLOCALIZED: It will provide/dispose fluids without affecting the source", + "create.ponder.hose_pulley_infinite.text_3": "UNLOCALIZED: Pipe networks can limitlessly take fluids from/to such pulleys", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + "create.ponder.hose_pulley_level.text_1": "UNLOCALIZED: While fully retracted, the Hose Pulley cannot operate", + "create.ponder.hose_pulley_level.text_2": "UNLOCALIZED: Draining runs from top to bottom", + "create.ponder.hose_pulley_level.text_3": "UNLOCALIZED: The surface level will end up just below where the hose ends", + "create.ponder.hose_pulley_level.text_4": "UNLOCALIZED: Filling runs from bottom to top", + "create.ponder.hose_pulley_level.text_5": "UNLOCALIZED: The filled pool will not grow beyond the layer above the hose end", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.item_drain.text_1": "UNLOCALIZED: Item Drains can extract fluids from items", + "create.ponder.item_drain.text_2": "UNLOCALIZED: Right-click it to pour fluids from your held item into it", + "create.ponder.item_drain.text_3": "UNLOCALIZED: When items are inserted from the side...", + "create.ponder.item_drain.text_4": "UNLOCALIZED: ...they roll across, emptying out their contained fluid", + "create.ponder.item_drain.text_5": "UNLOCALIZED: Pipe Networks can now pull the fluid from the drains' internal buffer", + "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 +2093,21 @@ "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_flow.text_1": "UNLOCALIZED: Mechanical Pumps govern the flow of their attached pipe networks", + "create.ponder.mechanical_pump_flow.text_2": "UNLOCALIZED: When powered, their arrow indicates the direction of flow", + "create.ponder.mechanical_pump_flow.text_3": "UNLOCALIZED: The network behind is now pulling fluids...", + "create.ponder.mechanical_pump_flow.text_4": "UNLOCALIZED: ...while the network in front is transferring it outward", + "create.ponder.mechanical_pump_flow.text_5": "UNLOCALIZED: Reversing the input rotation reverses the direction of flow", + "create.ponder.mechanical_pump_flow.text_6": "UNLOCALIZED: Use a Wrench to reverse the orientation of pumps manually", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_pump_speed.text_1": "UNLOCALIZED: Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away", + "create.ponder.mechanical_pump_speed.text_2": "UNLOCALIZED: Speeding up the input rotation changes the speed of flow propagation...", + "create.ponder.mechanical_pump_speed.text_3": "UNLOCALIZED: ...aswell as how quickly fluids are transferred", + "create.ponder.mechanical_pump_speed.text_4": "UNLOCALIZED: Pumps can combine their throughputs within shared pipe networks", + "create.ponder.mechanical_pump_speed.text_5": "UNLOCALIZED: Alternating their orientation can help align their flow directions", + "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", @@ -1926,11 +2133,22 @@ "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.nixie_tube.text_3": "UNLOCALIZED: Right-Click with Dye to change their display colour", "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_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + "create.ponder.portable_fluid_interface.text_1": "UNLOCALIZED: Fluid Tanks on moving contraptions cannot be accessed by any pipes", + "create.ponder.portable_fluid_interface.text_2": "UNLOCALIZED: This component can interact with fluid tanks without the need to stop the contraption", + "create.ponder.portable_fluid_interface.text_3": "UNLOCALIZED: Place a second one with a gap of 1 or 2 blocks inbetween", + "create.ponder.portable_fluid_interface.text_4": "UNLOCALIZED: Whenever they pass by each other, they will engage in a connection", + "create.ponder.portable_fluid_interface.text_5": "UNLOCALIZED: While engaged, the stationary interface will represent ALL Tanks on the contraption", + "create.ponder.portable_fluid_interface.text_6": "UNLOCALIZED: Fluid can now be inserted...", + "create.ponder.portable_fluid_interface.text_7": "UNLOCALIZED: ...or extracted from the contraption", + "create.ponder.portable_fluid_interface.text_8": "UNLOCALIZED: After no contents have been exchanged for a while, the contraption will continue on its way", + "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 +2246,25 @@ "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.smart_pipe.text_1": "UNLOCALIZED: Smart pipes can help control flows by fluid type", + "create.ponder.smart_pipe.text_2": "UNLOCALIZED: When placed directly at the source, they can specify the type of fluid to extract", + "create.ponder.smart_pipe.text_3": "UNLOCALIZED: Simply Right-Click their filter slot with any item containing the desired fluid", + "create.ponder.smart_pipe.text_4": "UNLOCALIZED: When placed further down a pipe network, smart pipes will only let matching fluids continue", + "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_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.spout_filling.text_1": "UNLOCALIZED: The Spout can fill fluid holding items provided beneath it", + "create.ponder.spout_filling.text_2": "UNLOCALIZED: The content of a Spout cannot be accessed manually", + "create.ponder.spout_filling.text_3": "UNLOCALIZED: Instead, Pipes can be used to supply it with fluids", + "create.ponder.spout_filling.text_4": "UNLOCALIZED: The Input items can be placed on a Depot under the Spout", + "create.ponder.spout_filling.text_5": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.spout_filling.text_6": "UNLOCALIZED: The Spout will hold and process them automatically", + "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 +2296,12 @@ "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.valve_pipe.text_1": "UNLOCALIZED: Valve pipes help control fluids propagating through pipe networks", + "create.ponder.valve_pipe.text_2": "UNLOCALIZED: Their shaft input controls whether fluid is currently allowed through", + "create.ponder.valve_pipe.text_3": "UNLOCALIZED: Given Rotational Force in the opening direction, the valve will open up", + "create.ponder.valve_pipe.text_4": "UNLOCALIZED: It can be closed again by reversing the input rotation", + "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..bdc4e385a 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: 953", "_": "->------------------------] Game Elements [------------------------<-", @@ -28,12 +28,16 @@ "block.create.belt": "Nastro meccanico", "block.create.birch_window": "Finestra di betulla", "block.create.birch_window_pane": "Pannello di finestra di betulla", + "block.create.black_nixie_tube": "UNLOCALIZED: Black Nixie Tube", "block.create.black_sail": "Vela nera", "block.create.black_seat": "Sedile nero", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "Maniglia per valvola nera", "block.create.blaze_burner": "Inceneritore di blaze", + "block.create.blue_nixie_tube": "UNLOCALIZED: Blue Nixie Tube", "block.create.blue_sail": "Vela blu", "block.create.blue_seat": "Sedile blu", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "Maniglia per valvola blu", "block.create.brass_belt_funnel": "Imbuto per nastro di ottone", "block.create.brass_block": "Blocco di ottone", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "Albero incassato di ottone", "block.create.brass_funnel": "Imbuto di ottone", "block.create.brass_tunnel": "Tunnel di ottone", + "block.create.brown_nixie_tube": "UNLOCALIZED: Brown Nixie Tube", "block.create.brown_sail": "Vela marrone", "block.create.brown_seat": "Sedile marrone", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "Maniglia per valvola marrone", "block.create.cart_assembler": "Assemblatore di carrelli da miniera", "block.create.chiseled_dark_scoria": "Scoria scura cesellata", @@ -73,8 +79,10 @@ "block.create.crushing_wheel": "Ruota di frantumazione", "block.create.crushing_wheel_controller": "Telecomando per ruota di frantumazione", "block.create.cuckoo_clock": "Orologio a cucù", + "block.create.cyan_nixie_tube": "UNLOCALIZED: Cyan Nixie Tube", "block.create.cyan_sail": "Vela ciano", "block.create.cyan_seat": "Sedile ciano", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "Maniglia per valvola ciano", "block.create.dark_oak_window": "Finestra di quercia scura", "block.create.dark_oak_window_pane": "Pannello di finestra di quercia scura", @@ -179,13 +187,18 @@ "block.create.granite_cobblestone_stairs": "Scalini di pietrisco di granito", "block.create.granite_cobblestone_wall": "Muretto di pietrisco di granito", "block.create.granite_pillar": "Pilastro di granito", + "block.create.gray_nixie_tube": "UNLOCALIZED: Gray Nixie Tube", "block.create.gray_sail": "Vela grigia", "block.create.gray_seat": "Sedile grigio", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "Maniglia per valvola grigia", + "block.create.green_nixie_tube": "UNLOCALIZED: Green Nixie Tube", "block.create.green_sail": "Vela verde", "block.create.green_seat": "Sedile verde", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "Maniglia per valvola verde", "block.create.hand_crank": "Manovella", + "block.create.haunted_bell": "UNLOCALIZED: Haunted Bell", "block.create.honey": "Miele", "block.create.horizontal_framed_glass": "Finestra di vetro orizzontale", "block.create.horizontal_framed_glass_pane": "Pannello di finestra di vetro orizzontale", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "Calcare stratificato", "block.create.layered_scoria": "Scoria stratificata", "block.create.layered_weathered_limestone": "Calcare consumato stratificato", + "block.create.lectern_controller": "UNLOCALIZED: Lectern Controller", + "block.create.light_blue_nixie_tube": "UNLOCALIZED: Light Blue Nixie Tube", "block.create.light_blue_sail": "Vela azzurra", "block.create.light_blue_seat": "Sedile azzurro", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "Maniglia per valvola azzurra", + "block.create.light_gray_nixie_tube": "UNLOCALIZED: Light Gray Nixie Tube", "block.create.light_gray_sail": "Vela grigio chiaro", "block.create.light_gray_seat": "Sedile grigio chiaro", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "Maniglia per valvola grigio chiaro", + "block.create.lime_nixie_tube": "UNLOCALIZED: Lime Nixie Tube", "block.create.lime_sail": "Vela lime", "block.create.lime_seat": "Sedile lime", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "Maniglia per valvola lime", "block.create.limesand": "Arenaria calcarea", "block.create.limestone": "Calcare", @@ -225,8 +245,10 @@ "block.create.limestone_pillar": "Pilastro di calcare", "block.create.linear_chassis": "Telaio lineare", "block.create.lit_blaze_burner": "Inceneritore di blaze acceso", + "block.create.magenta_nixie_tube": "UNLOCALIZED: Magenta Nixie Tube", "block.create.magenta_sail": "Vela magenta", "block.create.magenta_seat": "Sedile magenta", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "Maniglia per valvola magenta", "block.create.mechanical_arm": "Braccio meccanico", "block.create.mechanical_bearing": "Supporto meccanico", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "Pannello di finestra di quercia", "block.create.orange_sail": "Vela arancione", "block.create.orange_seat": "Sedile arancione", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "Maniglia per valvola arancione", "block.create.ornate_iron_window": "Finestra di ferro ornata", "block.create.ornate_iron_window_pane": "Pannello di finestra di ferro ornata", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "Lastra di calcare consumato lastricato", "block.create.paved_weathered_limestone_stairs": "Scalini di calcare consumato lastricato", "block.create.paved_weathered_limestone_wall": "Muretto di calcare consumato lastricato", + "block.create.peculiar_bell": "UNLOCALIZED: Peculiar Bell", + "block.create.pink_nixie_tube": "UNLOCALIZED: Pink Nixie Tube", "block.create.pink_sail": "Vela rosa", "block.create.pink_seat": "Sedile rosa", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "Maniglia per valvola rosa", "block.create.piston_extension_pole": "Palo di pistone", "block.create.polished_dark_scoria": "Scoria scura levigata", @@ -342,12 +368,16 @@ "block.create.powered_toggle_latch": "Leva alimentata alterata", "block.create.pulley_magnet": "Magnete della carrucola", "block.create.pulse_repeater": "Ripetitore di impulsi", + "block.create.purple_nixie_tube": "UNLOCALIZED: Purple Nixie Tube", "block.create.purple_sail": "Vela viola", "block.create.purple_seat": "Sedile viola", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "Maniglia per valvola viola", "block.create.radial_chassis": "Telaio radiale", + "block.create.red_nixie_tube": "UNLOCALIZED: Red Nixie Tube", "block.create.red_sail": "Vela rossa", "block.create.red_seat": "Sedile rosso", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "Maniglia per valvola rossa", "block.create.redstone_contact": "Contatto redstone", "block.create.redstone_link": "Collegamento redstone", @@ -402,24 +432,32 @@ "block.create.weathered_limestone_cobblestone_wall": "Muretto di pietrisco di calcare consumato", "block.create.weathered_limestone_pillar": "Pilastro di calcare consumato", "block.create.weighted_ejector": "UNLOCALIZED: Weighted Ejector", + "block.create.white_nixie_tube": "UNLOCALIZED: White Nixie Tube", "block.create.white_sail": "Vela bianca", "block.create.white_seat": "Sedile bianco", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "Maniglia per valvola bianca", "block.create.windmill_bearing": "Supporto per mulino a vento", "block.create.wooden_bracket": "Supporto di legno", + "block.create.yellow_nixie_tube": "UNLOCALIZED: Yellow Nixie Tube", "block.create.yellow_sail": "Vela gialla", "block.create.yellow_seat": "Sedile giallo", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "Maniglia per valvola gialla", "block.create.zinc_block": "Blocco di zinco", "block.create.zinc_ore": "Zinco grezzo", + "enchantment.create.capacity": "UNLOCALIZED: Capacity", + "enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery", + "entity.create.contraption": "Contrazione", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "entity.create.potato_projectile": "UNLOCALIZED: Potato Projectile", "entity.create.seat": "Sedile", "entity.create.stationary_contraption": "Contrazione stazionaria", "entity.create.super_glue": "Super colla", - "fluid.create.milk": "Latte", "fluid.create.potion": "Pozione", "fluid.create.tea": "Tè del costruttore", @@ -444,6 +482,8 @@ "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.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "item.create.crushed_aluminum_ore": "Alluminio grezzo frantumato", "item.create.crushed_brass": "Ottone frantumato", "item.create.crushed_copper_ore": "Rame grezzo frantumato", @@ -472,13 +512,17 @@ "item.create.handheld_worldshaper": "Plasmatore del mondo portatile", "item.create.honey_bucket": "Secchio di miele", "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", - "item.create.integrated_circuit": "Circuito integrato", + "item.create.incomplete_cogwheel": "UNLOCALIZED: Incomplete Cogwheel", + "item.create.incomplete_large_cogwheel": "UNLOCALIZED: Incomplete Large Cogwheel", + "item.create.incomplete_precision_mechanism": "UNLOCALIZED: Incomplete Precision Mechanism", "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", + "item.create.potato_cannon": "UNLOCALIZED: Potato Cannon", "item.create.powdered_obsidian": "Ossidiana in polvere", + "item.create.precision_mechanism": "UNLOCALIZED: Precision Mechanism", "item.create.propeller": "Elica", "item.create.red_sand_paper": "Carta vetrata rossa", "item.create.refined_radiance": "Radiance raffinata", @@ -623,8 +667,8 @@ "advancement.create.flywheel.desc": "Collega un motore ad un volano.", "advancement.create.overstress_flywheel": "Alti livelli di stress", "advancement.create.overstress_flywheel.desc": "Sovrastressa un motore fornace.", - "advancement.create.integrated_circuit": "Calcolo complesso", - "advancement.create.integrated_circuit.desc": "Assembla un circuito integrato.", + "advancement.create.precision_mechanism": "UNLOCALIZED: Complex Curiosities", + "advancement.create.precision_mechanism.desc": "UNLOCALIZED: Assemble a Precision Mechanism.", "advancement.create.mechanical_arm": "Mani occupate!", "advancement.create.mechanical_arm.desc": "Costruisci un braccio meccanico, seleziona gli input e gli output, piazzalo e alimentalo; poi guardalo mentre fa il lavoro sporco al tuo posto.", "advancement.create.musical_arm": "DJ, metti su la musica!", @@ -651,6 +695,8 @@ "advancement.create.wand_of_symmetry.desc": "Crea un'asta di simmetria.", "advancement.create.extendo_grip": "BOIOIOING", "advancement.create.extendo_grip.desc": "Procurati una presa extendo.", + "advancement.create.potato_cannon": "UNLOCALIZED: Fwoomp!", + "advancement.create.potato_cannon.desc": "UNLOCALIZED: Defeat an enemy with your Potato Cannon.", "advancement.create.dual_extendo_grip": "Boingaggio estremo", "advancement.create.dual_extendo_grip.desc": "Brandisci due prese extendo per raggiungere il superuomo.", "advancement.create.eob": "Fine della beta", @@ -663,15 +709,31 @@ "itemGroup.create.palettes": "Create: Blocchi", "death.attack.create.crush": "%1$s è stato frantumato", + "death.attack.create.crush.player": "UNLOCALIZED: %1$s was thrown into Crushing Wheels by %2$s", "death.attack.create.fan_fire": "%1$s è stato bruciato dall'aria calda", + "death.attack.create.fan_fire.player": "UNLOCALIZED: %1$s was thrown into a smoker by %2$s", "death.attack.create.fan_lava": "%1$s è stato bruciato dal ventilatore di lava", + "death.attack.create.fan_lava.player": "UNLOCALIZED: %1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "%1$s è stato trafitto dal trapano meccanico", + "death.attack.create.mechanical_drill.player": "UNLOCALIZED: %1$s was thrown in front of a Drill by %2$s", "death.attack.create.mechanical_saw": "%1$s è stato tagliato a metà dalla sega meccanica", + "death.attack.create.mechanical_saw.player": "UNLOCALIZED: %1$s was thrown into a Saw by %2$s", + "death.attack.create.potato_cannon": "UNLOCALIZED: %1$s was shot by %2$s's Potato Cannon", + "death.attack.create.potato_cannon.item": "UNLOCALIZED: %1$s was shot by %2$s using %3$s", "death.attack.create.cuckoo_clock_explosion": "%1$s è saltato in aria da un orologio a cucù manomesso", + "death.attack.create.cuckoo_clock_explosion.player": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", "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.ponder_index": "UNLOCALIZED: Ponder Index", + "create.menu.only_ingame": "UNLOCALIZED: Available in the Pause Menu", + "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", @@ -696,7 +758,18 @@ "create.recipe.mystery_conversion": "Metamorfosi cromatica", "create.recipe.spout_filling": "Riempimento da spruzzo", "create.recipe.draining": "Drenaggio di oggetti", + "create.recipe.sequenced_assembly": "UNLOCALIZED: Sequenced Assembly", + "create.recipe.assembly.next": "UNLOCALIZED: Next: %1$s", + "create.recipe.assembly.step": "UNLOCALIZED: Step %1$s:", + "create.recipe.assembly.progress": "UNLOCALIZED: Progress: %1$s/%2$s", + "create.recipe.assembly.pressing": "UNLOCALIZED: Process in Press", + "create.recipe.assembly.spout_filling_fluid": "UNLOCALIZED: Spout %1$s", + "create.recipe.assembly.deploying_item": "UNLOCALIZED: Deploy %1$s", + "create.recipe.assembly.cutting": "UNLOCALIZED: Cut with Saw", + "create.recipe.assembly.repeat": "UNLOCALIZED: Repeat Sequence %1$s Times", + "create.recipe.assembly.junk": "UNLOCALIZED: Random salvage", "create.recipe.processing.chance": "%1$s%% di probabilità", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "Nessun riscaldamento", "create.recipe.heat_requirement.heated": "Riscaldamento", "create.recipe.heat_requirement.superheated": "Super riscaldamento", @@ -725,6 +798,7 @@ "create.action.discard": "Scarta", "create.keyinfo.toolmenu": "Focalizzazione sul menù degli strumenti", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "Simula rotellina del mouse verso su (nel mondo)", "create.keyinfo.scrolldown": "Simula rotellina del mouse verso giù (nel mondo)", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "Premi shift per scorrere più velocemente", "create.gui.toolmenu.focusKey": "Premi [%1$s] per aprire il menù", "create.gui.toolmenu.cycle": "[SCORRI] per navigare", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Specchio", "create.gui.symmetryWand.orientation": "Orientamento", @@ -981,18 +1062,14 @@ "create.item_attributes.placeable.inverted": "non è posizionabile", "create.item_attributes.consumable": "è commestibile", "create.item_attributes.consumable.inverted": "non è commestibile", - "create.item_attributes.smeltable": "può essere fuso", - "create.item_attributes.smeltable.inverted": "non può essere fuso", - "create.item_attributes.washable": "può essere lavato", - "create.item_attributes.washable.inverted": "non può essere lavato", - "create.item_attributes.smokable": "può essere affumicato", - "create.item_attributes.smokable.inverted": "non può essere affumicato", - "create.item_attributes.crushable": "può essere frantumato", - "create.item_attributes.crushable.inverted": "non può essere frantumato", - "create.item_attributes.blastable": "è fondibile in un forno fusorio", - "create.item_attributes.blastable.inverted": "non è fondibile in un forno fusorio", + "create.item_attributes.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "è incantato", "create.item_attributes.enchanted.inverted": "non è incantato", + "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.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "è danneggiato", "create.item_attributes.damaged.inverted": "non è danneggiato", "create.item_attributes.badly_damaged": "è gravemente danneggiato", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "non può essere equipaggiato", "create.item_attributes.furnace_fuel": "è un combustibile per fornace", "create.item_attributes.furnace_fuel.inverted": "non è un combustibile per fornace", + "create.item_attributes.washable": "può essere lavato", + "create.item_attributes.washable.inverted": "non può essere lavato", + "create.item_attributes.crushable": "può essere frantumato", + "create.item_attributes.crushable.inverted": "non può essere frantumato", + "create.item_attributes.smeltable": "può essere fuso", + "create.item_attributes.smeltable.inverted": "non può essere fuso", + "create.item_attributes.smokable": "può essere affumicato", + "create.item_attributes.smokable.inverted": "non può essere affumicato", + "create.item_attributes.blastable": "è fondibile in un forno fusorio", + "create.item_attributes.blastable.inverted": "non è fondibile in un forno fusorio", + "create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s", + "create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s", + "create.item_attributes.shulker_level.full": "UNLOCALIZED: full", + "create.item_attributes.shulker_level.empty": "UNLOCALIZED: empty", + "create.item_attributes.shulker_level.partial": "UNLOCALIZED: partially filled", "create.item_attributes.in_tag": "è etichettato %1$s", "create.item_attributes.in_tag.inverted": "non è etichettato %1$s", "create.item_attributes.in_item_group": "appartiene a %1$s", @@ -1013,8 +1105,6 @@ "create.item_attributes.has_enchant.inverted": "non è stato incantato con %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.has_fluid": "contiene %1$s", "create.item_attributes.has_fluid.inverted": "non contiene %1$s", "create.item_attributes.has_name": "è stato rinominato in %1$s", @@ -1029,14 +1119,14 @@ "create.item_attributes.book_copy_second.inverted": "non è una copia di seconda generazione", "create.item_attributes.book_copy_tattered": "è in condizioni precarie", "create.item_attributes.book_copy_tattered.inverted": "non è in condizioni precarie", - "create.item_attributes.astralsorcery_crystal": "ha l'attributo del cristallo %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "non ha l'attributo del cristallo %1$s", - "create.item_attributes.astralsorcery_constellation": "è in sintonia con %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "non è in sintonia con %1$s", - "create.item_attributes.astralsorcery_perk_gem": "ha l'attributo benefico %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "non ha l'attributo benefico %1$s", "create.item_attributes.astralsorcery_amulet": "migliora %1$s", "create.item_attributes.astralsorcery_amulet.inverted": "non migliora %1$s", + "create.item_attributes.astralsorcery_constellation": "è in sintonia con %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "non è in sintonia con %1$s", + "create.item_attributes.astralsorcery_crystal": "ha l'attributo del cristallo %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "non ha l'attributo del cristallo %1$s", + "create.item_attributes.astralsorcery_perk_gem": "ha l'attributo benefico %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "non ha l'attributo benefico %1$s", "create.gui.attribute_filter.no_selected_attributes": "Nessun attributo selezionato", "create.gui.attribute_filter.selected_attributes": "Attributi selezionati:", @@ -1104,6 +1194,27 @@ "create.tooltip.chute.fans_pull_up": "I ventilatori tirano da sopra", "create.tooltip.chute.fans_pull_down": "I ventilatori tirano da sotto", "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "UNLOCALIZED: Currently distributing:", + "create.tooltip.brass_tunnel.contains_entry": "UNLOCALIZED: > %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "UNLOCALIZED: Right-Click to retrieve", + + "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.potato_cannon.ammo.attack_damage": "UNLOCALIZED: %1$s Attack Damage", + "create.potato_cannon.ammo.reload_ticks": "UNLOCALIZED: %1$s Reload Ticks", + "create.potato_cannon.ammo.knockback": "UNLOCALIZED: %1$s Knockback", "create.hint.hose_pulley.title": "Buco senza fondo", "create.hint.hose_pulley": "Il corpo fluido selezionato è considerato infinito.", @@ -1132,32 +1243,44 @@ "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.contraption_disassemble": "UNLOCALIZED: Contraption stops", + "create.subtitle.peculiar_bell_use": "UNLOCALIZED: Peculiar Bell tolls", + "create.subtitle.mixing": "UNLOCALIZED: Mixing noises", + "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", + "create.subtitle.fwoomp": "UNLOCALIZED: Potato Launcher fwoomps", + "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", + "create.subtitle.crushing_1": "UNLOCALIZED: Crushing noises", + "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.blaze_munch": "Il blaze lo gusta felicemente", + "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel flaps", + "create.subtitle.schematicannon_finish": "Finiture cannoneschematico", + "create.subtitle.haunted_bell_use": "UNLOCALIZED: Haunted Bell tolls", + "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.controller_put": "UNLOCALIZED: Controller thumps", + "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.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.potato_hit": "UNLOCALIZED: Vegetable impacts", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens", "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", - "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", "create.subtitle.deny": "UNLOCALIZED: Declining boop", - "create.subtitle.blaze_munch": "Il blaze lo gusta felicemente", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", "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.controller_take": "UNLOCALIZED: Lectern empties", "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", @@ -1179,14 +1302,6 @@ "block.create.metal_bracket.tooltip": "SUPPORTO DI METALLO", "block.create.metal_bracket.tooltip.summary": "_Decora_ i tuoi _alberi_, _ruote dentate_ e _tubi_ rinforzandoli col ferro.", - "block.create.copper_casing.tooltip": "INVOLUCRO DI RAME", - "block.create.copper_casing.tooltip.summary": "Involucro per macchine robusto con una varietà di usi. Utile per decorare.", - "block.create.copper_casing.tooltip.condition1": "Quando usato su un tubo per fluidi", - "block.create.copper_casing.tooltip.behaviour1": "_Riveste_ il _tubo per fluidi_ con l'_involucro di rame_. I tubi per fluidi incassati _bloccano le loro connessioni_, non reagendo più ai cambiamenti dei tubi vicini.", - - "block.create.encased_fluid_pipe.tooltip": "TUBO PER FLUIDI INCASSATO", - "block.create.encased_fluid_pipe.tooltip.summary": "Un _tubo per fluidi_ incassato con l'_involucro di rame_.", - "block.create.seat.tooltip": "SEDILE", "block.create.seat.tooltip.summary": "Siediti e goditi l'escursione! Ancora un giocatore a una macchina _in movimento_. Perfetto anche per l'arredamento! Dispone di una varietà di colori.", "block.create.seat.tooltip.condition1": "Clicca col destro sul sedile", @@ -1195,65 +1310,6 @@ "item.create.blaze_cake.tooltip": "TORTA PER BLAZE", "item.create.blaze_cake.tooltip.summary": "Un delizioso trattamento per i tuoi _inceneritori di blaze_. Alimentali col fuoco!", - "block.create.fluid_pipe.tooltip": "TUBO PER FLUIDI", - "block.create.fluid_pipe.tooltip.summary": "Usato per muovere _fluidi_ attraverso i tubi. Necessita di una _pompa meccanica_ per questo.", - "block.create.fluid_pipe.tooltip.condition1": "Trasferimento di fluidi", - "block.create.fluid_pipe.tooltip.behaviour1": "Può collegarsi ai contenitori di fluidi come _serbatoi_ o _bacinelle_. Gli estremi dei _tubi_ esposti possono anche drenare o piazzare blocchi di fluidi. Attento alle perdite!", - "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.hose_pulley.tooltip": "CARRUCOLA PER TUBI", - "block.create.hose_pulley.tooltip.summary": "Usata per _piazzare_ o _drenare_ vasti corpi fluidi.", - "block.create.hose_pulley.tooltip.condition1": "Quando alimentata da energia cinetica", - "block.create.hose_pulley.tooltip.behaviour1": "Tira su o giù la carrucola, la posizione della carrucola determina fino a dove c'è da _riempire_ o _svuotare_ il corpo.", - "block.create.hose_pulley.tooltip.condition2": "Quando un fluido è tirato dalla carrucola", - "block.create.hose_pulley.tooltip.behaviour2": "Inizia a _prendere blocchi_ di fluidi da dove la carrucola è stata abbassata. _Vasti corpi_ fluidi vengono considerati _infiniti_.", - "block.create.hose_pulley.tooltip.condition3": "Quando un fluido è spinto dalla carrucola", - "block.create.hose_pulley.tooltip.behaviour3": "Inizia a riempire col fluido _fino_ all'_altezza della carrucola_.", - - "block.create.fluid_tank.tooltip": "SERBATOIO PER FLUIDI", - "block.create.fluid_tank.tooltip.summary": "_Immagazzina_ i _fluidi_ che vuoi. Scala in larghezza e altezza.", - "block.create.fluid_tank.tooltip.condition1": "Clic destro con la chiave inglese", - "block.create.fluid_tank.tooltip.behaviour1": "Aggiungi/rimuovi vetrata", - - "block.create.creative_fluid_tank.tooltip": "SERBATOIO PER LIQUIDI (CREATIVA)", - "block.create.creative_fluid_tank.tooltip.summary": "Questo _serbatoio per liquidi_ permette di replicare infinite volte un certo _fluido_. Scala in larghezza e altezza.", - "block.create.creative_fluid_tank.tooltip.condition1": "Quando un fluido è nel serbatoio", - "block.create.creative_fluid_tank.tooltip.behaviour1": "Qualsiasi _estrazione_ da questo serbatoio fornisce un'_alimentazione infinita_ del fluido in questione. I fluidi _inseriti_ in questo serbatoio verranno _svuotati_.", - "block.create.creative_fluid_tank.tooltip.condition2": "Clic destro con la chiave inglese", - "block.create.creative_fluid_tank.tooltip.behaviour2": "Aggiungi/rimuovi vetrata", - - "block.create.fluid_valve.tooltip": "VALVOLA PER FLUIDI", - "block.create.fluid_valve.tooltip.summary": "Regola il flusso di un fluido lungo un tubo.", - "block.create.fluid_valve.tooltip.condition1": "Flusso controllabile", - "block.create.fluid_valve.tooltip.behaviour1": "Applicare una _forza rotazionale_ forza la _valvola_ a chiudersi, cessando lo scorrere di _fluidi_. Inverti la direzione della _forza rotazionale_ per riaprire la valvola.", - - "block.create.mechanical_pump.tooltip": "POMPA MECCANICA", - "block.create.mechanical_pump.tooltip.summary": "Utilizza la _forza rotazionale_ per muovere i _fluidi_ lungo un _tubo_. Ha un massimo raggio d'effetto in entrambe le direzioni. (16 blocchi di default)", - "block.create.mechanical_pump.tooltip.condition1": "Flusso del fluido", - "block.create.mechanical_pump.tooltip.behaviour1": "La _forza rotazionale_ applicata crea una pressione che pompa il _fluido_ in una rete di _tubi_. Inverti la direzione della _forza rotazionale_ per cambiare la direzione in cui il _fluido_ scorre.", - "block.create.mechanical_pump.tooltip.control1": "Clic destro con la chiave inglese", - "block.create.mechanical_pump.tooltip.action1": "Inverte la direzione della _pompa_, cambiando la direzione standard del flusso.", - - "block.create.smart_fluid_pipe.tooltip": "TUBO PER FLUIDI AVANZATO", - "block.create.smart_fluid_pipe.tooltip.summary": "Un _tubo per fluidi_ con filtro. Puoi specificare quali _fluidi_ possono passare.", - "block.create.smart_fluid_pipe.tooltip.condition1": "Quando un fluido è spinto dentro", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "Un tubo avanzato che riceve un fluido che non corrisponde al suo filtro ne blocca lo scorrere.", - "block.create.smart_fluid_pipe.tooltip.condition2": "Quando adiacente a un contenitore di fluidi", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "I tubi avanzati che _danno inizio_ ad un _flusso_ da qualsiasi contenitore estraggono solo i fluidi che _corrispondono_ al loro _filtro_.", - - "block.create.spout.tooltip": "SPRUZZO", - "block.create.spout.tooltip.summary": "Uno spruzzo per riempire i tuoi _oggetti per fluidi_.", - "block.create.spout.tooltip.condition1": "Trasferimento di fluidi", - "block.create.spout.tooltip.behaviour1": "Quando un _oggetto contenitore di fluidi_ come un _secchio_ o un'_ampolla_ è piazzato sotto, lo spruzzo lo riempie col _fluido_ al suo interno.", - "block.create.spout.tooltip.condition2": "Automazione di fluidi", - "block.create.spout.tooltip.behaviour2": "Lo spruzzo piazzato su un _nastro_ o un _deposito_ reagisce automaticamente con gli _oggetti contenitori di fluidi_ che ci passano sotto.", - - "block.create.item_drain.tooltip": "DRENANTE DI OGGETTI", - "block.create.item_drain.tooltip.summary": "Come un deposito, ma è grigliato per svuotare gli _oggetti riempiti da fluidi_.", - "block.create.item_drain.tooltip.condition1": "Trasferimento di fluidi", - "block.create.item_drain.tooltip.behaviour1": "Quando un _oggetto contenitore di fluidi_ come un _secchio_ o un'_ampolla_ è inserito a lato, il drenante lo svuota nel suo _contenitore di fluidi_. L'oggetto verrà poi espulso dal lato opposto.", - "item.create.wand_of_symmetry.tooltip": "ASTA DI SIMMETRIA", "item.create.wand_of_symmetry.tooltip.summary": "Rispecchia perfettamente il posizionamento dei blocchi su piani configurati.", "item.create.wand_of_symmetry.tooltip.condition1": "Nella hotbar", @@ -1283,6 +1339,15 @@ "item.create.extendo_grip.tooltip.summary": "Boioioing! _Incrementa notevolmente la distanza per piazzare_ di chi lo brandisce.", "item.create.extendo_grip.tooltip.condition1": "Quando in mano secondaria", "item.create.extendo_grip.tooltip.behaviour1": "Incrementa la _distanza per piazzare_ degli oggetti usati nella _mano primaria_.", + "item.create.extendo_grip.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", + + "item.create.potato_cannon.tooltip": "UNLOCALIZED: POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "UNLOCALIZED: Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", + "item.create.potato_cannon.tooltip.behaviour1": "UNLOCALIZED: _Shoots_ a suitable item from your _Inventory_.", + "item.create.potato_cannon.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.filter.tooltip": "FILTRO", "item.create.filter.tooltip.summary": "_Controlla_ _gli_ _output_ e gli _input_ dei dispositivi logistici con maggiore _precisione_, confrontandoli con una _serie_ _di_ _oggetti_ o diversi _filtri_ _nidificati_.", @@ -1358,12 +1423,14 @@ "block.create.turntable.tooltip": "PIATTO", "block.create.turntable.tooltip.summary": "Assorbe la _forza_ _di_ _rotazione_, girando.", - "block.create.portable_fluid_interface.tooltip": "INTERFACCIA PER FLUIDI PORTATILE", - "block.create.portable_fluid_interface.tooltip.summary": "Un punto di interscambio portatile per _spostare_ _fluidi_ a e da una _struttura_ mossa da un pistone, supporto, carrello da miniera o carrucola. Due interfacce che si incontrano devono essere piazzate _con le facciate anteriori che si guardano_ e spaziate di _1-2 blocchi_.", - "block.create.portable_fluid_interface.tooltip.condition1": "In movimento", - "block.create.portable_fluid_interface.tooltip.behaviour1": "Interagisce con le _interfacce di archiviazione portatili_ stazionarie per trasferire i fluidi a o dalla macchina. I tubi che immettono o estraggono dall'_interfaccia stazionaria_ interagiscono _direttamente_ con i serbatoi della macchina. La struttura si fermerà per un attimo per lo scambio di fluidi.", - "block.create.portable_fluid_interface.tooltip.condition2": "Quando alimentata da redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "_Disinnesca_ qualsiasi collegamento attivo immediatamente.", + "block.create.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "INTERRUTTORE ACCUMULATORE", "block.create.stockpile_switch.tooltip.summary": "Attiva/disattiva un segnale redstone in base allo _spazio_ _di_ _stoccaggio_ nel contenitore collegato.", @@ -1372,6 +1439,10 @@ "block.create.content_observer.tooltip": "OSSERVATORE DEI CONTENUTI", "block.create.content_observer.tooltip.summary": "_Rileva oggetti_ dentro i _contenitori_ ed i _nastri_ corrispondenti ad un _filtro_. Quando l'_inventario_ del blocco, _nastro_ or _scivolo_ contiene un oggetto corrispondente, questo componente emetterà un _segnale redstone_. Quando un _imbuto_ osservato _trasferisce_ un oggetto corrispondente, questo componente emetterà un _segnale redstone_ temporaneo.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "BAULE REGOLABILE", "block.create.adjustable_crate.tooltip.summary": "Questo _contenitore_ _di_ _stoccaggio_ consente il controllo manuale sulla sua capacità. Può contenere fino a _16_ _pile_ di qualsiasi oggetto. Supporta _comparatori_ _redstone_.", @@ -1383,6 +1454,11 @@ "block.create.creative_crate.tooltip.condition1": "Quando un oggetto è nel filtro", "block.create.creative_crate.tooltip.behaviour1": "Qualsiasi _estrazione_ da questo contenitore fornisce _provviste infinite_ dell'oggetto in questione. Gli oggetti _inseriti_ in questo baule verranno _svuotati_.", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "BINARIO DI CONTROLLO", "block.create.controller_rail.tooltip.summary": "Un _binario alimentato unidirezionale_ capace di _controllare precisamente_ la _velocità di movimento_ di un carrello da miniera.", "block.create.controller_rail.tooltip.condition1": "Quando alimentato da redstone", @@ -1398,26 +1474,61 @@ "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.linked_controller.tooltip.condition4": "UNLOCALIZED: R-Click on Lectern", + "item.create.linked_controller.tooltip.behaviour4": "UNLOCALIZED: Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the wielder 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: Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder 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.", + "block.create.peculiar_bell.tooltip": "UNLOCALIZED: PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "UNLOCALIZED: A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + + "block.create.haunted_bell.tooltip": "UNLOCALIZED: HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "UNLOCALIZED: A _Cursed Bell_ haunted by lost souls of the Nether.", + "block.create.haunted_bell.tooltip.condition1": "UNLOCALIZED: When Held or Rang", + "block.create.haunted_bell.tooltip.behaviour1": "UNLOCALIZED: Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn.", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1434,41 +1545,46 @@ "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.exit": "UNLOCALIZED: Exit", + "create.ponder.welcome": "UNLOCALIZED: Welcome to Ponder", + "create.ponder.categories": "UNLOCALIZED: Available Categories in Create", + "create.ponder.index_description": "UNLOCALIZED: Click one of the icons to learn about its associated Items and Blocks", + "create.ponder.index_title": "UNLOCALIZED: Ponder Index", + "create.ponder.shared.rpm16": "UNLOCALIZED: 16 RPM", "create.ponder.shared.behaviour_modify_wrench": "UNLOCALIZED: This behaviour can be modified using a Wrench", + "create.ponder.shared.storage_on_contraption": "UNLOCALIZED: Inventories attached to the Contraption will pick up their drops automatically", + "create.ponder.shared.sneak_and": "UNLOCALIZED: Sneak +", "create.ponder.shared.rpm8": "UNLOCALIZED: 8 RPM", "create.ponder.shared.ctrl_and": "UNLOCALIZED: Ctrl +", + "create.ponder.shared.rpm32": "UNLOCALIZED: 32 RPM", "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.shared.movement_anchors": "UNLOCALIZED: With the help of Chassis or Super Glue, larger structures can be moved.", "create.ponder.tag.redstone": "UNLOCALIZED: Logic Components", "create.ponder.tag.redstone.description": "UNLOCALIZED: Components which help with redstone engineering", + "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.fluids": "UNLOCALIZED: Fluid Manipulators", "create.ponder.tag.fluids.description": "UNLOCALIZED: Components which help relaying and making use of Fluids", + "create.ponder.tag.decoration": "UNLOCALIZED: Aesthetics", + "create.ponder.tag.decoration.description": "UNLOCALIZED: Components used mostly for decorative purposes", + "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.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.kinetic_appliances": "UNLOCALIZED: Kinetic Appliances", + "create.ponder.tag.kinetic_appliances.description": "UNLOCALIZED: Components which make use of Rotational Force", + "create.ponder.tag.kinetic_sources": "UNLOCALIZED: Kinetic Sources", + "create.ponder.tag.kinetic_sources.description": "UNLOCALIZED: Components which generate Rotational Force", + "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.kinetic_relays": "UNLOCALIZED: Kinetic Blocks", + "create.ponder.tag.kinetic_relays.description": "UNLOCALIZED: Components which help relaying Rotational Force elsewhere", + "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.creative": "UNLOCALIZED: Creative Mode", + "create.ponder.tag.creative.description": "UNLOCALIZED: Components not usually available for Survival Mode", + "create.ponder.tag.logistics": "UNLOCALIZED: Item Transportation", + "create.ponder.tag.logistics.description": "UNLOCALIZED: Components which help moving items around", "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", @@ -1580,7 +1696,8 @@ "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_modes.text_2": "UNLOCALIZED: This Arrow indicates which side of the Structure will be considered the front", + "create.ponder.cart_assembler_modes.text_3": "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", @@ -1594,7 +1711,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 +1751,12 @@ "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_fluid_tank.text_1": "UNLOCALIZED: Creative Fluid Tanks can be used to provide a bottomless supply of fluid", + "create.ponder.creative_fluid_tank.text_2": "UNLOCALIZED: Right-Click with a fluid containing item to configure it", + "create.ponder.creative_fluid_tank.text_3": "UNLOCALIZED: Pipe Networks can now endlessly draw the assigned fluid from the tank", + "create.ponder.creative_fluid_tank.text_4": "UNLOCALIZED: Any Fluids pushed back into a Creative Fluid Tank will be voided", + "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 +1793,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", @@ -1686,7 +1815,13 @@ "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.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item", + "create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they 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", @@ -1706,6 +1841,35 @@ "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_sizes.text_1": "UNLOCALIZED: Fluid Tanks can be combined to increase the total capacity", + "create.ponder.fluid_tank_sizes.text_2": "UNLOCALIZED: Their base square can be up to 3 blocks wide...", + "create.ponder.fluid_tank_sizes.text_3": "UNLOCALIZED: ...and grow in height by more than 30 additional layers", + "create.ponder.fluid_tank_sizes.text_4": "UNLOCALIZED: Using a Wrench, a tanks' window can be toggled", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.fluid_tank_storage.text_1": "UNLOCALIZED: Fluid Tanks can be used to store large amounts of fluid", + "create.ponder.fluid_tank_storage.text_2": "UNLOCALIZED: Pipe networks can push and pull fluids from any side", + "create.ponder.fluid_tank_storage.text_3": "UNLOCALIZED: The contained fluid can be measured by a Comparator", + "create.ponder.fluid_tank_storage.text_4": "UNLOCALIZED: However, in Survival Mode Fluids cannot be added or taken manually", + "create.ponder.fluid_tank_storage.text_5": "UNLOCALIZED: You can use Basins, Item Drains and Spouts to drain or fill fluid containing items", + "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 +1943,34 @@ "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.text_1": "UNLOCALIZED: Hose Pulleys can be used to fill or drain large bodies of Fluid", + "create.ponder.hose_pulley.text_2": "UNLOCALIZED: With the Kinetic Input, the height of the pulleys' hose can be controlled", + "create.ponder.hose_pulley.text_3": "UNLOCALIZED: The Pulley retracts while the input rotation is inverted", + "create.ponder.hose_pulley.text_4": "UNLOCALIZED: On the opposite side, pipes can be connected", + "create.ponder.hose_pulley.text_5": "UNLOCALIZED: Attached pipe networks can either provide fluid to the hose...", + "create.ponder.hose_pulley.text_6": "UNLOCALIZED: ...or pull from it, draining the pool instead", + "create.ponder.hose_pulley.text_7": "UNLOCALIZED: Fill and Drain speed of the pulley depends entirely on the fluid networks' throughput", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + "create.ponder.hose_pulley_infinite.text_1": "UNLOCALIZED: When deploying the Hose Pulley into a large enough ocean...", + "create.ponder.hose_pulley_infinite.text_2": "UNLOCALIZED: It will provide/dispose fluids without affecting the source", + "create.ponder.hose_pulley_infinite.text_3": "UNLOCALIZED: Pipe networks can limitlessly take fluids from/to such pulleys", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + "create.ponder.hose_pulley_level.text_1": "UNLOCALIZED: While fully retracted, the Hose Pulley cannot operate", + "create.ponder.hose_pulley_level.text_2": "UNLOCALIZED: Draining runs from top to bottom", + "create.ponder.hose_pulley_level.text_3": "UNLOCALIZED: The surface level will end up just below where the hose ends", + "create.ponder.hose_pulley_level.text_4": "UNLOCALIZED: Filling runs from bottom to top", + "create.ponder.hose_pulley_level.text_5": "UNLOCALIZED: The filled pool will not grow beyond the layer above the hose end", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.item_drain.text_1": "UNLOCALIZED: Item Drains can extract fluids from items", + "create.ponder.item_drain.text_2": "UNLOCALIZED: Right-click it to pour fluids from your held item into it", + "create.ponder.item_drain.text_3": "UNLOCALIZED: When items are inserted from the side...", + "create.ponder.item_drain.text_4": "UNLOCALIZED: ...they roll across, emptying out their contained fluid", + "create.ponder.item_drain.text_5": "UNLOCALIZED: Pipe Networks can now pull the fluid from the drains' internal buffer", + "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 +2093,21 @@ "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_flow.text_1": "UNLOCALIZED: Mechanical Pumps govern the flow of their attached pipe networks", + "create.ponder.mechanical_pump_flow.text_2": "UNLOCALIZED: When powered, their arrow indicates the direction of flow", + "create.ponder.mechanical_pump_flow.text_3": "UNLOCALIZED: The network behind is now pulling fluids...", + "create.ponder.mechanical_pump_flow.text_4": "UNLOCALIZED: ...while the network in front is transferring it outward", + "create.ponder.mechanical_pump_flow.text_5": "UNLOCALIZED: Reversing the input rotation reverses the direction of flow", + "create.ponder.mechanical_pump_flow.text_6": "UNLOCALIZED: Use a Wrench to reverse the orientation of pumps manually", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_pump_speed.text_1": "UNLOCALIZED: Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away", + "create.ponder.mechanical_pump_speed.text_2": "UNLOCALIZED: Speeding up the input rotation changes the speed of flow propagation...", + "create.ponder.mechanical_pump_speed.text_3": "UNLOCALIZED: ...aswell as how quickly fluids are transferred", + "create.ponder.mechanical_pump_speed.text_4": "UNLOCALIZED: Pumps can combine their throughputs within shared pipe networks", + "create.ponder.mechanical_pump_speed.text_5": "UNLOCALIZED: Alternating their orientation can help align their flow directions", + "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", @@ -1926,11 +2133,22 @@ "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.nixie_tube.text_3": "UNLOCALIZED: Right-Click with Dye to change their display colour", "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_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + "create.ponder.portable_fluid_interface.text_1": "UNLOCALIZED: Fluid Tanks on moving contraptions cannot be accessed by any pipes", + "create.ponder.portable_fluid_interface.text_2": "UNLOCALIZED: This component can interact with fluid tanks without the need to stop the contraption", + "create.ponder.portable_fluid_interface.text_3": "UNLOCALIZED: Place a second one with a gap of 1 or 2 blocks inbetween", + "create.ponder.portable_fluid_interface.text_4": "UNLOCALIZED: Whenever they pass by each other, they will engage in a connection", + "create.ponder.portable_fluid_interface.text_5": "UNLOCALIZED: While engaged, the stationary interface will represent ALL Tanks on the contraption", + "create.ponder.portable_fluid_interface.text_6": "UNLOCALIZED: Fluid can now be inserted...", + "create.ponder.portable_fluid_interface.text_7": "UNLOCALIZED: ...or extracted from the contraption", + "create.ponder.portable_fluid_interface.text_8": "UNLOCALIZED: After no contents have been exchanged for a while, the contraption will continue on its way", + "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 +2246,25 @@ "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.smart_pipe.text_1": "UNLOCALIZED: Smart pipes can help control flows by fluid type", + "create.ponder.smart_pipe.text_2": "UNLOCALIZED: When placed directly at the source, they can specify the type of fluid to extract", + "create.ponder.smart_pipe.text_3": "UNLOCALIZED: Simply Right-Click their filter slot with any item containing the desired fluid", + "create.ponder.smart_pipe.text_4": "UNLOCALIZED: When placed further down a pipe network, smart pipes will only let matching fluids continue", + "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_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.spout_filling.text_1": "UNLOCALIZED: The Spout can fill fluid holding items provided beneath it", + "create.ponder.spout_filling.text_2": "UNLOCALIZED: The content of a Spout cannot be accessed manually", + "create.ponder.spout_filling.text_3": "UNLOCALIZED: Instead, Pipes can be used to supply it with fluids", + "create.ponder.spout_filling.text_4": "UNLOCALIZED: The Input items can be placed on a Depot under the Spout", + "create.ponder.spout_filling.text_5": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.spout_filling.text_6": "UNLOCALIZED: The Spout will hold and process them automatically", + "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 +2296,12 @@ "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.valve_pipe.text_1": "UNLOCALIZED: Valve pipes help control fluids propagating through pipe networks", + "create.ponder.valve_pipe.text_2": "UNLOCALIZED: Their shaft input controls whether fluid is currently allowed through", + "create.ponder.valve_pipe.text_3": "UNLOCALIZED: Given Rotational Force in the opening direction, the valve will open up", + "create.ponder.valve_pipe.text_4": "UNLOCALIZED: It can be closed again by reversing the input rotation", + "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..ef0ca16be 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json +++ b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json @@ -1,10 +1,10 @@ { - "_": "Missing Localizations: 24", + "_": "Missing Localizations: 48", "_": "->------------------------] Game Elements [------------------------<-", "block.create.acacia_window": "アカシアの窓", - "block.create.acacia_window_pane": "アカシアの窓パネル", + "block.create.acacia_window_pane": "アカシアの窓板", "block.create.adjustable_chain_gearshift": "可変チェーンギアシフト", "block.create.adjustable_crate": "可変クレート", "block.create.adjustable_pulse_repeater": "可変パルスリピーター", @@ -14,12 +14,12 @@ "block.create.andesite_bricks": "安山岩レンガ", "block.create.andesite_bricks_slab": "安山岩レンガのハーフブロック", "block.create.andesite_bricks_stairs": "安山岩レンガの階段", - "block.create.andesite_bricks_wall": "安山岩レンガの壁", + "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_cobblestone_wall": "安山岩の丸石の塀", "block.create.andesite_encased_shaft": "安山岩のケース入りシャフト", "block.create.andesite_funnel": "安山岩ファンネル", "block.create.andesite_pillar": "安山岩の柱", @@ -27,13 +27,17 @@ "block.create.basin": "鉢", "block.create.belt": "メカニカルベルト", "block.create.birch_window": "シラカバの窓", - "block.create.birch_window_pane": "シラカバの窓パネル", + "block.create.birch_window_pane": "シラカバの窓板", + "block.create.black_nixie_tube": "黒色のニキシー管", "block.create.black_sail": "黒色の帆", "block.create.black_seat": "黒色のシート", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "黒色のバルブハンドル", "block.create.blaze_burner": "ブレイズバーナー", + "block.create.blue_nixie_tube": "青色のニキシー管", "block.create.blue_sail": "青色の帆", "block.create.blue_seat": "青色のシート", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "青色のバルブハンドル", "block.create.brass_belt_funnel": "真鍮のベルトファンネル", "block.create.brass_block": "真鍮ブロック", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "真鍮のケース入りシャフト", "block.create.brass_funnel": "真鍮ファンネル", "block.create.brass_tunnel": "真鍮トンネル", + "block.create.brown_nixie_tube": "茶色のニキシー管", "block.create.brown_sail": "茶色の帆", "block.create.brown_seat": "茶色のシート", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "茶色のバルブハンドル", "block.create.cart_assembler": "トロッコアセンブラ", "block.create.chiseled_dark_scoria": "模様入りのダークスコリア", @@ -58,7 +64,7 @@ "block.create.cogwheel": "歯車", "block.create.content_observer": "コンテンツオブザーバー", "block.create.controller_rail": "コントローラーレール", - "block.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "block.create.copper_backtank": "銅のバックタンク", "block.create.copper_block": "銅ブロック", "block.create.copper_casing": "銅ケーシング", "block.create.copper_ore": "銅鉱石", @@ -69,45 +75,47 @@ "block.create.creative_fluid_tank": "クリエイティブ液体タンク", "block.create.creative_motor": "クリエイティブモーター", "block.create.crimson_window": "真紅の窓", - "block.create.crimson_window_pane": "真紅の窓パネル", + "block.create.crimson_window_pane": "真紅の窓板", "block.create.crushing_wheel": "破砕ホイール", "block.create.crushing_wheel_controller": "破砕ホイールコントローラー", "block.create.cuckoo_clock": "鳩時計", + "block.create.cyan_nixie_tube": "水色のニキシー管", "block.create.cyan_sail": "水色の帆", "block.create.cyan_seat": "水色のシート", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "水色のバルブハンドル", "block.create.dark_oak_window": "ダークオークの窓", - "block.create.dark_oak_window_pane": "ダークオークの窓パネル", + "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_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_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_bricks_wall": "閃緑岩レンガの塀", "block.create.diorite_cobblestone": "閃緑岩の丸石", "block.create.diorite_cobblestone_slab": "閃緑岩の丸石のハーフブロック", "block.create.diorite_cobblestone_stairs": "閃緑岩の丸石の階段", - "block.create.diorite_cobblestone_wall": "閃緑岩の丸石の壁", + "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_bricks_wall": "苦灰岩レンガの塀", "block.create.dolomite_cobblestone": "苦灰岩の丸石", "block.create.dolomite_cobblestone_slab": "苦灰岩の丸石のハーフブロック", "block.create.dolomite_cobblestone_stairs": "苦灰岩の丸石の階段", - "block.create.dolomite_cobblestone_wall": "苦灰岩の丸石の壁", + "block.create.dolomite_cobblestone_wall": "苦灰岩の丸石の塀", "block.create.dolomite_pillar": "苦灰岩の柱", "block.create.encased_chain_drive": "ケース入りチェーンドライブ", "block.create.encased_fan": "ケース入りファン", @@ -115,39 +123,39 @@ "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_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_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_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_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_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_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_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_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.fancy_weathered_limestone_bricks_wall": "装飾された風化した石灰岩レンガの塀", "block.create.fluid_pipe": "液体パイプ", "block.create.fluid_tank": "液体タンク", "block.create.fluid_valve": "液体バルブ", @@ -159,11 +167,11 @@ "block.create.gabbro_bricks": "斑れい岩レンガ", "block.create.gabbro_bricks_slab": "斑れい岩レンガのハーフブロック", "block.create.gabbro_bricks_stairs": "斑れい岩レンガの階段", - "block.create.gabbro_bricks_wall": "斑れい岩レンガの壁", + "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_cobblestone_wall": "斑れい岩の丸石の塀", "block.create.gabbro_pillar": "斑れい岩の柱", "block.create.gantry_carriage": "ガントリーキャリッジ", "block.create.gantry_shaft": "ガントリーシャフト", @@ -173,26 +181,31 @@ "block.create.granite_bricks": "花崗岩レンガ", "block.create.granite_bricks_slab": "花崗岩レンガのハーフブロック", "block.create.granite_bricks_stairs": "花崗岩レンガの階段", - "block.create.granite_bricks_wall": "花崗岩レンガの壁", + "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_cobblestone_wall": "花崗岩の丸石の塀", "block.create.granite_pillar": "花崗岩の柱", + "block.create.gray_nixie_tube": "灰色のニキシー管", "block.create.gray_sail": "灰色の帆", "block.create.gray_seat": "灰色のシート", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "灰色のバルブハンドル", + "block.create.green_nixie_tube": "緑色のニキシー管", "block.create.green_sail": "緑色の帆", "block.create.green_seat": "緑色のシート", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "緑色のバルブハンドル", "block.create.hand_crank": "ハンドクランク", + "block.create.haunted_bell": "憑りつかれた鐘", "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.jungle_window_pane": "ジャングルの窓板", "block.create.large_cogwheel": "大きな歯車", "block.create.layered_andesite": "安山岩の組石", "block.create.layered_dark_scoria": "ダークスコリアの組石", @@ -203,30 +216,39 @@ "block.create.layered_limestone": "石灰岩の組石", "block.create.layered_scoria": "スコリアの組石", "block.create.layered_weathered_limestone": "風化した石灰岩の組石", + "block.create.lectern_controller": "書見台コントローラー", + "block.create.light_blue_nixie_tube": "空色のニキシー菅", "block.create.light_blue_sail": "空色の帆", "block.create.light_blue_seat": "空色のシート", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "空色のバルブハンドル", + "block.create.light_gray_nixie_tube": "薄灰色のニキシー管", "block.create.light_gray_sail": "薄灰色の帆", "block.create.light_gray_seat": "薄灰色のシート", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "薄灰色のバルブハンドル", + "block.create.lime_nixie_tube": "黄緑色のニキシー管", "block.create.lime_sail": "黄緑色の帆", "block.create.lime_seat": "黄緑色のシート", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "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_bricks_wall": "石灰岩レンガの塀", "block.create.limestone_cobblestone": "石灰岩の丸石", "block.create.limestone_cobblestone_slab": "石灰岩の丸石のハーフブロック", "block.create.limestone_cobblestone_stairs": "石灰岩の丸石の階段", - "block.create.limestone_cobblestone_wall": "石灰岩の丸石の壁", + "block.create.limestone_cobblestone_wall": "石灰岩の丸石の塀", "block.create.limestone_pillar": "石灰岩の柱", "block.create.linear_chassis": "リニアシャーシ", "block.create.lit_blaze_burner": "燃焼中のブレイズバーナー", + "block.create.magenta_nixie_tube": "赤紫色のニキシー管", "block.create.magenta_sail": "赤紫色の帆", "block.create.magenta_seat": "赤紫色のシート", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "赤紫色のバルブハンドル", "block.create.mechanical_arm": "メカニカルアーム", "block.create.mechanical_bearing": "メカニカルベアリング", @@ -257,12 +279,13 @@ "block.create.nixie_tube": "ニキシー管", "block.create.nozzle": "ノズル", "block.create.oak_window": "オークの窓", - "block.create.oak_window_pane": "オークの窓パネル", + "block.create.oak_window_pane": "オークの窓板", "block.create.orange_sail": "橙色の帆", "block.create.orange_seat": "橙色のシート", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "橙色のバルブハンドル", "block.create.ornate_iron_window": "鉄の装飾ガラス", - "block.create.ornate_iron_window_pane": "鉄の装飾ガラスパネル", + "block.create.ornate_iron_window_pane": "鉄の装飾ガラス板", "block.create.overgrown_andesite": "生い茂った安山岩", "block.create.overgrown_dark_scoria": "生い茂ったダークスコリア", "block.create.overgrown_diorite": "生い茂った閃緑岩", @@ -275,79 +298,86 @@ "block.create.paved_andesite": "舗装された安山岩", "block.create.paved_andesite_slab": "舗装された安山岩のハーフブロック", "block.create.paved_andesite_stairs": "舗装された安山岩の階段", - "block.create.paved_andesite_wall": "舗装された安山岩の壁", + "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_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_diorite_wall": "舗装された閃緑岩の塀", "block.create.paved_dolomite": "舗装された苦灰岩", "block.create.paved_dolomite_slab": "舗装された苦灰岩のハーフブロック", "block.create.paved_dolomite_stairs": "舗装された苦灰岩の階段", - "block.create.paved_dolomite_wall": "舗装された苦灰岩の壁", + "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_gabbro_wall": "舗装された斑れい岩の塀", "block.create.paved_granite": "舗装された花崗岩", "block.create.paved_granite_slab": "舗装された花崗岩のハーフブロック", "block.create.paved_granite_stairs": "舗装された花崗岩の階段", - "block.create.paved_granite_wall": "舗装された花崗岩の壁", + "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_limestone_wall": "舗装された石灰岩の塀", "block.create.paved_scoria": "舗装されたスコリア", "block.create.paved_scoria_slab": "舗装されたスコリアのハーフブロック", "block.create.paved_scoria_stairs": "舗装されたスコリアの階段", - "block.create.paved_scoria_wall": "舗装されたスコリアの壁", + "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.paved_weathered_limestone_wall": "舗装された風化した石灰岩の塀", + "block.create.peculiar_bell": "風変わりな鐘", + "block.create.pink_nixie_tube": "桃色のニキシー管", "block.create.pink_sail": "桃色の帆", "block.create.pink_seat": "桃色のシート", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "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_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_dolomite_wall": "磨かれた苦灰岩の塀", "block.create.polished_gabbro": "磨かれた斑れい岩", "block.create.polished_gabbro_slab": "磨かれた斑れい岩のハーフブロック", "block.create.polished_gabbro_stairs": "磨かれた斑れい岩の階段", - "block.create.polished_gabbro_wall": "磨かれた斑れい岩の壁", + "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_limestone_wall": "磨かれた石灰岩の塀", "block.create.polished_scoria": "磨かれたスコリア", "block.create.polished_scoria_slab": "磨かれたスコリアのハーフブロック", "block.create.polished_scoria_stairs": "磨かれたスコリアの階段", - "block.create.polished_scoria_wall": "磨かれたスコリアの壁", + "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.polished_weathered_limestone_wall": "磨かれた風化した石灰岩の塀", "block.create.portable_fluid_interface": "ポータブル液体インターフェース", "block.create.portable_storage_interface": "ポータブルストレージインターフェース", "block.create.powered_latch": "パワードラッチ", "block.create.powered_toggle_latch": "パワードトグルラッチ", "block.create.pulley_magnet": "プーリーマグネット", "block.create.pulse_repeater": "パルスリピーター", + "block.create.purple_nixie_tube": "紫色のニキシー管", "block.create.purple_sail": "紫色の帆", "block.create.purple_seat": "紫色のシート", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "紫色のバルブハンドル", "block.create.radial_chassis": "ラジアルシャーシ", + "block.create.red_nixie_tube": "赤色のニキシー管", "block.create.red_sail": "赤色の帆", "block.create.red_seat": "赤色のシート", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "赤色のバルブハンドル", "block.create.redstone_contact": "レッドストーンコンタクト", "block.create.redstone_link": "レッドストーンリンク", @@ -356,18 +386,18 @@ "block.create.rope": "ロープ", "block.create.rope_pulley": "ローププーリー", "block.create.rotation_speed_controller": "回転速度コントローラー", - "block.create.sail_frame": "帆のフレーム", + "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_bricks_wall": "スコリアレンガの塀", "block.create.scoria_cobblestone": "スコリアの丸石", "block.create.scoria_cobblestone_slab": "スコリアの丸石のハーフブロック", "block.create.scoria_cobblestone_stairs": "スコリアの丸石の階段", - "block.create.scoria_cobblestone_wall": "スコリアの丸石の壁", + "block.create.scoria_cobblestone_wall": "スコリアの丸石の塀", "block.create.scoria_pillar": "スコリアの柱", "block.create.secondary_linear_chassis": "セカンダリリニアシャーシ", "block.create.sequenced_gearshift": "シーケンスギアシフト", @@ -378,9 +408,9 @@ "block.create.speedometer": "速度メーター", "block.create.spout": "アイテム注液口", "block.create.spruce_window": "マツの窓", - "block.create.spruce_window_pane": "マツの窓パネル", + "block.create.spruce_window_pane": "マツの窓板", "block.create.sticker": "スティッカー", - "block.create.sticky_mechanical_piston": "粘着メカニカルピストン", + "block.create.sticky_mechanical_piston": "メカニカル粘着ピストン", "block.create.stockpile_switch": "在庫スイッチ", "block.create.stressometer": "応力メーター", "block.create.tiled_glass": "タイルガラス", @@ -389,37 +419,45 @@ "block.create.vertical_framed_glass": "縦型ガラス窓", "block.create.vertical_framed_glass_pane": "縦型ガラス窓板", "block.create.warped_window": "歪んだ窓", - "block.create.warped_window_pane": "歪んだ窓パネル", + "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_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_cobblestone_wall": "風化した石灰岩の丸石の塀", "block.create.weathered_limestone_pillar": "風化した石灰岩の柱", "block.create.weighted_ejector": "重量射出機", + "block.create.white_nixie_tube": "白色のニキシー管", "block.create.white_sail": "白色の帆", "block.create.white_seat": "白色のシート", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "白色のバルブハンドル", "block.create.windmill_bearing": "風車ベアリング", "block.create.wooden_bracket": "木製ブラケット", + "block.create.yellow_nixie_tube": "黄色のニキシー管", "block.create.yellow_sail": "黄色の帆", "block.create.yellow_seat": "黄色のシート", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "黄色のバルブハンドル", "block.create.zinc_block": "亜鉛ブロック", "block.create.zinc_ore": "亜鉛鉱石", + "enchantment.create.capacity": "容量増加", + "enchantment.create.potato_recovery": "ポテト回収", + "entity.create.contraption": "からくり", + "entity.create.crafting_blueprint": "クラフトブループリント", "entity.create.gantry_contraption": "ガントリーからくり", + "entity.create.potato_projectile": "ポテト弾", "entity.create.seat": "シート", "entity.create.stationary_contraption": "付設からくり", "entity.create.super_glue": "超粘着剤", - "fluid.create.milk": "牛乳", "fluid.create.potion": "ポーション", "fluid.create.tea": "建築家のお茶", @@ -439,11 +477,13 @@ "item.create.chocolate_glazed_berries": "チョコレートグレーズドベリー", "item.create.chromatic_compound": "色彩の化合物", "item.create.cinder_flour": "ネザーラックの粉", - "item.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "item.create.copper_backtank": "銅のバックタンク", "item.create.copper_ingot": "銅インゴット", "item.create.copper_nugget": "銅塊", "item.create.copper_sheet": "銅板", "item.create.crafter_slot_cover": "クラフタースロットカバー", + "item.create.crafting_blueprint": "クラフトブループリント", + "item.create.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "item.create.crushed_aluminum_ore": "砕いたアルミニウム鉱石", "item.create.crushed_brass": "砕いた真鍮", "item.create.crushed_copper_ore": "砕いた銅鉱石", @@ -458,8 +498,8 @@ "item.create.crushed_tin_ore": "砕いた錫鉱石", "item.create.crushed_uranium_ore": "砕いたウラン鉱石", "item.create.crushed_zinc_ore": "砕いた亜鉛鉱石", - "item.create.diving_boots": "UNLOCALIZED: Diving Boots", - "item.create.diving_helmet": "UNLOCALIZED: Diving Helmet", + "item.create.diving_boots": "潜水ブーツ", + "item.create.diving_helmet": "潜水ヘルメット", "item.create.dough": "生地", "item.create.electron_tube": "電子管", "item.create.empty_blaze_burner": "空のブレイズバーナー", @@ -472,13 +512,17 @@ "item.create.handheld_worldshaper": "携帯型ワールドシェーパー", "item.create.honey_bucket": "ハチミツ入りバケツ", "item.create.honeyed_apple": "リンゴのハチミツかけ", - "item.create.integrated_circuit": "集積回路", + "item.create.incomplete_cogwheel": "組み立て中の歯車", + "item.create.incomplete_large_cogwheel": "組み立て中の大きな歯車", + "item.create.incomplete_precision_mechanism": "組み立て中の精密機構", "item.create.iron_sheet": "鉄板", - "item.create.lapis_sheet": "ラピスラズリ板", + "item.create.linked_controller": "リンクコントローラー", "item.create.minecart_contraption": "からくり付きトロッコ", "item.create.minecart_coupling": "トロッコ連結器", "item.create.polished_rose_quartz": "磨かれたローズクォーツ", + "item.create.potato_cannon": "ポテトキャノン", "item.create.powdered_obsidian": "黒曜石の粉", + "item.create.precision_mechanism": "精密機構", "item.create.propeller": "プロペラ", "item.create.red_sand_paper": "赤い紙やすり", "item.create.refined_radiance": "高貴な光輝", @@ -502,7 +546,7 @@ "_": "->------------------------] Advancements [------------------------<-", "advancement.create.root": "Createへようこそ", - "advancement.create.root.desc": "素晴らしいからくり機構を作る時間だ!", + "advancement.create.root.desc": "素晴らしいからくり仕掛けを作る時間だ!", "advancement.create.andesite_alloy": "大いに押韻", "advancement.create.andesite_alloy.desc": "Createの素材には変な名前がついています、安山岩合金もその一つです", "advancement.create.its_alive": "こいつ…動くぞ!", @@ -511,51 +555,51 @@ "advancement.create.shifting_gears.desc": "大きい歯車と小さい歯車を噛み合わせて回転速度を変更する", "advancement.create.overstressed": "超過応力", "advancement.create.overstressed.desc": "応力の限界を肌で感じる", - "advancement.create.belt": "コンブ駆動", + "advancement.create.belt": "ベルトコンブア", "advancement.create.belt.desc": "2つのシャフトをメカニカルベルトで繋ぐ", - "advancement.create.tunnel": "隠せ!", - "advancement.create.tunnel.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": "机上の空論", "advancement.create.upward_chute.desc": "落ちているアイテムがファンで駆動するシュートに飛んでいく様子を見る", - "advancement.create.belt_funnel": "ファンネルのぶらさがってる、ひらひらしたやつ", - "advancement.create.belt_funnel.desc": "ベルトやデポ等の上に横向きのファンネルを置き、特殊形態にする", - "advancement.create.belt_funnel_kiss": "オウムと羽ばたき", + "advancement.create.belt_funnel": "ファンネルのひらひら", + "advancement.create.belt_funnel.desc": "ベルトやデポなどの上に横向きのファンネルを置き、特殊形態にする", + "advancement.create.belt_funnel_kiss": "コウノトリの羽ばたき", "advancement.create.belt_funnel_kiss.desc": "2つのベルトに載せたファンネルにキスをさせる", "advancement.create.fan": "メカニカルエアベンダー", "advancement.create.fan.desc": "ケース入りファンから出る風に乗る", - "advancement.create.fan_lava": "地熱暖房器具", + "advancement.create.fan_lava": "地熱ファンヒーター", "advancement.create.fan_lava.desc": "アイテムを精錬する熱風に巻き込まれる", - "advancement.create.fan_water": "奇妙な洗濯機", + "advancement.create.fan_water": "風変りな洗濯機", "advancement.create.fan_water.desc": "アイテムを洗浄する涼風に巻き込まれる", "advancement.create.fan_smoke": "メカニカルふいご", "advancement.create.fan_smoke.desc": "アイテムを燻製する暖風に巻き込まれる", - "advancement.create.wrench": "便利に設定", + "advancement.create.wrench": "便利な設定", "advancement.create.wrench.desc": "からくり作りに役立つレンチを作る", "advancement.create.goggles": "応力をこの目で", "advancement.create.goggles.desc": "機械からより多くの情報を手に入れるために、エンジニアのゴーグルを作る", "advancement.create.speedometer": "正確な速度は?", - "advancement.create.speedometer.desc": "動作中の速度メーターをゴーグルで見て、正確な値を読み取る", + "advancement.create.speedometer.desc": "動作中の回転速度メーターをゴーグルで見て、正確な値を読み取る", "advancement.create.stressometer": "正確な応力は?", "advancement.create.stressometer.desc": "動作中の応力メーターをゴーグルを通して見て、正確な値を読み取る", "advancement.create.aesthetics": "装飾ブーム!", "advancement.create.aesthetics.desc": "シャフト、パイプ、歯車に木製ブラケットや金属ブラケットを取り付ける", "advancement.create.reinforced": "補強ブーム!", - "advancement.create.reinforced.desc": "シャフト、パイプ、メカニカルベルトなどにケーシングブロックを取り付ける", + "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.lava_wheel.desc": "こんなはずじゃなかった", "advancement.create.cuckoo": "今がその時だ", "advancement.create.cuckoo.desc": "鳩時計が就寝時間を告げるのを目撃する", - "advancement.create.millstone": "ポケット粉砕機", + "advancement.create.millstone": "ポケットクラッシャー", "advancement.create.millstone.desc": "石臼を置いて、回転させる", - "advancement.create.windmill": "凱風快晴", + "advancement.create.windmill": "微風", "advancement.create.windmill.desc": "風車を組み立てる", "advancement.create.maxed_windmill": "雄風", "advancement.create.maxed_windmill.desc": "最強の風車を組み立てる", @@ -587,13 +631,13 @@ "advancement.create.copper_casing.desc": "銅と木材を使って銅ケーシングを作る", "advancement.create.spout": "ぱしゃぱしゃ", "advancement.create.spout.desc": "アイテム注液口が液体を充填している様子を見る", - "advancement.create.spout_potion": "大きな醸造台", + "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": "アイテムころりん", "advancement.create.chained_item_drain.desc": "自動化したアイテム排液口の上を転がるアイテムを見る", "advancement.create.glass_pipe": "フロウ・スパイ", "advancement.create.glass_pipe.desc": "まっすぐな液体パイプにレンチを使って、窓から通る液体を見る", @@ -609,7 +653,7 @@ "advancement.create.infinite_lava.desc": "無限と言えるほどの大量の溶岩を吸引する", "advancement.create.infinite_chocolate": "空想に溺れて", "advancement.create.infinite_chocolate.desc": "無限と言えるほどの大量の溶けたチョコレートを吸引する", - "advancement.create.crafter": "自動作業台", + "advancement.create.crafter": "部品集結!", "advancement.create.crafter.desc": "メカニカルクラフターを設置して、回転力を供給する", "advancement.create.clockwork_bearing": "時計仕掛け", "advancement.create.clockwork_bearing.desc": "時計仕掛けのベアリングの上に構造物を組み立てる", @@ -623,10 +667,10 @@ "advancement.create.flywheel.desc": "かまどエンジンを勢車に繋ぐ", "advancement.create.overstress_flywheel": "ハイレベル応力", "advancement.create.overstress_flywheel.desc": "かまどエンジンに超過応力をかける", - "advancement.create.integrated_circuit": "複素数の計算", - "advancement.create.integrated_circuit.desc": "集積回路を組み立てる", + "advancement.create.precision_mechanism": "手間暇かけた骨董品", + "advancement.create.precision_mechanism.desc": "精密機構を組み立てる", "advancement.create.mechanical_arm": "手が離せない!", - "advancement.create.mechanical_arm.desc": "搬入元と搬出先を設定したメカニカルアームを設置して、稼働させ、あなたのために一生懸命労働している様子を見る", + "advancement.create.mechanical_arm.desc": "搬入元と搬出先を設定したメカニカルアームを設置して稼働させ、あなたのために一生懸命働いている様子を見る", "advancement.create.musical_arm": "お気に入りの曲を流して!", "advancement.create.musical_arm.desc": "メカニカルアームがジュークボックスを使う様子を見る", "advancement.create.arm_many_targets": "整理整頓", @@ -651,6 +695,8 @@ "advancement.create.wand_of_symmetry.desc": "対象の杖を作る", "advancement.create.extendo_grip": "ビヨヨーン!", "advancement.create.extendo_grip.desc": "マジックハンドを手に入れる", + "advancement.create.potato_cannon": "バキューン!", + "advancement.create.potato_cannon.desc": "ポテトキャノンで敵を倒す", "advancement.create.dual_extendo_grip": "究極のビヨンビヨン時代", "advancement.create.dual_extendo_grip.desc": "二刀流のマジックハンドで超人的なリーチを手に入れる", "advancement.create.eob": "ベータ版はここまで", @@ -662,16 +708,32 @@ "itemGroup.create.base": "Create", "itemGroup.create.palettes": "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 は改ざんされた鳩時計に爆破された", + "death.attack.create.crush": "%1$sは破砕ホイールによって処理された", + "death.attack.create.crush.player": "%1$sは%2$sに破砕ホイールに投入された", + "death.attack.create.fan_fire": "%1$sはケース入りファンによって燻製にされた", + "death.attack.create.fan_fire.player": "%1$sは%2$sによって燻製にされた", + "death.attack.create.fan_lava": "%1$sはケース入りファンで精錬された", + "death.attack.create.fan_lava.player": "%1$sは%2$sによって熱風に投げ込まれた", + "death.attack.create.mechanical_drill": "%1$sはメカニカルドリルに突き抜かれた", + "death.attack.create.mechanical_drill.player": "%1$sは%2$sにドリルの目の前に投げ込まれた", + "death.attack.create.mechanical_saw": "%1$sはメカニカルソーで半分にカットされた", + "death.attack.create.mechanical_saw.player": "%1$sは%2$sによってメカニカルソーの回転する刃に投げ込まれた", + "death.attack.create.potato_cannon": "%1$sは%2$sのポテトキャノンに撃ち抜かれた", + "death.attack.create.potato_cannon.item": "%1$sは%3$sで%2$sに撃た抜かれた", + "death.attack.create.cuckoo_clock_explosion": "%1$sは改造された鳩時計に爆破された", + "death.attack.create.cuckoo_clock_explosion.player": "%1$sは何者かによって改造された鳩時計に爆破された", "create.block.deployer.damage_source_name": "悪いデプロイヤー", "create.block.cart_assembler.invalid": "トロッコアセンブラはレールの上にのみ設置できます", + "create.menu.return": "メニューに戻る", + "create.menu.configure": "設定...", + "create.menu.ponder_index": "思案索引", + "create.menu.only_ingame": "一時停止メニューで利用可能", + "create.menu.project_page": "プロジェクトページ", + "create.menu.report_bugs": "バグ報告", + "create.menu.support": "私たちを応援する", + "create.recipe.crushing": "粉砕", "create.recipe.milling": "製粉", "create.recipe.fan_washing": "一括洗浄", @@ -682,7 +744,7 @@ "create.recipe.fan_blasting.fan": "溶岩の奥のケース入りファン", "create.recipe.pressing": "プレス", "create.recipe.mixing": "混合", - "create.recipe.deploying": "UNLOCALIZED: Deploying", + "create.recipe.deploying": "使用", "create.recipe.automatic_shapeless": "自動不定形クラフト", "create.recipe.automatic_brewing": "自動醸造", "create.recipe.packing": "圧縮", @@ -696,7 +758,18 @@ "create.recipe.mystery_conversion": "神秘の変転", "create.recipe.spout_filling": "アイテム注液口による注入", "create.recipe.draining": "アイテムから排液", + "create.recipe.sequenced_assembly": "組立ライン", + "create.recipe.assembly.next": "次の工程: %1$s", + "create.recipe.assembly.step": "手順: %1$s:", + "create.recipe.assembly.progress": "進捗: %1$s/%2$s", + "create.recipe.assembly.pressing": "プレスする", + "create.recipe.assembly.spout_filling_fluid": "%1$sを注液", + "create.recipe.assembly.deploying_item": "%1$sを組み込む", + "create.recipe.assembly.cutting": "ソーでの切断", + "create.recipe.assembly.repeat": "%1$s回繰り返す", + "create.recipe.assembly.junk": "ランダムな仕損品", "create.recipe.processing.chance": "%1$s%%チャンス", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "加熱不要", "create.recipe.heat_requirement.heated": "加熱が必要", "create.recipe.heat_requirement.superheated": "極度の加熱が必要", @@ -725,6 +798,7 @@ "create.action.discard": "捨てる", "create.keyinfo.toolmenu": "ツールメニューをフォーカスする", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "マウスホイールアップをシミュレート(この世界で)", "create.keyinfo.scrolldown": "マウスホイールダウンをシミュレーション(この世界で)", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "シフトを押してスクロールを加速", "create.gui.toolmenu.focusKey": "[%1$s] 長押しでフォーカスする", "create.gui.toolmenu.cycle": "[スクロール] で循環", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "ミラーの種類", "create.gui.symmetryWand.orientation": "方向", @@ -748,16 +829,16 @@ "create.orientation.alongZ": "Z に沿る", "create.orientation.alongX": "X に沿る", - "create.gui.terrainzapper.title": "携帯型ワールドシェーパー", - "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.title": "携帯型ブロックザッパー", + "create.gui.terrainzapper.searchDiagonal": "対角線にフォロー", + "create.gui.terrainzapper.searchFuzzy": "素材の境界を無視", + "create.gui.terrainzapper.patternSection": "模様", + "create.gui.terrainzapper.pattern.solid": "敷き詰め", + "create.gui.terrainzapper.pattern.checkered": "市松模様", + "create.gui.terrainzapper.pattern.inversecheckered": "逆市松模様", + "create.gui.terrainzapper.pattern.chance25": "25%", + "create.gui.terrainzapper.pattern.chance50": "50%", + "create.gui.terrainzapper.pattern.chance75": "75%", "create.gui.terrainzapper.placement": "配置", "create.gui.terrainzapper.placement.merged": "合併", "create.gui.terrainzapper.placement.attached": "添える", @@ -766,8 +847,8 @@ "create.gui.terrainzapper.brush.cuboid": "直方体", "create.gui.terrainzapper.brush.sphere": "球体", "create.gui.terrainzapper.brush.cylinder": "円筒", - "create.gui.terrainzapper.brush.surface": "UNLOCALIZED: Surface", - "create.gui.terrainzapper.brush.cluster": "UNLOCALIZED: Cluster", + "create.gui.terrainzapper.brush.surface": "表面", + "create.gui.terrainzapper.brush.cluster": "鉱石", "create.gui.terrainzapper.tool": "ツール", "create.gui.terrainzapper.tool.fill": "埋立", "create.gui.terrainzapper.tool.place": "設置", @@ -777,8 +858,8 @@ "create.gui.terrainzapper.tool.flatten": "なだらかに", "create.terrainzapper.shiftRightClickToSet": "シフト-右クリックで形状を選択", - "create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s", - "create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material", + "create.terrainzapper.usingBlock": "使用中: %1$s", + "create.terrainzapper.leftClickToSet": "ブロックをスニークせず左クリックでブロックを選択", "create.minecart_coupling.two_couplings_max": "トロッコを2つ以上連結させることはできません", "create.minecart_coupling.unloaded": "列車の一部のあるチャンクがロードされていません", @@ -981,18 +1062,14 @@ "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.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "エンチャント済みか", "create.item_attributes.enchanted.inverted": "エンチャントなしか", + "create.item_attributes.max_enchanted": "最大レベルのエンチャントがされているか", + "create.item_attributes.max_enchanted.inverted": "最大レベルのエンチャントがされていないか", + "create.item_attributes.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "破損してるか", "create.item_attributes.damaged.inverted": "破損していないか", "create.item_attributes.badly_damaged": "ひどく損傷してるか", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "装備不可能か", "create.item_attributes.furnace_fuel": "かまどの燃料か", "create.item_attributes.furnace_fuel.inverted": "かまどの燃料でないか", + "create.item_attributes.washable": "洗浄可能か", + "create.item_attributes.washable.inverted": "洗浄不可能か", + "create.item_attributes.crushable": "粉砕可能か", + "create.item_attributes.crushable.inverted": "粉砕不可能か", + "create.item_attributes.smeltable": "精錬可能か", + "create.item_attributes.smeltable.inverted": "精錬不可能か", + "create.item_attributes.smokable": "燻製器で調理可能か", + "create.item_attributes.smokable.inverted": "燻製器で調理不可能か", + "create.item_attributes.blastable": "溶鉱炉で精錬可能か", + "create.item_attributes.blastable.inverted": "溶鉱炉で精錬不可能か", + "create.item_attributes.shulker_level": "%1$sシュルカーか", + "create.item_attributes.shulker_level.inverted": "%1$sシュルカーでないか", + "create.item_attributes.shulker_level.full": "満杯の", + "create.item_attributes.shulker_level.empty": "空の", + "create.item_attributes.shulker_level.partial": "一部埋まっている", "create.item_attributes.in_tag": "%1$sのタグが付けられてるか", "create.item_attributes.in_tag.inverted": "%1$sのタグがついていないか", "create.item_attributes.in_item_group": "%1$sに属してるか", @@ -1013,8 +1105,6 @@ "create.item_attributes.has_enchant.inverted": "エンチャントがされていないか", "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の名前が付けられているか", @@ -1029,14 +1119,14 @@ "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.item_attributes.astralsorcery_constellation": "%1$s に同調している", + "create.item_attributes.astralsorcery_constellation.inverted": "%1$s に同調していない", + "create.item_attributes.astralsorcery_crystal": "%1$s クリスタル属性を持つ", + "create.item_attributes.astralsorcery_crystal.inverted": "%1$s クリスタル属性を持たない", + "create.item_attributes.astralsorcery_perk_gem": "%1$s 特典属性がある", + "create.item_attributes.astralsorcery_perk_gem.inverted": "%1$s 特典属性がない", "create.gui.attribute_filter.no_selected_attributes": "属性が選択されていません", "create.gui.attribute_filter.selected_attributes": "選択された属性:", @@ -1104,6 +1194,27 @@ "create.tooltip.chute.fans_pull_up": "ファンが上から吸い込んでいます", "create.tooltip.chute.fans_pull_down": "ファンが下から吸い込んでいます", "create.tooltip.chute.contains": "内容物: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "配布中", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "右クリックで取り出し", + + "create.linked_controller.bind_mode": "割り当てモード", + "create.linked_controller.press_keybind": "%1$s、%2$s、%3$s、%4$s、%5$sまたは%6$sを押すとこの周波数がそのキーに割り当てられます", + "create.linked_controller.key_bound": "周波数を割り当てました %1$s", + "create.linked_controller.frequency_slot_1": "キーバインド: %1$s、周波数 #1", + "create.linked_controller.frequency_slot_2": "キーバインド: %1$s、周波数 #2", + + "create.crafting_blueprint.crafting_slot": "材料スロット", + "create.crafting_blueprint.filter_items_viable": "フィルターが使えます", + "create.crafting_blueprint.display_slot": "表示スロット", + "create.crafting_blueprint.inferred": "レシピから推測", + "create.crafting_blueprint.manually_assigned": "手動割り当て", + "create.crafting_blueprint.secondary_display_slot": "第2表示スロット", + "create.crafting_blueprint.optional": "オプション", + + "create.potato_cannon.ammo.attack_damage": "攻撃力: %1$s", + "create.potato_cannon.ammo.reload_ticks": "リロード時間(tick): %1$s", + "create.potato_cannon.ammo.knockback": "ノックバック: %1$s", "create.hint.hose_pulley.title": "底なし搬出", "create.hint.hose_pulley": "対象となる液体は無限とみなされています。", @@ -1132,34 +1243,46 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "このからくりトロッコは大きすぎて拾えません。", + "create.contraption.minecart_contraption_illegal_pickup": "神秘的な力がからくりカートを世界に縛り付けています。", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "歯車がゴロゴロと鳴る", - "create.subtitle.slime_added": "スライムがぐしゃっとつぶれる", "create.subtitle.contraption_disassemble": "からくりが止まる", - "create.subtitle.wrench_rotate": "レンチを使う", + "create.subtitle.peculiar_bell_use": "風変わりな鐘が鳴る", "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.fwoomp": "ポテトランチャーがバキューンと鳴る", + "create.subtitle.worldshaper_place": "ワールドシェーパーが設置する", + "create.subtitle.crushing_1": "粉砕音", "create.subtitle.depot_slide": "アイテムが滑る", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "メカニカルソーが動作する", "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.haunted_bell_use": "憑りつかれた鐘が鳴る", "create.subtitle.scroll_value": "スクロールのカチカチ音", + "create.subtitle.crafter_craft": "メカニカルクラフターがクラフトする", + "create.subtitle.controller_put": "コントローラのトントン音", + "create.subtitle.cranking": "ハンドクランクが回る", + "create.subtitle.wrench_remove": "機械を壊す", + "create.subtitle.cogs": "歯車がゴロゴロと鳴る", + "create.subtitle.slime_added": "スライムがぐしゃっとつぶれる", + "create.subtitle.wrench_rotate": "レンチが使用される", + "create.subtitle.potato_hit": "野菜が衝突する", + "create.subtitle.saw_activate_wood": "メカニカルソーが動作する", + "create.subtitle.haunted_bell_convert": "憑りつかれた鐘が目覚める", + "create.subtitle.deployer_polish": "デプロイヤーが磨く", + "create.subtitle.deny": "失敗音", + "create.subtitle.controller_click": "コントローラーのカチカチ音", + "create.subtitle.schematicannon_launch_block": "概略図砲が発射する", + "create.subtitle.copper_armor_equip": "潜水服がチャリンと鳴る", + "create.subtitle.controller_take": "書見台が空になる", "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", + "create.subtitle.confirm": "成功音", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1179,14 +1302,6 @@ "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": "右クリックしたとき", @@ -1195,65 +1310,6 @@ "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": "ホットバーにあるとき", @@ -1263,7 +1319,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": "_設定インターフェース_を開きます。", + "item.create.wand_of_symmetry.tooltip.action3": "_設定画面_を開きます。", "item.create.handheld_worldshaper.tooltip": "携帯型ワールドシェーパー", "item.create.handheld_worldshaper.tooltip.summary": "特色ある_風景_や_地形_を作成する便利なツール。", @@ -1272,7 +1328,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": "_設定インターフェース_を開きます。", + "item.create.handheld_worldshaper.tooltip.action3": "_設定画面_を開きます。", "item.create.tree_fertilizer.tooltip": "樹木の肥料", "item.create.tree_fertilizer.tooltip.summary": "一般的な種類の木の成長を早めるのに適したミネラルを配合した強力な肥料。", @@ -1283,30 +1339,39 @@ "item.create.extendo_grip.tooltip.summary": "ビヨヨーン!着用者の_射程_を大幅に_伸ばし_ます。", "item.create.extendo_grip.tooltip.condition1": "オフハンドに装備したとき", "item.create.extendo_grip.tooltip.behaviour1": "_メインハンド_で使うアイテムの_射程_を_伸ばし_ます。", + "item.create.extendo_grip.tooltip.condition2": "銅のバックタンクを装備したとき", + "item.create.extendo_grip.tooltip.behaviour2": "_耐久値_を消費しなくなります。代わりに_圧縮空気_をタンクから消費します。", + + "item.create.potato_cannon.tooltip": "ポテトキャノン", + "item.create.potato_cannon.tooltip.summary": "バキューン!自分が育てた野菜を敵に発射します。_銅のバックタンク_の圧縮空気でも動かせます。", + "item.create.potato_cannon.tooltip.condition1": "左クリックしたとき", + "item.create.potato_cannon.tooltip.behaviour1": "_インベントリ_の中から_適切_なアイテムを発射します。", + "item.create.potato_cannon.tooltip.condition2": "銅のバックタンクを装備した時", + "item.create.potato_cannon.tooltip.behaviour2": "_耐久性_を消費しなくなります。代わりに_圧縮空気_をタンクから消費します", "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.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.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.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ファイルに保存できます。", @@ -1322,9 +1387,9 @@ "item.create.schematic_and_quill.tooltip.action3": "選択を_リセット_して削除します。", "block.create.schematicannon.tooltip": "概略図砲", - "block.create.schematicannon.tooltip.summary": "ブロックを撃って、展開された_概略図_をもとにワールドに設置します。隣接する収納ブロックからのアイテムを自動搬入し、_火薬_を燃料とします。", + "block.create.schematicannon.tooltip.summary": "ブロックを撃って、_概略図_をもとにワールドに設置します。隣接する収納ブロックからのアイテムを自動搬入し、_火薬_を燃料とします。", "block.create.schematicannon.tooltip.condition1": "右クリックしたとき", - "block.create.schematicannon.tooltip.behaviour1": "_インターフェース_を開きます。", + "block.create.schematicannon.tooltip.behaviour1": "_UI_を開きます。", "block.create.schematic_table.tooltip": "概略図テーブル", "block.create.schematic_table.tooltip.summary": "保存された構造物を_空の概略図_に書き込みます。", @@ -1336,7 +1401,7 @@ "item.create.goggles.tooltip.condition1": "着用したとき", "item.create.goggles.tooltip.behaviour1": "設置された機械の_回転速度_および、_機械_の_応力への影響_と_許容量_を_色付きのインジケーター_で表示します。", "item.create.goggles.tooltip.condition2": "計器を見たとき", - "item.create.goggles.tooltip.behaviour2": "計器が接続されているネットワークの_回転速度_または_応力_に関する詳細情報を表示します。", + "item.create.goggles.tooltip.behaviour2": "計器が接続されている動力ネットワークの_回転速度_または_応力_に関する詳細情報を表示します。", "item.create.goggles.tooltip.condition3": "液体コンテナを見たとき", "item.create.goggles.tooltip.behaviour3": "ブロックの_容量_と、その中に貯蔵されている_液体_の詳細情報を表示します。", @@ -1358,31 +1423,42 @@ "block.create.turntable.tooltip": "ターンテーブル", "block.create.turntable.tooltip.summary": "_回転力_を洗練された乗り物酔いに変えます。", - "block.create.portable_fluid_interface.tooltip": "ポータブル液体インターフェース", - "block.create.portable_fluid_interface.tooltip.summary": "ピストン、ベアリング、トロッコ、またはプーリーで移動する_構造物_との間で_液体_を_移動_させる可搬式の交換ポイント。2つのインターフェースは、互いに_向かい合って_、_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.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "在庫スイッチ", - "block.create.stockpile_switch.tooltip.summary": "接続されたコンテナの_空き容量_に基づいてレッドストーン信号を切り替えます。便利なフィルターが付属しています。_コンパレータ―_とは違って、_在庫スイッチ_は、信号が反転される_しきい値_を設定できます。", + "block.create.stockpile_switch.tooltip.summary": "接続されたコンテナの_空き容量_によってレッドストーン信号を切り替えます。便利なフィルターが付属しています。_コンパレータ―_とは違って、_在庫スイッチ_は、信号が反転される_しきい値_を設定できます。", "block.create.stockpile_switch.tooltip.condition1": "右クリックしたとき", - "block.create.stockpile_switch.tooltip.behaviour1": "_設定インターフェース_を開きます。", + "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.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "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": "_インターフェース_を開きます。", + "block.create.adjustable_crate.tooltip.condition1": "右クリックしたとき", + "block.create.adjustable_crate.tooltip.behaviour1": "_UI_を開きます。", "block.create.creative_crate.tooltip": "クリエイティブクレート", - "block.create.creative_crate.tooltip.summary": "この_収納ブロック_は、あらゆるアイテムを無限に複製します。隣接する_概略図砲_へブロックを無限に供給します。", + "block.create.creative_crate.tooltip.summary": "あらゆるアイテムを無限に複製する_収納ブロック_。隣接する_概略図砲_へブロックを無限に供給します。", "block.create.creative_crate.tooltip.condition1": "フィルタースロットにアイテムが入っているとき", "block.create.creative_crate.tooltip.behaviour1": "このクレートから何かを_搬出_すると、指定されたアイテムが_無限_に_搬出_されます。このクレートに_搬入_されたアイテムは_消滅_します。", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "コントローラーレール", "block.create.controller_rail.tooltip.summary": "トロッコの_移動速度_を_細かく制御_できる_一方通行_の_パワード_レール", "block.create.controller_rail.tooltip.condition1": "レッドストーン信号を受けたとき", @@ -1398,26 +1474,61 @@ "item.create.refined_radiance.tooltip": "高貴な光輝", "item.create.refined_radiance.tooltip.summary": "_吸収した光輝_から鍛造した色彩素材。", + "item.create.refined_radiance.tooltip.condition1": "作業中", + "item.create.refined_radiance.tooltip.behaviour1": "この素材の使用方法は将来のリリースで実装予定です。", "item.create.shadow_steel.tooltip": "シャドウスチール", "item.create.shadow_steel.tooltip.summary": "_奈落の虚無_から鍛造した色彩素材。", + "item.create.shadow_steel.tooltip.condition1": "作業中", + "item.create.shadow_steel.tooltip.behaviour1": "この素材の使用方法は将来のリリースで実装予定です。", + + "item.create.linked_controller.tooltip": "リンクコントローラー", + "item.create.linked_controller.tooltip.summary": "_6つのボタン_に割り当てられた_レッドストーンリンク_周波数を_片手_で_制御_できます。", + "item.create.linked_controller.tooltip.condition1": "左クリック", + "item.create.linked_controller.tooltip.behaviour1": "コントローラーを_オンオフ_します。_制御_がオンのときは_移動_できません。", + "item.create.linked_controller.tooltip.condition2": "スニークしながら左クリック", + "item.create.linked_controller.tooltip.behaviour2": "手動_設定画面_を開きます", + "item.create.linked_controller.tooltip.condition3": "レッドストーンリンク受信機を左クリックしたとき", + "item.create.linked_controller.tooltip.behaviour3": "_割り当てモード_をオンにします。_6つのコントロール_のうち1つを押してリンクの周波数に_割り当て_ます。", + "item.create.linked_controller.tooltip.condition4": "書見台を左クリックしたとき", + "item.create.linked_controller.tooltip.behaviour4": "コントローラーを書見台に設置し、簡単に使えるようにします。(スニーク中に左クリックで取り出せます)", + + "item.create.diving_helmet.tooltip": "潜水ヘルメット", + "item.create.diving_helmet.tooltip.summary": "_銅のバックタンク_と一緒に使うと、長時間_水中_で_呼吸_できるようになるヘルメット。", + "item.create.diving_helmet.tooltip.condition1": "装備したとき", + "item.create.diving_helmet.tooltip.behaviour1": "バックタンクからゆっくりと_圧縮空気_を排出しながら、_水中呼吸_の効果を供給します。", + + "item.create.copper_backtank.tooltip": "銅のバックタンク", + "item.create.copper_backtank.tooltip.summary": "圧縮空気を運ぶため_携帯タンク_", + "item.create.copper_backtank.tooltip.condition1": "装備したとき", + "item.create.copper_backtank.tooltip.behaviour1": "必要な装備に_圧縮空気_を供給します。", + "item.create.copper_backtank.tooltip.condition2": "設置して動力を供給したとき", + "item.create.copper_backtank.tooltip.behaviour2": "_圧縮空気_を_集めます_。速度は回転速度によって決まります。", + + "item.create.diving_boots.tooltip": "潜水ブーツ", + "item.create.diving_boots.tooltip.summary": "海底を歩けるようになる_重いブーツ_。", + "item.create.diving_boots.tooltip.condition1": "装備したとき", + "item.create.diving_boots.tooltip.behaviour1": "_沈むのが早くなり_、_泳げなく_なります。その代わり、水中で_歩行_と_ジャンプ_が可能になります。また、メカニカルベルトの影響を受けなくなります。", + + "item.create.crafting_blueprint.tooltip": "クラフトブループリント", + "item.create.crafting_blueprint.tooltip.summary": "壁に_貼り_、_材料_の_配置_を_指定_することで手作業でのクラフトを簡単にできます。各スロットが1つのレシピを表しています。", + "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": "それを使ったことをすぐ後悔するだろう。", + "block.create.peculiar_bell.tooltip": "風変わりな鐘", + "block.create.peculiar_bell.tooltip.summary": "装飾用の_真鍮の鐘。_魂の炎_の真上に置くと、別の使い方が見つかるかもしれません...", + + "block.create.haunted_bell.tooltip": "憑りつかれた鐘", + "block.create.haunted_bell.tooltip.summary": "ネザーに彷徨う魂が宿る、呪われた鐘", + "block.create.haunted_bell.tooltip.condition1": "持ったとき、鳴らしたとき", + "block.create.haunted_bell.tooltip.behaviour1": "_敵モブ_がスポーンする近くの_光のない場所_を示します", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1434,41 +1545,46 @@ "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.exit": "終了", + "create.ponder.welcome": "思案画面へようこそ", + "create.ponder.categories": "Createで利用可能なカゴテリ", + "create.ponder.index_description": "アイテムをクリックすると、関連するアイテムやブロックの情報が表示されます。", + "create.ponder.index_title": "思案索引", + "create.ponder.shared.rpm16": "16 RPM", "create.ponder.shared.behaviour_modify_wrench": "この挙動はレンチを使って変更できます", + "create.ponder.shared.storage_on_contraption": "構造物中の収納ブロックは自動的にドロップを拾います", + "create.ponder.shared.sneak_and": "スニーク +", "create.ponder.shared.rpm8": "8 RPM", "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm32": "32 RPM", "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": "からくり構造部品", - "create.ponder.tag.contraption_actor.description": "ブロックを動かす機械に取り付けたときに特別な動作をする機械です", - "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": "からくり機械", - "create.ponder.tag.movement_anchor.description": "取り付けたブロック構造物を様々な方法で動かすことができるからくりを作ることができる機械です", - "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.shared.movement_anchors": "シャーシや超粘着剤を使えば大きな構造物も動かせます", "create.ponder.tag.redstone": "制御機械", "create.ponder.tag.redstone.description": "レッドストーン工学に役立つ機械です", + "create.ponder.tag.contraption_assembly": "ブロック組み立て用品", + "create.ponder.tag.contraption_assembly.description": "アニメーションして動く構造物を組み立てるための道具や機械です", "create.ponder.tag.fluids": "液体制御機械", "create.ponder.tag.fluids.description": "液体の輸送や利用に役立つ機械です", + "create.ponder.tag.decoration": "装飾", + "create.ponder.tag.decoration.description": "主に装飾に使うブロックです", + "create.ponder.tag.windmill_sails": "風車ベアリング用の帆", + "create.ponder.tag.windmill_sails.description": "風車につける構造物を組み立てたときに帆にカウントされるブロック。どのブロックを使っても同じ効率です", + "create.ponder.tag.arm_targets": "メカニカルアームのターゲット", + "create.ponder.tag.arm_targets.description": "メカニカルアームの搬入元または搬出先にできる機械/ブロックです", + "create.ponder.tag.kinetic_appliances": "作業機械", + "create.ponder.tag.kinetic_appliances.description": "回転力を利用する機械です", + "create.ponder.tag.kinetic_sources": "原動機", + "create.ponder.tag.kinetic_sources.description": "回転力を生み出す機械です", + "create.ponder.tag.movement_anchor": "からくり機械", + "create.ponder.tag.movement_anchor.description": "取り付けたブロック構造物を様々な方法で動かすことができるからくりを作ることができる機械です", + "create.ponder.tag.kinetic_relays": "伝達機械", + "create.ponder.tag.kinetic_relays.description": "回転力の伝達に役立つ機械です", + "create.ponder.tag.contraption_actor": "からくり構造部品", + "create.ponder.tag.contraption_actor.description": "ブロックを動かす機械に取り付けたときに特別な動作をする機械です", + "create.ponder.tag.creative": "クリエイティブ限定", + "create.ponder.tag.creative.description": "サバイバルモードでは通常入手できない機械です", + "create.ponder.tag.logistics": "輸送機械", + "create.ponder.tag.logistics.description": "アイテムの運搬を補助する機械です", "create.ponder.adjustable_pulse_repeater.header": "可変パルスリピーターによる信号制御", "create.ponder.adjustable_pulse_repeater.text_1": "可変パルスリピーターは信号を遅延し、短いパルスにして出力します", @@ -1494,10 +1610,10 @@ "create.ponder.andesite_tunnel.text_4": "残ったものは、そのルートを進み続けます", "create.ponder.basin.header": "鉢によるアイテム加工", - "create.ponder.basin.text_1": "鉢には材料となるアイテムや液体を入れられます", + "create.ponder.basin.text_1": "鉢には素材となるアイテムや液体を入れられます", "create.ponder.basin.text_2": "鉢は完成品アイテムを斜め下へ搬出しようとします", - "create.ponder.basin.text_3": "搬出できる機械が存在する場合、鉢には搬出用の蛇口が表示されます", - "create.ponder.basin.text_4": "ここではいくつかの選択肢があります", + "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": "これは、完成品アイテムを材料として再利用する必要がある場合に役立ちます", @@ -1506,7 +1622,7 @@ "create.ponder.bearing_modes.header": ":メカニカルベアリングの動作モード", "create.ponder.bearing_modes.text_1": "止まったとき、ベアリングは格子に沿った近い角度に構造物を配置します", - "create.ponder.bearing_modes.text_2": "通常のブロックに戻らないように設定したり、開始時の角度のみブロックに戻るように設定することもできます", + "create.ponder.bearing_modes.text_2": "通常のブロックに戻らないように設定したり、開始時の角度のみブロックに戻るように設定したりできます", "create.ponder.belt_casing.header": "ケース入りベルト", "create.ponder.belt_casing.text_1": "真鍮か安山岩のケーシングを使ってメカニカルベルトを飾れます", @@ -1515,16 +1631,16 @@ "create.ponder.belt_connector.header": "メカニカルベルトの使い方", "create.ponder.belt_connector.text_1": "メカニカルベルトを持って2つのシャフトを右クリックすると、シャフトにベルトコンベアを繋げて設置されます", "create.ponder.belt_connector.text_2": "誤ったシャフトをクリックしてしまった場合、スニークしながら右クリックでキャンセルできます", - "create.ponder.belt_connector.text_3": "ベルトの何処にでもシャフトを追加できます", + "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_2": "1.水平", "create.ponder.belt_directions.text_3": "2.斜め", - "create.ponder.belt_directions.text_4": "3.垂直方向", + "create.ponder.belt_directions.text_4": "3.垂直", "create.ponder.belt_directions.text_5": "4.垂直方向のシャフトを水平に", "create.ponder.belt_directions.text_6": "これらはすべて接続可能な方向です。ベルトの長さは2~20ブロックの間で自由に接続できます", @@ -1535,7 +1651,7 @@ "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_3": "ブレイズケーキを与えると、バーナーはさらに火力を出せます", "create.ponder.blaze_burner.text_4": "供給作業は、デプロイヤーやメカニカルアームで自動化できます", "create.ponder.brass_funnel.header": "真鍮ファンネル", @@ -1554,7 +1670,7 @@ "create.ponder.brass_tunnel.text_7": "搬入したアイテムは、接続されているすべての搬出口に分配されます", "create.ponder.brass_tunnel.text_8": "アイテムをトンネルへ直接搬入することもできます", - "create.ponder.brass_tunnel_modes.header": "真鍮トンネルのモード", + "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": "アイテムはグループ内の全てのトンネルがアイテムを搬入できる場合のみ通過を許可します", @@ -1569,34 +1685,35 @@ "create.ponder.brass_tunnel_modes.text_9": "「ランダム」は、スタック全体をランダムに選択された搬出口に分配します ", "create.ponder.cart_assembler.header": "トロッコアセンブラによる構造物の移動", - "create.ponder.cart_assembler.text_1": "レッドストーン信号を受けたアセンブラは、通過するトロッコに接続された構造物を取り付けます", + "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": "2つのトロッコアセンブラが構造物を共有している場合...", - "create.ponder.cart_assembler_dual.text_2": "...どちらかにレッドストーン信号を受けると、列車が組み立てられます", + "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_modes.text_2": "この矢印は、構造物のどちら側が前面かを示します", + "create.ponder.cart_assembler_modes.text_3": "アセンブラが「常に向きを固定する」に設定されている場合、からくりの向きは変わりません", "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_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_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": "信号を受けている時は、列内の他のチェーンドライブに伝達される速度が2倍になります", - "create.ponder.chain_gearshift.text_3": "信号を受けているチェーンギアシフトが動力源に無い場合、速度が半分になります", + "create.ponder.chain_gearshift.text_3": "信号を受けているチェーンギアシフトが動力源でない場合、速度が半分になります", "create.ponder.chain_gearshift.text_4": "いずれの場合も、列内のチェーンドライブは常に「信号入りチェーンギアシフト」の2倍の速度で動作します", "create.ponder.chain_gearshift.text_5": "レッドストーン信号の強度で、比率を1と2の間でより正確に調整できます", "create.ponder.chain_gearshift.text_6": "12 RPM", @@ -1608,7 +1725,7 @@ "create.ponder.chute_upward.header": "シュートでの上方向へ運搬", "create.ponder.chute_upward.text_1": "シュートの上部または下部にファンを配置すると、アイテムを上方向へ運搬できます", - "create.ponder.chute_upward.text_2": "エンジニアのゴーグルを付けてシュートを見ると、移動方向の情報が表示されます", + "create.ponder.chute_upward.text_2": "エンジニアのゴーグルを付けてシュートを見ると、移動方向が表示されます", "create.ponder.chute_upward.text_3": "ブロックで詰まっている端では、アイテムを側面から搬出入する必要があります", "create.ponder.clockwork_bearing.header": "時計仕掛けのベアリングを使った構造物のアニメーション", @@ -1622,21 +1739,27 @@ "create.ponder.clockwork_bearing.text_8": "2つ目の構造物は分針として回転します", "create.ponder.clutch.header": "クラッチによる回転力の制御", - "create.ponder.clutch.text_1": "クラッチは直線に回転を伝達します", - "create.ponder.clutch.text_2": "レッドストーン信号を受けると、回転の伝達を停止します", + "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": "大きな歯車から歯車に接続すると、伝達される回転速度が2倍になります", - "create.ponder.cog_speedup.text_3": "逆に接続すると、伝達される回転速度が半分になります", + "create.ponder.cog_speedup.text_2": "大きな歯車から歯車に接続すると、伝達先の回転速度が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": "クリエイティブ液体タンク", + "create.ponder.creative_fluid_tank.text_1": "クリエイティブ液体タンクは、液体を無限に供給できます", + "create.ponder.creative_fluid_tank.text_2": "液体容器アイテムで右クリックで液体を指定できます", + "create.ponder.creative_fluid_tank.text_3": "液体ネットワークはタンクから指定された液体を無限に引き出すことができます", + "create.ponder.creative_fluid_tank.text_4": "クリエイティブ液体タンクに押し入れた液体は消滅します", + "create.ponder.creative_motor.header": "クリエイティブモーターによる回転力の生成", - "create.ponder.creative_motor.text_1": "クリエイティブモーターは、コンパクトで調整できる原動機です", - "create.ponder.creative_motor.text_2": "背面パネルを見てスクロールすると、モーターの回転速度を変更できます", + "create.ponder.creative_motor.text_1": "クリエイティブモーターは、コンパクトで調整可能な原動機です", + "create.ponder.creative_motor.text_2": "背面パネルを見ながらスクロールすると、モーターの回転速度を変更できます", "create.ponder.crushing_wheels.header": "破砕ホイールによるアイテム加工", "create.ponder.crushing_wheels.text_1": "一対の破砕ホイールは、非常に効果的にアイテムを粉砕できます", @@ -1652,7 +1775,7 @@ "create.ponder.deployer.text_13": "フィルターを設定すると、一致するアイテムを持っている時だけ稼働します", "create.ponder.deployer.text_14": "また、フィルターに一致するアイテムのみが搬入されるようになり...", "create.ponder.deployer.text_15": "...一致しないアイテムのみが搬出されます", - "create.ponder.deployer.text_2": "動作は、常に前方2ブロックの位置へ行われます", + "create.ponder.deployer.text_2": "動作は、常に手前2ブロックの位置へ行われます", "create.ponder.deployer.text_3": "真正面のブロックが邪魔になることはありません", "create.ponder.deployer.text_4": "デプロイヤーは以下の動作に使えます", "create.ponder.deployer.text_5": "ブロックの設置", @@ -1666,31 +1789,43 @@ "create.ponder.deployer_contraption.text_2": "...稼働した場所ごとに稼働し、からくり内の収納ブロックのアイテムを使用します", "create.ponder.deployer_contraption.text_3": "フィルタースロットを使って、どのアイテムを使用するか指定できます", - "create.ponder.deployer_modes.header": "デプロイヤーのモード", + "create.ponder.deployer_modes.header": "デプロイヤーの動作モード", "create.ponder.deployer_modes.text_1": "デフォルトでは、デプロイヤーは右クリックの動作を模倣します", "create.ponder.deployer_modes.text_2": "レンチを使えば、左クリックの動作を模倣するように設定できます", + "create.ponder.deployer_processing.header": "デプロイヤーによるアイテムの処理", + "create.ponder.deployer_processing.text_1": "装着されたアイテムで、デプロイヤーの先にあるアイテムを処理することができます", + "create.ponder.deployer_processing.text_2": "加工したいアイテムはドロップしたり、デプロイヤーの下のデポに置いてください", + "create.ponder.deployer_processing.text_3": "ベルトでアイテムを供給すると", + "create.ponder.deployer_processing.text_4": "デプロイヤーが自動でアイテムを止め、加工します。", + "create.ponder.deployer_redstone.header": "レッドストーン信号によるデプロイヤーの制御", "create.ponder.deployer_redstone.text_1": "レッドストーン信号を受けている間、デプロイヤーは稼働しません", "create.ponder.deployer_redstone.text_2": "デプロイヤーは停止する前に、開始したサイクルは終了させます", - "create.ponder.deployer_redstone.text_3": "その為、オフのパルス信号を使って丁度1サイクルだけ稼働させられます", + "create.ponder.deployer_redstone.text_3": "その為、反転したパルス信号を使って丁度1サイクルだけ稼働させられます", "create.ponder.depot.header": "デポの使い方", "create.ponder.depot.text_1": "デポは動かないメカニカルベルトのようなブロックです", - "create.ponder.depot.text_2": "右クリックして、手動でのアイテム搬出入できます", + "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_1": "空のバーナーでブレイズを右クリックすると捕獲できます", "create.ponder.empty_blaze_burner.text_2": "また、ブレイズはスポーンブロックから直接捕獲することもできます", - "create.ponder.empty_blaze_burner.text_3": "これで、様々な機械で利用する理想的な熱源が得られます", + "create.ponder.empty_blaze_burner.text_3": "これで、様々な機械で利用できる理想的な熱源が得られます", "create.ponder.empty_blaze_burner.text_4": "空のブレイズバーナーは火打石と打ち金を使って火を付ければ装飾にも使えます", - "create.ponder.empty_blaze_burner.text_5": "しかし、これは加工用の熱源には適していません", + "create.ponder.empty_blaze_burner.text_5": "さらに、魂の宿ったアイテムを使うことで炎を変化させられます", + "create.ponder.empty_blaze_burner.text_6": "しかし、これは加工用の熱源には適していません", + + "create.ponder.encased_fluid_pipe.header": "ケース入り液体パイプ", + "create.ponder.encased_fluid_pipe.text_1": "銅ケーシングで液体パイプを飾ることができます", + "create.ponder.encased_fluid_pipe.text_2": "ただの飾りではなく、ケース入りパイプは接続がロックされます", + "create.ponder.encased_fluid_pipe.text_3": "隣接するブロックの設置や破壊などの更新に反応しなくなります", "create.ponder.fan_direction.header": "ケース入りファンの気流", "create.ponder.fan_direction.text_1": "ケース入りファンは、回転力を利用して気流を生み出します", - "create.ponder.fan_direction.text_2": "気流の強さと方向は、供給される回転力に依存します", + "create.ponder.fan_direction.text_2": "気流の強さと方向は、供給される回転力によって決まります", "create.ponder.fan_processing.header": "ケース付きファンによるアイテム加工", "create.ponder.fan_processing.text_1": "溶岩を通過した気流は、加熱されます", @@ -1706,6 +1841,35 @@ "create.ponder.fan_source.text_1": "ファンを熱源に向けて設置すると、回転力を生成できます", "create.ponder.fan_source.text_2": "レッドストーン信号を受けると、回転力が生成されます", + "create.ponder.fluid_pipe_flow.header": "銅パイプを使った液体の移動", + "create.ponder.fluid_pipe_flow.text_1": "液体パイプは2つ以上の液体源と輸送先を繋ぐことができます", + "create.ponder.fluid_pipe_flow.text_2": "レンチを使うと、まっすぐなパイプに窓を付けられます", + "create.ponder.fluid_pipe_flow.text_3": "窓付きパイプは側面と隣接するパイプとつながりません", + "create.ponder.fluid_pipe_flow.text_4": "メカニカルポンプを使えば液体を輸送できます", + "create.ponder.fluid_pipe_flow.text_5": "はじめは液体が輸送されません", + "create.ponder.fluid_pipe_flow.text_6": "液れが終点まで届くと徐々に輸送されていきます", + "create.ponder.fluid_pipe_flow.text_7": "つまり、パイプブロック自体には液体は物理的に入っていないということです", + + "create.ponder.fluid_pipe_interaction.header": "液体容器の排出と充填", + "create.ponder.fluid_pipe_interaction.text_1": "液体ネットワークは終点でさまざまなブロックとやりとりできます", + "create.ponder.fluid_pipe_interaction.text_2": "液体を溜めることができれば、どのようなブロックでも液体の搬入・搬出ができます", + "create.ponder.fluid_pipe_interaction.text_3": "開いているパイプの端の目の前の液体ブロックは吸い込めます", + "create.ponder.fluid_pipe_interaction.text_4": "また、開いたスペースに液体ブロックを設置できます", + "create.ponder.fluid_pipe_interaction.text_5": "パイプは、いくつかのブロックから直接液体を吸い込めます", + + "create.ponder.fluid_tank_sizes.header": "液体タンクのサイズ", + "create.ponder.fluid_tank_sizes.text_1": "液体タンクは複数組み合わせて容量を増やせます。", + "create.ponder.fluid_tank_sizes.text_2": "横幅は最大3ブロック", + "create.ponder.fluid_tank_sizes.text_3": "高さは30ブロック以上重ねられます", + "create.ponder.fluid_tank_sizes.text_4": "レンチを使って、タンクの窓を付け外しできます", + + "create.ponder.fluid_tank_storage.header": "液体タンクへの液体の貯蔵", + "create.ponder.fluid_tank_storage.text_1": "液体タンクは大量の液体を貯蔵することができます", + "create.ponder.fluid_tank_storage.text_2": "どの方向からでも液体を搬出入できます", + "create.ponder.fluid_tank_storage.text_3": "コンパレーターで液体量を測れます", + "create.ponder.fluid_tank_storage.text_4": "しかし、サバイバルモードでは手動で液体を出し入れできません。", + "create.ponder.fluid_tank_storage.text_5": "鉢、アイテム排液口、アイテム注液口などを使えばアイテムから液体を出し入れできます。", + "create.ponder.flywheel.header": "勢車による回転力の生成", "create.ponder.flywheel.text_1": "かまどエンジンで回転力を生成するには、勢車が必要です", "create.ponder.flywheel.text_2": "これによって生成される回転力は、非常に大きな応力許容量を持っています", @@ -1718,9 +1882,9 @@ "create.ponder.funnel_compat.text_4": "アイテム排液口など", "create.ponder.funnel_direction.header": "運搬の方向", - "create.ponder.funnel_direction.text_1": "通常の配置では、収納ブロックからアイテムを搬出ます", + "create.ponder.funnel_direction.text_1": "通常の配置では、収納ブロックからアイテムを搬出します", "create.ponder.funnel_direction.text_2": "スニークしながら設置すると、収納ブロックにアイテムを搬入します", - "create.ponder.funnel_direction.text_3": "レンチを使って、設置後にファンネルのモードを変えられます", + "create.ponder.funnel_direction.text_3": "レンチを使って、設置後にファンネルの動作モードを変えられます", "create.ponder.funnel_direction.text_4": "ほとんどの方向で同じことができます", "create.ponder.funnel_direction.text_5": "ベルト上のファンネルは、ベルトの移動方向に応じて搬入/搬出が決まります", @@ -1741,18 +1905,18 @@ "create.ponder.furnace_engine.text_3": "溶鉱炉を使うと、エンジンの効率が2倍になります", "create.ponder.gantry_carriage.header": "ガントリーキャリッジの使い方", - "create.ponder.gantry_carriage.text_1": "ガントリーキャリッジは、ガントリーシャフトに取り付けてスライドさせられます", - "create.ponder.gantry_carriage.text_2": "ガントリーの仕掛けは、取り付けたブロックを動かせます", + "create.ponder.gantry_carriage.text_1": "ガントリーキャリッジは、ガントリーシャフトに取り付けてスライドできます", + "create.ponder.gantry_carriage.text_2": "ガントリーは、取り付けられたブロックを動かします", - "create.ponder.gantry_cascaded.header": "立体ガンドリー", + "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_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_3": "また、シャフトの回転方向によっても決まります", "create.ponder.gantry_direction.text_4": "キャリッジへ伝達する回転力も同じルールが適用されます", "create.ponder.gantry_redstone.header": "ガントリーでの回転力の伝播", @@ -1766,11 +1930,11 @@ "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.gearbox.text_3": "直角に曲げて伝達すると、鏡映しの方向に回転します", + "create.ponder.gearbox.text_4": "まっすぐ伝達すると、回転方向が逆になります", "create.ponder.gearshift.header": "ギアシフトによる回転力の制御", - "create.ponder.gearshift.text_1": "ギアシフトは、直線に回転を伝達します", + "create.ponder.gearshift.text_1": "ギアシフトは、まっすぐ回転を伝達します", "create.ponder.gearshift.text_2": "レッドストーン信号を受けると、回転方向を逆に伝達します", "create.ponder.hand_crank.header": "ハンドクランクによる回転力の生成", @@ -1779,6 +1943,34 @@ "create.ponder.hand_crank.text_3": "回転速度は比較的速めです", "create.ponder.hand_crank.text_4": "スニークしながら右クリックし続けると、時計回りに回転します", + "create.ponder.hose_pulley.header": "ホースプーリーを使った液体の吸入・放出", + "create.ponder.hose_pulley.text_1": "ホースプーリーは、大規模な液体の吸入や放出に使います", + "create.ponder.hose_pulley.text_2": "回転力の入出口はプーリーのホースの高さを変えるのに使います", + "create.ponder.hose_pulley.text_3": "回転方向を逆にするとプーリーが収納されます", + "create.ponder.hose_pulley.text_4": "反対側にはパイプを接続できます", + "create.ponder.hose_pulley.text_5": "接続された液体ネットワークはプーリーに液体を供給し、放出できます", + "create.ponder.hose_pulley.text_6": "また、プーリーから吸い出し、代わりに吸入することもできます", + "create.ponder.hose_pulley.text_7": "プーリーの吸入・放出速度は液体ネットワークの性能で決まります", + + "create.ponder.hose_pulley_infinite.header": "大規模な液体の無限の吸入・放出", + "create.ponder.hose_pulley_infinite.text_1": "ホースプーリーを十分に大きな海に設置すると", + "create.ponder.hose_pulley_infinite.text_2": "海に影響を与えずに液体を吸入・放出できます", + "create.ponder.hose_pulley_infinite.text_3": "つまり、液体ネットワークはこのプーリーから液体を無限に出し入れできます", + + "create.ponder.hose_pulley_level.header": "ホースプーリーの吸入・放出レベル", + "create.ponder.hose_pulley_level.text_1": "完全に収納された状態では、ホースプーリーは稼働しません", + "create.ponder.hose_pulley_level.text_2": "上から下に水を吸入します", + "create.ponder.hose_pulley_level.text_3": "表面の高さはホースのすぐ下になります", + "create.ponder.hose_pulley_level.text_4": "下から上に向かって放出します", + "create.ponder.hose_pulley_level.text_5": "ホースの端より上に放出されることはありません", + + "create.ponder.item_drain.header": "アイテム排液口で液体容器を空にする", + "create.ponder.item_drain.text_1": "アイテム排液口はアイテムから液体を取り出せます", + "create.ponder.item_drain.text_2": "右クリックすると、持っているアイテムの中の液体を注ぐことができます", + "create.ponder.item_drain.text_3": "横からアイテムを入れると...", + "create.ponder.item_drain.text_4": "...中に詰まった液体を出しながら横に転がっていきます", + "create.ponder.item_drain.text_5": "液体ネットワークで、排液口から液体を取り出せます", + "create.ponder.large_cogwheel.header": "大きな歯車による回転力の伝達", "create.ponder.large_cogwheel.text_1": "大きな歯車は、直角に接続できます", "create.ponder.large_cogwheel.text_2": "回転力の回転軸を変えてに伝達するのに役立ちます", @@ -1789,12 +1981,12 @@ "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_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_1": "リニアシャーシは、隣の同じ種類のシャーシと繋がります", "create.ponder.linear_chassis_group.text_2": "からくり機械で1つを動かすと、他のリニアシャーシも一緒に動きます", "create.ponder.linear_chassis_group.text_3": "異なる種類のシャーシや、別の方向を向いているシャーシは接続されません", @@ -1819,7 +2011,7 @@ "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_3": "アームは複数の有効な搬出先が設定されていると...", "create.ponder.mechanical_arm_modes.text_4": "...設定に従ってアイテムを分配します", "create.ponder.mechanical_arm_modes.text_5": "レンチを持ってスクロールすると設定を変えられます", "create.ponder.mechanical_arm_modes.text_6": "「順繰り分配」は、有効な全ての搬出先へ順番に搬出します", @@ -1833,8 +2025,8 @@ "create.ponder.mechanical_arm_redstone.text_3": "それを利用し、反転したパルス信号を使って1回だけ稼働させられます", "create.ponder.mechanical_bearing.header": "メカニカルベアリングによる構造物の移動", - "create.ponder.mechanical_bearing.text_1": "メカニカルベアリングは、前方にブロックを取り付けられます", - "create.ponder.mechanical_bearing.text_2": "回転力を供給すると、組み立てた構造物を回転できます", + "create.ponder.mechanical_bearing.text_1": "メカニカルベアリングは、手前にブロックを取り付けられます", + "create.ponder.mechanical_bearing.text_2": "回転力を供給すると、組み立てた構造物を回せます", "create.ponder.mechanical_crafter.header": "メカニカルクラフターの配置", "create.ponder.mechanical_crafter.text_1": "メカニカルクラフターは、あらゆるクラフトレシピを自動化できます", @@ -1858,7 +2050,7 @@ "create.ponder.mechanical_drill.header": "メカニカルドリルでブロックを破壊する", "create.ponder.mechanical_drill.text_1": "メカニカルドリルは回転力を供給すると、目の前のブロックを破壊します", - "create.ponder.mechanical_drill.text_2": "採掘速度は回転速度に依存します", + "create.ponder.mechanical_drill.text_2": "採掘速度は回転速度で決まります", "create.ponder.mechanical_drill_contraption.header": "からくりに組み込んでのメカニカルドリルの使い方", "create.ponder.mechanical_drill_contraption.text_1": "からくりの一部として、メカニカルドリルを動かすと...", @@ -1872,34 +2064,49 @@ "create.ponder.mechanical_mixer.text_1": "ミキサーと鉢があれば、いくつかのクラフトレシピを自動化できます", "create.ponder.mechanical_mixer.text_2": "自動化できるのは不定形レシピといくつかの追加レシピです", "create.ponder.mechanical_mixer.text_3": "レシピの中には、ブレイズバーナーの熱を必要とするものもあります", - "create.ponder.mechanical_mixer.text_4": "フィルタースロットは、2つのレシピが競合する場合に使えます", + "create.ponder.mechanical_mixer.text_4": "フィルタースロットは、2つのレシピが競合するときに使えます", "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.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_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_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.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": "フィルタースロットは、2つのレシピが競合する場合に使えます", + "create.ponder.mechanical_press_compacting.text_4": "フィルタースロットは、2つのレシピが競合するときに使えます", + + "create.ponder.mechanical_pump_flow.header": "メカニカルポンプによる液体輸送", + "create.ponder.mechanical_pump_flow.text_1": "メカニカルポンプは、接続されたネットワークの液体の流れを制御します", + "create.ponder.mechanical_pump_flow.text_2": "稼働させると、矢印が液体の流れる方向を示します", + "create.ponder.mechanical_pump_flow.text_3": "後ろのネットワークが液体を吸い取っているのに対し...", + "create.ponder.mechanical_pump_flow.text_4": "...前のネットワークが液体を外側に送っています", + "create.ponder.mechanical_pump_flow.text_5": "回転方向を逆にすると、流れの方向が逆になります", + "create.ponder.mechanical_pump_flow.text_6": "レンチを使って手動でポンプの向きを変えることもできます", + + "create.ponder.mechanical_pump_speed.header": "メカニカルポンプの輸送速度", + "create.ponder.mechanical_pump_speed.text_1": "速度に関わらず、メカニカルポンプは16ブロック先までのパイプに影響を与えます", + "create.ponder.mechanical_pump_speed.text_2": "回転速度を速くすることで、流れの送られる速度と...", + "create.ponder.mechanical_pump_speed.text_3": "...液体の輸送速度が変わります", + "create.ponder.mechanical_pump_speed.text_4": "液体ネットワーク内のポンプはそれぞれ別の速度で動かすことができます", + "create.ponder.mechanical_pump_speed.text_5": "向きを交互にすることで、流れの方向を揃えることができます", "create.ponder.mechanical_saw_breaker.header": "メカニカルソーによる伐採", "create.ponder.mechanical_saw_breaker.text_1": "メカニカルソーは回転力を供給すると、目の前の木を伐採できます", @@ -1914,7 +2121,7 @@ "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.mechanical_saw_processing.text_5": "フィルターがない場合、ソーは全ての加工を順番に繰り返します", "create.ponder.millstone.header": "石臼でのアイテム加工", "create.ponder.millstone.text_1": "石臼はアイテムを粉砕加工する機械です", @@ -1926,17 +2133,28 @@ "create.ponder.nixie_tube.header": "ニキシー管の使い方", "create.ponder.nixie_tube.text_1": "ニキシー管は受けたレッドストーン信号の強度を表示します", "create.ponder.nixie_tube.text_2": "金床で名付けた名札を使って、好きな文字を表示することもできます", + "create.ponder.nixie_tube.text_3": "染料で右クリックすることで表示の色を変えられます", "create.ponder.piston_pole.header": "ピストン延長ポール", "create.ponder.piston_pole.text_1": "ポールが無いとメカニカルピストンは動きません", "create.ponder.piston_pole.text_2": "後ろに付けたポールの長さによって、伸び縮みする長さが決まります", + "create.ponder.portable_fluid_interface.header": "からくり液体交換", + "create.ponder.portable_fluid_interface.text_1": "移動しているからくりの液体タンクは、どんなパイプでも出し入れできません", + "create.ponder.portable_fluid_interface.text_2": "この機械は、からくりをブロックに戻すことなく液体を出し入れできます", + "create.ponder.portable_fluid_interface.text_3": "1~2ブロックの隙間を開けて2つ目のインターフェースを設置しましょう", + "create.ponder.portable_fluid_interface.text_4": "すれ違ったときに必ず接続されます", + "create.ponder.portable_fluid_interface.text_5": "接続中は、設置されている方のインターフェースはからくり内全てのタンクのように振る舞います", + "create.ponder.portable_fluid_interface.text_6": "液体の搬入と...", + "create.ponder.portable_fluid_interface.text_7": "...搬出ができるます", + "create.ponder.portable_fluid_interface.text_8": "しばらく中身が出し入れされないと、このからくりはまた動き出します", + "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_3": "1~2ブロックの間隔をあけて、2つ目のインターフェースを設置しましょう", "create.ponder.portable_storage_interface.text_4": "両者がすれ違うたびに接続されます", - "create.ponder.portable_storage_interface.text_5": "接続されている間、設置されている方のインターフェースはからくり内全ての収納ブロックのように振る舞います", + "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": "しばらくの間アイテムのやり取りがないと、からくりは稼働を再開します", @@ -1948,19 +2166,19 @@ "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_latch.text_4": "パワードラッチは、手動でもオンオフできます", "create.ponder.powered_toggle_latch.header": "パワードトグルラッチによる信号制御", "create.ponder.powered_toggle_latch.text_1": "パワードトグルラッチはレッドストーン信号で切り替えできるレバーです", "create.ponder.powered_toggle_latch.text_2": "後ろからの信号で切り替えできます", "create.ponder.powered_toggle_latch.text_3": "何度も信号を送るとオンとオフと繰り返します", - "create.ponder.powered_toggle_latch.text_4": "パワードトグルラッチは、手動で切り替えることもできます", + "create.ponder.powered_toggle_latch.text_4": "パワードトグルラッチは、手動でもオンオフもできます", "create.ponder.pulse_repeater.header": "パルスリピーターによる信号制御", "create.ponder.pulse_repeater.text_1": "パルスリピーターは、レッドストーン信号を短縮して1tickのパルス信号にします", "create.ponder.radial_chassis.header": "ラジアルシャーシによるブロックの取り付け", - "create.ponder.radial_chassis.text_1": "ラジアルシャーシは、同種のシャーシブロックと繋がります", + "create.ponder.radial_chassis.text_1": "ラジアルシャーシは、同じ種類のシャーシと繋がります", "create.ponder.radial_chassis.text_2": "からくり機械によって1つが動かされると、他も一緒に動きます", "create.ponder.radial_chassis.text_3": "ラジアルシャーシの側面を粘着面にできます", "create.ponder.radial_chassis.text_4": "もう一度クリックすると、他の全ての面も粘着面になります", @@ -1984,7 +2202,7 @@ "create.ponder.rope_pulley.header": "ローププーリーによる構造物の移動", "create.ponder.rope_pulley.text_1": "ローププーリーは、回転力を供給するとブロックを垂直に動かせます", - "create.ponder.rope_pulley.text_2": "移動の方向と速度は、供給される回転力に依存します", + "create.ponder.rope_pulley.text_2": "移動の方向と速度は、供給される回転力で決まります", "create.ponder.rope_pulley_attachment.header": "プーリーをからくりの一部として動かす", "create.ponder.rope_pulley_attachment.text_1": "プーリーがからくりによって動かされると...", @@ -1993,11 +2211,11 @@ "create.ponder.rope_pulley_modes.header": "ローププーリーの動作モード", "create.ponder.rope_pulley_modes.text_1": "プーリーの動きが止まると、移動した構造物はブロックに戻ります", - "create.ponder.rope_pulley_modes.text_2": "ブロックに戻らないように設定することも、動かし始めた場所でのみブロックに戻るように設定することもできます", + "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.rotation_speed_controller.text_2": "側面のパネルを見ながらスクロールすると、伝達する回転速度を調整できます", "create.ponder.sail.header": "帆による風車の組み立て", "create.ponder.sail.text_1": "帆は、風車を作るのに便利なブロックです", @@ -2011,7 +2229,7 @@ "create.ponder.sequenced_gearshift.header": "シーケンスギアシフトによる回転の制御", "create.ponder.sequenced_gearshift.text_1": "シーケンスギアシフトは、設定されたプログラムに従って回転を伝達します", - "create.ponder.sequenced_gearshift.text_2": "右クリックで設定インターフェースを開けます", + "create.ponder.sequenced_gearshift.text_2": "右クリックで設定画面を開けます", "create.ponder.sequenced_gearshift.text_3": "レッドストーン信号を受けると、設定されたプログラムを実行します", "create.ponder.sequenced_gearshift.text_4": "終了すると止まり、また次のレッドストーン信号を受けると同じように実行します", "create.ponder.sequenced_gearshift.text_5": "レッドストーンコンパレータで、現在の進捗を読み取れます", @@ -2028,22 +2246,36 @@ "create.ponder.smart_chute.text_3": "マウスホイールで搬出するスタック量を指定できます", "create.ponder.smart_chute.text_4": "レッドストーン信号で、スマートシュートを停止させることもできます", + "create.ponder.smart_pipe.header": "スマートパイプによる液体制御", + "create.ponder.smart_pipe.text_1": "スマートパイプは液体の種類によって流れを制御できます", + "create.ponder.smart_pipe.text_2": "搬入元に直接つなげることで、搬出する液体の種類を指定できます", + "create.ponder.smart_pipe.text_3": "フィルタースロットを右クリックして、液体の入ったアイテムを装着して指定することもできます", + "create.ponder.smart_pipe.text_4": "スマートパイプは、パイプネットワークの搬出先に設置すると指定された液体のみを流します", + "create.ponder.speedometer.header": "速度メーターによる動力情報の監視", "create.ponder.speedometer.text_1": "速度メーターは、接続された機械の現在の回転速度を表示します", "create.ponder.speedometer.text_2": "エンジニアのゴーグルを装着していると、より詳細な情報を得られます", "create.ponder.speedometer.text_3": "コンパレータは、速度メーターの測定値に応じたレッドストーン信号を出力します", + "create.ponder.spout_filling.header": "アイテム注液口によるアイテム充填", + "create.ponder.spout_filling.text_1": "注液口は、その下に用意されたアイテムを液体で満たすことができます", + "create.ponder.spout_filling.text_2": "注液口の中身は手動で出し入れすることはできません", + "create.ponder.spout_filling.text_3": "代わりに、パイプを使って液体を供給しましょう", + "create.ponder.spout_filling.text_4": "容器アイテムは、注液口の下のデポに置きましょう", + "create.ponder.spout_filling.text_5": "ベルトでアイテムを供給すると...", + "create.ponder.spout_filling.text_6": "...注液口が自動でアイテムを止め、加工します", + "create.ponder.stabilized_bearings.header": "からくりの角度の固定", - "create.ponder.stabilized_bearings.text_1": "メカニカルベアリングが動いている構造物に組み込まれているとき ...", + "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.sticker.text_2": "レッドストーン信号を受けると、状態が切り替わります", + "create.ponder.sticker.text_3": "付いているときは、からくりが動かされるとブロックも一緒に動きます", + "create.ponder.sticker.text_4": "もう一度信号を受けると、ブロックは外れます", "create.ponder.stressometer.header": "応力メーターによる動力情報の監視", "create.ponder.stressometer.text_1": "応力メーターは、接続された動力ネットワークの現在の応力許容量を表示します", @@ -2064,6 +2296,12 @@ "create.ponder.valve_handle.text_4": "スニーク状態で右クリックし続けると、時計回りに回転します", "create.ponder.valve_handle.text_5": "バルブハンドルは、染色できます", + "create.ponder.valve_pipe.header": "バルブによる液体制御", + "create.ponder.valve_pipe.text_1": "バルブは、液体ネットワークに流れる液体を制御するのに役立ちます", + "create.ponder.valve_pipe.text_2": "回転力で、液体が現在通過できるか制御します", + "create.ponder.valve_pipe.text_3": "開放方向に回転力を与えるとバルブが開きます", + "create.ponder.valve_pipe.text_4": "回転方向を逆にすることでバルブを閉められます", + "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..0042ac488 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: 63", "_": "->------------------------] Game Elements [------------------------<-", @@ -7,10 +7,10 @@ "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.adjustable_pulse_repeater": "가변 펄스 중계기", + "block.create.adjustable_repeater": "가변 중계기", "block.create.analog_lever": "아날로그 레버", - "block.create.andesite_belt_funnel": "안산암 깔때기", + "block.create.andesite_belt_funnel": "안산암 퍼널", "block.create.andesite_bricks": "안산암 벽돌", "block.create.andesite_bricks_slab": "안산암 벽돌 반 블록", "block.create.andesite_bricks_stairs": "안산암 벽돌 계단", @@ -21,28 +21,34 @@ "block.create.andesite_cobblestone_stairs": "안산암 조약돌 계단", "block.create.andesite_cobblestone_wall": "안산암 조약돌 담장", "block.create.andesite_encased_shaft": "안산암 케이스를 씌운 축", - "block.create.andesite_funnel": "안산암 깔때기", + "block.create.andesite_funnel": "안산암 퍼널", "block.create.andesite_pillar": "안산암 기둥", "block.create.andesite_tunnel": "안산암 터널", "block.create.basin": "대야", - "block.create.belt": "컨베이어 벨트", + "block.create.belt": "벨트", "block.create.birch_window": "자작나무 유리창", "block.create.birch_window_pane": "자작나무 유리판", + "block.create.black_nixie_tube": "검은색 닉시관", "block.create.black_sail": "검은색 날개", "block.create.black_seat": "검은색 좌석", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "검은색 밸브 손잡이", "block.create.blaze_burner": "블레이즈 버너", + "block.create.blue_nixie_tube": "파란색 닉시관", "block.create.blue_sail": "파란색 날개", "block.create.blue_seat": "파란색 좌석", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "파란색 밸브 손잡이", - "block.create.brass_belt_funnel": "황동 깔때기", + "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_funnel": "황동 퍼널", "block.create.brass_tunnel": "황동 터널", + "block.create.brown_nixie_tube": "갈색 닉시관", "block.create.brown_sail": "갈색 날개", "block.create.brown_seat": "갈색 좌석", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "갈색 밸브 손잡이", "block.create.cart_assembler": "카트 조립기", "block.create.chiseled_dark_scoria": "조각된 짙은 스코리아", @@ -58,7 +64,7 @@ "block.create.cogwheel": "톱니바퀴", "block.create.content_observer": "정보 감지기", "block.create.controller_rail": "방향 레일", - "block.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "block.create.copper_backtank": "구리 산소통", "block.create.copper_block": "구리 블록", "block.create.copper_casing": "구리 케이스", "block.create.copper_ore": "구리 광석", @@ -68,13 +74,15 @@ "block.create.creative_crate": "크리에이티브 창고", "block.create.creative_fluid_tank": "크리에이티브 탱크", "block.create.creative_motor": "크리에이티브 모터", - "block.create.crimson_window": "UNLOCALIZED: Crimson Window", - "block.create.crimson_window_pane": "UNLOCALIZED: Crimson Window Pane", + "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_nixie_tube": "청록색 닉시관", "block.create.cyan_sail": "청록색 날개", "block.create.cyan_seat": "청록색 좌석", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "청록색 밸브 손잡이", "block.create.dark_oak_window": "짙은 참나무 유리창", "block.create.dark_oak_window_pane": "짙은 참나무 유리판", @@ -109,7 +117,7 @@ "block.create.dolomite_cobblestone_stairs": "백운암 조약돌 계단", "block.create.dolomite_cobblestone_wall": "백운암 조약돌 담장", "block.create.dolomite_pillar": "백운암 기둥", - "block.create.encased_chain_drive": "케이스를 씌운 축", + "block.create.encased_chain_drive": "체인 드라이브", "block.create.encased_fan": "선풍기", "block.create.encased_fluid_pipe": "구리 케이스를 씌운 파이프", "block.create.fancy_andesite_bricks": "장식된 안산암 벽돌", @@ -165,27 +173,32 @@ "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": "액체 파이프", "block.create.granite_bricks": "화강암 벽돌", - "block.create.granite_bricks_slab": "화강함 벽돌 반 블록", - "block.create.granite_bricks_stairs": "화강함 벽돌 계단", - "block.create.granite_bricks_wall": "화강함 벽돌 담장", + "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_nixie_tube": "회색 닉시관", "block.create.gray_sail": "회색 날개", "block.create.gray_seat": "회색 좌석", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "회색 밸브 손잡이", + "block.create.green_nixie_tube": "초록색 닉시관", "block.create.green_sail": "초록색 날개", "block.create.green_seat": "초록색 좌석", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "초록색 밸브 손잡이", "block.create.hand_crank": "핸드 크랭크", + "block.create.haunted_bell": "귀신들린 종", "block.create.honey": "꿀", "block.create.horizontal_framed_glass": "수평 유리", "block.create.horizontal_framed_glass_pane": "수평 유리판", @@ -194,23 +207,30 @@ "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.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.lectern_controller": "독서대 조작기", + "block.create.light_blue_nixie_tube": "하늘핵 닉시관", "block.create.light_blue_sail": "하늘색 날개", "block.create.light_blue_seat": "하늘색 좌석", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "하늘색 밸브 손잡이", + "block.create.light_gray_nixie_tube": "회백색 닉시관", "block.create.light_gray_sail": "회백색 날개", "block.create.light_gray_seat": "회백색 좌석", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "회백색 밸브 손잡이", + "block.create.lime_nixie_tube": "연두색 닉시관", "block.create.lime_sail": "연두색 날개", "block.create.lime_seat": "연두색 좌석", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "연두색 밸브 손잡이", "block.create.limesand": "석회모래", "block.create.limestone": "석회암", @@ -225,12 +245,14 @@ "block.create.limestone_pillar": "석회암 기둥", "block.create.linear_chassis": "어두운 직선 섀시", "block.create.lit_blaze_burner": "불타는 빈 블레이즈 버너", + "block.create.magenta_nixie_tube": "자홍색 닉시관", "block.create.magenta_sail": "자홍색 날개", "block.create.magenta_seat": "자홍색 좌석", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "자홍색 밸브 손잡이", "block.create.mechanical_arm": "기계 팔", "block.create.mechanical_bearing": "베어링", - "block.create.mechanical_crafter": "기계식 조합기", + "block.create.mechanical_crafter": "조합기", "block.create.mechanical_drill": "드릴", "block.create.mechanical_harvester": "수확기", "block.create.mechanical_mixer": "믹서", @@ -246,20 +268,21 @@ "block.create.mossy_andesite": "이끼 낀 안산암", "block.create.mossy_dark_scoria": "이끼 낀 짙은 스코리아", "block.create.mossy_diorite": "이끼 낀 섬록암", - "block.create.mossy_dolomite": "이끼낀 백운암", - "block.create.mossy_gabbro": "이끼낀 반려암", + "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.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_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "주황색 밸브 손잡이", "block.create.ornate_iron_window": "장식된 철 유리창", "block.create.ornate_iron_window_pane": "장식된 철 유리판", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "포장된 풍화된 석회암 반 블록", "block.create.paved_weathered_limestone_stairs": "포장된 풍화된 석회암 계단", "block.create.paved_weathered_limestone_wall": "포장된 풍화된 석회암 담장", + "block.create.peculiar_bell": "황동 종", + "block.create.pink_nixie_tube": "분홍색 닉시관", "block.create.pink_sail": "분홍색 날개", "block.create.pink_seat": "분홍색 좌석", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "분홍색 밸브 손잡이", "block.create.piston_extension_pole": "피스톤 연장 축", "block.create.polished_dark_scoria": "윤나는 짙은 스코리아", @@ -336,18 +362,22 @@ "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.portable_fluid_interface": "액체 인터페이스", + "block.create.portable_storage_interface": "아이템 인터페이스", "block.create.powered_latch": "레드스톤 걸쇠", "block.create.powered_toggle_latch": "레드스톤 토글 걸쇠", "block.create.pulley_magnet": "도르래 자석", - "block.create.pulse_repeater": "펄스 리피터", + "block.create.pulse_repeater": "펄스 중계기", + "block.create.purple_nixie_tube": "보라샥 닉시관", "block.create.purple_sail": "보라색 날개", "block.create.purple_seat": "보라색 좌석", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "보라색 밸브 손잡이", "block.create.radial_chassis": "원형 섀시", + "block.create.red_nixie_tube": "빨간색 닉시관", "block.create.red_sail": "빨간색 날개", "block.create.red_seat": "빨간색 좌석", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "빨간색 밸브 손잡이", "block.create.redstone_contact": "동형 감지기", "block.create.redstone_link": "레드스톤 링크", @@ -356,8 +386,8 @@ "block.create.rope": "밧줄", "block.create.rope_pulley": "밧줄 도르래", "block.create.rotation_speed_controller": "회전 속도 컨트롤러", - "block.create.sail_frame": "풍차 날개 프레임", - "block.create.schematic_table": "청사진 테이블", + "block.create.sail_frame": "풍차 날개 틀", + "block.create.schematic_table": "청사진 탁자", "block.create.schematicannon": "청사진 대포", "block.create.scoria": "스코리아", "block.create.scoria_bricks": "스코리아 벽돌", @@ -373,14 +403,14 @@ "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.spout": "주입기", "block.create.spruce_window": "가문비나무 유리창", "block.create.spruce_window_pane": "가문비나무 유리판", - "block.create.sticker": "UNLOCALIZED: Sticker", - "block.create.sticky_mechanical_piston": "끈끈이 기계식 피스톤", + "block.create.sticker": "부착기", + "block.create.sticky_mechanical_piston": "기계식 끈끈이 피스톤", "block.create.stockpile_switch": "수량 스위치", "block.create.stressometer": "피로도 계측기", "block.create.tiled_glass": "타일 유리", @@ -388,9 +418,9 @@ "block.create.turntable": "돌림판", "block.create.vertical_framed_glass": "수직 유리", "block.create.vertical_framed_glass_pane": "수직 유리판", - "block.create.warped_window": "UNLOCALIZED: Warped Window", - "block.create.warped_window_pane": "UNLOCALIZED: Warped Window Pane", - "block.create.water_wheel": "물레방아", + "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": "풍화된 석회암 벽돌 반 블록", @@ -401,32 +431,40 @@ "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_nixie_tube": "하얀색 닉시관", "block.create.white_sail": "하얀색 날개", "block.create.white_seat": "하얀색 좌석", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "하얀색 밸브 손잡이", "block.create.windmill_bearing": "풍차 베어링", "block.create.wooden_bracket": "나무 지지대", + "block.create.yellow_nixie_tube": "노란색 닉시관", "block.create.yellow_sail": "노란색 날개", "block.create.yellow_seat": "노란색 좌석", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "노란색 밸브 손잡이", - "block.create.zinc_block": "아연 블", + "block.create.zinc_block": "아연 블록", "block.create.zinc_ore": "아연 광석", - "entity.create.contraption": "장치", - "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "enchantment.create.capacity": "저장량", + "enchantment.create.potato_recovery": "대포알 회수", + + "entity.create.contraption": "구조물", + "entity.create.crafting_blueprint": "조합 청사진", + "entity.create.gantry_contraption": "갠트리 구조물", + "entity.create.potato_projectile": "감자포 투사체", "entity.create.seat": "좌석", - "entity.create.stationary_contraption": "고정된 장치", + "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.belt_connector": "벨트", "item.create.blaze_cake": "블레이즈 케이크", "item.create.blaze_cake_base": "블레이즈 케이크 틀", "item.create.brass_hand": "황동 손", @@ -434,16 +472,18 @@ "item.create.brass_nugget": "황동 조각", "item.create.brass_sheet": "황동 판", "item.create.builders_tea": "건축가의 차", - "item.create.chest_minecart_contraption": "상자가 실린 광산 수레 장치", + "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", + "item.create.copper_backtank": "구리 산소통", "item.create.copper_ingot": "구리 주괴", "item.create.copper_nugget": "구리 조각", "item.create.copper_sheet": "구리 판", "item.create.crafter_slot_cover": "조합기 슬롯 덮개", + "item.create.crafting_blueprint": "조합 청사진", + "item.create.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "item.create.crushed_aluminum_ore": "UNLOCALIZED: Crushed Aluminum Ore", "item.create.crushed_brass": "분쇄된 황동", "item.create.crushed_copper_ore": "분쇄된 구리 광석", @@ -458,27 +498,31 @@ "item.create.crushed_tin_ore": "UNLOCALIZED: Crushed Tin Ore", "item.create.crushed_uranium_ore": "UNLOCALIZED: Crushed Uranium Ore", "item.create.crushed_zinc_ore": "분쇄된 아연 광석", - "item.create.diving_boots": "UNLOCALIZED: Diving Boots", - "item.create.diving_helmet": "UNLOCALIZED: Diving Helmet", + "item.create.diving_boots": "다이빙 부츠", + "item.create.diving_helmet": "다이빙 헬멧", "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.furnace_minecart_contraption": "화로가 실린 광산 수레 구조물", "item.create.goggles": "엔지니어의 고글", "item.create.golden_sheet": "금 판", - "item.create.handheld_worldshaper": "휴대용 세계편집기", + "item.create.handheld_worldshaper": "크리에이티브 세계편집기", "item.create.honey_bucket": "꿀 양동이", - "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", - "item.create.integrated_circuit": "집적 회로", + "item.create.honeyed_apple": "꿀 바른 사과", + "item.create.incomplete_cogwheel": "미완성된 톱니바퀴", + "item.create.incomplete_large_cogwheel": "미완성된 큰 톱니바퀴", + "item.create.incomplete_precision_mechanism": "미완성된 정밀 기계장치", "item.create.iron_sheet": "철 판", - "item.create.lapis_sheet": "청금석 판", - "item.create.minecart_contraption": "광산 수레 장치", + "item.create.linked_controller": "레드스톤 링크 조작기", + "item.create.minecart_contraption": "광산 수레 구조물", "item.create.minecart_coupling": "광산 수레 커플링", "item.create.polished_rose_quartz": "윤나는 장밋빛 석영", + "item.create.potato_cannon": "감자포", "item.create.powdered_obsidian": "흑요석 가루", + "item.create.precision_mechanism": "정밀 기계장치", "item.create.propeller": "프로펠러", "item.create.red_sand_paper": "붉은 사포", "item.create.refined_radiance": "정제된 광채", @@ -488,7 +532,7 @@ "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": "대칭의 지팡이", @@ -501,30 +545,30 @@ "_": "->------------------------] Advancements [------------------------<-", - "advancement.create.root": "Create모드에 어서오세요", - "advancement.create.root.desc": "멋진 장치들을 만들 시간입니다!", - "advancement.create.andesite_alloy": "합금..?", + "advancement.create.root": "Create!", + "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.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.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.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.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": "지열 난방기", @@ -538,43 +582,43 @@ "advancement.create.goggles": "피로돋보기", "advancement.create.goggles.desc": "장치에 대한 운동 정보를 가져다 줄 고글을 만드세요.", "advancement.create.speedometer": "근데 얼마나 빨라?", - "advancement.create.speedometer.desc": "속도 계측기를 가동하세요. 고글을 통해 수치가 얼마나 되는지 보세요.", + "advancement.create.speedometer.desc": "속도 계측기를 작동하세요. 고글을 통해 수치가 얼마나 되는지 보세요.", "advancement.create.stressometer": "근데 얼마나 피로해?", - "advancement.create.stressometer.desc": "피로도 계측기를 가동하세요. 고글을 통해 수치가 얼마나 되는지 보세요.", - "advancement.create.aesthetics": "짠! 예술!", + "advancement.create.stressometer.desc": "피로도 계측기를 작동하세요. 고글을 통해 수치가 얼마나 되는지 보세요.", + "advancement.create.aesthetics": "미적 감각!", "advancement.create.aesthetics.desc": "축, 파이프, 톱니바퀴에 지지대를 설치하세요.", - "advancement.create.reinforced": "짠! 강화!", + "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.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.millstone.desc": "멧돌을 설치하고 작동시키세요.", + "advancement.create.windmill": "산들 바람", "advancement.create.windmill.desc": "풍차 베어링을 작동시키세요.", - "advancement.create.maxed_windmill": "강한 바람", + "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.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": "삐-빅", "advancement.create.electron_tube.desc": "전지 튜브를 만드세요. 발전된 장치들에 쓰입니다.", - "advancement.create.mechanical_saw": "벌목기 가동", - "advancement.create.mechanical_saw.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.mixer.desc": "대야 위에 믹서를 설치하고, 작동시켜 재료를 만드세요.", "advancement.create.blaze_burner": "살아있는 불", "advancement.create.blaze_burner.desc": "블레이즈 버너를 얻으세요.", "advancement.create.compact": "자동 압축", @@ -586,46 +630,46 @@ "advancement.create.copper_casing": "구리 시대", "advancement.create.copper_casing.desc": "구리 판을 이용해 구리 케이스를 만드세요.", "advancement.create.spout": "쪼르록", - "advancement.create.spout.desc": "수도꼭지가 아이템에 액체를 채우는 것을 보세요.", + "advancement.create.spout.desc": "주입기를 사용하여 아이템에 액체를 채우세요.", "advancement.create.spout_potion": "대규모 양조", - "advancement.create.spout_potion.desc": "수도꼭지가 병에 포션을 채우는 것을 보세요.", + "advancement.create.spout_potion.desc": "주입기를 사용하여 유리병에 물약을 채우세요.", "advancement.create.chocolate": "상상의 세계", - "advancement.create.chocolate.desc": "양동이에 녹은 초콜릿을 채우세요.", + "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.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": "지옥을 흡수하다", "advancement.create.infinite_lava.desc": "무한으로 인식되는 용암 웅덩이에서 용암을 끌어올리세요.", "advancement.create.infinite_chocolate": "상상 속에 잠기다", - "advancement.create.infinite_chocolate.desc": "무한으로 인식되는 초콜릿 웅덩이에서 초콜릿을 끌어올리세요..", + "advancement.create.infinite_chocolate.desc": "무한으로 인식되는 초콜릿 웅덩이에서 초콜릿을 끌어올리세요.", "advancement.create.crafter": "자동 조합", - "advancement.create.crafter.desc": "기계식 조합기를 설치하고 가동시키세요.", + "advancement.create.crafter.desc": "기계식 조합기를 설치하고 작동시키세요.", "advancement.create.clockwork_bearing": "시계 제작", "advancement.create.clockwork_bearing.desc": "시계 베어링에 구조물을 달고 작동시키세요.", - "advancement.create.nixie_tube": "스타일있게 표시하기", - "advancement.create.nixie_tube.desc": "디지털 표시등을 얻고 설치하세요.", + "advancement.create.nixie_tube": "나는 스타일있게 표시해", + "advancement.create.nixie_tube.desc": "닉시관을 만들고 설치하세요.", "advancement.create.deployer": "찌르고, 설치하고, 공격!", - "advancement.create.deployer.desc": "당신의 분신, 배포기를 설치하고 가동시키세요.", + "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": "정말정말 높은 피로", "advancement.create.overstress_flywheel.desc": "화로 엔진을 과부하하세요.", - "advancement.create.integrated_circuit": "복잡한 계산", - "advancement.create.integrated_circuit.desc": "집적 회로를 제작하세요.", - "advancement.create.mechanical_arm": "할일이 많아!", + "advancement.create.precision_mechanism": "복잡한 호기심", + "advancement.create.precision_mechanism.desc": "정밀 기계장치를 조립하세요.", + "advancement.create.mechanical_arm": "바쁘다 바빠!", "advancement.create.mechanical_arm.desc": "기계 팔을 조합하고, 입력부와 출력부를 정하고, 설치한 다음 돌리세요. 그리고 그것이 작동하는 것을 보세요.", "advancement.create.musical_arm": "볼륨 최대로!", "advancement.create.musical_arm.desc": "기계 팔이 주크박스를 작동시키는 것을 보세요.", @@ -637,20 +681,22 @@ "advancement.create.fist_bump.desc": "두 배포기를 서로 부딫치게 하세요.", "advancement.create.crushing_wheel": "한 쌍의 거인들", "advancement.create.crushing_wheel.desc": "더 많은 재료를 더 효율적으로 갈 분쇄 휠을 만드세요.", - "advancement.create.blaze_cake": "설탕 러시", + "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": "공허에서의 복귀", "advancement.create.shadow_steel.desc": "무의 금속, 그림자 강철을 생성하세요.", - "advancement.create.refined_radiance": "빛으로 제련되다", + "advancement.create.refined_radiance": "빛으로부터의 자극", "advancement.create.refined_radiance.desc": "강력한 색채 물질, 정제된 빛을 생성하세요.", "advancement.create.chromatic_age": "양극 시대", "advancement.create.chromatic_age.desc": "빛과 어둠의 케이스를 제작하세요.", "advancement.create.wand_of_symmetry": "빛나는 건축", "advancement.create.wand_of_symmetry.desc": "대칭의 지팡이를 만드세요.", "advancement.create.extendo_grip": "띠요오옹!", - "advancement.create.extendo_grip.desc": "외장형 연장 팔을 드세요.", + "advancement.create.extendo_grip.desc": "외장형 연장 팔을 손에 쥐세요.", + "advancement.create.potato_cannon": "퐁!", + "advancement.create.potato_cannon.desc": "감자포로 적을 처치하세요.", "advancement.create.dual_extendo_grip": "궁극의 띠용!", "advancement.create.dual_extendo_grip.desc": "쌍으로 외장형 연장 팔을 들어 인간을 뛰어넘은 사거리를 가지세요.", "advancement.create.eob": "End of Beta", @@ -662,18 +708,34 @@ "itemGroup.create.base": "Create", "itemGroup.create.palettes": "Create 팔레트", - "death.attack.create.crush": "%1$s이(가) 분쇄 휠에 의해 가공되었습니다", - "death.attack.create.fan_fire": "%1$s이(가) 뜨거운 바람에 의해 익어버렸습니다", - "death.attack.create.fan_lava": "%1$s이(가) 용암 바람으로 구워졌습니다", + "death.attack.create.crush": "%1$s이(가) 분쇄 휠로 가공되었습니다", + "death.attack.create.crush.player": "%1$s이(가) %2$s 때문에 분쇄 휠에서 가공되었습니다", + "death.attack.create.fan_fire": "%1$s이(가) 뜨거운 바람에 익어버렸습니다", + "death.attack.create.fan_fire.player": "%1$s이(가) %2$s 때문에 뜨거운 바람으로 익어버렸습니다", + "death.attack.create.fan_lava": "%1$s이(가) 용암 바람으로 제가 되었습니다", + "death.attack.create.fan_lava.player": "%1$s이(가) %2$s 때문에 용암 바람으로 재가 되었습니다", "death.attack.create.mechanical_drill": "%1$s이(가) 드릴에 관통당했습니다", + "death.attack.create.mechanical_drill.player": "%1$s이(가) %2$s 때문에 드릴에 관통당했습니다", "death.attack.create.mechanical_saw": "%1$s이(가) 톱날에 반으로 갈라져 죽었습니다", + "death.attack.create.mechanical_saw.player": "%1$s이(가) %2$s 때문에 톱날에 반으로 갈라져 죽었습니다", + "death.attack.create.potato_cannon": "%1$s이(가) %2$s의 감자포에 맞고 죽었습니다.", + "death.attack.create.potato_cannon.item": "%1$s이(가) %3$s을(를) 사용한 %2$s에게 맞아 죽었습니다.", "death.attack.create.cuckoo_clock_explosion": "%1$s이(가) 조작된 뻐꾸기 시계에 의해 폭파당했습니다", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s이(가) 조작된 뻐꾸기 시계에 의해 폭파당했습니다", "create.block.deployer.damage_source_name": "배포기", - "create.block.cart_assembler.invalid": "카트조립기를 레일 위에 설치하세요", + "create.block.cart_assembler.invalid": "카트 조립기를 레일 위에 설치하세요", + + "create.menu.return": "메뉴로 돌아가기", + "create.menu.configure": "설정...", + "create.menu.ponder_index": "분석 메뉴", + "create.menu.only_ingame": "일시 정지 메뉴에서 가능합니다", + "create.menu.project_page": "Curseforge 페이지", + "create.menu.report_bugs": "버그 제보하기", + "create.menu.support": "후원하기", "create.recipe.crushing": "분쇄", - "create.recipe.milling": "맷돌질", + "create.recipe.milling": "제분", "create.recipe.fan_washing": "세척", "create.recipe.fan_washing.fan": "물과 선풍기", "create.recipe.fan_smoking": "훈연", @@ -690,16 +752,27 @@ "create.recipe.sawing": "제재", "create.recipe.mechanical_crafting": "기계 조합", "create.recipe.automatic_shaped": "유형 자동 조합", - "create.recipe.block_cutting": "블 절단", - "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", + "create.recipe.block_cutting": "블록 절단", + "create.recipe.wood_cutting": "나무 절단", "create.recipe.sandpaper_polishing": "사포질", "create.recipe.mystery_conversion": "?", "create.recipe.spout_filling": "채우기", "create.recipe.draining": "배수", + "create.recipe.sequenced_assembly": "순서 조립", + "create.recipe.assembly.next": "다음 단계: %1$s", + "create.recipe.assembly.step": "단계 %1$s:", + "create.recipe.assembly.progress": "진행도: %1$s/%2$s", + "create.recipe.assembly.pressing": "압착하기", + "create.recipe.assembly.spout_filling_fluid": "%1$s 주입하기", + "create.recipe.assembly.deploying_item": "%1$s 사용하기", + "create.recipe.assembly.cutting": "톱으로 자르기", + "create.recipe.assembly.repeat": "%1$s번 반복하기", + "create.recipe.assembly.junk": "조립 실패한 조각들", "create.recipe.processing.chance": "%1$s%% 확률", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "열이 필요하지 않음", - "create.recipe.heat_requirement.heated": "고온으로 가열됨", - "create.recipe.heat_requirement.superheated": "초고온으로 가열됨", + "create.recipe.heat_requirement.heated": "가열됨", + "create.recipe.heat_requirement.superheated": "초고온 가열됨", "create.generic.range": "범위", "create.generic.radius": "반지름", @@ -725,8 +798,9 @@ "create.action.discard": "삭제", "create.keyinfo.toolmenu": "메뉴 세부정보 보기", - "create.keyinfo.scrollup": "Simulate Mousewheel Up (inworld)", - "create.keyinfo.scrolldown": "Simulate Mousewheel Down (inworld)", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", + "create.keyinfo.scrollup": "마우스 휠을 위로 이동 (인게임에서)", + "create.keyinfo.scrolldown": "마우스 휠을 아래로 이동 (인게임에서)", "create.gui.scrollInput.defaultTitle": "옵션을 선택하세요:", "create.gui.scrollInput.scrollToModify": "스크롤로 수정하기", @@ -735,12 +809,19 @@ "create.gui.scrollInput.shiftScrollsFaster": "쉬프트-스크롤로 빨리 수정하기", "create.gui.toolmenu.focusKey": "[%1$s]를 눌러 세부정보 보기", "create.gui.toolmenu.cycle": "스크롤로 순환", - "create.gui.symmetryWand.mirrorType": "반사", - "create.gui.symmetryWand.orientation": "방위", - "create.symmetry.mirror.plane": "거울 모드", - "create.symmetry.mirror.doublePlane": "사각형 모드", - "create.symmetry.mirror.triplePlane": "팔각형 모드", + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + + "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": "대각선으로", @@ -748,37 +829,37 @@ "create.orientation.alongZ": "Z좌표를 따라", "create.orientation.alongX": "X좌표를 따라", - "create.gui.terrainzapper.title": "휴대용 세계편집기", - "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.placement": "설치방식", + "create.gui.terrainzapper.title": "크리에이티브 세계편집기", + "create.gui.terrainzapper.searchDiagonal": "대각선 블록 포함", + "create.gui.terrainzapper.searchFuzzy": "물질 경계 무시", + "create.gui.terrainzapper.patternSection": "패턴", + "create.gui.terrainzapper.pattern.solid": "기본", + "create.gui.terrainzapper.pattern.checkered": "체스판", + "create.gui.terrainzapper.pattern.inversecheckered": "반전된 체스판", + "create.gui.terrainzapper.pattern.chance25": "랜덤하게 25% 채우기", + "create.gui.terrainzapper.pattern.chance50": "랜덤하게 50% 채우기", + "create.gui.terrainzapper.pattern.chance75": "랜덤하게 75% 채우기", + "create.gui.terrainzapper.placement": "설치 기준", "create.gui.terrainzapper.placement.merged": "선택한 블록에", - "create.gui.terrainzapper.placement.attached": "선택한 블록 옆에", + "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.brush.surface": "UNLOCALIZED: Surface", - "create.gui.terrainzapper.brush.cluster": "UNLOCALIZED: Cluster", - "create.gui.terrainzapper.tool": "도구", + "create.gui.terrainzapper.brush.cylinder": "원기둥", + "create.gui.terrainzapper.brush.surface": "면", + "create.gui.terrainzapper.brush.cluster": "원", + "create.gui.terrainzapper.tool": "설치 방식", "create.gui.terrainzapper.tool.fill": "채우기", - "create.gui.terrainzapper.tool.place": "설치", + "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.gui.terrainzapper.tool.flatten": "다듬기", "create.terrainzapper.shiftRightClickToSet": "쉬프트-우클릭으로 모양 설정하기", - "create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s", - "create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material", + "create.terrainzapper.usingBlock": "사용 중: %1$s", + "create.terrainzapper.leftClickToSet": "좌클릭으로 재료로 쓸 블록을 선택하세요", "create.minecart_coupling.two_couplings_max": "광산 수레는 최대 2개의 커플링만 가질 수 있습니다", "create.minecart_coupling.unloaded": "열차 일부분이 로딩되지 않은 청크에 있는 것 같습니다", @@ -787,18 +868,18 @@ "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.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.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.clock_hands": "시계침", "create.contraptions.clockwork.hour_first": "시침 먼저", "create.contraptions.clockwork.minute_first": "분침 먼저", "create.contraptions.clockwork.hour_first_24": "24시간 바늘 먼저", @@ -806,69 +887,69 @@ "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.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.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.gauge.info_header": "게이지 정보:", + "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": "[%1$s,%2$s,%3$s]에 움직일 수 없는 [%4$s]이(가) 있습니다.", + "create.gui.assembly.exception.chunkNotLoaded": "[%1$s,%2$s,%3$s]에 있는 블록이 로드되지 않은 청크에 있습니다.", + "create.gui.assembly.exception.structureTooLarge": "이 구조물에 너무 많은 블록이 포함되어 있습니다.\n설정된 최댓값: %1$s개", + "create.gui.assembly.exception.tooManyPistonPoles": "이 피스톤에 너무 많은 연장 축이 부착되어 있습니다.\n설정된 최댓값: %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.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.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": "UNLOCALIZED: Turn by angle", - "create.gui.sequenced_gearshift.instruction.turn_angle": "회전", + "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": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", - "create.gui.sequenced_gearshift.instruction.turn_distance": "피스톤", + "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.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.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": "입력된 속도의 2배, 그대로 회전", - "create.gui.sequenced_gearshift.speed.back": "입력된 속도, 반대로 회전", - "create.gui.sequenced_gearshift.speed.back_fast": "입력된 속도의 2배, 반대로 회전", + "create.gui.sequenced_gearshift.speed.forward": "입력 속도, 그대로 회전", + "create.gui.sequenced_gearshift.speed.forward_fast": "입력 속도의 2배, 그대로 회전", + "create.gui.sequenced_gearshift.speed.back": "입력 속도, 반대로 회전", + "create.gui.sequenced_gearshift.speed.back_fast": "입력 속도의 2배, 반대로 회전", - "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.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": "My Schematic", + "create.schematicAndQuill.saved": "%1$s으(로) 저장했습니다", "create.schematic.invalid": "[!] 없는 아이템 - 청사진 테이블을 이용하세요", "create.schematic.position": "위치", @@ -887,12 +968,12 @@ "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.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": "청사진을 수직 이동시킵니다.", @@ -904,7 +985,7 @@ "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.1": "[우클릭]으로 현재 지점에 설치합니다.", "create.schematic.tool.print.description.2": "이 도구는 크리에이티브 모드 전용입니다.", "create.schematic.tool.print.description.3": "", "create.schematic.tool.flip.description.0": "당신이 보는 면으로 청사진을 뒤집습니다.", @@ -914,7 +995,7 @@ "create.schematics.synchronizing": "동기화 중...", "create.schematics.uploadTooLarge": "청사진이 너무 큽니다!.", - "create.schematics.maxAllowedSize": "최대 청사진 파일 크기는:", + "create.schematics.maxAllowedSize": "최대 청사진 파일 크기:", "create.gui.schematicTable.refresh": "파일 새로고침", "create.gui.schematicTable.open_folder": "폴더 열기", @@ -924,7 +1005,7 @@ "create.gui.schematicTable.uploading": "업로딩 중...", "create.gui.schematicTable.finished": "업로드 완료!", "create.gui.schematicannon.title": "청사진 대포", - "create.gui.schematicannon.listPrinter": "재료 목록 프린터", + "create.gui.schematicannon.listPrinter": "재료 목록 인쇄", "create.gui.schematicannon.gunpowderLevel": "화약 용량 %1$s%%", "create.gui.schematicannon.shotsRemaining": "남은 발포 수 : %1$s", "create.gui.schematicannon.shotsRemainingWithBackup": "화약 여분: %1$s", @@ -945,16 +1026,16 @@ "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.gui.schematicannon.option.replaceWithEmpty.description": "대포가 작업구역의 블록들을 제거합니다.", "create.schematicannon.status.idle": "휴식", "create.schematicannon.status.ready": "준비됨", - "create.schematicannon.status.running": "가동 중", + "create.schematicannon.status.running": "작동 중", "create.schematicannon.status.finished": "완료", - "create.schematicannon.status.paused": "멈춤", + "create.schematicannon.status.paused": "일시 중지", "create.schematicannon.status.stopped": "중단됨", "create.schematicannon.status.noGunpowder": "화약이 부족함", - "create.schematicannon.status.targetNotLoaded": "블록이 준비되지 않음", + "create.schematicannon.status.targetNotLoaded": "목표가 없음", "create.schematicannon.status.targetOutsideRange": "목표가 너무 멀리 떨어져 있습니다.", "create.schematicannon.status.searching": "검색 중", "create.schematicannon.status.skipping": "건너뛰는 중", @@ -965,8 +1046,8 @@ "create.schematicannon.status.schematicNotPlaced": "청사진이 전개되지 않음", "create.schematicannon.status.schematicExpired": "청사진 파일이 제거됨", - "create.materialChecklist": "UNLOCALIZED: Material Checklist", - "create.materialChecklist.blocksNotLoaded": "UNLOCALIZED: * Disclaimer *\n\nMaterial List may be inaccurate due to relevant chunks not being loaded.", + "create.materialChecklist": "재료 목록", + "create.materialChecklist.blocksNotLoaded": "* 경고 *\n\n관련된 청크가 불러와지지 않아 재료 목록이 부정확할 수 있습니다.", "create.gui.filter.deny_list": "UNLOCALIZED: Deny-List", "create.gui.filter.deny_list.description": "UNLOCALIZED: Items pass if they do NOT match any of the above. An empty Deny-List accepts everything.", @@ -981,18 +1062,14 @@ "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.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "마법부여됨", "create.item_attributes.enchanted.inverted": "마법부여되지 않음", + "create.item_attributes.max_enchanted": "마법부여가 최고 레벨임", + "create.item_attributes.max_enchanted.inverted": "마법부여가 최고 레벨이 아님", + "create.item_attributes.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "내구도가 닮", "create.item_attributes.damaged.inverted": "내구도가 닳지 않음", "create.item_attributes.badly_damaged": "심각하게 내구도가 닮", @@ -1003,58 +1080,71 @@ "create.item_attributes.equipable.inverted": "장착할 수 없음", "create.item_attributes.furnace_fuel": "화로 연료로 쓸 수 있음", "create.item_attributes.furnace_fuel.inverted": "화로 연료로 쓸 수 없음", + "create.item_attributes.washable": "세척될 수 있음", + "create.item_attributes.washable.inverted": "세척될 수 없음", + "create.item_attributes.crushable": "분쇄될 수 있음", + "create.item_attributes.crushable.inverted": "분쇄될 수 없음", + "create.item_attributes.smeltable": "구워질 수 있음", + "create.item_attributes.smeltable.inverted": "구워질 수 없음", + "create.item_attributes.smokable": "훈연될 수 있음", + "create.item_attributes.smokable.inverted": "훈연될 수 없음", + "create.item_attributes.blastable": "용광로에 녹일 수 있음", + "create.item_attributes.blastable.inverted": "용광로에 녹일 수 없음", + "create.item_attributes.shulker_level": "셜커가 %1$s있음", + "create.item_attributes.shulker_level.inverted": "셜커가 %1$s있지 않음", + "create.item_attributes.shulker_level.full": "가득 차", + "create.item_attributes.shulker_level.empty": "비어", + "create.item_attributes.shulker_level.partial": "조금 차", "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": "UNLOCALIZED: is enchanted with %1$s", - "create.item_attributes.has_enchant.inverted": "UNLOCALIZED: is not enchanted with %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.has_fluid": "UNLOCALIZED: contains %1$s", - "create.item_attributes.has_fluid.inverted": "UNLOCALIZED: does not contain %1$s", - "create.item_attributes.has_name": "UNLOCALIZED: has the custom name %1$s", - "create.item_attributes.has_name.inverted": "UNLOCALIZED: does not have the custom name %1$s", - "create.item_attributes.book_author": "UNLOCALIZED: was authored by %1$s", - "create.item_attributes.book_author.inverted": "UNLOCALIZED: was not authored by %1$s", - "create.item_attributes.book_copy_original": "UNLOCALIZED: is an original", - "create.item_attributes.book_copy_original.inverted": "UNLOCALIZED: is not an original", - "create.item_attributes.book_copy_first": "UNLOCALIZED: is a first-generation copy", - "create.item_attributes.book_copy_first.inverted": "UNLOCALIZED: is not a first-generation copy", - "create.item_attributes.book_copy_second": "UNLOCALIZED: is a second-generation copy", - "create.item_attributes.book_copy_second.inverted": "UNLOCALIZED: is not a second-generation copy", - "create.item_attributes.book_copy_tattered": "UNLOCALIZED: is a tattered mess", - "create.item_attributes.book_copy_tattered.inverted": "UNLOCALIZED: is not a tattered mess", - "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", - "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", - "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", - "create.item_attributes.astralsorcery_amulet": "UNLOCALIZED: improves %1$s", - "create.item_attributes.astralsorcery_amulet.inverted": "UNLOCALIZED: does not improve %1$s", + "create.item_attributes.has_enchant": "%1$s 마법부여를 가지고 있음", + "create.item_attributes.has_enchant.inverted": "%1$s 마법부여를 가지고 있지 않음", + "create.item_attributes.color": "염색됨", + "create.item_attributes.color.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_amulet": "%1$s이(가) 향상됨", + "create.item_attributes.astralsorcery_amulet.inverted": "%1$s이(가) 향상되지 않음", + "create.item_attributes.astralsorcery_constellation": "%1$s에 조율됨", + "create.item_attributes.astralsorcery_constellation.inverted": "%1$s에 조율되지 않음", + "create.item_attributes.astralsorcery_crystal": "%1$s 수정 속성을 가짐", + "create.item_attributes.astralsorcery_crystal.inverted": "%1$s 수정 속성을 가지고 있지 않음", + "create.item_attributes.astralsorcery_perk_gem": "%1$s 퍽 속성을 가짐", + "create.item_attributes.astralsorcery_perk_gem.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": "UNLOCALIZED: Allow-List (Any)", - "create.gui.attribute_filter.allow_list_disjunctive.description": "UNLOCALIZED: Items pass if they have any of the selected attributes.", - "create.gui.attribute_filter.allow_list_conjunctive": "UNLOCALIZED: Allow-List (All)", - "create.gui.attribute_filter.allow_list_conjunctive.description": "UNLOCALIZED: Items pass only if they have ALL of the selected attributes.", - "create.gui.attribute_filter.deny_list": "UNLOCALIZED: Deny-List", - "create.gui.attribute_filter.deny_list.description": "UNLOCALIZED: Items pass if they do NOT have any of the selected attributes.", + "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": "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", + "create.tooltip.speedRequirement": "요구 회전속도: %1$s", "create.tooltip.speedRequirement.none": "없음", "create.tooltip.speedRequirement.medium": "보통", "create.tooltip.speedRequirement.high": "빠름", @@ -1062,7 +1152,7 @@ "create.tooltip.stressImpact.low": "낮음", "create.tooltip.stressImpact.medium": "보통", "create.tooltip.stressImpact.high": "높음", - "create.tooltip.stressImpact.overstressed": "과부하됨", + "create.tooltip.stressImpact.overstressed": "과부하", "create.tooltip.capacityProvided": "피로도 용량: %1$s", "create.tooltip.capacityProvided.low": "적음", "create.tooltip.capacityProvided.medium": "보통", @@ -1070,49 +1160,70 @@ "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.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": "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": "다수의 입력부가 존재할 때", + "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.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.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.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": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.tooltip.chute.contains": "들어있는 아이템: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "분배 중인 아이템:", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "우클릭하여 회수", - "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": "연결 모드 활성화", + "create.linked_controller.press_keybind": "%1$s, %2$s, %3$s, %4$s, %5$s, %6$s 중 하나를 눌러 이 주파수를 해당 조작키에 연결하세요", + "create.linked_controller.key_bound": "%1$s에 주파수가 연결되었습니다", + "create.linked_controller.frequency_slot_1": "조작키: %1$s, 주파수 #1", + "create.linked_controller.frequency_slot_2": "조작키: %1$s, 주파수 #2", + + "create.crafting_blueprint.crafting_slot": "재료 슬롯", + "create.crafting_blueprint.filter_items_viable": "필터도 가능합니다", + "create.crafting_blueprint.display_slot": "전시 슬롯", + "create.crafting_blueprint.inferred": "실제 조합법과 같음", + "create.crafting_blueprint.manually_assigned": "직접 지정함", + "create.crafting_blueprint.secondary_display_slot": "두번째 전시 슬롯", + "create.crafting_blueprint.optional": "추가적", + + "create.potato_cannon.ammo.attack_damage": "%1$s 공격 피해", + "create.potato_cannon.ammo.reload_ticks": "%1$s 재장전 틱", + "create.potato_cannon.ammo.knockback": "%1$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.mechanical_arm_no_targets": "이 _기계 팔_은 _목표_가 설정되지 않았습니다. _기계 팔을 손에 들고_ 벨트, 아이템 거치대, 퍼널을 _우클릭_하여 목표로 지정하세요.", + "create.hint.empty_bearing.title": "베어링 업데이트", "create.hint.empty_bearing": "_맨 손_으로 베어링을 _우클릭_하여 구조물을 _부착_하세요.", - "create.hint.full_deployer.title": "UNLOCALIZED: Deployer Item Overflow", - "create.hint.full_deployer": "UNLOCALIZED: It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", + "create.hint.full_deployer.title": "배포기 아이템 과적", + "create.hint.full_deployer": "이 _배포기_는 _배출_할 아이템을 가지고 있습니다. 호퍼 , 퍼널 등을 이용해 아이템을 빼내세요.", "create.gui.config.overlay1": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", @@ -1131,35 +1242,47 @@ "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": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_too_big": "이 수레 구조물은 들기에 너무 큽니다", + "create.contraption.minecart_contraption_illegal_pickup": "신비로운 힘이 이 수레 구조물을 세계에 묶어두고 있습니다", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "슬라임이 철퍽거림", - "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.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.contraption_disassemble": "구조물이 멈춤", + "create.subtitle.peculiar_bell_use": "황동 종이 울림", + "create.subtitle.mixing": "섞는 소리", + "create.subtitle.mechanical_press_activation_belt": "압착기가 작동함", + "create.subtitle.fwoomp": "감자포를 쏨", + "create.subtitle.worldshaper_place": "세계편집기가 쏨", + "create.subtitle.crushing_1": "분쇄되는 소리", + "create.subtitle.depot_slide": "아이템이 미끄러짐", + "create.subtitle.saw_activate_stone": "톱이 작동함", + "create.subtitle.blaze_munch": "블레이즈 버너가 섭취함", + "create.subtitle.funnel_flap": "퍼널이 펄럭거림", "create.subtitle.schematicannon_finish": "청사진 대포가 끝남", - "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", - "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", + "create.subtitle.haunted_bell_use": "귀신들린 종이 울림", + "create.subtitle.scroll_value": "스크롤 소리", + "create.subtitle.crafter_craft": "조합기가 조합함", + "create.subtitle.controller_put": "조작기를 놓음", + "create.subtitle.cranking": "크랭크가 돌아감", + "create.subtitle.wrench_remove": "장치가 부숴짐", + "create.subtitle.cogs": "톱니바퀴가 돌아감", + "create.subtitle.slime_added": "슬라임이 철퍽거림", + "create.subtitle.wrench_rotate": "렌치를 사용함", + "create.subtitle.potato_hit": "채소가 부딫힘", + "create.subtitle.saw_activate_wood": "톱이 작동함", + "create.subtitle.haunted_bell_convert": "종에 귀신이 들림", + "create.subtitle.deployer_polish": "배포기가 윤나게 함", + "create.subtitle.deny": "취소음", + "create.subtitle.controller_click": "조작기를 누름", + "create.subtitle.schematicannon_launch_block": "청사진 대포가 발사함", + "create.subtitle.copper_armor_equip": "잠수용 장비가 철커덕거림", + "create.subtitle.controller_take": "독서대가 비워짐", + "create.subtitle.mechanical_press_activation": "압착기가 작동함", + "create.subtitle.contraption_assemble": "구조물이 움직임", + "create.subtitle.crafter_click": "조합기가 작동함", + "create.subtitle.depot_plop": "아이템이 놓임", + "create.subtitle.confirm": "확인음", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1179,83 +1302,16 @@ "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": "ENCASED FLUID PIPE", - "block.create.encased_fluid_pipe.tooltip.summary": "_구리 케이스_를 씌운 액체 파이프입니다.", - "block.create.seat.tooltip": "SEAT", - "block.create.seat.tooltip.summary": "앉아서 드라이브를 즐기세요! _움직이는 장치_에 _플레이어_를 _고정_시킵니다. 가구용으로도 좋습니다! 다양한 색깔이 존재합니다.", + "block.create.seat.tooltip.summary": "앉아서 드라이브를 즐기세요! _움직이는 구조물_에 _플레이어_를 _고정_시킵니다. 가구용으로도 좋습니다! 다양한 색깔이 존재합니다.", "block.create.seat.tooltip.condition1": "좌석에 우클릭", "block.create.seat.tooltip.behaviour1": "플레이어가 좌석에 _앉습니다_. _왼쪽 쉬프트_를 눌러 좌석에서 _일어섭니다_.", "item.create.blaze_cake.tooltip": "블레이즈 케이크", - "item.create.blaze_cake.tooltip.summary": "열심히 일하는 _블레이즈_ _버너_의 식사입니다. 그들을 더 화끈하게 만드세요!", - - "block.create.fluid_pipe.tooltip": "FLUID PIPE", - "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.hose_pulley.tooltip": "HOSE PULLEY", - "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": "FLUID TANK", - "block.create.fluid_tank.tooltip.summary": "당신이 좋아하는 _액체_를 모두 _저장_하세요. 넓이와 높이를 조정할 수 있습니다.", - "block.create.fluid_tank.tooltip.condition1": "렌치로 우클릭", - "block.create.fluid_tank.tooltip.behaviour1": "창문 설정을 변경합니다.", - - "block.create.creative_fluid_tank.tooltip": "CREATIVE FLUID TANK", - "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": "FLUID VALVE", - "block.create.fluid_valve.tooltip.summary": "파이프 속 액체의 흐름을 멈춥니다.", - "block.create.fluid_valve.tooltip.condition1": "설정가능한 흐름", - "block.create.fluid_valve.tooltip.behaviour1": "_회전력_은 밸브를 닫게만들어, 액체의 흐름을 _중지_시킵니다. _반대_ _방향의_ 회전력은 밸브를 다시 엽니다.", - - "block.create.mechanical_pump.tooltip": "MECHANICAL PUMP", - "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": "SMART FLUID PIPE", - "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": "SPOUT", - "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": "ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "액체 용기를 _비우기위해_ 철창을 붙인 아이템 거치대입니다.", - "block.create.item_drain.tooltip.condition1": "액체 수송", - "block.create.item_drain.tooltip.behaviour1": "_양동이나 병같은_ 액체 용기가 옆에서 들어오면, 배수구는 자신의 용기에 액체를 _쏟아낼_ 것입니다. 아이템은 반대편으로 배출됩니다.", + "item.create.blaze_cake.tooltip.summary": "열심히 일하는 _블레이즈_ _버너_의 식사입니다. 블레이즈를 더 뜨겁게 만드세요!", "item.create.wand_of_symmetry.tooltip": "SYMMETRY WAND", - "item.create.wand_of_symmetry.tooltip.summary": "설정된 반사 모드에 따라 블록 설치를 _똑같이_ _재현_합니다.", + "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": "땅에다 우클릭", @@ -1283,9 +1339,18 @@ "item.create.extendo_grip.tooltip.summary": "띠요오옹! 사용자의 _사거리_를 늘려줍니다.", "item.create.extendo_grip.tooltip.condition1": "다른 손에 있을 때", "item.create.extendo_grip.tooltip.behaviour1": "_기존_ _손_에있는 아이템의 사거리를 늘립니다.", + "item.create.extendo_grip.tooltip.condition2": "구리 산소통을 착용했을 때", + "item.create.extendo_grip.tooltip.behaviour2": "_내구도_가 _소모되지_ _않고_, 탱크에서 _공기_가 _소모됩니다_.", + + "item.create.potato_cannon.tooltip": "POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "퐁! 집에서 키운 작물로 적을 처치하세요! _구리_ _산소통_의 산소로 움직일 수 있습니다.", + "item.create.potato_cannon.tooltip.condition1": "우클릭", + "item.create.potato_cannon.tooltip.behaviour1": "_인벤토리_에서 적당한 아이템을 _쏩니다_.", + "item.create.potato_cannon.tooltip.condition2": "구리 산소통을 착용했을 때", + "item.create.potato_cannon.tooltip.behaviour2": "_내구도_가 _소모되지_ _않고_, 탱크에서 _공기_가 _소모됩니다_.", "item.create.filter.tooltip": "FILTER", - "item.create.filter.tooltip.summary": "장치의 _입력_과 _출력_을 필터 _아이템_ 목록에 따라 _조정_합니다.", + "item.create.filter.tooltip.summary": "장치의 _입력_과 _출력_을 _필터_ 목록에 따라 _조정_합니다.", "item.create.filter.tooltip.condition1": "필터 슬롯에 있을 때", "item.create.filter.tooltip.behaviour1": "필터 _설정_에 따라 아이템 흐름을 _조정_합니다.", "item.create.filter.tooltip.condition2": "우클릭", @@ -1303,7 +1368,7 @@ "item.create.schematic.tooltip": "SCHEMATIC", "item.create.schematic.tooltip.summary": "세계에 구조물을 _홀로그램으로_ 불러와 지정하고 설치합니다. 지정된 홀로그램은 _청사진_ _대포_의 _작업_ _영역_이 됩니다.", - "item.create.schematic.tooltip.condition1": "들고 있을 떄", + "item.create.schematic.tooltip.condition1": "들고 있을 때", "item.create.schematic.tooltip.behaviour1": "UI의 도구로 _변경/설치_ 할 수 있습니다.", "item.create.schematic.tooltip.control1": "웅크린 상태에서 우클릭", "item.create.schematic.tooltip.action1": "정확한 _좌표_ 입력을 위한 창을 엽니다.", @@ -1322,9 +1387,9 @@ "item.create.schematic_and_quill.tooltip.action3": "선택 영역을 리셋하고 _삭제_합니다.", "block.create.schematicannon.tooltip": "SCHEMATICANNON", - "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.summary": "장착된 청사진을 바탕으로 블록들을 _발포_합니다. _화약_을 연료로 사용하고 주변 보관함에서 아이템을 사용합니다.", + "block.create.schematicannon.tooltip.condition1": "우클릭", + "block.create.schematicannon.tooltip.behaviour1": "설정 창을 엽니다.", "block.create.schematic_table.tooltip": "SCHEMATIC TABLE", "block.create.schematic_table.tooltip.summary": "_빈_ _청사진_에 저장된 청사진을 불러옵니다.", @@ -1337,18 +1402,18 @@ "item.create.goggles.tooltip.behaviour1": "해당 장치의 _속도_, _피로도_, _용량_을 레벨에 따라 에 따라 색상 UI를 보여줍니다.", "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.condition3": "액체 용기를 바라볼 때", + "item.create.goggles.tooltip.behaviour3": "_용량_이 얼마나 되는지, _어떤 액체_가 들어있는 지 알려줍니다.", - "item.create.wrench.tooltip": "WRENCH", + "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": "_장치_를 _해체_하고 _즉시_ _인벤토리_로 넣습니다.", + "item.create.wrench.tooltip.action2": "_장치_를 _해체_하고 _즉시_ _보관함_으로 넣습니다.", "block.create.nozzle.tooltip": "NOZZLE", - "block.create.nozzle.tooltip.summary": "덮힌 환풍기 _앞_에 붙여 환풍기의 효과를 _전방_으로 _확대_합니다.", + "block.create.nozzle.tooltip.summary": "선풍기 _앞_에 붙여 선풍기의 효과를 _전방향_으로 _확대_합니다.", "block.create.cuckoo_clock.tooltip": "CUCKOO CLOCK", "block.create.cuckoo_clock.tooltip.summary": "_시간의_ _흐름_을 알고 공간을 _꾸미는_ 데 좋은 공예품입니다.", @@ -1356,33 +1421,44 @@ "block.create.cuckoo_clock.tooltip.behaviour1": "현재 시각을 보여주고 하루에 두 번 울립니다. 점심과 플레이어가 바로 잘 수 있는 저녁에 울립니다.", "block.create.turntable.tooltip": "TURNTABLE", - "block.create.turntable.tooltip.summary": "_회전력_으로 _멀미_를 일으킵니다.", + "block.create.turntable.tooltip.summary": "_동력_으로 _멀미_를 일으킵니다.", - "block.create.portable_fluid_interface.tooltip": "PORTABLE FLUID INTERFACE", - "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.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "stockpile_switch", - "block.create.stockpile_switch.tooltip.summary": "붙어있는 _저장소_에 들어있는 아이템을 기반으로 레드스톤 신호를 보냅니다. 필터도 제공됩니다. _비교기_와 반대로, 수량 스위치는 신호가 반전되는 _임계점_을 조절할 수 있습니다.", - "block.create.stockpile_switch.tooltip.condition1": "우클릭 할 때", - "block.create.stockpile_switch.tooltip.behaviour1": "UI를 엽니다.", + "block.create.stockpile_switch.tooltip.summary": "붙어있는 _보관함_에 들어있는 아이템을 기반으로 레드스톤 신호를 보냅니다. 필터도 제공됩니다. _비교기_와 반대로, 수량 스위치는 신호가 반전되는 _임계점_을 조절할 수 있습니다.", + "block.create.stockpile_switch.tooltip.condition1": "우클릭", + "block.create.stockpile_switch.tooltip.behaviour1": "설정 창을 엽니다.", "block.create.content_observer.tooltip": "CONTENT OBSERVER", - "block.create.content_observer.tooltip.summary": "저장소나 벨트의 아이템을 등록된 _필터_를 이용해 _탐지_합니다. _인벤토리, 벨트, 슈트_ 안에 해당 아이템을 탐지하는 동안, 레드스톤 신호를 보냅니다. _깔대기_가 해당 아이템을 수송하면, _1틱_의 레드스톤 신호를 보냅니다.", + "block.create.content_observer.tooltip.summary": "보관함이나 벨트의 아이템을 등록된 _필터_를 이용해 _탐지_합니다. _보관함, 벨트, 슈트_ 안에 해당 아이템을 탐지하는 동안, 레드스톤 신호를 보냅니다. _퍼널_가 해당 아이템을 수송하면, _1틱_의 레드스톤 신호를 보냅니다.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "ADJUSTABLE CRATE", - "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": "THE ENDLESS CRATE", "block.create.creative_crate.tooltip.summary": "이 상자는 아무 아이템을 _무한히_ 저장합니다. 청사진 대포 옆에 놓을 시 준비물을 _전부_ 공급합니다.", "block.create.creative_crate.tooltip.condition1": "필터에 아이템을 설정할 시", "block.create.creative_crate.tooltip.behaviour1": "선택된 아이템을 _무한정_으로 _빼낼_ 수 있습니다. 대신 _들어간_ 아이템은 _삭제_됩니다.", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "CONTROLLER RAIL", "block.create.controller_rail.tooltip.summary": "_광산 수레_의 _이동속도_를 _세밀하게_ _조정_할 수 있는 _양방향_ _전동 레일_입니다.", "block.create.controller_rail.tooltip.condition1": "레드스톤 신호를 받을 때", @@ -1394,716 +1470,878 @@ "item.create.sand_paper.tooltip.behaviour1": "_다른 손_에있는 아이템과 _바닥에 있는 아이템_을 윤냅니다.", "item.create.builders_tea.tooltip": "BUILDERS TEA", - "item.create.builders_tea.tooltip.summary": "하루를 시작하기에 좋은 음료입니다. _ 새로운 영감_을 줍니다.", + "item.create.builders_tea.tooltip.summary": "하루를 시작하기에 좋은 음료입니다. _새로운 영감_을 줍니다.", "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": "LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "_여섯_ _버튼_으로 _레드스톤_ _링크_와 연결되는 _휴대용_ _조작기_입니다.", + "item.create.linked_controller.tooltip.condition1": "우클릭", + "item.create.linked_controller.tooltip.behaviour1": "조작기를 킵니다. 조작하면서 _움직일_ _수_ _없습니다_.", + "item.create.linked_controller.tooltip.condition2": "웅크리면서 우클릭", + "item.create.linked_controller.tooltip.behaviour2": "_설정_ _창_을 엽니다.", + "item.create.linked_controller.tooltip.condition3": "레드스톤 링크 수신기에 우클릭", + "item.create.linked_controller.tooltip.behaviour3": "_연결_ _모드_를 활성화하고, _여섯_ _버튼_ 중 하나를 눌러 조작기를 주파수와 연결합니다.", + "item.create.linked_controller.tooltip.condition4": "독서대에 우클릭", + "item.create.linked_controller.tooltip.behaviour4": "조작기를 독서대에 올려놓아 쉽게 조작할 수 있습니다. (웅크리면서 우클릭으로 회수헙니다.)", + + "item.create.diving_helmet.tooltip": "DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "_구리_ _산소통_과 함께, 착용자가 물 속에서 _오랫동안_ _호흡_할 수 있게합니다.", + "item.create.diving_helmet.tooltip.condition1": "착용했을 때", + "item.create.diving_helmet.tooltip.behaviour1": "산소통에서 공기를 느리게 빨아들이며 _수중_ _호흡_ 효과를 제공합니다.", + + "item.create.copper_backtank.tooltip": "COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "공기를 옮길 수 있는 _착용가능한_ 탱크입니다.", + "item.create.copper_backtank.tooltip.condition1": "착용했을 때", + "item.create.copper_backtank.tooltip.behaviour1": "필요한 장비에 _공기_를 제공합니다.", + "item.create.copper_backtank.tooltip.condition2": "설치되고 동력으로 회전될 때", + "item.create.copper_backtank.tooltip.behaviour2": "동력 속도에 따라 _공기_를 _모읍니다_.", + + "item.create.diving_boots.tooltip": "DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "해저를 돌아다니기에 적합한 _무거운_ _부츠_ 한 켤레입니다.", + "item.create.diving_boots.tooltip.condition1": "착용했을 때", + "item.create.diving_boots.tooltip.behaviour1": "착용자는 빠르게 가라앉고 _수영_할 수 _없습니다_. 대신 물 속에서 _걷고_, _뛸_ 수 있습니다. 또한 _벨트_에 영향받지 않습니다.", + + "item.create.crafting_blueprint.tooltip": "CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "벽에 설치해 _특정_ _재료_로 더 _쉽게_ _조합_할 수 있습니다. 각 슬롯은 조합법을 나타냅니다.", + "item.create.crafting_blueprint.condition1": "빈 슬롯을 우클릭", + "item.create.crafting_blueprint.behaviour1": "_조합법_과 전시할 아이템을 설정하는 창을 엽니다.", + "item.create.crafting_blueprint.condition2": "설정된 슬롯에 우클릭", + "item.create.crafting_blueprint.behaviour2": "자신의 _인벤토리_에서 해당 슬롯의 _조합법_을 _실행_합니다. _웅크리면서_ 우클릭하면 한 번에 여러개를 조합합니다.", "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.", + "block.create.peculiar_bell.tooltip": "PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "장식을 위한 황동 종입니다. 영혼 불꽃 위에 설치하면 _기이한_ 일이 일어난다고 합니다...", + + "block.create.haunted_bell.tooltip": "HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "지옥의 길잃은 영혼들이 씌인 _저주받은_ 종입니다.", + "block.create.haunted_bell.tooltip.condition1": "들고 있거나 종을 울릴 때", + "block.create.haunted_bell.tooltip.behaviour1": "_적대적_ _몹_이 생성되는 _빛이_ _없는_ 자리를 표시합니다.", "_": "->------------------------] 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.exit": "나가기", + "create.ponder.welcome": "분석 메뉴에 어서오세요", + "create.ponder.categories": "Create에서 둘러볼 수 있는 목록들", + "create.ponder.index_description": "아이콘을 클릭해 관련 아이템과 블록에 대해 알아볼 수 있습니다.", + "create.ponder.index_title": "분석 메뉴 제목", + "create.ponder.shared.rpm16": "16 RPM", + "create.ponder.shared.behaviour_modify_wrench": "이 기능은 렌치를 이용해 변경할 수 있습니다.", + "create.ponder.shared.storage_on_contraption": "구조물에 부착된 보관함은 구조물이 떨어뜨린 아이템을 자동으로 줍습니다.", + "create.ponder.shared.sneak_and": "웅크리기 +", + "create.ponder.shared.rpm8": "8 RPM", + "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm32": "32 RPM", + "create.ponder.shared.rpm16_source": "기본 속도: 16 RPM", + "create.ponder.shared.movement_anchors": "섀시나 강력 접착제를 이용해 큰 구조물도 옮길 수 있습니다.", + "create.ponder.tag.redstone": "레드스톤 부품", + "create.ponder.tag.redstone.description": "레드스톤 공학에 쓰이는 부품입니다.", + "create.ponder.tag.contraption_assembly": "블록 부착 도구", + "create.ponder.tag.contraption_assembly.description": "블록들을 이어 구조물로 만들게해주는 도구와 부품입니다.", + "create.ponder.tag.fluids": "액체 조정", + "create.ponder.tag.fluids.description": "액체를 나르고 사용하는 장치입니다.", + "create.ponder.tag.decoration": "장식", + "create.ponder.tag.decoration.description": "주로 장식 용도로 쓰이는 부품입니다.", + "create.ponder.tag.windmill_sails": "풍차 베어링의 날개", + "create.ponder.tag.windmill_sails.description": "조립되었을 때 풍차 구조물의 동력에 영향을 주는 블록들입니다. 이 블록들은 동일한 효율을 가집니다.", + "create.ponder.tag.arm_targets": "기계 팔의 목표 대상", + "create.ponder.tag.arm_targets.description": "기계 팔이 가져가거나 놓을 곳으로 선택할 수 있는 부품입니다.", + "create.ponder.tag.kinetic_appliances": "동력 장치", + "create.ponder.tag.kinetic_appliances.description": "동력을 사용하는 장치입니다.", + "create.ponder.tag.kinetic_sources": "동력 생산", + "create.ponder.tag.kinetic_sources.description": "동력을 생산하는 장치입니다.", + "create.ponder.tag.movement_anchor": "이동 고정장치", + "create.ponder.tag.movement_anchor.description": "부착된 구조물을 다양한 방법으로 움직이게하는 장치입니다.", + "create.ponder.tag.kinetic_relays": "동력 부품", + "create.ponder.tag.kinetic_relays.description": "동력을 다른 곳으로 연결할 때 도움을 주는 부품입니다.", + "create.ponder.tag.contraption_actor": "구조물 장치", + "create.ponder.tag.contraption_actor.description": "움직이는 구조물에 부착되어 특정 기능을 수행하는 장치입니다.", + "create.ponder.tag.creative": "크리에이티브 모드", + "create.ponder.tag.creative.description": "서바이벌 모드에서는 얻을 수 없는 부품입니다.", + "create.ponder.tag.logistics": "아이템 수송", + "create.ponder.tag.logistics.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": "...터널은 통과하는 아이템 스택에서 1개의 아이템을 분리시킵니다.", + "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_modes.text_3": "조립기 설정에서 회전을 잠갔다면, 구조물은 회전하지 않습니다.", + + "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": "신호를 받으면, 다른 체인 드라이브에 전달되는 속도는 2배가 됩니다.", + "create.ponder.chain_gearshift.text_3": "반대로 벨트 변속기가 직접 회전을 받지 않고 있다면, 변속기의 속도는 절반이 됩니다.", + "create.ponder.chain_gearshift.text_4": "두 가지 경우에도, 같은 줄의 체인 드라이브의 속도는 변속기 속도의 2배가 됩니다.", + "create.ponder.chain_gearshift.text_5": "아날로그 레버를 사용하면, 속도 비율을 1 ~ 2배 사이로 맞출 수 있습니다.", + "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": "엔지니어의 고글로 슈트를 관찰하여 이동 방향을 확인하세요.", + "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": "큰 쪽에서 작은 쪽으로 가는 속도는 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": "크리에이티브 탱크", + "create.ponder.creative_fluid_tank.text_1": "크리에이티브 탱크는 무한히 액체를 공급합니다.", + "create.ponder.creative_fluid_tank.text_2": "액체가 든 용기로 우클릭하여 액체를 채울 수 있습니다.", + "create.ponder.creative_fluid_tank.text_3": "파이프로 탱크에서 액체를 무한히 뽑아낼 수 있습니다.", + "create.ponder.creative_fluid_tank.text_4": "크리에이티브 탱크로 들어가는 모든 액체는 사라집니다.", + + "create.ponder.creative_motor.header": "크리에이티브 모터를 이용해 동력 생산하기", + "create.ponder.creative_motor.text_1": "크리에이티브 모터는 동력을 쉽게 생산, 조절합니다.", + "create.ponder.creative_motor.text_2": "모터 후면을 스크롤해서 모터의 RPM을 조절합니다.", + + "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": "배포기로 아이템 가공하기", + "create.ponder.deployer_processing.text_1": "배포기가 적절한 아이템을 가지고 있으면, 아래 있는 아이템을 가공합니다.", + "create.ponder.deployer_processing.text_2": "가공할 아이템은 배포기 아래에 떨구거나 아이템 거치대에 올려두어야 합니다.", + "create.ponder.deployer_processing.text_3": "아이템이 벨트에 있으면...", + "create.ponder.deployer_processing.text_4": "...압착기가 알아서 아이템 이동을 멈추고 가공합니다.", + + "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.empty_blaze_burner.text_6": "그러나 장치에 쓰일 열원으로는 적합하지 않습니다.", + + "create.ponder.encased_fluid_pipe.header": "파이프에 케이스 씌우기", + "create.ponder.encased_fluid_pipe.text_1": "구리 케이스로 파이프를 꾸밀 수 있습니다.", + "create.ponder.encased_fluid_pipe.text_2": "파이프를 가려주는 것 외에도, 파이프의 방향을 고정시키는 역할도 합니다.", + "create.ponder.encased_fluid_pipe.text_3": "이 파이프는 이제 나중에 추가된 블록에 영향받지 않습니다.", + + "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": "파이프로 액체 옮기기", + "create.ponder.fluid_pipe_flow.text_1": "파이프는 한 종류의 액체만 옮깁니다.", + "create.ponder.fluid_pipe_flow.text_2": "렌치를 이용하여 직선 파이프에 창문을 달 수 있습니다.", + "create.ponder.fluid_pipe_flow.text_3": "창문이 있는 파이프는 옆에 있는 파이프와 연결되지 않습니다.", + "create.ponder.fluid_pipe_flow.text_4": "펌프를 이용하면 파이프로 액체를 옮길 수 있습니다.", + "create.ponder.fluid_pipe_flow.text_5": "처음엔 액체가 빠지지 않습니다.", + "create.ponder.fluid_pipe_flow.text_6": "액체 흐름이 이어지면, 시작 탱크에서 끝 탱크로 액체가 본격적으로 이동합니다.", + "create.ponder.fluid_pipe_flow.text_7": "이렇기 때문에, 파이프는 실질적으로 아무런 액체도 담지 않습니다.", + + "create.ponder.fluid_pipe_interaction.header": "액체 용기를 비우고 채우기", + "create.ponder.fluid_pipe_interaction.text_1": "파이프의 끝은 다양한 블록과 상호작용할 수 있습니다.", + "create.ponder.fluid_pipe_interaction.text_2": "액체를 담을 수 있는 모든 블록은 비우거나 채울 수 있습니다.", + "create.ponder.fluid_pipe_interaction.text_3": "끝 부분에 있는 액체의 원천도 흡수할 수 있으며...", + "create.ponder.fluid_pipe_interaction.text_4": "...비어있는 곳에 액체를 배출할 수도 있습니다.", + "create.ponder.fluid_pipe_interaction.text_5": "다양한 다른 블록에서도 액체를 뽑아낼 수도 있습니다.", + + "create.ponder.fluid_tank_sizes.header": "액체 탱크의 크기", + "create.ponder.fluid_tank_sizes.text_1": "액체 탱크는 여러개 연결하여 용량을 늘릴 수 있습니다.", + "create.ponder.fluid_tank_sizes.text_2": "밑면 너비는 3블록까지 늘릴 수 있습니다.", + "create.ponder.fluid_tank_sizes.text_3": "높이는 32블록까지 가능합니다.", + "create.ponder.fluid_tank_sizes.text_4": "렌치를 이용해 탱크의 창문을 닫을 수 있습니다.", + + "create.ponder.fluid_tank_storage.header": "탱크에 액체 저장하기", + "create.ponder.fluid_tank_storage.text_1": "탱크는 많은 양의 액체를 저장합니다.", + "create.ponder.fluid_tank_storage.text_2": "어느 쪽에서나 파이프로 액체를 넣고 빼낼 수 있습니다.", + "create.ponder.fluid_tank_storage.text_3": "담긴 액체의 양은 비교기로 측정할 수 있습니다.", + "create.ponder.fluid_tank_storage.text_4": "그러나 서바이벌 모드에서는 액체를 직접 빼내고 넣을 순 없습니다.", + "create.ponder.fluid_tank_storage.text_5": "대야, 아이템 배수구, 주입기를 통해 액체를 빼내거나 채울 수 있습니다.", + + "create.ponder.flywheel.header": "플라이휠로 동력 생산하기", + "create.ponder.flywheel.text_1": "플라이휠로 동력을 생산하기 위해선, 화로 엔진이 필요합니다.", + "create.ponder.flywheel.text_2": "플라이휠은 피로도 용량이 매우 높습니다.", + "create.ponder.flywheel.text_3": "용광로를 사용하면 동력 속도가 2배가 됩니다.", + + "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": "용광로를 사용하면 동력 속도가 2배가 됩니다.", + + "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": "호스 도르래로 액체 채우고 비우기", + "create.ponder.hose_pulley.text_1": "호스 도르래는 많은 양의 액체를 채우거나 비울 수 있습니다.", + "create.ponder.hose_pulley.text_2": "동력을 전달하여 호스의 높이를 정합니다.", + "create.ponder.hose_pulley.text_3": "동력 방향이 반전되면 호스는 올라갑니다.", + "create.ponder.hose_pulley.text_4": "반대쪽에는 파이프를 연결할 수 있습니다.", + "create.ponder.hose_pulley.text_5": "연결된 파이프에서 호스로 전달하여 액체를 채우거나...", + "create.ponder.hose_pulley.text_6": "...반대 방향으로 방향을 바꿔 액체를 비울 수 있습니다.", + "create.ponder.hose_pulley.text_7": "호스의 채우거나 비우는 속도는 펌프 속도에 기반합니다.", + + "create.ponder.hose_pulley_infinite.header": "매우 많은 양의 액체를 채우고 비우기", + "create.ponder.hose_pulley_infinite.text_1": "넓은 바다에서 호스 도르래를 작동시키면...", + "create.ponder.hose_pulley_infinite.text_2": "...물 블록을 없애거나 추가하지 않고 액체를 얻거나 버릴 수 있습니다.", + "create.ponder.hose_pulley_infinite.text_3": "파이프로 이런 도르래에서 무한한 액체를 얻을 수 있습니다.", + + "create.ponder.hose_pulley_level.header": "호스 도르래의 채우고 비우는 기준", + "create.ponder.hose_pulley_level.text_1": "호스가 완전히 올라가 있을 때, 도르래는 작동하지 않습니다.", + "create.ponder.hose_pulley_level.text_2": "맨 위부터 비웁니다.", + "create.ponder.hose_pulley_level.text_3": "호스 끝부분 아래의 액체는 그대로 남습니다.", + "create.ponder.hose_pulley_level.text_4": "맨 아래부터 채웁니다.", + "create.ponder.hose_pulley_level.text_5": "호스 끝부분 위는 채우지 않습니다.", + + "create.ponder.item_drain.header": "아이템 배수구로 액체 비우기", + "create.ponder.item_drain.text_1": "배수구는 아이템에서 액체를 비웁니다.", + "create.ponder.item_drain.text_2": "우클릭하여 손에 든 아이템에서 액체를 붓습니다.", + "create.ponder.item_drain.text_3": "아이템이 옆에서 들어온다면...", + "create.ponder.item_drain.text_4": "...아이템은 굴라가며 담긴 액체를 비웁니다.", + "create.ponder.item_drain.text_5": "배수구 탱크에 있는 액체는 파이프로 옮길 수 있습니다.", + + "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": "펌프를 이용해 액체 옮기기", + "create.ponder.mechanical_pump_flow.text_1": "펌프는 연결된 파이프속 흐름을 관리합니다.", + "create.ponder.mechanical_pump_flow.text_2": "동력을 전달받으면 화살표가 흐름의 방향을 알려줍니다.", + "create.ponder.mechanical_pump_flow.text_3": "화살표 뒤의 파이프는 액체를 뽑아내고...", + "create.ponder.mechanical_pump_flow.text_4": "...화살표 앞의 파이프는 액체를 밀어냅니다.", + "create.ponder.mechanical_pump_flow.text_5": "동력 방향을 반전시키면 흐름의 방향도 반전됩니다.", + "create.ponder.mechanical_pump_flow.text_6": "렌치로 펌프 방향 자체를 돌릴 수도 있습니다.", + + "create.ponder.mechanical_pump_speed.header": "펌프의 처리율", + "create.ponder.mechanical_pump_speed.text_1": "동력 속도와는 상관없이 펌프는 16블록 길이의 파이프까지 영향을 미칩니다.", + "create.ponder.mechanical_pump_speed.text_2": "동력 속도를 높이면 액체가 흐르는 속도가 높아지고...", + "create.ponder.mechanical_pump_speed.text_3": "...옮기는 액체의 양도 증가합니다.", + "create.ponder.mechanical_pump_speed.text_4": "펌프는 병렬로 설치할 수 있습니다.", + "create.ponder.mechanical_pump_speed.text_5": "펌프 방향을 바꾸어 흐름의 뱡향을 통일할 수 있습니다.", + + "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.nixie_tube.text_3": "염료를 들고 우클릭하여 색을 바꿀 수 있습니다.", + + "create.ponder.piston_pole.header": "피스톤 연장 축", + "create.ponder.piston_pole.text_1": "연장 축이 없으면, 기계식 피스톤은 움직일 수 없습니다.", + "create.ponder.piston_pole.text_2": "연장 축의 수가 곧 피스톤이 연장할 수 있는 거리입니다.", + + "create.ponder.portable_fluid_interface.header": "구조물 장치의 액체 교환", + "create.ponder.portable_fluid_interface.text_1": "액체 인터페이스는 장치를 멈추지 않아도 탱크와 상호작용할 수 있습니다.", + "create.ponder.portable_fluid_interface.text_2": "UNLOCALIZED: This component can interact with fluid tanks without the need to stop the contraption", + "create.ponder.portable_fluid_interface.text_3": "두 번째 인터페이스를 1~2 블록 띄우고 설치하세요.", + "create.ponder.portable_fluid_interface.text_4": "서로를 마주칠 때마다, 접속을 시도합니다.", + "create.ponder.portable_fluid_interface.text_5": "접속한 상태에서, 블록 상태의 인터페이스는 장치의 모든 탱크와 동일합니다.", + "create.ponder.portable_fluid_interface.text_6": "액체를 넣을 수도 있고...", + "create.ponder.portable_fluid_interface.text_7": "...장치에서 액체를 뺄 수도 있습니다.", + "create.ponder.portable_fluid_interface.text_8": "일정 시간동안 액체가 교환되지 않으면, 장치는 움직입니다.", + + "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": "레드스톤 토글 걸쇠 사용하기", + "create.ponder.powered_toggle_latch.text_1": "레드스톤 토글 걸쇠는 설정 가능한 레버입니다.", + "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": "펄스 중계기는 어느 레드스톤 신호라도 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": "스크롤하여 톱니바퀴에 전달되는 RPM을 조절합니다.", + + "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": "스마트 파이프를 통한 액체 필터", + "create.ponder.smart_pipe.text_1": "스마트 파이프는 필터 기능이 있는 파이프입니다.", + "create.ponder.smart_pipe.text_2": "비울 곳에다 설치하면, 어떤 액체를 뽑아낼지 설정할 수 있습니다.", + "create.ponder.smart_pipe.text_3": "필터 슬롯에 원하는 액체가 담긴 용기를 우클릭하면 됩니다.", + "create.ponder.smart_pipe.text_4": "다른 곳에 설치하면, 스마트 파이프는 맞는 액체만 통과시킵니다.", + + "create.ponder.speedometer.header": "속도 계측기를 통한 정보 확인", + "create.ponder.speedometer.text_1": "속도 계측기는 연결된 장치의 속도를 표시합니다.", + "create.ponder.speedometer.text_2": "고글을 장착하면, 세부 정보를 확인할 수 있습니다.", + "create.ponder.speedometer.text_3": "속도 계측기의 측정값에 따라 비교기가 레드스톤 신호를 내보냅니다.", + + "create.ponder.spout_filling.header": "주입기로 아이템에 액체 채우기", + "create.ponder.spout_filling.text_1": "주입기는 아래있는 아이템을 액체를 채웁니다.", + "create.ponder.spout_filling.text_2": "주입기 탱크는 직접 건드릴 수 없습니다.", + "create.ponder.spout_filling.text_3": "대신, 파이프로 액체를 공급할 수는 있습니다.", + "create.ponder.spout_filling.text_4": "주입기 아래 아이템 거치대에 아이템을 놓아, 액체를 채울 수 있습니다.", + "create.ponder.spout_filling.text_5": "아이템이 벨트에 있으면...", + "create.ponder.spout_filling.text_6": "...주입기가 알아서 아이템 이동을 멈추고 가공합니다.", + + "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": "고글을 장착하면, 세부 정보를 확인할 수 있습니다.", + "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": "밸브로 흐름 조절하기", + "create.ponder.valve_pipe.text_1": "밸브는 파이프 속 액체 흐름을 조절합니다.", + "create.ponder.valve_pipe.text_2": "밸브의 축으로 액체가 통과할 수 있는지 조절합니다.", + "create.ponder.valve_pipe.text_3": "동력을 제공하면 밸브가 열립니다.", + "create.ponder.valve_pipe.text_4": "반대 방향으로 동력을 제공하면 밸브가 닫힙니다.", + + "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/lang/unfinished/nl_nl.json b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json index acb783a8e..fc55f3e62 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: 1805", "_": "->------------------------] Game Elements [------------------------<-", @@ -28,12 +28,16 @@ "block.create.belt": "Mechanische Transportband", "block.create.birch_window": "UNLOCALIZED: Birch Window", "block.create.birch_window_pane": "UNLOCALIZED: Birch Window Pane", + "block.create.black_nixie_tube": "UNLOCALIZED: Black Nixie Tube", "block.create.black_sail": "UNLOCALIZED: Black Sail", "block.create.black_seat": "UNLOCALIZED: Black Seat", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "UNLOCALIZED: Black Valve Handle", "block.create.blaze_burner": "UNLOCALIZED: Blaze Burner", + "block.create.blue_nixie_tube": "UNLOCALIZED: Blue Nixie Tube", "block.create.blue_sail": "UNLOCALIZED: Blue Sail", "block.create.blue_seat": "UNLOCALIZED: Blue Seat", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "UNLOCALIZED: Blue Valve Handle", "block.create.brass_belt_funnel": "UNLOCALIZED: Brass Belt Funnel", "block.create.brass_block": "UNLOCALIZED: Block of Brass", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "UNLOCALIZED: Brass Encased Shaft", "block.create.brass_funnel": "UNLOCALIZED: Brass Funnel", "block.create.brass_tunnel": "UNLOCALIZED: Brass Tunnel", + "block.create.brown_nixie_tube": "UNLOCALIZED: Brown Nixie Tube", "block.create.brown_sail": "UNLOCALIZED: Brown Sail", "block.create.brown_seat": "UNLOCALIZED: Brown Seat", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "UNLOCALIZED: Brown Valve Handle", "block.create.cart_assembler": "Kar Assembler", "block.create.chiseled_dark_scoria": "UNLOCALIZED: Chiseled Dark Scoria", @@ -73,8 +79,10 @@ "block.create.crushing_wheel": "Verpulveraar", "block.create.crushing_wheel_controller": "UNLOCALIZED: Crushing Wheel Controller", "block.create.cuckoo_clock": "UNLOCALIZED: Cuckoo Clock", + "block.create.cyan_nixie_tube": "UNLOCALIZED: Cyan Nixie Tube", "block.create.cyan_sail": "UNLOCALIZED: Cyan Sail", "block.create.cyan_seat": "UNLOCALIZED: Cyan Seat", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "UNLOCALIZED: Cyan Valve Handle", "block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window", "block.create.dark_oak_window_pane": "UNLOCALIZED: Dark Oak Window Pane", @@ -179,13 +187,18 @@ "block.create.granite_cobblestone_stairs": "UNLOCALIZED: Granite Cobblestone Stairs", "block.create.granite_cobblestone_wall": "UNLOCALIZED: Granite Cobblestone Wall", "block.create.granite_pillar": "UNLOCALIZED: Granite Pillar", + "block.create.gray_nixie_tube": "UNLOCALIZED: Gray Nixie Tube", "block.create.gray_sail": "UNLOCALIZED: Gray Sail", "block.create.gray_seat": "UNLOCALIZED: Gray Seat", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "UNLOCALIZED: Gray Valve Handle", + "block.create.green_nixie_tube": "UNLOCALIZED: Green Nixie Tube", "block.create.green_sail": "UNLOCALIZED: Green Sail", "block.create.green_seat": "UNLOCALIZED: Green Seat", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "UNLOCALIZED: Green Valve Handle", "block.create.hand_crank": "UNLOCALIZED: Hand Crank", + "block.create.haunted_bell": "UNLOCALIZED: Haunted Bell", "block.create.honey": "UNLOCALIZED: Honey", "block.create.horizontal_framed_glass": "UNLOCALIZED: Horizontal Framed Glass", "block.create.horizontal_framed_glass_pane": "UNLOCALIZED: Horizontal Framed Glass Pane", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "UNLOCALIZED: Layered Limestone", "block.create.layered_scoria": "UNLOCALIZED: Layered Scoria", "block.create.layered_weathered_limestone": "UNLOCALIZED: Layered Weathered Limestone", + "block.create.lectern_controller": "UNLOCALIZED: Lectern Controller", + "block.create.light_blue_nixie_tube": "UNLOCALIZED: Light Blue Nixie Tube", "block.create.light_blue_sail": "UNLOCALIZED: Light Blue Sail", "block.create.light_blue_seat": "UNLOCALIZED: Light Blue Seat", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "UNLOCALIZED: Light Blue Valve Handle", + "block.create.light_gray_nixie_tube": "UNLOCALIZED: Light Gray Nixie Tube", "block.create.light_gray_sail": "UNLOCALIZED: Light Gray Sail", "block.create.light_gray_seat": "UNLOCALIZED: Light Gray Seat", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "UNLOCALIZED: Light Gray Valve Handle", + "block.create.lime_nixie_tube": "UNLOCALIZED: Lime Nixie Tube", "block.create.lime_sail": "UNLOCALIZED: Lime Sail", "block.create.lime_seat": "UNLOCALIZED: Lime Seat", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "UNLOCALIZED: Lime Valve Handle", "block.create.limesand": "Kalkzand", "block.create.limestone": "Kalksteen", @@ -225,8 +245,10 @@ "block.create.limestone_pillar": "Kalksteen Pillar", "block.create.linear_chassis": "Lineaar Frame", "block.create.lit_blaze_burner": "UNLOCALIZED: Lit Blaze Burner", + "block.create.magenta_nixie_tube": "UNLOCALIZED: Magenta Nixie Tube", "block.create.magenta_sail": "UNLOCALIZED: Magenta Sail", "block.create.magenta_seat": "UNLOCALIZED: Magenta Seat", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "UNLOCALIZED: Magenta Valve Handle", "block.create.mechanical_arm": "UNLOCALIZED: Mechanical Arm", "block.create.mechanical_bearing": "Mechanische Lager", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "UNLOCALIZED: Oak Window Pane", "block.create.orange_sail": "UNLOCALIZED: Orange Sail", "block.create.orange_seat": "UNLOCALIZED: Orange Seat", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "UNLOCALIZED: Orange Valve Handle", "block.create.ornate_iron_window": "UNLOCALIZED: Ornate Iron Window", "block.create.ornate_iron_window_pane": "UNLOCALIZED: Ornate Iron Window Pane", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "UNLOCALIZED: Paved Weathered Limestone Slab", "block.create.paved_weathered_limestone_stairs": "UNLOCALIZED: Paved Weathered Limestone Stairs", "block.create.paved_weathered_limestone_wall": "UNLOCALIZED: Paved Weathered Limestone Wall", + "block.create.peculiar_bell": "UNLOCALIZED: Peculiar Bell", + "block.create.pink_nixie_tube": "UNLOCALIZED: Pink Nixie Tube", "block.create.pink_sail": "UNLOCALIZED: Pink Sail", "block.create.pink_seat": "UNLOCALIZED: Pink Seat", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "UNLOCALIZED: Pink Valve Handle", "block.create.piston_extension_pole": "Zuiger Verlengpaal", "block.create.polished_dark_scoria": "UNLOCALIZED: Polished Dark Scoria", @@ -342,12 +368,16 @@ "block.create.powered_toggle_latch": "UNLOCALIZED: Powered Toggle Latch", "block.create.pulley_magnet": "UNLOCALIZED: Pulley Magnet", "block.create.pulse_repeater": "Pulse Versterker", + "block.create.purple_nixie_tube": "UNLOCALIZED: Purple Nixie Tube", "block.create.purple_sail": "UNLOCALIZED: Purple Sail", "block.create.purple_seat": "UNLOCALIZED: Purple Seat", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "UNLOCALIZED: Purple Valve Handle", "block.create.radial_chassis": "Rotation Frame", + "block.create.red_nixie_tube": "UNLOCALIZED: Red Nixie Tube", "block.create.red_sail": "UNLOCALIZED: Red Sail", "block.create.red_seat": "UNLOCALIZED: Red Seat", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "UNLOCALIZED: Red Valve Handle", "block.create.redstone_contact": "Redstone redstone_contact", "block.create.redstone_link": "Redstone Brug", @@ -402,24 +432,32 @@ "block.create.weathered_limestone_cobblestone_wall": "UNLOCALIZED: Weathered Limestone Cobblestone Wall", "block.create.weathered_limestone_pillar": "Verweerde Kalksteen Pilaar", "block.create.weighted_ejector": "UNLOCALIZED: Weighted Ejector", + "block.create.white_nixie_tube": "UNLOCALIZED: White Nixie Tube", "block.create.white_sail": "UNLOCALIZED: White Sail", "block.create.white_seat": "UNLOCALIZED: White Seat", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle", "block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing", "block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket", + "block.create.yellow_nixie_tube": "UNLOCALIZED: Yellow Nixie Tube", "block.create.yellow_sail": "UNLOCALIZED: Yellow Sail", "block.create.yellow_seat": "UNLOCALIZED: Yellow Seat", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle", "block.create.zinc_block": "UNLOCALIZED: Block of Zinc", "block.create.zinc_ore": "UNLOCALIZED: Zinc Ore", + "enchantment.create.capacity": "UNLOCALIZED: Capacity", + "enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery", + "entity.create.contraption": "UNLOCALIZED: Contraption", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "entity.create.potato_projectile": "UNLOCALIZED: Potato Projectile", "entity.create.seat": "UNLOCALIZED: Seat", "entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption", "entity.create.super_glue": "UNLOCALIZED: Super Glue", - "fluid.create.milk": "UNLOCALIZED: Milk", "fluid.create.potion": "UNLOCALIZED: Potion", "fluid.create.tea": "UNLOCALIZED: Builder's Tea", @@ -444,6 +482,8 @@ "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.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "item.create.crushed_aluminum_ore": "UNLOCALIZED: Crushed Aluminum Ore", "item.create.crushed_brass": "Gemalen Brons", "item.create.crushed_copper_ore": "UNLOCALIZED: Crushed Copper Ore", @@ -472,13 +512,17 @@ "item.create.handheld_worldshaper": "UNLOCALIZED: Creative Worldshaper", "item.create.honey_bucket": "UNLOCALIZED: Honey Bucket", "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", - "item.create.integrated_circuit": "UNLOCALIZED: Integrated Circuit", + "item.create.incomplete_cogwheel": "UNLOCALIZED: Incomplete Cogwheel", + "item.create.incomplete_large_cogwheel": "UNLOCALIZED: Incomplete Large Cogwheel", + "item.create.incomplete_precision_mechanism": "UNLOCALIZED: Incomplete Precision Mechanism", "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", + "item.create.potato_cannon": "UNLOCALIZED: Potato Cannon", "item.create.powdered_obsidian": "UNLOCALIZED: Powdered Obsidian", + "item.create.precision_mechanism": "UNLOCALIZED: Precision Mechanism", "item.create.propeller": "Propeller", "item.create.red_sand_paper": "UNLOCALIZED: Red Sand Paper", "item.create.refined_radiance": "UNLOCALIZED: Refined Radiance", @@ -623,8 +667,8 @@ "advancement.create.flywheel.desc": "UNLOCALIZED: Successfully connect an engine to the Flywheel.", "advancement.create.overstress_flywheel": "UNLOCALIZED: High levels of Stress", "advancement.create.overstress_flywheel.desc": "UNLOCALIZED: Overstress a Furnace Engine.", - "advancement.create.integrated_circuit": "UNLOCALIZED: Complex Calculation", - "advancement.create.integrated_circuit.desc": "UNLOCALIZED: Assemble an Integrated Circuit.", + "advancement.create.precision_mechanism": "UNLOCALIZED: Complex Curiosities", + "advancement.create.precision_mechanism.desc": "UNLOCALIZED: Assemble a Precision Mechanism.", "advancement.create.mechanical_arm": "UNLOCALIZED: Busy Hands!", "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch as it does all the work for you.", "advancement.create.musical_arm": "UNLOCALIZED: Play Me My Theme Tune!", @@ -639,7 +683,7 @@ "advancement.create.crushing_wheel.desc": "UNLOCALIZED: Create some Crushing Wheels to break down more materials more effectively.", "advancement.create.blaze_cake": "UNLOCALIZED: Sugar Rush", "advancement.create.blaze_cake.desc": "UNLOCALIZED: Bake your blaze burner a special cake.", - "advancement.create.chromatic_compound": "UNLOCALIZED: Bipolar Minerals", + "advancement.create.chromatic_compound": "UNLOCALIZED: Mysterious Minerals", "advancement.create.chromatic_compound.desc": "UNLOCALIZED: Create a Bar of Chromatic Compound.", "advancement.create.shadow_steel": "UNLOCALIZED: Void Returner", "advancement.create.shadow_steel.desc": "UNLOCALIZED: Create Shadow Steel, a metal bar of nothingness.", @@ -651,6 +695,8 @@ "advancement.create.wand_of_symmetry.desc": "UNLOCALIZED: Craft a Staff of Symmetry.", "advancement.create.extendo_grip": "UNLOCALIZED: Boioioing!", "advancement.create.extendo_grip.desc": "UNLOCALIZED: Get hold of an Extendo Grip.", + "advancement.create.potato_cannon": "UNLOCALIZED: Fwoomp!", + "advancement.create.potato_cannon.desc": "UNLOCALIZED: Defeat an enemy with your Potato Cannon.", "advancement.create.dual_extendo_grip": "UNLOCALIZED: Ultimate Boing-age", "advancement.create.dual_extendo_grip.desc": "UNLOCALIZED: Dual wield Extendo Grips for super-human reach.", "advancement.create.eob": "UNLOCALIZED: End of Beta", @@ -663,15 +709,31 @@ "itemGroup.create.palettes": "UNLOCALIZED: Create Palettes", "death.attack.create.crush": "%1$s is verwerkd door verpulverende wielen", + "death.attack.create.crush.player": "UNLOCALIZED: %1$s was thrown into Crushing Wheels by %2$s", "death.attack.create.fan_fire": "%1$s is verbrand door hete lucht", + "death.attack.create.fan_fire.player": "UNLOCALIZED: %1$s was thrown into a smoker by %2$s", "death.attack.create.fan_lava": "%1$s is verbrand door een lava ventilator", + "death.attack.create.fan_lava.player": "UNLOCALIZED: %1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "%1$s is gespietst door een mechanische boor", + "death.attack.create.mechanical_drill.player": "UNLOCALIZED: %1$s was thrown in front of a Drill by %2$s", "death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by a Mechanical Saw", + "death.attack.create.mechanical_saw.player": "UNLOCALIZED: %1$s was thrown into a Saw by %2$s", + "death.attack.create.potato_cannon": "UNLOCALIZED: %1$s was shot by %2$s's Potato Cannon", + "death.attack.create.potato_cannon.item": "UNLOCALIZED: %1$s was shot by %2$s using %3$s", "death.attack.create.cuckoo_clock_explosion": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", + "death.attack.create.cuckoo_clock_explosion.player": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", "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.ponder_index": "UNLOCALIZED: Ponder Index", + "create.menu.only_ingame": "UNLOCALIZED: Available in the Pause Menu", + "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", @@ -696,7 +758,18 @@ "create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion", "create.recipe.spout_filling": "UNLOCALIZED: Filling by Spout", "create.recipe.draining": "UNLOCALIZED: Item Draining", + "create.recipe.sequenced_assembly": "UNLOCALIZED: Sequenced Assembly", + "create.recipe.assembly.next": "UNLOCALIZED: Next: %1$s", + "create.recipe.assembly.step": "UNLOCALIZED: Step %1$s:", + "create.recipe.assembly.progress": "UNLOCALIZED: Progress: %1$s/%2$s", + "create.recipe.assembly.pressing": "UNLOCALIZED: Process in Press", + "create.recipe.assembly.spout_filling_fluid": "UNLOCALIZED: Spout %1$s", + "create.recipe.assembly.deploying_item": "UNLOCALIZED: Deploy %1$s", + "create.recipe.assembly.cutting": "UNLOCALIZED: Cut with Saw", + "create.recipe.assembly.repeat": "UNLOCALIZED: Repeat Sequence %1$s Times", + "create.recipe.assembly.junk": "UNLOCALIZED: Random salvage", "create.recipe.processing.chance": "%1$s%% Kans", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required", "create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated", "create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated", @@ -725,6 +798,7 @@ "create.action.discard": "Weggooien", "create.keyinfo.toolmenu": "Focus Gereedschap Menu", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "UNLOCALIZED: Simulate Mousewheel Up (inworld)", "create.keyinfo.scrolldown": "UNLOCALIZED: Simulate Mousewheel Down (inworld)", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "Shift om sneller te Scrollen", "create.gui.toolmenu.focusKey": "Hou [%1$s] ingedrukt om te Focusen", "create.gui.toolmenu.cycle": "[SCROLL] om te Cycleën", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Spiegelen", "create.gui.symmetryWand.orientation": "Orientatie", @@ -981,18 +1062,14 @@ "create.item_attributes.placeable.inverted": "UNLOCALIZED: is not placeable", "create.item_attributes.consumable": "UNLOCALIZED: can be eaten", "create.item_attributes.consumable.inverted": "UNLOCALIZED: cannot be eaten", - "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", - "create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted", - "create.item_attributes.washable": "UNLOCALIZED: can be Washed", - "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", - "create.item_attributes.smokable": "UNLOCALIZED: can be Smoked", - "create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked", - "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", - "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", - "create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace", - "create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace", + "create.item_attributes.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "UNLOCALIZED: is enchanted", "create.item_attributes.enchanted.inverted": "UNLOCALIZED: is unenchanted", + "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.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "UNLOCALIZED: is damaged", "create.item_attributes.damaged.inverted": "UNLOCALIZED: is not damaged", "create.item_attributes.badly_damaged": "UNLOCALIZED: is heavily damaged", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "UNLOCALIZED: cannot be equipped", "create.item_attributes.furnace_fuel": "UNLOCALIZED: is furnace fuel", "create.item_attributes.furnace_fuel.inverted": "UNLOCALIZED: is not furnace fuel", + "create.item_attributes.washable": "UNLOCALIZED: can be Washed", + "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", + "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", + "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", + "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", + "create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted", + "create.item_attributes.smokable": "UNLOCALIZED: can be Smoked", + "create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked", + "create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace", + "create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace", + "create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s", + "create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s", + "create.item_attributes.shulker_level.full": "UNLOCALIZED: full", + "create.item_attributes.shulker_level.empty": "UNLOCALIZED: empty", + "create.item_attributes.shulker_level.partial": "UNLOCALIZED: partially filled", "create.item_attributes.in_tag": "UNLOCALIZED: is tagged %1$s", "create.item_attributes.in_tag.inverted": "UNLOCALIZED: is not tagged %1$s", "create.item_attributes.in_item_group": "UNLOCALIZED: is in group '%1$s'", @@ -1013,8 +1105,6 @@ "create.item_attributes.has_enchant.inverted": "UNLOCALIZED: is not enchanted with %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.has_fluid": "UNLOCALIZED: contains %1$s", "create.item_attributes.has_fluid.inverted": "UNLOCALIZED: does not contain %1$s", "create.item_attributes.has_name": "UNLOCALIZED: has the custom name %1$s", @@ -1029,14 +1119,14 @@ "create.item_attributes.book_copy_second.inverted": "UNLOCALIZED: is not a second-generation copy", "create.item_attributes.book_copy_tattered": "UNLOCALIZED: is a tattered mess", "create.item_attributes.book_copy_tattered.inverted": "UNLOCALIZED: is not a tattered mess", - "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", - "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", - "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", "create.item_attributes.astralsorcery_amulet": "UNLOCALIZED: improves %1$s", "create.item_attributes.astralsorcery_amulet.inverted": "UNLOCALIZED: does not improve %1$s", + "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", + "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", "create.gui.attribute_filter.no_selected_attributes": "UNLOCALIZED: No attributes selected", "create.gui.attribute_filter.selected_attributes": "UNLOCALIZED: Selected attributes:", @@ -1104,6 +1194,27 @@ "create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above", "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "UNLOCALIZED: Currently distributing:", + "create.tooltip.brass_tunnel.contains_entry": "UNLOCALIZED: > %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "UNLOCALIZED: Right-Click to retrieve", + + "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.potato_cannon.ammo.attack_damage": "UNLOCALIZED: %1$s Attack Damage", + "create.potato_cannon.ammo.reload_ticks": "UNLOCALIZED: %1$s Reload Ticks", + "create.potato_cannon.ammo.knockback": "UNLOCALIZED: %1$s Knockback", "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", @@ -1132,32 +1243,44 @@ "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.contraption_disassemble": "UNLOCALIZED: Contraption stops", + "create.subtitle.peculiar_bell_use": "UNLOCALIZED: Peculiar Bell tolls", + "create.subtitle.mixing": "UNLOCALIZED: Mixing noises", + "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", + "create.subtitle.fwoomp": "UNLOCALIZED: Potato Launcher fwoomps", + "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", + "create.subtitle.crushing_1": "UNLOCALIZED: Crushing noises", + "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", + "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel flaps", + "create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings", + "create.subtitle.haunted_bell_use": "UNLOCALIZED: Haunted Bell tolls", + "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.controller_put": "UNLOCALIZED: Controller thumps", + "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.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.potato_hit": "UNLOCALIZED: Vegetable impacts", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens", "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", - "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", "create.subtitle.deny": "UNLOCALIZED: Declining boop", - "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", "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.controller_take": "UNLOCALIZED: Lectern empties", "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", @@ -1179,14 +1302,6 @@ "block.create.metal_bracket.tooltip": "UNLOCALIZED: METAL BRACKET", "block.create.metal_bracket.tooltip.summary": "UNLOCALIZED: _Decorate_ your _Shafts, Cogwheels_ and _Pipes_ with an industrial and sturdy bit of reinforcement.", - "block.create.copper_casing.tooltip": "UNLOCALIZED: COPPER CASING", - "block.create.copper_casing.tooltip.summary": "UNLOCALIZED: Robust machine casing with a variety of uses. Safe for decoration.", - "block.create.copper_casing.tooltip.condition1": "UNLOCALIZED: When used on Fluid Pipe", - "block.create.copper_casing.tooltip.behaviour1": "UNLOCALIZED: _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": "UNLOCALIZED: ENCASED FLUID PIPE", - "block.create.encased_fluid_pipe.tooltip.summary": "UNLOCALIZED: A _Fluid Pipe_ encased with the _Copper Casing_.", - "block.create.seat.tooltip": "UNLOCALIZED: SEAT", "block.create.seat.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: Right click on Seat", @@ -1195,65 +1310,6 @@ "item.create.blaze_cake.tooltip": "UNLOCALIZED: BLAZE CAKE", "item.create.blaze_cake.tooltip.summary": "UNLOCALIZED: A Delicious treat for your hard-working _Blaze Burners_. Gets them all fired up!", - "block.create.fluid_pipe.tooltip": "UNLOCALIZED: FLUID PIPE", - "block.create.fluid_pipe.tooltip.summary": "UNLOCALIZED: Used for moving _fluids_ around. Needs a _Mechanical Pump_ to get the _fluid_ moving.", - "block.create.fluid_pipe.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.fluid_pipe.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Places a window on the pipe if available", - - "block.create.hose_pulley.tooltip": "UNLOCALIZED: HOSE PULLEY", - "block.create.hose_pulley.tooltip.summary": "UNLOCALIZED: Used for _placing_ or _draining_ large _fluid bodies_ in the world.", - "block.create.hose_pulley.tooltip.condition1": "UNLOCALIZED: When Powered by Kinetics", - "block.create.hose_pulley.tooltip.behaviour1": "UNLOCALIZED: _Raises_ or _Lowers_ the hose, location of the hose determines up to which _height extraction_ or _filling_ will act.", - "block.create.hose_pulley.tooltip.condition2": "UNLOCALIZED: When Fluids pulled from Pulley", - "block.create.hose_pulley.tooltip.behaviour2": "UNLOCALIZED: 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": "UNLOCALIZED: When Fluids pushed to Pulley", - "block.create.hose_pulley.tooltip.behaviour3": "UNLOCALIZED: Starts _filling fluid_ into the world _up to_ the _hose_ ends' _height_.", - - "block.create.fluid_tank.tooltip": "UNLOCALIZED: FLUID TANK", - "block.create.fluid_tank.tooltip.summary": "UNLOCALIZED: _Stores_ all your favourite _fluids_. Scales in width and height.", - "block.create.fluid_tank.tooltip.condition1": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_tank.tooltip.behaviour1": "UNLOCALIZED: Changes the optional window", - - "block.create.creative_fluid_tank.tooltip": "UNLOCALIZED: CREATIVE FLUID TANK", - "block.create.creative_fluid_tank.tooltip.summary": "UNLOCALIZED: This _Fluid Tank_ allows infinite replication of any Fluid. Scales in width and height.", - "block.create.creative_fluid_tank.tooltip.condition1": "UNLOCALIZED: When Fluid in Tank", - "block.create.creative_fluid_tank.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.creative_fluid_tank.tooltip.behaviour2": "UNLOCALIZED: Changes the optional window", - - "block.create.fluid_valve.tooltip": "UNLOCALIZED: FLUID VALVE", - "block.create.fluid_valve.tooltip.summary": "UNLOCALIZED: Halts the flow of fluid down a pipe.", - "block.create.fluid_valve.tooltip.condition1": "UNLOCALIZED: Controllable flow", - "block.create.fluid_valve.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: MECHANICAL PUMP", - "block.create.mechanical_pump.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: Fluid Flow", - "block.create.mechanical_pump.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.mechanical_pump.tooltip.action1": "UNLOCALIZED: Reverses the direction of the _pump_, switching the default direction of the flow", - - "block.create.smart_fluid_pipe.tooltip": "UNLOCALIZED: SMART FLUID PIPE", - "block.create.smart_fluid_pipe.tooltip.summary": "UNLOCALIZED: A _fluid pipe_ with a filter. Can specify which _fluids_ pass through.", - "block.create.smart_fluid_pipe.tooltip.condition1": "UNLOCALIZED: When Fluids are pushed into it", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "UNLOCALIZED: Smart pipes receiving fluid that does not match its filter will block the flow.", - "block.create.smart_fluid_pipe.tooltip.condition2": "UNLOCALIZED: When adjacent to fluid container", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Smart pipes _starting_ a _flow_ from any container will only extract fluids that _match_ its _filter._", - - "block.create.spout.tooltip": "UNLOCALIZED: SPOUT", - "block.create.spout.tooltip.summary": "UNLOCALIZED: An injector for refilling your _fluid items._", - "block.create.spout.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.spout.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Fluid Automation", - "block.create.spout.tooltip.behaviour2": "UNLOCALIZED: 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": "UNLOCALIZED: ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "UNLOCALIZED: A grated depot for emptying your _fluid items._", - "block.create.item_drain.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.item_drain.tooltip.behaviour1": "UNLOCALIZED: 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": "SYMMETRIE STAF", "item.create.wand_of_symmetry.tooltip.summary": "Spiegelt uw blokplaatsing perfect over de geconfigureerde vlakken.", "item.create.wand_of_symmetry.tooltip.condition1": "Waneer in de Actiebalk", @@ -1280,9 +1336,18 @@ "item.create.tree_fertilizer.tooltip.behaviour1": "Groeit bomen onafhankelijk van beschikbare ruimte", "item.create.extendo_grip.tooltip": "UNLOCALIZED: EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder.", + "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder. Can be powered with Air Pressure from a _Copper_ _Backtank_", "item.create.extendo_grip.tooltip.condition1": "UNLOCALIZED: When in Off-Hand", "item.create.extendo_grip.tooltip.behaviour1": "UNLOCALIZED: Increases _reach distance_ of items used in the _Main-Hand_.", + "item.create.extendo_grip.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", + + "item.create.potato_cannon.tooltip": "UNLOCALIZED: POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "UNLOCALIZED: Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", + "item.create.potato_cannon.tooltip.behaviour1": "UNLOCALIZED: _Shoots_ a suitable item from your _Inventory_.", + "item.create.potato_cannon.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.filter.tooltip": "UNLOCALIZED: FILTER", "item.create.filter.tooltip.summary": "UNLOCALIZED: _Controls outputs_ and _inputs_ of logistical devices with more _precision_, matching them against a _set of items_ or several _nested filters_.", @@ -1358,12 +1423,14 @@ "block.create.turntable.tooltip": "DRAAISCHIJF", "block.create.turntable.tooltip.summary": "Verandert _Rotatiekracht_ in verfijnde bewegingsziekte.", - "block.create.portable_fluid_interface.tooltip": "UNLOCALIZED: PORTABLE FLUID INTERFACE", - "block.create.portable_fluid_interface.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: While Moving", - "block.create.portable_fluid_interface.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: When Powered by Redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "UNLOCALIZED: _Disengages_ any active connection immediately.", + "block.create.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "VOORRAAD SCHAKELAAR", "block.create.stockpile_switch.tooltip.summary": "Schakelt een Redstone signaal op basis van de _Opslagruimte_ in de aangesloten Container.", @@ -1371,7 +1438,11 @@ "block.create.stockpile_switch.tooltip.behaviour1": "Stopt met het aanbieden van _Redstone_ _Kracht_", "block.create.content_observer.tooltip": "UNLOCALIZED: CONTENT OBSERVER", - "block.create.content_observer.tooltip.summary": "UNLOCALIZED: _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_.", + "block.create.content_observer.tooltip.summary": "UNLOCALIZED: _Detects Items_ or _Fluids_ inside _containers_, _pipes_ or _conveyors_ matching a configured _filter_.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "FLEXKRAT", "block.create.adjustable_crate.tooltip.summary": "Met deze _Opslag_ _Container_ kan de capaciteit handmatig worden geregeld. Het kan tot _16_ _Stapels_ van elk item bevatten", @@ -1383,6 +1454,11 @@ "block.create.creative_crate.tooltip.condition1": "UNLOCALIZED: When Item in Filter Slot", "block.create.creative_crate.tooltip.behaviour1": "UNLOCALIZED: Anything _extracting_ from this container will provide an _endless supply_ of the item specified. Items _inserted_ into this crate will be _voided._", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "UNLOCALIZED: CONTROLLER RAIL", "block.create.controller_rail.tooltip.summary": "UNLOCALIZED: A _uni-directional powered rail_ capable of _fine control_ over a minecarts' _movement speed_.", "block.create.controller_rail.tooltip.condition1": "UNLOCALIZED: When Powered by Redstone", @@ -1398,26 +1474,61 @@ "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.linked_controller.tooltip.condition4": "UNLOCALIZED: R-Click on Lectern", + "item.create.linked_controller.tooltip.behaviour4": "UNLOCALIZED: Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the wielder 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: Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder 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.", + "block.create.peculiar_bell.tooltip": "UNLOCALIZED: PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "UNLOCALIZED: A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + + "block.create.haunted_bell.tooltip": "UNLOCALIZED: HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "UNLOCALIZED: A _Cursed Bell_ haunted by lost souls of the Nether.", + "block.create.haunted_bell.tooltip.condition1": "UNLOCALIZED: When Held or Rang", + "block.create.haunted_bell.tooltip.behaviour1": "UNLOCALIZED: Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn.", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1434,41 +1545,46 @@ "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.exit": "UNLOCALIZED: Exit", + "create.ponder.welcome": "UNLOCALIZED: Welcome to Ponder", + "create.ponder.categories": "UNLOCALIZED: Available Categories in Create", + "create.ponder.index_description": "UNLOCALIZED: Click one of the icons to learn about its associated Items and Blocks", + "create.ponder.index_title": "UNLOCALIZED: Ponder Index", + "create.ponder.shared.rpm16": "UNLOCALIZED: 16 RPM", "create.ponder.shared.behaviour_modify_wrench": "UNLOCALIZED: This behaviour can be modified using a Wrench", + "create.ponder.shared.storage_on_contraption": "UNLOCALIZED: Inventories attached to the Contraption will pick up their drops automatically", + "create.ponder.shared.sneak_and": "UNLOCALIZED: Sneak +", "create.ponder.shared.rpm8": "UNLOCALIZED: 8 RPM", "create.ponder.shared.ctrl_and": "UNLOCALIZED: Ctrl +", + "create.ponder.shared.rpm32": "UNLOCALIZED: 32 RPM", "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.shared.movement_anchors": "UNLOCALIZED: With the help of Chassis or Super Glue, larger structures can be moved.", "create.ponder.tag.redstone": "UNLOCALIZED: Logic Components", "create.ponder.tag.redstone.description": "UNLOCALIZED: Components which help with redstone engineering", + "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.fluids": "UNLOCALIZED: Fluid Manipulators", "create.ponder.tag.fluids.description": "UNLOCALIZED: Components which help relaying and making use of Fluids", + "create.ponder.tag.decoration": "UNLOCALIZED: Aesthetics", + "create.ponder.tag.decoration.description": "UNLOCALIZED: Components used mostly for decorative purposes", + "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.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.kinetic_appliances": "UNLOCALIZED: Kinetic Appliances", + "create.ponder.tag.kinetic_appliances.description": "UNLOCALIZED: Components which make use of Rotational Force", + "create.ponder.tag.kinetic_sources": "UNLOCALIZED: Kinetic Sources", + "create.ponder.tag.kinetic_sources.description": "UNLOCALIZED: Components which generate Rotational Force", + "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.kinetic_relays": "UNLOCALIZED: Kinetic Blocks", + "create.ponder.tag.kinetic_relays.description": "UNLOCALIZED: Components which help relaying Rotational Force elsewhere", + "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.creative": "UNLOCALIZED: Creative Mode", + "create.ponder.tag.creative.description": "UNLOCALIZED: Components not usually available for Survival Mode", + "create.ponder.tag.logistics": "UNLOCALIZED: Item Transportation", + "create.ponder.tag.logistics.description": "UNLOCALIZED: Components which help moving items around", "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", @@ -1580,7 +1696,8 @@ "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_modes.text_2": "UNLOCALIZED: This Arrow indicates which side of the Structure will be considered the front", + "create.ponder.cart_assembler_modes.text_3": "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", @@ -1594,7 +1711,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 +1751,12 @@ "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_fluid_tank.text_1": "UNLOCALIZED: Creative Fluid Tanks can be used to provide a bottomless supply of fluid", + "create.ponder.creative_fluid_tank.text_2": "UNLOCALIZED: Right-Click with a fluid containing item to configure it", + "create.ponder.creative_fluid_tank.text_3": "UNLOCALIZED: Pipe Networks can now endlessly draw the assigned fluid from the tank", + "create.ponder.creative_fluid_tank.text_4": "UNLOCALIZED: Any Fluids pushed back into a Creative Fluid Tank will be voided", + "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 +1793,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", @@ -1686,7 +1815,13 @@ "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.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item", + "create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they 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", @@ -1706,6 +1841,35 @@ "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_sizes.text_1": "UNLOCALIZED: Fluid Tanks can be combined to increase the total capacity", + "create.ponder.fluid_tank_sizes.text_2": "UNLOCALIZED: Their base square can be up to 3 blocks wide...", + "create.ponder.fluid_tank_sizes.text_3": "UNLOCALIZED: ...and grow in height by more than 30 additional layers", + "create.ponder.fluid_tank_sizes.text_4": "UNLOCALIZED: Using a Wrench, a tanks' window can be toggled", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.fluid_tank_storage.text_1": "UNLOCALIZED: Fluid Tanks can be used to store large amounts of fluid", + "create.ponder.fluid_tank_storage.text_2": "UNLOCALIZED: Pipe networks can push and pull fluids from any side", + "create.ponder.fluid_tank_storage.text_3": "UNLOCALIZED: The contained fluid can be measured by a Comparator", + "create.ponder.fluid_tank_storage.text_4": "UNLOCALIZED: However, in Survival Mode Fluids cannot be added or taken manually", + "create.ponder.fluid_tank_storage.text_5": "UNLOCALIZED: You can use Basins, Item Drains and Spouts to drain or fill fluid containing items", + "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 +1943,34 @@ "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.text_1": "UNLOCALIZED: Hose Pulleys can be used to fill or drain large bodies of Fluid", + "create.ponder.hose_pulley.text_2": "UNLOCALIZED: With the Kinetic Input, the height of the pulleys' hose can be controlled", + "create.ponder.hose_pulley.text_3": "UNLOCALIZED: The Pulley retracts while the input rotation is inverted", + "create.ponder.hose_pulley.text_4": "UNLOCALIZED: On the opposite side, pipes can be connected", + "create.ponder.hose_pulley.text_5": "UNLOCALIZED: Attached pipe networks can either provide fluid to the hose...", + "create.ponder.hose_pulley.text_6": "UNLOCALIZED: ...or pull from it, draining the pool instead", + "create.ponder.hose_pulley.text_7": "UNLOCALIZED: Fill and Drain speed of the pulley depends entirely on the fluid networks' throughput", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + "create.ponder.hose_pulley_infinite.text_1": "UNLOCALIZED: When deploying the Hose Pulley into a large enough ocean...", + "create.ponder.hose_pulley_infinite.text_2": "UNLOCALIZED: It will provide/dispose fluids without affecting the source", + "create.ponder.hose_pulley_infinite.text_3": "UNLOCALIZED: Pipe networks can limitlessly take fluids from/to such pulleys", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + "create.ponder.hose_pulley_level.text_1": "UNLOCALIZED: While fully retracted, the Hose Pulley cannot operate", + "create.ponder.hose_pulley_level.text_2": "UNLOCALIZED: Draining runs from top to bottom", + "create.ponder.hose_pulley_level.text_3": "UNLOCALIZED: The surface level will end up just below where the hose ends", + "create.ponder.hose_pulley_level.text_4": "UNLOCALIZED: Filling runs from bottom to top", + "create.ponder.hose_pulley_level.text_5": "UNLOCALIZED: The filled pool will not grow beyond the layer above the hose end", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.item_drain.text_1": "UNLOCALIZED: Item Drains can extract fluids from items", + "create.ponder.item_drain.text_2": "UNLOCALIZED: Right-click it to pour fluids from your held item into it", + "create.ponder.item_drain.text_3": "UNLOCALIZED: When items are inserted from the side...", + "create.ponder.item_drain.text_4": "UNLOCALIZED: ...they roll across, emptying out their contained fluid", + "create.ponder.item_drain.text_5": "UNLOCALIZED: Pipe Networks can now pull the fluid from the drains' internal buffer", + "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 +2093,21 @@ "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_flow.text_1": "UNLOCALIZED: Mechanical Pumps govern the flow of their attached pipe networks", + "create.ponder.mechanical_pump_flow.text_2": "UNLOCALIZED: When powered, their arrow indicates the direction of flow", + "create.ponder.mechanical_pump_flow.text_3": "UNLOCALIZED: The network behind is now pulling fluids...", + "create.ponder.mechanical_pump_flow.text_4": "UNLOCALIZED: ...while the network in front is transferring it outward", + "create.ponder.mechanical_pump_flow.text_5": "UNLOCALIZED: Reversing the input rotation reverses the direction of flow", + "create.ponder.mechanical_pump_flow.text_6": "UNLOCALIZED: Use a Wrench to reverse the orientation of pumps manually", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_pump_speed.text_1": "UNLOCALIZED: Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away", + "create.ponder.mechanical_pump_speed.text_2": "UNLOCALIZED: Speeding up the input rotation changes the speed of flow propagation...", + "create.ponder.mechanical_pump_speed.text_3": "UNLOCALIZED: ...aswell as how quickly fluids are transferred", + "create.ponder.mechanical_pump_speed.text_4": "UNLOCALIZED: Pumps can combine their throughputs within shared pipe networks", + "create.ponder.mechanical_pump_speed.text_5": "UNLOCALIZED: Alternating their orientation can help align their flow directions", + "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", @@ -1926,11 +2133,22 @@ "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.nixie_tube.text_3": "UNLOCALIZED: Right-Click with Dye to change their display colour", "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_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + "create.ponder.portable_fluid_interface.text_1": "UNLOCALIZED: Fluid Tanks on moving contraptions cannot be accessed by any pipes", + "create.ponder.portable_fluid_interface.text_2": "UNLOCALIZED: This component can interact with fluid tanks without the need to stop the contraption", + "create.ponder.portable_fluid_interface.text_3": "UNLOCALIZED: Place a second one with a gap of 1 or 2 blocks inbetween", + "create.ponder.portable_fluid_interface.text_4": "UNLOCALIZED: Whenever they pass by each other, they will engage in a connection", + "create.ponder.portable_fluid_interface.text_5": "UNLOCALIZED: While engaged, the stationary interface will represent ALL Tanks on the contraption", + "create.ponder.portable_fluid_interface.text_6": "UNLOCALIZED: Fluid can now be inserted...", + "create.ponder.portable_fluid_interface.text_7": "UNLOCALIZED: ...or extracted from the contraption", + "create.ponder.portable_fluid_interface.text_8": "UNLOCALIZED: After no contents have been exchanged for a while, the contraption will continue on its way", + "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 +2246,25 @@ "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.smart_pipe.text_1": "UNLOCALIZED: Smart pipes can help control flows by fluid type", + "create.ponder.smart_pipe.text_2": "UNLOCALIZED: When placed directly at the source, they can specify the type of fluid to extract", + "create.ponder.smart_pipe.text_3": "UNLOCALIZED: Simply Right-Click their filter slot with any item containing the desired fluid", + "create.ponder.smart_pipe.text_4": "UNLOCALIZED: When placed further down a pipe network, smart pipes will only let matching fluids continue", + "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_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.spout_filling.text_1": "UNLOCALIZED: The Spout can fill fluid holding items provided beneath it", + "create.ponder.spout_filling.text_2": "UNLOCALIZED: The content of a Spout cannot be accessed manually", + "create.ponder.spout_filling.text_3": "UNLOCALIZED: Instead, Pipes can be used to supply it with fluids", + "create.ponder.spout_filling.text_4": "UNLOCALIZED: The Input items can be placed on a Depot under the Spout", + "create.ponder.spout_filling.text_5": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.spout_filling.text_6": "UNLOCALIZED: The Spout will hold and process them automatically", + "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 +2296,12 @@ "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.valve_pipe.text_1": "UNLOCALIZED: Valve pipes help control fluids propagating through pipe networks", + "create.ponder.valve_pipe.text_2": "UNLOCALIZED: Their shaft input controls whether fluid is currently allowed through", + "create.ponder.valve_pipe.text_3": "UNLOCALIZED: Given Rotational Force in the opening direction, the valve will open up", + "create.ponder.valve_pipe.text_4": "UNLOCALIZED: It can be closed again by reversing the input rotation", + "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..abc75b34e 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: 295", "_": "->------------------------] Game Elements [------------------------<-", @@ -28,12 +28,16 @@ "block.create.belt": "Taśma", "block.create.birch_window": "Brzozowe okno", "block.create.birch_window_pane": "Brzozowa szyba okienna", + "block.create.black_nixie_tube": "UNLOCALIZED: Black Nixie Tube", "block.create.black_sail": "Czarny żagiel", "block.create.black_seat": "Czarne siedzenie", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "Czarne pokrętło", "block.create.blaze_burner": "Płomienny palnik", + "block.create.blue_nixie_tube": "UNLOCALIZED: Blue Nixie Tube", "block.create.blue_sail": "Niebieski żagiel", "block.create.blue_seat": "Niebieskie siedzenie", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "Niebieskie pokrętło", "block.create.brass_belt_funnel": "Mosiężny lejek taśmowy", "block.create.brass_block": "Blok mosiądzu", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "Mosiężny izolowany wał", "block.create.brass_funnel": "Mosiężny lejek", "block.create.brass_tunnel": "Mosiężny tunel", + "block.create.brown_nixie_tube": "UNLOCALIZED: Brown Nixie Tube", "block.create.brown_sail": "Brązowy żagiel", "block.create.brown_seat": "Brązowe siedzenie", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "Brązowe pokrętło", "block.create.cart_assembler": "Monter wagoników", "block.create.chiseled_dark_scoria": "Rzeźbiony ciemny żużel", @@ -58,7 +64,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", @@ -73,8 +79,10 @@ "block.create.crushing_wheel": "Koło kruszące", "block.create.crushing_wheel_controller": "Sterownik koła kruszącego", "block.create.cuckoo_clock": "Zegar z kukułką", + "block.create.cyan_nixie_tube": "UNLOCALIZED: Cyan Nixie Tube", "block.create.cyan_sail": "Błękitny żagiel", "block.create.cyan_seat": "Błękitne siedzenie", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "Błękitne pokrętło", "block.create.dark_oak_window": "Ciemnodębowe okno", "block.create.dark_oak_window_pane": "Ciemnodębowa szyba okienna", @@ -179,13 +187,18 @@ "block.create.granite_cobblestone_stairs": "Granitowe brukowe schody", "block.create.granite_cobblestone_wall": "Granitowy brukowy murek", "block.create.granite_pillar": "Granitowy filar", + "block.create.gray_nixie_tube": "UNLOCALIZED: Gray Nixie Tube", "block.create.gray_sail": "Szary żagiel", "block.create.gray_seat": "Szare siedzenie", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "Szare pokrętło", + "block.create.green_nixie_tube": "UNLOCALIZED: Green Nixie Tube", "block.create.green_sail": "Zielony żagiel", "block.create.green_seat": "Zielone siedzenie", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "Zielone pokrętło", "block.create.hand_crank": "Ręczna korba", + "block.create.haunted_bell": "UNLOCALIZED: Haunted Bell", "block.create.honey": "Miód", "block.create.horizontal_framed_glass": "Poziome oprawione szkło", "block.create.horizontal_framed_glass_pane": "Pozioma oprawiona szyba", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "Warstwowy wapień", "block.create.layered_scoria": "Warstwowy żużel", "block.create.layered_weathered_limestone": "Warstwowy zwietrzały wapień", + "block.create.lectern_controller": "UNLOCALIZED: Lectern Controller", + "block.create.light_blue_nixie_tube": "UNLOCALIZED: Light Blue Nixie Tube", "block.create.light_blue_sail": "Jasnoniebieski żagiel", "block.create.light_blue_seat": "Jasnoniebieskie siedzenie", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "Jasnoniebieskie pokrętło", + "block.create.light_gray_nixie_tube": "UNLOCALIZED: Light Gray Nixie Tube", "block.create.light_gray_sail": "Jasnoszary żagiel", "block.create.light_gray_seat": "Jasnoszare siedzenie", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "Jasnoszare pokrętło", + "block.create.lime_nixie_tube": "UNLOCALIZED: Lime Nixie Tube", "block.create.lime_sail": "Jasnozielony żagiel", "block.create.lime_seat": "Jasnozielone siedzenie", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "Jasnozielone pokrętło", "block.create.limesand": "Piasek wapienny", "block.create.limestone": "Wapień", @@ -225,8 +245,10 @@ "block.create.limestone_pillar": "Wapienny filar", "block.create.linear_chassis": "Stelaż liniowy", "block.create.lit_blaze_burner": "Zapalony płomienny palnik", + "block.create.magenta_nixie_tube": "UNLOCALIZED: Magenta Nixie Tube", "block.create.magenta_sail": "Karmazynowy żagiel", "block.create.magenta_seat": "Karmazynowe siedzenie", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "Karmazynowe pokrętło", "block.create.mechanical_arm": "Ramie mechaniczne", "block.create.mechanical_bearing": "Mechaniczne łożysko", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "Dębowa szyba okienna", "block.create.orange_sail": "Pomarańczowy żagiel", "block.create.orange_seat": "Pomarańczowe siedzenie", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "Pomarańczowe pokrętło", "block.create.ornate_iron_window": "Ozdobne żelazne okno", "block.create.ornate_iron_window_pane": "Ozdobna żelazne szyba okienna", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "Wygładzona zwietrzała wapienna płyta", "block.create.paved_weathered_limestone_stairs": "Wygładzone zwietrzałe wapienne schody", "block.create.paved_weathered_limestone_wall": "Wygładzony zwietrzały wapienny murek", + "block.create.peculiar_bell": "UNLOCALIZED: Peculiar Bell", + "block.create.pink_nixie_tube": "UNLOCALIZED: Pink Nixie Tube", "block.create.pink_sail": "Różowy żagiel", "block.create.pink_seat": "Różowe siedzenie", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "Różowe pokrętło", "block.create.piston_extension_pole": "Przedłużenie tłoka", "block.create.polished_dark_scoria": "Wypolerowany ciemny żużel", @@ -342,12 +368,16 @@ "block.create.powered_toggle_latch": "Zasilany przełącznik", "block.create.pulley_magnet": "Krążek z magnesem", "block.create.pulse_repeater": "Przekaźnik pulsowy", + "block.create.purple_nixie_tube": "UNLOCALIZED: Purple Nixie Tube", "block.create.purple_sail": "Fioletowy żagiel", "block.create.purple_seat": "Fioletowe siedzenie", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "Fioletowe pokrętło", "block.create.radial_chassis": "Stelaż promienisty", + "block.create.red_nixie_tube": "UNLOCALIZED: Red Nixie Tube", "block.create.red_sail": "Czerwony żagiel", "block.create.red_seat": "Czerwone siedzenie", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "Czerwone pokrętło", "block.create.redstone_contact": "Przełącznik kontaktowy", "block.create.redstone_link": "Emiter sygnału", @@ -402,24 +432,32 @@ "block.create.weathered_limestone_cobblestone_wall": "Zwietrzały wapienny brukowy murek", "block.create.weathered_limestone_pillar": "Zwietrzały wapienny filar", "block.create.weighted_ejector": "Wyrzutnia odważnikowa", + "block.create.white_nixie_tube": "UNLOCALIZED: White Nixie Tube", "block.create.white_sail": "Biały żagiel", "block.create.white_seat": "Białe siedzenie", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "Białe pokrętło", "block.create.windmill_bearing": "Łożysko wiatraka", "block.create.wooden_bracket": "Drewniany wspornik", + "block.create.yellow_nixie_tube": "UNLOCALIZED: Yellow Nixie Tube", "block.create.yellow_sail": "Żółty żagiel", "block.create.yellow_seat": "Żółte siedzenie", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "Żółte pokrętło", "block.create.zinc_block": "Blok cynku", "block.create.zinc_ore": "Ruda cynku", + "enchantment.create.capacity": "UNLOCALIZED: Capacity", + "enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery", + "entity.create.contraption": "Maszyna", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "Maszyna suwnicowa", + "entity.create.potato_projectile": "UNLOCALIZED: Potato Projectile", "entity.create.seat": "Siedzenie", "entity.create.stationary_contraption": "Maszyna stacjonarna", "entity.create.super_glue": "Super Glue", - "fluid.create.milk": "Mleko", "fluid.create.potion": "Mikstura", "fluid.create.tea": "Herbatka Budowniczego", @@ -439,11 +477,13 @@ "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.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "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 +498,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", @@ -472,13 +512,17 @@ "item.create.handheld_worldshaper": "Ręczny kształter", "item.create.honey_bucket": "Wiadro miodu", "item.create.honeyed_apple": "Jabłko w miodzie", - "item.create.integrated_circuit": "Układ scalony", + "item.create.incomplete_cogwheel": "UNLOCALIZED: Incomplete Cogwheel", + "item.create.incomplete_large_cogwheel": "UNLOCALIZED: Incomplete Large Cogwheel", + "item.create.incomplete_precision_mechanism": "UNLOCALIZED: Incomplete Precision Mechanism", "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", + "item.create.potato_cannon": "UNLOCALIZED: Potato Cannon", "item.create.powdered_obsidian": "Sproszkowany obsydian", + "item.create.precision_mechanism": "UNLOCALIZED: Precision Mechanism", "item.create.propeller": "Śmigło", "item.create.red_sand_paper": "Czerwony papier ścierny", "item.create.refined_radiance": "Świetlisty materiał", @@ -623,8 +667,8 @@ "advancement.create.flywheel.desc": "Skutecznie podłącz silnik do koła zamachowego.", "advancement.create.overstress_flywheel": "Wysoki poziom obciążenia", "advancement.create.overstress_flywheel.desc": "Przeładuj silnik spalinowy.", - "advancement.create.integrated_circuit": "Skomplikowane obliczenia", - "advancement.create.integrated_circuit.desc": "Złóż układ scalony.", + "advancement.create.precision_mechanism": "UNLOCALIZED: Complex Curiosities", + "advancement.create.precision_mechanism.desc": "UNLOCALIZED: Assemble a Precision Mechanism.", "advancement.create.mechanical_arm": "Ręce pełne roboty", "advancement.create.mechanical_arm.desc": "Wytwórz ramię mechaniczne, wybierz miejsca wejścia i wyjścia, postaw je i wpraw w ruch. Patrz jak robi wszystko za Ciebie.", "advancement.create.musical_arm": "Zagraj coś dla mnie!", @@ -651,6 +695,8 @@ "advancement.create.wand_of_symmetry.desc": "Zdobądź różdżkę symetrii.", "advancement.create.extendo_grip": "Dalej dalej ręce Gadżeta!", "advancement.create.extendo_grip.desc": "Złap w ręce Wydłużony Chwytak.", + "advancement.create.potato_cannon": "UNLOCALIZED: Fwoomp!", + "advancement.create.potato_cannon.desc": "UNLOCALIZED: Defeat an enemy with your Potato Cannon.", "advancement.create.dual_extendo_grip": "Bioniczne modyfikacje", "advancement.create.dual_extendo_grip.desc": "Użyj dwóch Wydłużonych Chwytaków, aby posiąść nadludzki zasięg.", "advancement.create.eob": "Koniec Bety", @@ -663,15 +709,31 @@ "itemGroup.create.palettes": "Palety Create", "death.attack.create.crush": "Gracz %1$s został zgnieciony przez koło kruszące", + "death.attack.create.crush.player": "UNLOCALIZED: %1$s was thrown into Crushing Wheels by %2$s", "death.attack.create.fan_fire": "Gracz %1$s poparzył się gorącym powietrzem", + "death.attack.create.fan_fire.player": "UNLOCALIZED: %1$s was thrown into a smoker by %2$s", "death.attack.create.fan_lava": "Gracz %1$s poparzył się kroplami lawy", + "death.attack.create.fan_lava.player": "UNLOCALIZED: %1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "Gracz %1$s nabił się na mechaniczne wiertło", + "death.attack.create.mechanical_drill.player": "UNLOCALIZED: %1$s was thrown in front of a Drill by %2$s", "death.attack.create.mechanical_saw": "Gracz %1$s został przecięty na pół przez mechaniczną piłę", + "death.attack.create.mechanical_saw.player": "UNLOCALIZED: %1$s was thrown into a Saw by %2$s", + "death.attack.create.potato_cannon": "UNLOCALIZED: %1$s was shot by %2$s's Potato Cannon", + "death.attack.create.potato_cannon.item": "UNLOCALIZED: %1$s was shot by %2$s using %3$s", "death.attack.create.cuckoo_clock_explosion": "Gracz %1$s został wysadzony w powietrze przez uszkodzony zegar z kukułką", + "death.attack.create.cuckoo_clock_explosion.player": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", "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.ponder_index": "UNLOCALIZED: Ponder Index", + "create.menu.only_ingame": "UNLOCALIZED: Available in the Pause Menu", + "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 +744,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", @@ -696,7 +758,18 @@ "create.recipe.mystery_conversion": "Tajemnicza przemiana", "create.recipe.spout_filling": "Wypełnianie", "create.recipe.draining": "Osuszanie", + "create.recipe.sequenced_assembly": "UNLOCALIZED: Sequenced Assembly", + "create.recipe.assembly.next": "UNLOCALIZED: Next: %1$s", + "create.recipe.assembly.step": "UNLOCALIZED: Step %1$s:", + "create.recipe.assembly.progress": "UNLOCALIZED: Progress: %1$s/%2$s", + "create.recipe.assembly.pressing": "UNLOCALIZED: Process in Press", + "create.recipe.assembly.spout_filling_fluid": "UNLOCALIZED: Spout %1$s", + "create.recipe.assembly.deploying_item": "UNLOCALIZED: Deploy %1$s", + "create.recipe.assembly.cutting": "UNLOCALIZED: Cut with Saw", + "create.recipe.assembly.repeat": "UNLOCALIZED: Repeat Sequence %1$s Times", + "create.recipe.assembly.junk": "UNLOCALIZED: Random salvage", "create.recipe.processing.chance": "%1$s%% szans", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "Nie wymaga podgrzewania", "create.recipe.heat_requirement.heated": "Podrzewane", "create.recipe.heat_requirement.superheated": "Silnie podgrzewane", @@ -725,6 +798,7 @@ "create.action.discard": "Odrzuć", "create.keyinfo.toolmenu": "Menu narzędzi", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "Symuluj przewijanie w górę (w świecie)", "create.keyinfo.scrolldown": "Symuluj przewijanie w dół (w świecie)", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "Naciśnij Shift, aby przewijać szybciej", "create.gui.toolmenu.focusKey": "Przytrzymaj [%1$s], aby skupić", "create.gui.toolmenu.cycle": "[SCROLL] przewijać", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Odbicie lustrzane", "create.gui.symmetryWand.orientation": "Orientacja", @@ -749,15 +830,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 +847,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 +858,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.", @@ -981,18 +1062,14 @@ "create.item_attributes.placeable.inverted": "nie jest stawialny", "create.item_attributes.consumable": "jadalny", "create.item_attributes.consumable.inverted": "niejadalny", - "create.item_attributes.smeltable": "może zostać przepalony", - "create.item_attributes.smeltable.inverted": "nie może zostać przepalony", - "create.item_attributes.washable": "może zostać opłukany", - "create.item_attributes.washable.inverted": "nie może zostać opłukany", - "create.item_attributes.smokable": "może być wędzony", - "create.item_attributes.smokable.inverted": "nie może być wędzony", - "create.item_attributes.crushable": "może być rozkruszony", - "create.item_attributes.crushable.inverted": "nie może być rozkruszony", - "create.item_attributes.blastable": "może być stopiony w piecu hutniczym", - "create.item_attributes.blastable.inverted": "nie może być stopiony w piecu hutniczym", + "create.item_attributes.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "jest zaklęty", "create.item_attributes.enchanted.inverted": "nie jest zaklęty", + "create.item_attributes.max_enchanted": "jest zaklęte na maksymalny poziom", + "create.item_attributes.max_enchanted.inverted": "nie jest zaklęte na maksymalny poziom", + "create.item_attributes.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "jest uszkodzony", "create.item_attributes.damaged.inverted": "nie jest uszkodzony", "create.item_attributes.badly_damaged": "jest silnie uszkodzony", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "nie może zostać założony", "create.item_attributes.furnace_fuel": "jest paliwem dla pieca", "create.item_attributes.furnace_fuel.inverted": "nie jest paliwem dla pieca", + "create.item_attributes.washable": "może zostać opłukany", + "create.item_attributes.washable.inverted": "nie może zostać opłukany", + "create.item_attributes.crushable": "może być rozkruszony", + "create.item_attributes.crushable.inverted": "nie może być rozkruszony", + "create.item_attributes.smeltable": "może zostać przepalony", + "create.item_attributes.smeltable.inverted": "nie może zostać przepalony", + "create.item_attributes.smokable": "może być wędzony", + "create.item_attributes.smokable.inverted": "nie może być wędzony", + "create.item_attributes.blastable": "może być stopiony w piecu hutniczym", + "create.item_attributes.blastable.inverted": "nie może być stopiony w piecu hutniczym", + "create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s", + "create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s", + "create.item_attributes.shulker_level.full": "UNLOCALIZED: full", + "create.item_attributes.shulker_level.empty": "UNLOCALIZED: empty", + "create.item_attributes.shulker_level.partial": "UNLOCALIZED: partially filled", "create.item_attributes.in_tag": "posiada znacznik %1$s", "create.item_attributes.in_tag.inverted": "nie posiada znacznika %1$s", "create.item_attributes.in_item_group": "jest w grupie \"%1$s\"", @@ -1013,8 +1105,6 @@ "create.item_attributes.has_enchant.inverted": "nie posiada zaklęcia %1$s", "create.item_attributes.color": "jest zafarbowane, kolor %1$s", "create.item_attributes.color.inverted": "nie jest zafarbowane, kolor %1$s", - "create.item_attributes.max_enchanted": "jest zaklęte na maksymalny poziom", - "create.item_attributes.max_enchanted.inverted": "nie jest zaklęte na maksymalny poziom", "create.item_attributes.has_fluid": "zawiera %1$s", "create.item_attributes.has_fluid.inverted": "nie zawiera %1$s", "create.item_attributes.has_name": "posiada nazwę %1$s", @@ -1029,14 +1119,14 @@ "create.item_attributes.book_copy_second.inverted": "nie jest kopią kopii", "create.item_attributes.book_copy_tattered": "jest postrzępiona", "create.item_attributes.book_copy_tattered.inverted": "nie jest postrzępiona", - "create.item_attributes.astralsorcery_crystal": "posiada właściwości kryształu %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "nie posiada właściwości kryształu %1$s", - "create.item_attributes.astralsorcery_constellation": "jest dopasowany do %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "nie jest dopasowany do %1$s", - "create.item_attributes.astralsorcery_perk_gem": "posiada dodatkową właściwość %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "nie posiada dodatkowej właściwości %1$s", "create.item_attributes.astralsorcery_amulet": "ulepsza %1$s", "create.item_attributes.astralsorcery_amulet.inverted": "nie ulepsza %1$s", + "create.item_attributes.astralsorcery_constellation": "jest dopasowany do %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "nie jest dopasowany do %1$s", + "create.item_attributes.astralsorcery_crystal": "posiada właściwości kryształu %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "nie posiada właściwości kryształu %1$s", + "create.item_attributes.astralsorcery_perk_gem": "posiada dodatkową właściwość %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "nie posiada dodatkowej właściwości %1$s", "create.gui.attribute_filter.no_selected_attributes": "Brak wybranych właściwości", "create.gui.attribute_filter.selected_attributes": "Wybrane właściwości:", @@ -1104,6 +1194,27 @@ "create.tooltip.chute.fans_pull_up": "Wiatraki ciągną od góry", "create.tooltip.chute.fans_pull_down": "Wiatraki ciągną od dołu", "create.tooltip.chute.contains": "Zawiera: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "UNLOCALIZED: Currently distributing:", + "create.tooltip.brass_tunnel.contains_entry": "UNLOCALIZED: > %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "UNLOCALIZED: Right-Click to retrieve", + + "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.potato_cannon.ammo.attack_damage": "UNLOCALIZED: %1$s Attack Damage", + "create.potato_cannon.ammo.reload_ticks": "UNLOCALIZED: %1$s Reload Ticks", + "create.potato_cannon.ammo.knockback": "UNLOCALIZED: %1$s Knockback", "create.hint.hose_pulley.title": "Niewyczerpany zapas", "create.hint.hose_pulley": "Wybrane zbiornik cieczy jest uznany za nieskończony", @@ -1131,35 +1242,47 @@ "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.contraption_disassemble": "Maszyna staje", + "create.subtitle.peculiar_bell_use": "UNLOCALIZED: Peculiar Bell tolls", + "create.subtitle.mixing": "Dźwięki mieszania", + "create.subtitle.mechanical_press_activation_belt": "Mechaniczna prasa stuka", + "create.subtitle.fwoomp": "UNLOCALIZED: Potato Launcher fwoomps", + "create.subtitle.worldshaper_place": "Kształter strzela", + "create.subtitle.crushing_1": "UNLOCALIZED: Crushing noises", + "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.haunted_bell_use": "UNLOCALIZED: Haunted Bell tolls", + "create.subtitle.scroll_value": "Kliknięcie", + "create.subtitle.crafter_craft": "Mechaniczny stół rzemieślniczy konstruuje", + "create.subtitle.controller_put": "UNLOCALIZED: Controller thumps", + "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.potato_hit": "UNLOCALIZED: Vegetable impacts", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens", + "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.controller_take": "UNLOCALIZED: Lectern empties", "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 [------------------------<-", @@ -1179,14 +1302,6 @@ "block.create.metal_bracket.tooltip": "METALOWY WSPORNIK", "block.create.metal_bracket.tooltip.summary": "_Udekoruj_ swoje _wały_, _koła zębate_ i _rury_ wytrzymałą, przemysłową podporą.", - "block.create.copper_casing.tooltip": "MIEDZIANA OBUDOWA", - "block.create.copper_casing.tooltip.summary": "Solidna obudowa dla maszyn, z wieloma zastosowaniami. Przydatna w dekoracji.", - "block.create.copper_casing.tooltip.condition1": "Kiedy użyta na rurze", - "block.create.copper_casing.tooltip.behaviour1": "_Przykrywa_ rurę _miedzianą obudową_.  Połączenia izolowanych rur zostaną _unieruchomione_ i nie będą reagować na zmiany w ich otoczeniu.", - - "block.create.encased_fluid_pipe.tooltip": "IZOLOWANA RURA", - "block.create.encased_fluid_pipe.tooltip.summary": "Rura _przykryta_ miedzianą obudową.", - "block.create.seat.tooltip": "SIEDZENIE", "block.create.seat.tooltip.summary": "Usiądź i ciesz się jazdą! Przyczepi gracza do _ruchomej maszyny_.  Również świetne do tworzenia stojących mebli! Dostępne w wielu kolorach.", "block.create.seat.tooltip.condition1": "Kliknięcie PPM na siedzenie", @@ -1195,65 +1310,6 @@ "item.create.blaze_cake.tooltip": "PŁOMIENNE CIASTO", "item.create.blaze_cake.tooltip.summary": "Pyszna przekąska dla Twoich cięzko pracujących _płomiennych palników_. Rozpala je wszystkie!", - "block.create.fluid_pipe.tooltip": "RURA", - "block.create.fluid_pipe.tooltip.summary": "Używana do transportu _płynów_. _Mechaniczna pompa_ jest potrzebna, aby wprawić płyny w ruch.", - "block.create.fluid_pipe.tooltip.condition1": "Transport płynów", - "block.create.fluid_pipe.tooltip.behaviour1": "Może połączyć się ze pojemnikami, takimi jak _tygle_ czy _zbiorniki_. Odsłonięte zakończenia rur mogą osuszać lub wypełniać płynami. Uważaj na przecieki!", - "block.create.fluid_pipe.tooltip.condition2": "Kliknięcie PPM z użyciem klucza", - "block.create.fluid_pipe.tooltip.behaviour2": "Tworzy w rurze _okno_, jeśli jest to możliwe.", - - "block.create.hose_pulley.tooltip": "KRĄŻEK Z WĘŻEM", - "block.create.hose_pulley.tooltip.summary": "Używane do _osuszania_ lub _wypełniania_ płynami.", - "block.create.hose_pulley.tooltip.condition1": "Kiedy zasilone siłą obrotową", - "block.create.hose_pulley.tooltip.behaviour1": "_Podnosi_ lub _opuszcza_ wąż; pozycja węża określa, do jakiej _wysokości_ będzie on działał.", - "block.create.hose_pulley.tooltip.condition2": "Kiedy płyny wyciągane są z węża", - "block.create.hose_pulley.tooltip.behaviour2": "Rozpoczyna _osuszanie_ bloków ze zbiornika, do którego opuszczono wąż. Bardzo duże zbiorniki będą uznawane za _nieskończone_.", - "block.create.hose_pulley.tooltip.condition3": "Kiedy płyny pompowane są do węża\n", - "block.create.hose_pulley.tooltip.behaviour3": "Rozpoczyna _wypełnianie_ bloków płynem, aż do wysokości węża.", - - "block.create.fluid_tank.tooltip": "ZBIORNIK", - "block.create.fluid_tank.tooltip.summary": "_Składuje_ wszystkie Twoje ulubione _płyny_. Zmienia rozmiar wraz z wysokością i szerokością.", - "block.create.fluid_tank.tooltip.condition1": "Kliknięcie PPM kluczem", - "block.create.fluid_tank.tooltip.behaviour1": "Tworzy w zbiorniku _okno_, jeśli jest to możliwe.", - - "block.create.creative_fluid_tank.tooltip": "KREATYWNY ZBIORNIK", - "block.create.creative_fluid_tank.tooltip.summary": "Ten _zbiornik_ pozwala na nieskończone powielanie każdego płynu. Zmienia rozmiar wraz z wysokością i szerokością.", - "block.create.creative_fluid_tank.tooltip.condition1": "Kiedy w zbiorniku", - "block.create.creative_fluid_tank.tooltip.behaviour1": "Wszystko, co _wyciąga_ z tego zbiornika będzie dostarczać _nieskończoną ilość_ wybranego płynu. Płyny wpompowane do tego zbiornika będą niszczone.", - "block.create.creative_fluid_tank.tooltip.condition2": "Kliknięcie PPM kluczem", - "block.create.creative_fluid_tank.tooltip.behaviour2": "Tworzy w zbiorniku _okno_, jeśli jest to możliwe.", - - "block.create.fluid_valve.tooltip": "ZAWÓR", - "block.create.fluid_valve.tooltip.summary": "Zatrzymuje przepływ płynu przez rurę", - "block.create.fluid_valve.tooltip.condition1": "Kontrola nad przepływem", - "block.create.fluid_valve.tooltip.behaviour1": "Zastosowanie _siły obrotu_ zamknie _zawór_, zatrzymując przepływ płynu. Odwróć kierunek siły obrotu, aby _otworzyć_ zawór.", - - "block.create.mechanical_pump.tooltip": "MECHANICZNA POMPA", - "block.create.mechanical_pump.tooltip.summary": "Pobiera _siłę obrotu_ i używa jej, aby pompować płyn przez _rurę_. Posiada maksymalny zasięg w obie strony. (domyślnie 16 bloków)", - "block.create.mechanical_pump.tooltip.condition1": "Przepływ", - "block.create.mechanical_pump.tooltip.behaviour1": "Zastosowanie _siły obrotu_ wytwarza ciśnienie, które przepycha _płyn_ przez system _rur_. Odwróć kierunek siły obrotu, aby odwrócić kierunek przepływu.", - "block.create.mechanical_pump.tooltip.control1": "Kliknięcie PPM kluczem", - "block.create.mechanical_pump.tooltip.action1": "Odwraca kierunek _pompowania_.", - - "block.create.smart_fluid_pipe.tooltip": "INTELIGENTA RURA", - "block.create.smart_fluid_pipe.tooltip.summary": "Rura z _filtrem_. Może wybrać, jakie płyny mogą zostać przepuszczone.", - "block.create.smart_fluid_pipe.tooltip.condition1": "Kiedy płyny są wepchnięte", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "Inteligentne rury otrzymujące płyn, który nie pasuje do filtra, zablokują przepływ.", - "block.create.smart_fluid_pipe.tooltip.condition2": "Kiedy przylegający do zbiornika", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "Inteligentne rury _rozpoczynające_ przepływ z dowolnego zbiornika będą wyciągać jedynie te płyny, które _pasują_ do _filtra_.", - - "block.create.spout.tooltip": "KANISTER", - "block.create.spout.tooltip.summary": "Przydatny do _napełniania_ płynami.", - "block.create.spout.tooltip.condition1": "Transport płynów", - "block.create.spout.tooltip.behaviour1": "Kiedy _pojemnik_, taki jak _wiaderko_ lub _butelka_ jest położona pod spodem, kanister spróbuje napełnić go przechowywanym wewnątrz _płynem_.", - "block.create.spout.tooltip.condition2": "Automatyzacja płynów", - "block.create.spout.tooltip.behaviour2": "Kanister postawiony nad _taśmociągiem_ lub _składnicą_ automatycznie zareaguje na _pojemniki_ przechodzące pod spodem.", - - "block.create.item_drain.tooltip": "ODPŁYW", - "block.create.item_drain.tooltip.summary": "Metalowa kratka do opróżniania _pojemników_ z _płynami_.", - "block.create.item_drain.tooltip.condition1": "Transport płynów", - "block.create.item_drain.tooltip.behaviour1": "Kiedy _pojemnik_, taki jak _wiaderko_ lub _butelka_ jest wsadzony od boku, odpływ spróbuje opróżnić go do własnego zbiornika. Przedmiot będzie następnie wyrzucony drugą stroną.", - "item.create.wand_of_symmetry.tooltip": "RÓŻDŻKA SYMETRII", "item.create.wand_of_symmetry.tooltip.summary": "Idealnie odbija lustrzanie bloki wzdłuż wybranych płaszczyzn.", "item.create.wand_of_symmetry.tooltip.condition1": "Kiedy w pasku szybkiego wyboru", @@ -1283,6 +1339,15 @@ "item.create.extendo_grip.tooltip.summary": "Mocno _wydłuża zasięg_ rąk posiadacza.", "item.create.extendo_grip.tooltip.condition1": "Kiedy w drugiej ręce", "item.create.extendo_grip.tooltip.behaviour1": "_Wydłuża zasięg_ głównej ręki.", + "item.create.extendo_grip.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", + + "item.create.potato_cannon.tooltip": "UNLOCALIZED: POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "UNLOCALIZED: Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", + "item.create.potato_cannon.tooltip.behaviour1": "UNLOCALIZED: _Shoots_ a suitable item from your _Inventory_.", + "item.create.potato_cannon.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.filter.tooltip": "FILTR", "item.create.filter.tooltip.summary": "_Kontroluje_ wejścia i wyjścia urządzeń logistycznych z _większą precyzją_, przypasowując przedmioty do listy przedmiotów zawartej w filtrze lub wielu filtrach schowanych jeden w drugi.", @@ -1358,12 +1423,14 @@ "block.create.turntable.tooltip": "TALERZ OBROTOWY", "block.create.turntable.tooltip.summary": "Zamienia _siłę obrotu_ na _chorobę lokomocyjną_.", - "block.create.portable_fluid_interface.tooltip": "PRZENOŚNY INTERFEJS PŁYNÓW", - "block.create.portable_fluid_interface.tooltip.summary": "Przenośne miejsce wymiany służące do _transportu płynów_ z- i do _struktury_ przesuwanej przez tłok, łożysko, wagonik, lub krążek. Dwa interfejsy muszą być _skierowane w swoją stronę_ i być _od 1 do 2 bloków_ od siebie.", - "block.create.portable_fluid_interface.tooltip.condition1": "W czasie poruszania", - "block.create.portable_fluid_interface.tooltip.behaviour1": "Współpracuje ze stojącymi _przenośnymi interfejsami magazynu_, aby przetransportować płyn z- lub do maszyny. Rury wpychające lub wyciągające ze _stojącego interfejsu_ będą działać na zbiorniki _bezpośrednio w maszynie_. Maszyna na chwile stanie, aby wymienić płyny.", - "block.create.portable_fluid_interface.tooltip.condition2": "Kiedy zasilony przez Redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "Natychmiastowo _ucina_ jakiekolwiek aktywne połączenia.", + "block.create.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "PRZEŁĄCZNIK ZAWARTOŚCIOWY", "block.create.stockpile_switch.tooltip.summary": "Przełącza sygnał Redstone bazując na _ilości przedmiotów_ przechowywanych w sąsiadującym bloku. Może posiadać filtr. W odróżnieniu od _komparatora_, przełącznik zawartościowy pozwala na konfigurację _progów_, przy których sygnały są odwrotne.", @@ -1372,6 +1439,10 @@ "block.create.content_observer.tooltip": "DETEKTOR ZAWARTOŚCI", "block.create.content_observer.tooltip.summary": "_Wykrywa przedmioty_ zawarte w sąsiadującym _bloku_ lub _taśmociągu_, które pasują do ustalonego filtra. Kiedy obserwowany blok _zawiera_ ten przedmiot, detektor wyśle _sygnał Redstone_.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "REGULOWANA SKRZYNKA", "block.create.adjustable_crate.tooltip.summary": "Ta skrzynia pozwala na _ręczną kontrolę_ jej pojemności. Może pomieścić do _16 stosów_ dowolnego przedmiotu. Działa z _komparatorami_.", @@ -1383,6 +1454,11 @@ "block.create.creative_crate.tooltip.condition1": "Kiedy przedmiot jest w slocie na filtr", "block.create.creative_crate.tooltip.behaviour1": "Bloki _wyciągające_ przedmioty z tego bloku będą miały _nieskończony zapas_ wybranego przedmiotu. Przedmioty włożone do tej skrzynki będą _usuwane_.", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "TORY STERUJĄCE", "block.create.controller_rail.tooltip.summary": "_Wielokierunkowy_ zasilany tor pozwalający na _dokładną kontrolę_ nad _prędkością wagonika_.", "block.create.controller_rail.tooltip.condition1": "Kiedy zasilone przez Redstone", @@ -1398,26 +1474,61 @@ "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.linked_controller.tooltip.condition4": "UNLOCALIZED: R-Click on Lectern", + "item.create.linked_controller.tooltip.behaviour4": "UNLOCALIZED: Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the wielder 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: Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder 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ł.", + "block.create.peculiar_bell.tooltip": "UNLOCALIZED: PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "UNLOCALIZED: A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + + "block.create.haunted_bell.tooltip": "UNLOCALIZED: HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "UNLOCALIZED: A _Cursed Bell_ haunted by lost souls of the Nether.", + "block.create.haunted_bell.tooltip.condition1": "UNLOCALIZED: When Held or Rang", + "block.create.haunted_bell.tooltip.behaviour1": "UNLOCALIZED: Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn.", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1434,41 +1545,46 @@ "create.ponder.replay": "Powtórka", "create.ponder.think_back": "Powrót", "create.ponder.slow_text": "Komfortowe czytanie", - "create.ponder.shared.movement_anchors": "Z pomocą stelaży lub Super Glue, większe struktury mogą być przesuwane.", - "create.ponder.shared.rpm32": "32 Ob/min", - "create.ponder.shared.sneak_and": "Skradanie +", - "create.ponder.shared.storage_on_contraption": "Pojemniki przyłączone do maszyny będą podnosiły przedmioty automatycznie", + "create.ponder.exit": "UNLOCALIZED: Exit", + "create.ponder.welcome": "UNLOCALIZED: Welcome to Ponder", + "create.ponder.categories": "UNLOCALIZED: Available Categories in Create", + "create.ponder.index_description": "UNLOCALIZED: Click one of the icons to learn about its associated Items and Blocks", + "create.ponder.index_title": "UNLOCALIZED: Ponder Index", + "create.ponder.shared.rpm16": "16 Ob/min", "create.ponder.shared.behaviour_modify_wrench": "To zachowanie może być zmodyfikowane przy pomocy klucza", + "create.ponder.shared.storage_on_contraption": "Pojemniki przyłączone do maszyny będą podnosiły przedmioty automatycznie", + "create.ponder.shared.sneak_and": "Skradanie +", "create.ponder.shared.rpm8": "8 Ob/min", "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm32": "32 Ob/min", "create.ponder.shared.rpm16_source": "Źródło: 16 Ob/min", - "create.ponder.shared.rpm16": "16 Ob/min", - "create.ponder.tag.kinetic_sources": "Źródła siły obrotowej", - "create.ponder.tag.kinetic_sources.description": "Komponenty, które generują siłę obrotu", - "create.ponder.tag.contraption_actor": "Komponenty aktywne maszyn", - "create.ponder.tag.contraption_actor.description": "Komponenty, które posiadają specjalne zachowanie będąc podłączonymi do maszyny", - "create.ponder.tag.arm_targets": "Cele dla mechanicznego ramienia", - "create.ponder.tag.arm_targets.description": "Komponenty, które mogą być wybrane, jako wejście lub wyjście dla mechanicznego ramienia", - "create.ponder.tag.logistics": "Transport przedmiotów", - "create.ponder.tag.logistics.description": "Komponenty, które pomagają w transporcie przedmiotów", - "create.ponder.tag.movement_anchor": "Komponenty ruchome", - "create.ponder.tag.movement_anchor.description": "Komponenty, które pozwalają na tworzenie ruchomych maszyn, poruszając ją na wiele różnych sposobów.", - "create.ponder.tag.creative": "Tryb kreatywny", - "create.ponder.tag.creative.description": "Komponenty niedostępne na trybie przetrwania", - "create.ponder.tag.kinetic_relays": "Bloki obrotowe", - "create.ponder.tag.kinetic_relays.description": "Komponenty, które pomagają w przekazywaniu siły obrotowej w inne miejsca", - "create.ponder.tag.windmill_sails": "Bloki żaglo-podobne", - "create.ponder.tag.windmill_sails.description": "Bloki, które dokładają się do siły, z jaką obracają się łopaty maszyny wiatrakowej.", - "create.ponder.tag.contraption_assembly": "Bloki do tworzenia maszyn", - "create.ponder.tag.contraption_assembly.description": "Narzędzia i komponenty używane do konstrukcji ruchomych maszyn", - "create.ponder.tag.decoration": "Dekoracje", - "create.ponder.tag.decoration.description": "Komponenty używane głównie do celów estetycznych", - "create.ponder.tag.kinetic_appliances": "Urządzenia obrotowe", - "create.ponder.tag.kinetic_appliances.description": "Komponenty używające siły obrotowej", + "create.ponder.shared.movement_anchors": "Z pomocą stelaży lub Super Glue, większe struktury mogą być przesuwane.", "create.ponder.tag.redstone": "Komponenty logiczne", "create.ponder.tag.redstone.description": "Komponenty przydatne w Redstonie", + "create.ponder.tag.contraption_assembly": "Bloki do tworzenia maszyn", + "create.ponder.tag.contraption_assembly.description": "Narzędzia i komponenty używane do konstrukcji ruchomych maszyn", "create.ponder.tag.fluids": "Manipulator płynów", "create.ponder.tag.fluids.description": "Komponenty przydatne przy pracy z płynami", + "create.ponder.tag.decoration": "Dekoracje", + "create.ponder.tag.decoration.description": "Komponenty używane głównie do celów estetycznych", + "create.ponder.tag.windmill_sails": "Bloki żaglo-podobne", + "create.ponder.tag.windmill_sails.description": "Bloki, które dokładają się do siły, z jaką obracają się łopaty maszyny wiatrakowej.", + "create.ponder.tag.arm_targets": "Cele dla mechanicznego ramienia", + "create.ponder.tag.arm_targets.description": "Komponenty, które mogą być wybrane, jako wejście lub wyjście dla mechanicznego ramienia", + "create.ponder.tag.kinetic_appliances": "Urządzenia obrotowe", + "create.ponder.tag.kinetic_appliances.description": "Komponenty używające siły obrotowej", + "create.ponder.tag.kinetic_sources": "Źródła siły obrotowej", + "create.ponder.tag.kinetic_sources.description": "Komponenty, które generują siłę obrotu", + "create.ponder.tag.movement_anchor": "Komponenty ruchome", + "create.ponder.tag.movement_anchor.description": "Komponenty, które pozwalają na tworzenie ruchomych maszyn, poruszając ją na wiele różnych sposobów.", + "create.ponder.tag.kinetic_relays": "Bloki obrotowe", + "create.ponder.tag.kinetic_relays.description": "Komponenty, które pomagają w przekazywaniu siły obrotowej w inne miejsca", + "create.ponder.tag.contraption_actor": "Komponenty aktywne maszyn", + "create.ponder.tag.contraption_actor.description": "Komponenty, które posiadają specjalne zachowanie będąc podłączonymi do maszyny", + "create.ponder.tag.creative": "Tryb kreatywny", + "create.ponder.tag.creative.description": "Komponenty niedostępne na trybie przetrwania", + "create.ponder.tag.logistics": "Transport przedmiotów", + "create.ponder.tag.logistics.description": "Komponenty, które pomagają w transporcie przedmiotów", "create.ponder.adjustable_pulse_repeater.header": "Kontrola sygnałów z wykorzystaniem regulowanych przekaźników pulsu", "create.ponder.adjustable_pulse_repeater.text_1": "Regulowane przekaźniki pulsu emitują krótki puls po opóźnieniu", @@ -1538,11 +1654,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", @@ -1581,6 +1697,7 @@ "create.ponder.cart_assembler_modes.header": "Dostosowywanie orientacji maszyn w wagoniku", "create.ponder.cart_assembler_modes.text_1": "Maszyny w wagoniku obracają się wraz z wagonikiem", "create.ponder.cart_assembler_modes.text_2": "Jeśli monter jest ustawiony na tryb 'Zablokuj obrót', maszyna nigdy nie zmieni swojej orientacji", + "create.ponder.cart_assembler_modes.text_3": "UNLOCALIZED: If the Assembler is set to Lock Rotation, the contraptions' orientation will never change", "create.ponder.cart_assembler_rails.header": "Inne typy wagoników i torów", "create.ponder.cart_assembler_rails.text_1": "Montery wagoników stojące na zwykłych torach nie zmienią prędkości przejeżdżającego wagonika", @@ -1634,6 +1751,12 @@ "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_fluid_tank.text_1": "UNLOCALIZED: Creative Fluid Tanks can be used to provide a bottomless supply of fluid", + "create.ponder.creative_fluid_tank.text_2": "UNLOCALIZED: Right-Click with a fluid containing item to configure it", + "create.ponder.creative_fluid_tank.text_3": "UNLOCALIZED: Pipe Networks can now endlessly draw the assigned fluid from the tank", + "create.ponder.creative_fluid_tank.text_4": "UNLOCALIZED: Any Fluids pushed back into a Creative Fluid Tank will be voided", + "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 +1793,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ść", @@ -1686,7 +1815,13 @@ "create.ponder.empty_blaze_burner.text_2": "Ewentualnie, Płomyk może być zabrany prosto z jego Spawnera", "create.ponder.empty_blaze_burner.text_3": "Masz teraz idealne źródło ciepła dla przeróżnych maszyn", "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.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item", + "create.ponder.empty_blaze_burner.text_6": "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", @@ -1706,6 +1841,35 @@ "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_sizes.text_1": "UNLOCALIZED: Fluid Tanks can be combined to increase the total capacity", + "create.ponder.fluid_tank_sizes.text_2": "UNLOCALIZED: Their base square can be up to 3 blocks wide...", + "create.ponder.fluid_tank_sizes.text_3": "UNLOCALIZED: ...and grow in height by more than 30 additional layers", + "create.ponder.fluid_tank_sizes.text_4": "UNLOCALIZED: Using a Wrench, a tanks' window can be toggled", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.fluid_tank_storage.text_1": "UNLOCALIZED: Fluid Tanks can be used to store large amounts of fluid", + "create.ponder.fluid_tank_storage.text_2": "UNLOCALIZED: Pipe networks can push and pull fluids from any side", + "create.ponder.fluid_tank_storage.text_3": "UNLOCALIZED: The contained fluid can be measured by a Comparator", + "create.ponder.fluid_tank_storage.text_4": "UNLOCALIZED: However, in Survival Mode Fluids cannot be added or taken manually", + "create.ponder.fluid_tank_storage.text_5": "UNLOCALIZED: You can use Basins, Item Drains and Spouts to drain or fill fluid containing items", + "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 +1943,34 @@ "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.text_1": "UNLOCALIZED: Hose Pulleys can be used to fill or drain large bodies of Fluid", + "create.ponder.hose_pulley.text_2": "UNLOCALIZED: With the Kinetic Input, the height of the pulleys' hose can be controlled", + "create.ponder.hose_pulley.text_3": "UNLOCALIZED: The Pulley retracts while the input rotation is inverted", + "create.ponder.hose_pulley.text_4": "UNLOCALIZED: On the opposite side, pipes can be connected", + "create.ponder.hose_pulley.text_5": "UNLOCALIZED: Attached pipe networks can either provide fluid to the hose...", + "create.ponder.hose_pulley.text_6": "UNLOCALIZED: ...or pull from it, draining the pool instead", + "create.ponder.hose_pulley.text_7": "UNLOCALIZED: Fill and Drain speed of the pulley depends entirely on the fluid networks' throughput", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + "create.ponder.hose_pulley_infinite.text_1": "UNLOCALIZED: When deploying the Hose Pulley into a large enough ocean...", + "create.ponder.hose_pulley_infinite.text_2": "UNLOCALIZED: It will provide/dispose fluids without affecting the source", + "create.ponder.hose_pulley_infinite.text_3": "UNLOCALIZED: Pipe networks can limitlessly take fluids from/to such pulleys", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + "create.ponder.hose_pulley_level.text_1": "UNLOCALIZED: While fully retracted, the Hose Pulley cannot operate", + "create.ponder.hose_pulley_level.text_2": "UNLOCALIZED: Draining runs from top to bottom", + "create.ponder.hose_pulley_level.text_3": "UNLOCALIZED: The surface level will end up just below where the hose ends", + "create.ponder.hose_pulley_level.text_4": "UNLOCALIZED: Filling runs from bottom to top", + "create.ponder.hose_pulley_level.text_5": "UNLOCALIZED: The filled pool will not grow beyond the layer above the hose end", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.item_drain.text_1": "UNLOCALIZED: Item Drains can extract fluids from items", + "create.ponder.item_drain.text_2": "UNLOCALIZED: Right-click it to pour fluids from your held item into it", + "create.ponder.item_drain.text_3": "UNLOCALIZED: When items are inserted from the side...", + "create.ponder.item_drain.text_4": "UNLOCALIZED: ...they roll across, emptying out their contained fluid", + "create.ponder.item_drain.text_5": "UNLOCALIZED: Pipe Networks can now pull the fluid from the drains' internal buffer", + "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 +2093,21 @@ "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_flow.text_1": "UNLOCALIZED: Mechanical Pumps govern the flow of their attached pipe networks", + "create.ponder.mechanical_pump_flow.text_2": "UNLOCALIZED: When powered, their arrow indicates the direction of flow", + "create.ponder.mechanical_pump_flow.text_3": "UNLOCALIZED: The network behind is now pulling fluids...", + "create.ponder.mechanical_pump_flow.text_4": "UNLOCALIZED: ...while the network in front is transferring it outward", + "create.ponder.mechanical_pump_flow.text_5": "UNLOCALIZED: Reversing the input rotation reverses the direction of flow", + "create.ponder.mechanical_pump_flow.text_6": "UNLOCALIZED: Use a Wrench to reverse the orientation of pumps manually", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_pump_speed.text_1": "UNLOCALIZED: Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away", + "create.ponder.mechanical_pump_speed.text_2": "UNLOCALIZED: Speeding up the input rotation changes the speed of flow propagation...", + "create.ponder.mechanical_pump_speed.text_3": "UNLOCALIZED: ...aswell as how quickly fluids are transferred", + "create.ponder.mechanical_pump_speed.text_4": "UNLOCALIZED: Pumps can combine their throughputs within shared pipe networks", + "create.ponder.mechanical_pump_speed.text_5": "UNLOCALIZED: Alternating their orientation can help align their flow directions", + "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ą", @@ -1926,11 +2133,22 @@ "create.ponder.nixie_tube.header": "Używanie lamp cyfrowych", "create.ponder.nixie_tube.text_1": "Kiedy zasilone, lampy cyfrowe wyświetlą siłę sygnału Redstone, jaki otrzymują", "create.ponder.nixie_tube.text_2": "Używając znaczników i kowadła można wyświetlić własny tekst", + "create.ponder.nixie_tube.text_3": "UNLOCALIZED: Right-Click with Dye to change their display colour", "create.ponder.piston_pole.header": "Przedłużenia tłoka", "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.text_1": "UNLOCALIZED: Fluid Tanks on moving contraptions cannot be accessed by any pipes", + "create.ponder.portable_fluid_interface.text_2": "UNLOCALIZED: This component can interact with fluid tanks without the need to stop the contraption", + "create.ponder.portable_fluid_interface.text_3": "UNLOCALIZED: Place a second one with a gap of 1 or 2 blocks inbetween", + "create.ponder.portable_fluid_interface.text_4": "UNLOCALIZED: Whenever they pass by each other, they will engage in a connection", + "create.ponder.portable_fluid_interface.text_5": "UNLOCALIZED: While engaged, the stationary interface will represent ALL Tanks on the contraption", + "create.ponder.portable_fluid_interface.text_6": "UNLOCALIZED: Fluid can now be inserted...", + "create.ponder.portable_fluid_interface.text_7": "UNLOCALIZED: ...or extracted from the contraption", + "create.ponder.portable_fluid_interface.text_8": "UNLOCALIZED: After no contents have been exchanged for a while, the contraption will continue on its way", + "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 +2246,25 @@ "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.smart_pipe.text_1": "UNLOCALIZED: Smart pipes can help control flows by fluid type", + "create.ponder.smart_pipe.text_2": "UNLOCALIZED: When placed directly at the source, they can specify the type of fluid to extract", + "create.ponder.smart_pipe.text_3": "UNLOCALIZED: Simply Right-Click their filter slot with any item containing the desired fluid", + "create.ponder.smart_pipe.text_4": "UNLOCALIZED: When placed further down a pipe network, smart pipes will only let matching fluids continue", + "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_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.spout_filling.text_1": "UNLOCALIZED: The Spout can fill fluid holding items provided beneath it", + "create.ponder.spout_filling.text_2": "UNLOCALIZED: The content of a Spout cannot be accessed manually", + "create.ponder.spout_filling.text_3": "UNLOCALIZED: Instead, Pipes can be used to supply it with fluids", + "create.ponder.spout_filling.text_4": "UNLOCALIZED: The Input items can be placed on a Depot under the Spout", + "create.ponder.spout_filling.text_5": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.spout_filling.text_6": "UNLOCALIZED: The Spout will hold and process them automatically", + "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 +2296,12 @@ "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.valve_pipe.text_1": "UNLOCALIZED: Valve pipes help control fluids propagating through pipe networks", + "create.ponder.valve_pipe.text_2": "UNLOCALIZED: Their shaft input controls whether fluid is currently allowed through", + "create.ponder.valve_pipe.text_3": "UNLOCALIZED: Given Rotational Force in the opening direction, the valve will open up", + "create.ponder.valve_pipe.text_4": "UNLOCALIZED: It can be closed again by reversing the input rotation", + "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..9f1e08c86 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: 1846", "_": "->------------------------] Game Elements [------------------------<-", @@ -28,12 +28,16 @@ "block.create.belt": "Esteira Mecânica", "block.create.birch_window": "UNLOCALIZED: Birch Window", "block.create.birch_window_pane": "UNLOCALIZED: Birch Window Pane", + "block.create.black_nixie_tube": "UNLOCALIZED: Black Nixie Tube", "block.create.black_sail": "UNLOCALIZED: Black Sail", "block.create.black_seat": "UNLOCALIZED: Black Seat", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "UNLOCALIZED: Black Valve Handle", "block.create.blaze_burner": "UNLOCALIZED: Blaze Burner", + "block.create.blue_nixie_tube": "UNLOCALIZED: Blue Nixie Tube", "block.create.blue_sail": "UNLOCALIZED: Blue Sail", "block.create.blue_seat": "UNLOCALIZED: Blue Seat", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "UNLOCALIZED: Blue Valve Handle", "block.create.brass_belt_funnel": "UNLOCALIZED: Brass Belt Funnel", "block.create.brass_block": "UNLOCALIZED: Block of Brass", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "UNLOCALIZED: Brass Encased Shaft", "block.create.brass_funnel": "UNLOCALIZED: Brass Funnel", "block.create.brass_tunnel": "UNLOCALIZED: Brass Tunnel", + "block.create.brown_nixie_tube": "UNLOCALIZED: Brown Nixie Tube", "block.create.brown_sail": "UNLOCALIZED: Brown Sail", "block.create.brown_seat": "UNLOCALIZED: Brown Seat", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "UNLOCALIZED: Brown Valve Handle", "block.create.cart_assembler": "UNLOCALIZED: Cart Assembler", "block.create.chiseled_dark_scoria": "UNLOCALIZED: Chiseled Dark Scoria", @@ -73,8 +79,10 @@ "block.create.crushing_wheel": "Roda de Moer", "block.create.crushing_wheel_controller": "UNLOCALIZED: Crushing Wheel Controller", "block.create.cuckoo_clock": "UNLOCALIZED: Cuckoo Clock", + "block.create.cyan_nixie_tube": "UNLOCALIZED: Cyan Nixie Tube", "block.create.cyan_sail": "UNLOCALIZED: Cyan Sail", "block.create.cyan_seat": "UNLOCALIZED: Cyan Seat", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "UNLOCALIZED: Cyan Valve Handle", "block.create.dark_oak_window": "UNLOCALIZED: Dark Oak Window", "block.create.dark_oak_window_pane": "UNLOCALIZED: Dark Oak Window Pane", @@ -179,13 +187,18 @@ "block.create.granite_cobblestone_stairs": "UNLOCALIZED: Granite Cobblestone Stairs", "block.create.granite_cobblestone_wall": "UNLOCALIZED: Granite Cobblestone Wall", "block.create.granite_pillar": "UNLOCALIZED: Granite Pillar", + "block.create.gray_nixie_tube": "UNLOCALIZED: Gray Nixie Tube", "block.create.gray_sail": "UNLOCALIZED: Gray Sail", "block.create.gray_seat": "UNLOCALIZED: Gray Seat", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "UNLOCALIZED: Gray Valve Handle", + "block.create.green_nixie_tube": "UNLOCALIZED: Green Nixie Tube", "block.create.green_sail": "UNLOCALIZED: Green Sail", "block.create.green_seat": "UNLOCALIZED: Green Seat", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "UNLOCALIZED: Green Valve Handle", "block.create.hand_crank": "UNLOCALIZED: Hand Crank", + "block.create.haunted_bell": "UNLOCALIZED: Haunted Bell", "block.create.honey": "UNLOCALIZED: Honey", "block.create.horizontal_framed_glass": "UNLOCALIZED: Horizontal Framed Glass", "block.create.horizontal_framed_glass_pane": "UNLOCALIZED: Horizontal Framed Glass Pane", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "UNLOCALIZED: Layered Limestone", "block.create.layered_scoria": "UNLOCALIZED: Layered Scoria", "block.create.layered_weathered_limestone": "UNLOCALIZED: Layered Weathered Limestone", + "block.create.lectern_controller": "UNLOCALIZED: Lectern Controller", + "block.create.light_blue_nixie_tube": "UNLOCALIZED: Light Blue Nixie Tube", "block.create.light_blue_sail": "UNLOCALIZED: Light Blue Sail", "block.create.light_blue_seat": "UNLOCALIZED: Light Blue Seat", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "UNLOCALIZED: Light Blue Valve Handle", + "block.create.light_gray_nixie_tube": "UNLOCALIZED: Light Gray Nixie Tube", "block.create.light_gray_sail": "UNLOCALIZED: Light Gray Sail", "block.create.light_gray_seat": "UNLOCALIZED: Light Gray Seat", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "UNLOCALIZED: Light Gray Valve Handle", + "block.create.lime_nixie_tube": "UNLOCALIZED: Lime Nixie Tube", "block.create.lime_sail": "UNLOCALIZED: Lime Sail", "block.create.lime_seat": "UNLOCALIZED: Lime Seat", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "UNLOCALIZED: Lime Valve Handle", "block.create.limesand": "Areia Calcária", "block.create.limestone": "Calcário", @@ -225,8 +245,10 @@ "block.create.limestone_pillar": "Pilar de Calcário", "block.create.linear_chassis": "Chassis de Translado", "block.create.lit_blaze_burner": "UNLOCALIZED: Lit Blaze Burner", + "block.create.magenta_nixie_tube": "UNLOCALIZED: Magenta Nixie Tube", "block.create.magenta_sail": "UNLOCALIZED: Magenta Sail", "block.create.magenta_seat": "UNLOCALIZED: Magenta Seat", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "UNLOCALIZED: Magenta Valve Handle", "block.create.mechanical_arm": "UNLOCALIZED: Mechanical Arm", "block.create.mechanical_bearing": "Rolamento Mecânico", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "UNLOCALIZED: Oak Window Pane", "block.create.orange_sail": "UNLOCALIZED: Orange Sail", "block.create.orange_seat": "UNLOCALIZED: Orange Seat", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "UNLOCALIZED: Orange Valve Handle", "block.create.ornate_iron_window": "UNLOCALIZED: Ornate Iron Window", "block.create.ornate_iron_window_pane": "UNLOCALIZED: Ornate Iron Window Pane", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "UNLOCALIZED: Paved Weathered Limestone Slab", "block.create.paved_weathered_limestone_stairs": "UNLOCALIZED: Paved Weathered Limestone Stairs", "block.create.paved_weathered_limestone_wall": "UNLOCALIZED: Paved Weathered Limestone Wall", + "block.create.peculiar_bell": "UNLOCALIZED: Peculiar Bell", + "block.create.pink_nixie_tube": "UNLOCALIZED: Pink Nixie Tube", "block.create.pink_sail": "UNLOCALIZED: Pink Sail", "block.create.pink_seat": "UNLOCALIZED: Pink Seat", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "UNLOCALIZED: Pink Valve Handle", "block.create.piston_extension_pole": "Vara de Extensão do Pistão", "block.create.polished_dark_scoria": "UNLOCALIZED: Polished Dark Scoria", @@ -342,12 +368,16 @@ "block.create.powered_toggle_latch": "UNLOCALIZED: Powered Toggle Latch", "block.create.pulley_magnet": "UNLOCALIZED: Pulley Magnet", "block.create.pulse_repeater": "Repetidor de Pulso", + "block.create.purple_nixie_tube": "UNLOCALIZED: Purple Nixie Tube", "block.create.purple_sail": "UNLOCALIZED: Purple Sail", "block.create.purple_seat": "UNLOCALIZED: Purple Seat", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "UNLOCALIZED: Purple Valve Handle", "block.create.radial_chassis": "Chassis de Rotação", + "block.create.red_nixie_tube": "UNLOCALIZED: Red Nixie Tube", "block.create.red_sail": "UNLOCALIZED: Red Sail", "block.create.red_seat": "UNLOCALIZED: Red Seat", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "UNLOCALIZED: Red Valve Handle", "block.create.redstone_contact": "Contato de Redstone", "block.create.redstone_link": "Conexão de Redstone", @@ -402,24 +432,32 @@ "block.create.weathered_limestone_cobblestone_wall": "UNLOCALIZED: Weathered Limestone Cobblestone Wall", "block.create.weathered_limestone_pillar": "Pilar de Calcário Resistido", "block.create.weighted_ejector": "UNLOCALIZED: Weighted Ejector", + "block.create.white_nixie_tube": "UNLOCALIZED: White Nixie Tube", "block.create.white_sail": "UNLOCALIZED: White Sail", "block.create.white_seat": "UNLOCALIZED: White Seat", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "UNLOCALIZED: White Valve Handle", "block.create.windmill_bearing": "UNLOCALIZED: Windmill Bearing", "block.create.wooden_bracket": "UNLOCALIZED: Wooden Bracket", + "block.create.yellow_nixie_tube": "UNLOCALIZED: Yellow Nixie Tube", "block.create.yellow_sail": "UNLOCALIZED: Yellow Sail", "block.create.yellow_seat": "UNLOCALIZED: Yellow Seat", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "UNLOCALIZED: Yellow Valve Handle", "block.create.zinc_block": "UNLOCALIZED: Block of Zinc", "block.create.zinc_ore": "UNLOCALIZED: Zinc Ore", + "enchantment.create.capacity": "UNLOCALIZED: Capacity", + "enchantment.create.potato_recovery": "UNLOCALIZED: Potato Recovery", + "entity.create.contraption": "UNLOCALIZED: Contraption", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "entity.create.potato_projectile": "UNLOCALIZED: Potato Projectile", "entity.create.seat": "UNLOCALIZED: Seat", "entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption", "entity.create.super_glue": "UNLOCALIZED: Super Glue", - "fluid.create.milk": "UNLOCALIZED: Milk", "fluid.create.potion": "UNLOCALIZED: Potion", "fluid.create.tea": "UNLOCALIZED: Builder's Tea", @@ -444,6 +482,8 @@ "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.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "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", @@ -472,13 +512,17 @@ "item.create.handheld_worldshaper": "UNLOCALIZED: Creative Worldshaper", "item.create.honey_bucket": "UNLOCALIZED: Honey Bucket", "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", - "item.create.integrated_circuit": "UNLOCALIZED: Integrated Circuit", + "item.create.incomplete_cogwheel": "UNLOCALIZED: Incomplete Cogwheel", + "item.create.incomplete_large_cogwheel": "UNLOCALIZED: Incomplete Large Cogwheel", + "item.create.incomplete_precision_mechanism": "UNLOCALIZED: Incomplete Precision Mechanism", "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", + "item.create.potato_cannon": "UNLOCALIZED: Potato Cannon", "item.create.powdered_obsidian": "UNLOCALIZED: Powdered Obsidian", + "item.create.precision_mechanism": "UNLOCALIZED: Precision Mechanism", "item.create.propeller": "Hélice", "item.create.red_sand_paper": "UNLOCALIZED: Red Sand Paper", "item.create.refined_radiance": "UNLOCALIZED: Refined Radiance", @@ -623,8 +667,8 @@ "advancement.create.flywheel.desc": "UNLOCALIZED: Successfully connect an engine to the Flywheel.", "advancement.create.overstress_flywheel": "UNLOCALIZED: High levels of Stress", "advancement.create.overstress_flywheel.desc": "UNLOCALIZED: Overstress a Furnace Engine.", - "advancement.create.integrated_circuit": "UNLOCALIZED: Complex Calculation", - "advancement.create.integrated_circuit.desc": "UNLOCALIZED: Assemble an Integrated Circuit.", + "advancement.create.precision_mechanism": "UNLOCALIZED: Complex Curiosities", + "advancement.create.precision_mechanism.desc": "UNLOCALIZED: Assemble a Precision Mechanism.", "advancement.create.mechanical_arm": "UNLOCALIZED: Busy Hands!", "advancement.create.mechanical_arm.desc": "UNLOCALIZED: Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch as it does all the work for you.", "advancement.create.musical_arm": "UNLOCALIZED: Play Me My Theme Tune!", @@ -639,7 +683,7 @@ "advancement.create.crushing_wheel.desc": "UNLOCALIZED: Create some Crushing Wheels to break down more materials more effectively.", "advancement.create.blaze_cake": "UNLOCALIZED: Sugar Rush", "advancement.create.blaze_cake.desc": "UNLOCALIZED: Bake your blaze burner a special cake.", - "advancement.create.chromatic_compound": "UNLOCALIZED: Bipolar Minerals", + "advancement.create.chromatic_compound": "UNLOCALIZED: Mysterious Minerals", "advancement.create.chromatic_compound.desc": "UNLOCALIZED: Create a Bar of Chromatic Compound.", "advancement.create.shadow_steel": "UNLOCALIZED: Void Returner", "advancement.create.shadow_steel.desc": "UNLOCALIZED: Create Shadow Steel, a metal bar of nothingness.", @@ -651,6 +695,8 @@ "advancement.create.wand_of_symmetry.desc": "UNLOCALIZED: Craft a Staff of Symmetry.", "advancement.create.extendo_grip": "UNLOCALIZED: Boioioing!", "advancement.create.extendo_grip.desc": "UNLOCALIZED: Get hold of an Extendo Grip.", + "advancement.create.potato_cannon": "UNLOCALIZED: Fwoomp!", + "advancement.create.potato_cannon.desc": "UNLOCALIZED: Defeat an enemy with your Potato Cannon.", "advancement.create.dual_extendo_grip": "UNLOCALIZED: Ultimate Boing-age", "advancement.create.dual_extendo_grip.desc": "UNLOCALIZED: Dual wield Extendo Grips for super-human reach.", "advancement.create.eob": "UNLOCALIZED: End of Beta", @@ -663,15 +709,31 @@ "itemGroup.create.palettes": "UNLOCALIZED: Create Palettes", "death.attack.create.crush": "%1$s foi processado pelas Rodas de Moer", + "death.attack.create.crush.player": "UNLOCALIZED: %1$s was thrown into Crushing Wheels by %2$s", "death.attack.create.fan_fire": "%1$s foi queimado por ar quente", + "death.attack.create.fan_fire.player": "UNLOCALIZED: %1$s was thrown into a smoker by %2$s", "death.attack.create.fan_lava": "%1$s foi queimado pelo ventilador de lava", + "death.attack.create.fan_lava.player": "UNLOCALIZED: %1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "%1$s foi empalado pela Furadeira Mecânica", + "death.attack.create.mechanical_drill.player": "UNLOCALIZED: %1$s was thrown in front of a Drill by %2$s", "death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by a Mechanical Saw", + "death.attack.create.mechanical_saw.player": "UNLOCALIZED: %1$s was thrown into a Saw by %2$s", + "death.attack.create.potato_cannon": "UNLOCALIZED: %1$s was shot by %2$s's Potato Cannon", + "death.attack.create.potato_cannon.item": "UNLOCALIZED: %1$s was shot by %2$s using %3$s", "death.attack.create.cuckoo_clock_explosion": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", + "death.attack.create.cuckoo_clock_explosion.player": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", "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.ponder_index": "UNLOCALIZED: Ponder Index", + "create.menu.only_ingame": "UNLOCALIZED: Available in the Pause Menu", + "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", @@ -696,7 +758,18 @@ "create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion", "create.recipe.spout_filling": "UNLOCALIZED: Filling by Spout", "create.recipe.draining": "UNLOCALIZED: Item Draining", + "create.recipe.sequenced_assembly": "UNLOCALIZED: Sequenced Assembly", + "create.recipe.assembly.next": "UNLOCALIZED: Next: %1$s", + "create.recipe.assembly.step": "UNLOCALIZED: Step %1$s:", + "create.recipe.assembly.progress": "UNLOCALIZED: Progress: %1$s/%2$s", + "create.recipe.assembly.pressing": "UNLOCALIZED: Process in Press", + "create.recipe.assembly.spout_filling_fluid": "UNLOCALIZED: Spout %1$s", + "create.recipe.assembly.deploying_item": "UNLOCALIZED: Deploy %1$s", + "create.recipe.assembly.cutting": "UNLOCALIZED: Cut with Saw", + "create.recipe.assembly.repeat": "UNLOCALIZED: Repeat Sequence %1$s Times", + "create.recipe.assembly.junk": "UNLOCALIZED: Random salvage", "create.recipe.processing.chance": "%1$s%% de chance", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required", "create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated", "create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated", @@ -725,6 +798,7 @@ "create.action.discard": "Descartar", "create.keyinfo.toolmenu": "Menu Focal da Ferramenta", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "UNLOCALIZED: Simulate Mousewheel Up (inworld)", "create.keyinfo.scrolldown": "UNLOCALIZED: Simulate Mousewheel Down (inworld)", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "UNLOCALIZED: Shift to Scroll Faster", "create.gui.toolmenu.focusKey": "Segure [%1$s] para Focar", "create.gui.toolmenu.cycle": "[SCROLL] para Circular", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Espelhar", "create.gui.symmetryWand.orientation": "Orientação", @@ -981,18 +1062,14 @@ "create.item_attributes.placeable.inverted": "UNLOCALIZED: is not placeable", "create.item_attributes.consumable": "UNLOCALIZED: can be eaten", "create.item_attributes.consumable.inverted": "UNLOCALIZED: cannot be eaten", - "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", - "create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted", - "create.item_attributes.washable": "UNLOCALIZED: can be Washed", - "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", - "create.item_attributes.smokable": "UNLOCALIZED: can be Smoked", - "create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked", - "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", - "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", - "create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace", - "create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace", + "create.item_attributes.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "UNLOCALIZED: is enchanted", "create.item_attributes.enchanted.inverted": "UNLOCALIZED: is unenchanted", + "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.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "UNLOCALIZED: is damaged", "create.item_attributes.damaged.inverted": "UNLOCALIZED: is not damaged", "create.item_attributes.badly_damaged": "UNLOCALIZED: is heavily damaged", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "UNLOCALIZED: cannot be equipped", "create.item_attributes.furnace_fuel": "UNLOCALIZED: is furnace fuel", "create.item_attributes.furnace_fuel.inverted": "UNLOCALIZED: is not furnace fuel", + "create.item_attributes.washable": "UNLOCALIZED: can be Washed", + "create.item_attributes.washable.inverted": "UNLOCALIZED: cannot be Washed", + "create.item_attributes.crushable": "UNLOCALIZED: can be Crushed", + "create.item_attributes.crushable.inverted": "UNLOCALIZED: cannot be Crushed", + "create.item_attributes.smeltable": "UNLOCALIZED: can be Smelted", + "create.item_attributes.smeltable.inverted": "UNLOCALIZED: cannot be Smelted", + "create.item_attributes.smokable": "UNLOCALIZED: can be Smoked", + "create.item_attributes.smokable.inverted": "UNLOCALIZED: cannot be Smoked", + "create.item_attributes.blastable": "UNLOCALIZED: is smeltable in Blast Furnace", + "create.item_attributes.blastable.inverted": "UNLOCALIZED: is not smeltable in Blast Furnace", + "create.item_attributes.shulker_level": "UNLOCALIZED: is shulker %1$s", + "create.item_attributes.shulker_level.inverted": "UNLOCALIZED: is shulker not %1$s", + "create.item_attributes.shulker_level.full": "UNLOCALIZED: full", + "create.item_attributes.shulker_level.empty": "UNLOCALIZED: empty", + "create.item_attributes.shulker_level.partial": "UNLOCALIZED: partially filled", "create.item_attributes.in_tag": "UNLOCALIZED: is tagged %1$s", "create.item_attributes.in_tag.inverted": "UNLOCALIZED: is not tagged %1$s", "create.item_attributes.in_item_group": "UNLOCALIZED: is in group '%1$s'", @@ -1013,8 +1105,6 @@ "create.item_attributes.has_enchant.inverted": "UNLOCALIZED: is not enchanted with %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.has_fluid": "UNLOCALIZED: contains %1$s", "create.item_attributes.has_fluid.inverted": "UNLOCALIZED: does not contain %1$s", "create.item_attributes.has_name": "UNLOCALIZED: has the custom name %1$s", @@ -1029,14 +1119,14 @@ "create.item_attributes.book_copy_second.inverted": "UNLOCALIZED: is not a second-generation copy", "create.item_attributes.book_copy_tattered": "UNLOCALIZED: is a tattered mess", "create.item_attributes.book_copy_tattered.inverted": "UNLOCALIZED: is not a tattered mess", - "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", - "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", - "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", "create.item_attributes.astralsorcery_amulet": "UNLOCALIZED: improves %1$s", "create.item_attributes.astralsorcery_amulet.inverted": "UNLOCALIZED: does not improve %1$s", + "create.item_attributes.astralsorcery_constellation": "UNLOCALIZED: is attuned to %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "UNLOCALIZED: is not attuned to %1$s", + "create.item_attributes.astralsorcery_crystal": "UNLOCALIZED: has crystal attribute %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "UNLOCALIZED: does not have crystal attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem": "UNLOCALIZED: has perk attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "UNLOCALIZED: does not have perk attribute %1$s", "create.gui.attribute_filter.no_selected_attributes": "UNLOCALIZED: No attributes selected", "create.gui.attribute_filter.selected_attributes": "UNLOCALIZED: Selected attributes:", @@ -1104,6 +1194,27 @@ "create.tooltip.chute.fans_pull_up": "UNLOCALIZED: Fans pull from Above", "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "UNLOCALIZED: Currently distributing:", + "create.tooltip.brass_tunnel.contains_entry": "UNLOCALIZED: > %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "UNLOCALIZED: Right-Click to retrieve", + + "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.potato_cannon.ammo.attack_damage": "UNLOCALIZED: %1$s Attack Damage", + "create.potato_cannon.ammo.reload_ticks": "UNLOCALIZED: %1$s Reload Ticks", + "create.potato_cannon.ammo.knockback": "UNLOCALIZED: %1$s Knockback", "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", @@ -1132,32 +1243,44 @@ "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.contraption_disassemble": "UNLOCALIZED: Contraption stops", + "create.subtitle.peculiar_bell_use": "UNLOCALIZED: Peculiar Bell tolls", + "create.subtitle.mixing": "UNLOCALIZED: Mixing noises", + "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", + "create.subtitle.fwoomp": "UNLOCALIZED: Potato Launcher fwoomps", + "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", + "create.subtitle.crushing_1": "UNLOCALIZED: Crushing noises", + "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", + "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel flaps", + "create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings", + "create.subtitle.haunted_bell_use": "UNLOCALIZED: Haunted Bell tolls", + "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.controller_put": "UNLOCALIZED: Controller thumps", + "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.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.potato_hit": "UNLOCALIZED: Vegetable impacts", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.haunted_bell_convert": "UNLOCALIZED: Haunted Bell awakens", "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", - "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", "create.subtitle.deny": "UNLOCALIZED: Declining boop", - "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", "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.controller_take": "UNLOCALIZED: Lectern empties", "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", @@ -1179,14 +1302,6 @@ "block.create.metal_bracket.tooltip": "UNLOCALIZED: METAL BRACKET", "block.create.metal_bracket.tooltip.summary": "UNLOCALIZED: _Decorate_ your _Shafts, Cogwheels_ and _Pipes_ with an industrial and sturdy bit of reinforcement.", - "block.create.copper_casing.tooltip": "UNLOCALIZED: COPPER CASING", - "block.create.copper_casing.tooltip.summary": "UNLOCALIZED: Robust machine casing with a variety of uses. Safe for decoration.", - "block.create.copper_casing.tooltip.condition1": "UNLOCALIZED: When used on Fluid Pipe", - "block.create.copper_casing.tooltip.behaviour1": "UNLOCALIZED: _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": "UNLOCALIZED: ENCASED FLUID PIPE", - "block.create.encased_fluid_pipe.tooltip.summary": "UNLOCALIZED: A _Fluid Pipe_ encased with the _Copper Casing_.", - "block.create.seat.tooltip": "UNLOCALIZED: SEAT", "block.create.seat.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: Right click on Seat", @@ -1195,65 +1310,6 @@ "item.create.blaze_cake.tooltip": "UNLOCALIZED: BLAZE CAKE", "item.create.blaze_cake.tooltip.summary": "UNLOCALIZED: A Delicious treat for your hard-working _Blaze Burners_. Gets them all fired up!", - "block.create.fluid_pipe.tooltip": "UNLOCALIZED: FLUID PIPE", - "block.create.fluid_pipe.tooltip.summary": "UNLOCALIZED: Used for moving _fluids_ around. Needs a _Mechanical Pump_ to get the _fluid_ moving.", - "block.create.fluid_pipe.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.fluid_pipe.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Places a window on the pipe if available", - - "block.create.hose_pulley.tooltip": "UNLOCALIZED: HOSE PULLEY", - "block.create.hose_pulley.tooltip.summary": "UNLOCALIZED: Used for _placing_ or _draining_ large _fluid bodies_ in the world.", - "block.create.hose_pulley.tooltip.condition1": "UNLOCALIZED: When Powered by Kinetics", - "block.create.hose_pulley.tooltip.behaviour1": "UNLOCALIZED: _Raises_ or _Lowers_ the hose, location of the hose determines up to which _height extraction_ or _filling_ will act.", - "block.create.hose_pulley.tooltip.condition2": "UNLOCALIZED: When Fluids pulled from Pulley", - "block.create.hose_pulley.tooltip.behaviour2": "UNLOCALIZED: 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": "UNLOCALIZED: When Fluids pushed to Pulley", - "block.create.hose_pulley.tooltip.behaviour3": "UNLOCALIZED: Starts _filling fluid_ into the world _up to_ the _hose_ ends' _height_.", - - "block.create.fluid_tank.tooltip": "UNLOCALIZED: FLUID TANK", - "block.create.fluid_tank.tooltip.summary": "UNLOCALIZED: _Stores_ all your favourite _fluids_. Scales in width and height.", - "block.create.fluid_tank.tooltip.condition1": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_tank.tooltip.behaviour1": "UNLOCALIZED: Changes the optional window", - - "block.create.creative_fluid_tank.tooltip": "UNLOCALIZED: CREATIVE FLUID TANK", - "block.create.creative_fluid_tank.tooltip.summary": "UNLOCALIZED: This _Fluid Tank_ allows infinite replication of any Fluid. Scales in width and height.", - "block.create.creative_fluid_tank.tooltip.condition1": "UNLOCALIZED: When Fluid in Tank", - "block.create.creative_fluid_tank.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.creative_fluid_tank.tooltip.behaviour2": "UNLOCALIZED: Changes the optional window", - - "block.create.fluid_valve.tooltip": "UNLOCALIZED: FLUID VALVE", - "block.create.fluid_valve.tooltip.summary": "UNLOCALIZED: Halts the flow of fluid down a pipe.", - "block.create.fluid_valve.tooltip.condition1": "UNLOCALIZED: Controllable flow", - "block.create.fluid_valve.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: MECHANICAL PUMP", - "block.create.mechanical_pump.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: Fluid Flow", - "block.create.mechanical_pump.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.mechanical_pump.tooltip.action1": "UNLOCALIZED: Reverses the direction of the _pump_, switching the default direction of the flow", - - "block.create.smart_fluid_pipe.tooltip": "UNLOCALIZED: SMART FLUID PIPE", - "block.create.smart_fluid_pipe.tooltip.summary": "UNLOCALIZED: A _fluid pipe_ with a filter. Can specify which _fluids_ pass through.", - "block.create.smart_fluid_pipe.tooltip.condition1": "UNLOCALIZED: When Fluids are pushed into it", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "UNLOCALIZED: Smart pipes receiving fluid that does not match its filter will block the flow.", - "block.create.smart_fluid_pipe.tooltip.condition2": "UNLOCALIZED: When adjacent to fluid container", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Smart pipes _starting_ a _flow_ from any container will only extract fluids that _match_ its _filter._", - - "block.create.spout.tooltip": "UNLOCALIZED: SPOUT", - "block.create.spout.tooltip.summary": "UNLOCALIZED: An injector for refilling your _fluid items._", - "block.create.spout.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.spout.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: Fluid Automation", - "block.create.spout.tooltip.behaviour2": "UNLOCALIZED: 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": "UNLOCALIZED: ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "UNLOCALIZED: A grated depot for emptying your _fluid items._", - "block.create.item_drain.tooltip.condition1": "UNLOCALIZED: Fluid Transfer", - "block.create.item_drain.tooltip.behaviour1": "UNLOCALIZED: 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": "VARINHA DE SIMETRIA", "item.create.wand_of_symmetry.tooltip.summary": "Espelhar perfeitamente a colocação de blocos nos planos configurados.", "item.create.wand_of_symmetry.tooltip.condition1": "Quando na Hotbar", @@ -1280,9 +1336,18 @@ "item.create.tree_fertilizer.tooltip.behaviour1": "Cresce Arvores independentemente das suas Regras de espaço", "item.create.extendo_grip.tooltip": "UNLOCALIZED: EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder.", + "item.create.extendo_grip.tooltip.summary": "UNLOCALIZED: Boioioing! Greatly _increases reach distance_ of the wielder. Can be powered with Air Pressure from a _Copper_ _Backtank_", "item.create.extendo_grip.tooltip.condition1": "UNLOCALIZED: When in Off-Hand", "item.create.extendo_grip.tooltip.behaviour1": "UNLOCALIZED: Increases _reach distance_ of items used in the _Main-Hand_.", + "item.create.extendo_grip.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", + + "item.create.potato_cannon.tooltip": "UNLOCALIZED: POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "UNLOCALIZED: Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", + "item.create.potato_cannon.tooltip.behaviour1": "UNLOCALIZED: _Shoots_ a suitable item from your _Inventory_.", + "item.create.potato_cannon.tooltip.condition2": "UNLOCALIZED: While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.behaviour2": "UNLOCALIZED: _No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.filter.tooltip": "UNLOCALIZED: FILTER", "item.create.filter.tooltip.summary": "UNLOCALIZED: _Controls outputs_ and _inputs_ of logistical devices with more _precision_, matching them against a _set of items_ or several _nested filters_.", @@ -1358,12 +1423,14 @@ "block.create.turntable.tooltip": "MESA GIRATÓRIA", "block.create.turntable.tooltip.summary": "Muda a _Força_ _Rotacional_ em uma forma refinada de Enjoo.", - "block.create.portable_fluid_interface.tooltip": "UNLOCALIZED: PORTABLE FLUID INTERFACE", - "block.create.portable_fluid_interface.tooltip.summary": "UNLOCALIZED: 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": "UNLOCALIZED: While Moving", - "block.create.portable_fluid_interface.tooltip.behaviour1": "UNLOCALIZED: 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": "UNLOCALIZED: When Powered by Redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "UNLOCALIZED: _Disengages_ any active connection immediately.", + "block.create.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "DISJUNTOR DE ARMAZENAMENTO", "block.create.stockpile_switch.tooltip.summary": "Alterna um sinal de Redstone com base no _Espaço_ de _Armazenamento_ do Reciente conectado.", @@ -1371,7 +1438,11 @@ "block.create.stockpile_switch.tooltip.behaviour1": "Para de enviar _Sinal_ de _Redstone_", "block.create.content_observer.tooltip": "UNLOCALIZED: CONTENT OBSERVER", - "block.create.content_observer.tooltip.summary": "UNLOCALIZED: _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_.", + "block.create.content_observer.tooltip.summary": "UNLOCALIZED: _Detects Items_ or _Fluids_ inside _containers_, _pipes_ or _conveyors_ matching a configured _filter_.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "adjustable_crate", "block.create.adjustable_crate.tooltip.summary": "Este _Recipiente_ de _Armazenamento_ permite controle Manual da sua capacidade. Pode conter até _16_ _Pilhas_ de qualquer Item", @@ -1383,6 +1454,11 @@ "block.create.creative_crate.tooltip.condition1": "UNLOCALIZED: When Item in Filter Slot", "block.create.creative_crate.tooltip.behaviour1": "UNLOCALIZED: Anything _extracting_ from this container will provide an _endless supply_ of the item specified. Items _inserted_ into this crate will be _voided._", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "UNLOCALIZED: CONTROLLER RAIL", "block.create.controller_rail.tooltip.summary": "UNLOCALIZED: A _uni-directional powered rail_ capable of _fine control_ over a minecarts' _movement speed_.", "block.create.controller_rail.tooltip.condition1": "UNLOCALIZED: When Powered by Redstone", @@ -1398,26 +1474,61 @@ "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.linked_controller.tooltip.condition4": "UNLOCALIZED: R-Click on Lectern", + "item.create.linked_controller.tooltip.behaviour4": "UNLOCALIZED: Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the wielder 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: Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder 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.", + "block.create.peculiar_bell.tooltip": "UNLOCALIZED: PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "UNLOCALIZED: A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + + "block.create.haunted_bell.tooltip": "UNLOCALIZED: HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "UNLOCALIZED: A _Cursed Bell_ haunted by lost souls of the Nether.", + "block.create.haunted_bell.tooltip.condition1": "UNLOCALIZED: When Held or Rang", + "block.create.haunted_bell.tooltip.behaviour1": "UNLOCALIZED: Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn.", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1434,41 +1545,46 @@ "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.exit": "UNLOCALIZED: Exit", + "create.ponder.welcome": "UNLOCALIZED: Welcome to Ponder", + "create.ponder.categories": "UNLOCALIZED: Available Categories in Create", + "create.ponder.index_description": "UNLOCALIZED: Click one of the icons to learn about its associated Items and Blocks", + "create.ponder.index_title": "UNLOCALIZED: Ponder Index", + "create.ponder.shared.rpm16": "UNLOCALIZED: 16 RPM", "create.ponder.shared.behaviour_modify_wrench": "UNLOCALIZED: This behaviour can be modified using a Wrench", + "create.ponder.shared.storage_on_contraption": "UNLOCALIZED: Inventories attached to the Contraption will pick up their drops automatically", + "create.ponder.shared.sneak_and": "UNLOCALIZED: Sneak +", "create.ponder.shared.rpm8": "UNLOCALIZED: 8 RPM", "create.ponder.shared.ctrl_and": "UNLOCALIZED: Ctrl +", + "create.ponder.shared.rpm32": "UNLOCALIZED: 32 RPM", "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.shared.movement_anchors": "UNLOCALIZED: With the help of Chassis or Super Glue, larger structures can be moved.", "create.ponder.tag.redstone": "UNLOCALIZED: Logic Components", "create.ponder.tag.redstone.description": "UNLOCALIZED: Components which help with redstone engineering", + "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.fluids": "UNLOCALIZED: Fluid Manipulators", "create.ponder.tag.fluids.description": "UNLOCALIZED: Components which help relaying and making use of Fluids", + "create.ponder.tag.decoration": "UNLOCALIZED: Aesthetics", + "create.ponder.tag.decoration.description": "UNLOCALIZED: Components used mostly for decorative purposes", + "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.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.kinetic_appliances": "UNLOCALIZED: Kinetic Appliances", + "create.ponder.tag.kinetic_appliances.description": "UNLOCALIZED: Components which make use of Rotational Force", + "create.ponder.tag.kinetic_sources": "UNLOCALIZED: Kinetic Sources", + "create.ponder.tag.kinetic_sources.description": "UNLOCALIZED: Components which generate Rotational Force", + "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.kinetic_relays": "UNLOCALIZED: Kinetic Blocks", + "create.ponder.tag.kinetic_relays.description": "UNLOCALIZED: Components which help relaying Rotational Force elsewhere", + "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.creative": "UNLOCALIZED: Creative Mode", + "create.ponder.tag.creative.description": "UNLOCALIZED: Components not usually available for Survival Mode", + "create.ponder.tag.logistics": "UNLOCALIZED: Item Transportation", + "create.ponder.tag.logistics.description": "UNLOCALIZED: Components which help moving items around", "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", @@ -1580,7 +1696,8 @@ "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_modes.text_2": "UNLOCALIZED: This Arrow indicates which side of the Structure will be considered the front", + "create.ponder.cart_assembler_modes.text_3": "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", @@ -1594,7 +1711,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 +1751,12 @@ "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_fluid_tank.text_1": "UNLOCALIZED: Creative Fluid Tanks can be used to provide a bottomless supply of fluid", + "create.ponder.creative_fluid_tank.text_2": "UNLOCALIZED: Right-Click with a fluid containing item to configure it", + "create.ponder.creative_fluid_tank.text_3": "UNLOCALIZED: Pipe Networks can now endlessly draw the assigned fluid from the tank", + "create.ponder.creative_fluid_tank.text_4": "UNLOCALIZED: Any Fluids pushed back into a Creative Fluid Tank will be voided", + "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 +1793,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", @@ -1686,7 +1815,13 @@ "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.empty_blaze_burner.text_5": "UNLOCALIZED: The flame can be transformed using a soul-infused item", + "create.ponder.empty_blaze_burner.text_6": "UNLOCALIZED: However, without a blaze they 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", @@ -1706,6 +1841,35 @@ "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_sizes.text_1": "UNLOCALIZED: Fluid Tanks can be combined to increase the total capacity", + "create.ponder.fluid_tank_sizes.text_2": "UNLOCALIZED: Their base square can be up to 3 blocks wide...", + "create.ponder.fluid_tank_sizes.text_3": "UNLOCALIZED: ...and grow in height by more than 30 additional layers", + "create.ponder.fluid_tank_sizes.text_4": "UNLOCALIZED: Using a Wrench, a tanks' window can be toggled", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.fluid_tank_storage.text_1": "UNLOCALIZED: Fluid Tanks can be used to store large amounts of fluid", + "create.ponder.fluid_tank_storage.text_2": "UNLOCALIZED: Pipe networks can push and pull fluids from any side", + "create.ponder.fluid_tank_storage.text_3": "UNLOCALIZED: The contained fluid can be measured by a Comparator", + "create.ponder.fluid_tank_storage.text_4": "UNLOCALIZED: However, in Survival Mode Fluids cannot be added or taken manually", + "create.ponder.fluid_tank_storage.text_5": "UNLOCALIZED: You can use Basins, Item Drains and Spouts to drain or fill fluid containing items", + "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 +1943,34 @@ "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.text_1": "UNLOCALIZED: Hose Pulleys can be used to fill or drain large bodies of Fluid", + "create.ponder.hose_pulley.text_2": "UNLOCALIZED: With the Kinetic Input, the height of the pulleys' hose can be controlled", + "create.ponder.hose_pulley.text_3": "UNLOCALIZED: The Pulley retracts while the input rotation is inverted", + "create.ponder.hose_pulley.text_4": "UNLOCALIZED: On the opposite side, pipes can be connected", + "create.ponder.hose_pulley.text_5": "UNLOCALIZED: Attached pipe networks can either provide fluid to the hose...", + "create.ponder.hose_pulley.text_6": "UNLOCALIZED: ...or pull from it, draining the pool instead", + "create.ponder.hose_pulley.text_7": "UNLOCALIZED: Fill and Drain speed of the pulley depends entirely on the fluid networks' throughput", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + "create.ponder.hose_pulley_infinite.text_1": "UNLOCALIZED: When deploying the Hose Pulley into a large enough ocean...", + "create.ponder.hose_pulley_infinite.text_2": "UNLOCALIZED: It will provide/dispose fluids without affecting the source", + "create.ponder.hose_pulley_infinite.text_3": "UNLOCALIZED: Pipe networks can limitlessly take fluids from/to such pulleys", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + "create.ponder.hose_pulley_level.text_1": "UNLOCALIZED: While fully retracted, the Hose Pulley cannot operate", + "create.ponder.hose_pulley_level.text_2": "UNLOCALIZED: Draining runs from top to bottom", + "create.ponder.hose_pulley_level.text_3": "UNLOCALIZED: The surface level will end up just below where the hose ends", + "create.ponder.hose_pulley_level.text_4": "UNLOCALIZED: Filling runs from bottom to top", + "create.ponder.hose_pulley_level.text_5": "UNLOCALIZED: The filled pool will not grow beyond the layer above the hose end", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.item_drain.text_1": "UNLOCALIZED: Item Drains can extract fluids from items", + "create.ponder.item_drain.text_2": "UNLOCALIZED: Right-click it to pour fluids from your held item into it", + "create.ponder.item_drain.text_3": "UNLOCALIZED: When items are inserted from the side...", + "create.ponder.item_drain.text_4": "UNLOCALIZED: ...they roll across, emptying out their contained fluid", + "create.ponder.item_drain.text_5": "UNLOCALIZED: Pipe Networks can now pull the fluid from the drains' internal buffer", + "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 +2093,21 @@ "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_flow.text_1": "UNLOCALIZED: Mechanical Pumps govern the flow of their attached pipe networks", + "create.ponder.mechanical_pump_flow.text_2": "UNLOCALIZED: When powered, their arrow indicates the direction of flow", + "create.ponder.mechanical_pump_flow.text_3": "UNLOCALIZED: The network behind is now pulling fluids...", + "create.ponder.mechanical_pump_flow.text_4": "UNLOCALIZED: ...while the network in front is transferring it outward", + "create.ponder.mechanical_pump_flow.text_5": "UNLOCALIZED: Reversing the input rotation reverses the direction of flow", + "create.ponder.mechanical_pump_flow.text_6": "UNLOCALIZED: Use a Wrench to reverse the orientation of pumps manually", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_pump_speed.text_1": "UNLOCALIZED: Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away", + "create.ponder.mechanical_pump_speed.text_2": "UNLOCALIZED: Speeding up the input rotation changes the speed of flow propagation...", + "create.ponder.mechanical_pump_speed.text_3": "UNLOCALIZED: ...aswell as how quickly fluids are transferred", + "create.ponder.mechanical_pump_speed.text_4": "UNLOCALIZED: Pumps can combine their throughputs within shared pipe networks", + "create.ponder.mechanical_pump_speed.text_5": "UNLOCALIZED: Alternating their orientation can help align their flow directions", + "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", @@ -1926,11 +2133,22 @@ "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.nixie_tube.text_3": "UNLOCALIZED: Right-Click with Dye to change their display colour", "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_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + "create.ponder.portable_fluid_interface.text_1": "UNLOCALIZED: Fluid Tanks on moving contraptions cannot be accessed by any pipes", + "create.ponder.portable_fluid_interface.text_2": "UNLOCALIZED: This component can interact with fluid tanks without the need to stop the contraption", + "create.ponder.portable_fluid_interface.text_3": "UNLOCALIZED: Place a second one with a gap of 1 or 2 blocks inbetween", + "create.ponder.portable_fluid_interface.text_4": "UNLOCALIZED: Whenever they pass by each other, they will engage in a connection", + "create.ponder.portable_fluid_interface.text_5": "UNLOCALIZED: While engaged, the stationary interface will represent ALL Tanks on the contraption", + "create.ponder.portable_fluid_interface.text_6": "UNLOCALIZED: Fluid can now be inserted...", + "create.ponder.portable_fluid_interface.text_7": "UNLOCALIZED: ...or extracted from the contraption", + "create.ponder.portable_fluid_interface.text_8": "UNLOCALIZED: After no contents have been exchanged for a while, the contraption will continue on its way", + "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 +2246,25 @@ "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.smart_pipe.text_1": "UNLOCALIZED: Smart pipes can help control flows by fluid type", + "create.ponder.smart_pipe.text_2": "UNLOCALIZED: When placed directly at the source, they can specify the type of fluid to extract", + "create.ponder.smart_pipe.text_3": "UNLOCALIZED: Simply Right-Click their filter slot with any item containing the desired fluid", + "create.ponder.smart_pipe.text_4": "UNLOCALIZED: When placed further down a pipe network, smart pipes will only let matching fluids continue", + "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_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.spout_filling.text_1": "UNLOCALIZED: The Spout can fill fluid holding items provided beneath it", + "create.ponder.spout_filling.text_2": "UNLOCALIZED: The content of a Spout cannot be accessed manually", + "create.ponder.spout_filling.text_3": "UNLOCALIZED: Instead, Pipes can be used to supply it with fluids", + "create.ponder.spout_filling.text_4": "UNLOCALIZED: The Input items can be placed on a Depot under the Spout", + "create.ponder.spout_filling.text_5": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.spout_filling.text_6": "UNLOCALIZED: The Spout will hold and process them automatically", + "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 +2296,12 @@ "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.valve_pipe.text_1": "UNLOCALIZED: Valve pipes help control fluids propagating through pipe networks", + "create.ponder.valve_pipe.text_2": "UNLOCALIZED: Their shaft input controls whether fluid is currently allowed through", + "create.ponder.valve_pipe.text_3": "UNLOCALIZED: Given Rotational Force in the opening direction, the valve will open up", + "create.ponder.valve_pipe.text_4": "UNLOCALIZED: It can be closed again by reversing the input rotation", + "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..d6bd88fc7 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: 44", "_": "->------------------------] Game Elements [------------------------<-", @@ -27,13 +27,17 @@ "block.create.basin": "Чаша", "block.create.belt": "Конвейер", "block.create.birch_window": "Берёзовое окно", - "block.create.birch_window_pane": "Панель берёзового окна", + "block.create.birch_window_pane": "Панель из берёзового окна", + "block.create.black_nixie_tube": "Чёрный газоразрядный индикатор", "block.create.black_sail": "Чёрный парус", "block.create.black_seat": "Чёрное сиденье", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "Чёрный ручной вентиль", "block.create.blaze_burner": "Горелка Всполоха", + "block.create.blue_nixie_tube": "Синий газоразрядный индикатор", "block.create.blue_sail": "Синий парус", "block.create.blue_seat": "Синее сиденье", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "Синий ручной вентиль", "block.create.brass_belt_funnel": "Латунная конвейерная воронка", "block.create.brass_block": "Латунный блок", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "Вал в латунном корпусе", "block.create.brass_funnel": "Латунная воронка", "block.create.brass_tunnel": "Латунный туннель", + "block.create.brown_nixie_tube": "Коричневый газоразрядный индикатор", "block.create.brown_sail": "Коричневый парус", "block.create.brown_seat": "Коричневое сиденье", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "Коричневый ручной вентиль", "block.create.cart_assembler": "Сборщик вагонеток", "block.create.chiseled_dark_scoria": "Резной тёмный пепел", @@ -52,13 +58,13 @@ "block.create.chiseled_scoria": "Резной пепел", "block.create.chiseled_weathered_limestone": "Выветренный резной известняк", "block.create.chocolate": "Шоколад", - "block.create.chute": "Желоб", + "block.create.chute": "Жёлоб", "block.create.clockwork_bearing": "Часовой механизм", "block.create.clutch": "Сцепление", "block.create.cogwheel": "Шестерня", - "block.create.content_observer": "Наблюдетель за содержимым", + "block.create.content_observer": "Наблюдатель за содержимым", "block.create.controller_rail": "Контролирующая рельса", - "block.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "block.create.copper_backtank": "Медный баллон", "block.create.copper_block": "Медный блок", "block.create.copper_casing": "Медный корпус", "block.create.copper_ore": "Медная руда", @@ -73,8 +79,10 @@ "block.create.crushing_wheel": "Колесо дробления", "block.create.crushing_wheel_controller": "Контроллер колеса дробления", "block.create.cuckoo_clock": "Часы с кукушкой", + "block.create.cyan_nixie_tube": "Бирюзовый газоразрядный индикатор", "block.create.cyan_sail": "Бирюзовый парус", - "block.create.cyan_seat": "Бирюзовое сииденье", + "block.create.cyan_seat": "Бирюзовое сиденье", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "Бирюзовый ручной вентиль", "block.create.dark_oak_window": "Окно из тёмного дуба", "block.create.dark_oak_window_pane": "Панель из окна из тёмного дуб", @@ -83,11 +91,11 @@ "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.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": "Диоритовый кирпич", @@ -165,8 +173,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": "Стеклянная жидкостная труба", @@ -179,17 +187,22 @@ "block.create.granite_cobblestone_stairs": "Ступени из гранит-булыжника", "block.create.granite_cobblestone_wall": "Стена из гранит-булыжника", "block.create.granite_pillar": "Гранитная колонна", + "block.create.gray_nixie_tube": "Серый газоразрядный индикатор", "block.create.gray_sail": "Серый парус", "block.create.gray_seat": "Серое сиденье", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "Серый ручной вентиль", + "block.create.green_nixie_tube": "Зелёный газоразрядный индикатор", "block.create.green_sail": "Зелёный парус", "block.create.green_seat": "Зелёное сиденье", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "Зелёный ручной вентиль", "block.create.hand_crank": "Рукоятка", + "block.create.haunted_bell": "Призрачный колокол", "block.create.honey": "Мёд", "block.create.horizontal_framed_glass": "Горизонтальное обрамлённое стекло", "block.create.horizontal_framed_glass_pane": "Горизонтальная обрамлённая стеклянная панель", - "block.create.hose_pulley": "Шкив с шлангом", + "block.create.hose_pulley": "Шкив со шлангом", "block.create.item_drain": "Предметный осушитель", "block.create.jungle_window": "Окно из тропического дерева", "block.create.jungle_window_pane": "Панель окна из тропического дерева", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "Слоистый известняк", "block.create.layered_scoria": "Слоистый пепел", "block.create.layered_weathered_limestone": "Слоистый выветренный известняк", + "block.create.lectern_controller": "Контроллер кафедры", + "block.create.light_blue_nixie_tube": "Голубой газоразрядный индикатор", "block.create.light_blue_sail": "Голубой парус", "block.create.light_blue_seat": "Голубое сиденье", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "Голубой ручной вентиль", + "block.create.light_gray_nixie_tube": "Светло-серый газоразрядный индикатор", "block.create.light_gray_sail": "Светло-серый парус", "block.create.light_gray_seat": "Светло-серое сиденье", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "Светло-серый ручной вентиль", + "block.create.lime_nixie_tube": "Лаймовый газоразрядный индикатор", "block.create.lime_sail": "Лаймовый парус", "block.create.lime_seat": "Лаймовое сиденье", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "Лаймовый ручной вентиль", "block.create.limesand": "Известковый песок", "block.create.limestone": "Известняк", @@ -224,9 +244,11 @@ "block.create.limestone_cobblestone_wall": "Стена из известняк-булыжника", "block.create.limestone_pillar": "Известковая колонна", "block.create.linear_chassis": "Линейное шасси", - "block.create.lit_blaze_burner": "Зажжёная горелка Всполоха", + "block.create.lit_blaze_burner": "Зажжённая горелка Всполоха", + "block.create.magenta_nixie_tube": "Пурпурный газоразрядный индикатор", "block.create.magenta_sail": "Пурпурный парус", "block.create.magenta_seat": "Пурпурное сиденье", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "Пурпурный ручной вентиль", "block.create.mechanical_arm": "Механическая рука", "block.create.mechanical_bearing": "Механический вращатель", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "Панель из дубового окна", "block.create.orange_sail": "Оранжевый парус", "block.create.orange_seat": "Оранжевое сиденье", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "Оранжевый ручной вентиль", "block.create.ornate_iron_window": "Украшенное железное окно", "block.create.ornate_iron_window_pane": "Панель из украшенного железного окна", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "Плита из мощёного выветренного известняка", "block.create.paved_weathered_limestone_stairs": "Ступени из мощёного выветренного известняка", "block.create.paved_weathered_limestone_wall": "Стена из мощёного выветренного известняка", + "block.create.peculiar_bell": "Особенный колокол", + "block.create.pink_nixie_tube": "Розовый газоразрядный индикатор", "block.create.pink_sail": "Розовый парус", "block.create.pink_seat": "Розовое сиденье", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "Розовый ручной вентиль", "block.create.piston_extension_pole": "Удлинитель поршня", "block.create.polished_dark_scoria": "Полированный тёмный пепел", @@ -320,10 +346,10 @@ "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_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": "Ступени из полированного известняка", @@ -338,19 +364,23 @@ "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": "Механизированная рычаг-защёлка", + "block.create.powered_latch": "Питаемый рычаг", + "block.create.powered_toggle_latch": "Питаемый рычаг-переключатель", "block.create.pulley_magnet": "Магнитный шкив", "block.create.pulse_repeater": "Импульсный повторитель", + "block.create.purple_nixie_tube": "Фиолетовый газоразрядный индикатор", "block.create.purple_sail": "Фиолетовый парус", "block.create.purple_seat": "Фиолетовое сиденье", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "Фиолетовый ручной вентиль", "block.create.radial_chassis": "Радиальное шасси", + "block.create.red_nixie_tube": "Красный газоразрядный индикатор", "block.create.red_sail": "Красный парус", "block.create.red_seat": "Красное сиденье", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "Красный ручной вентиль", - "block.create.redstone_contact": "Контакт сигнала красного камня", - "block.create.redstone_link": "Беспроводной передатчик сигнала красного камня", + "block.create.redstone_contact": "Контакт редстоун сигнала", + "block.create.redstone_link": "Беспроводной передатчик редстоун сигнала", "block.create.refined_radiance_casing": "Сияющий корпус", "block.create.reinforced_rail": "Усиленные рельсы", "block.create.rope": "Канат", @@ -364,16 +394,16 @@ "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_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": "Вторичное линейное шасси", "block.create.sequenced_gearshift": "Последовательный переключатель передач", "block.create.shadow_steel_casing": "Теневой корпус", "block.create.shaft": "Вал", - "block.create.smart_chute": "Умный желоб", + "block.create.smart_chute": "Умный жёлоб", "block.create.smart_fluid_pipe": "Умная жидкостная труба", "block.create.speedometer": "Спидометр", "block.create.spout": "Дозатор", @@ -382,7 +412,7 @@ "block.create.sticker": "Блок-липучка", "block.create.sticky_mechanical_piston": "Липкий механический поршень", "block.create.stockpile_switch": "Настраиваемый компаратор", - "block.create.stressometer": "Динамометр", + "block.create.stressometer": "Стрессометр", "block.create.tiled_glass": "Плиточное стекло", "block.create.tiled_glass_pane": "Плиточная стеклянная панель", "block.create.turntable": "Поворотный стол", @@ -402,24 +432,32 @@ "block.create.weathered_limestone_cobblestone_wall": "Стена из известняк-булыжника", "block.create.weathered_limestone_pillar": "Колонна из выветренного известняка", "block.create.weighted_ejector": "Взвешенная катапульта", + "block.create.white_nixie_tube": "Белый газоразрядный индикатор", "block.create.white_sail": "Белый парус", "block.create.white_seat": "Белое сиденье", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "Белый ручной вентиль", "block.create.windmill_bearing": "Подшипник ветряной мельницы", "block.create.wooden_bracket": "Деревянная скоба", + "block.create.yellow_nixie_tube": "Жёлтый газоразрядный индикатор", "block.create.yellow_sail": "Жёлтый парус", "block.create.yellow_seat": "Жёлтое сиденье", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "Жёлтый ручной вентиль", "block.create.zinc_block": "Цинковый блок", "block.create.zinc_ore": "Цинковая руда", + "enchantment.create.capacity": "Вместимость", + "enchantment.create.potato_recovery": "Возобновление картофеля", + "entity.create.contraption": "Штуковина", - "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "entity.create.crafting_blueprint": "Создание чертежа", + "entity.create.gantry_contraption": "Крановая штуковина", + "entity.create.potato_projectile": "Картофельный снаряд", "entity.create.seat": "Сиденье", "entity.create.stationary_contraption": "Стационарная штуковина", "entity.create.super_glue": "Супер-клей", - "fluid.create.milk": "Молоко", "fluid.create.potion": "Зелье", "fluid.create.tea": "Чай Строителя", @@ -434,17 +472,19 @@ "item.create.brass_nugget": "Кусочек латуни", "item.create.brass_sheet": "Латунный лист", "item.create.builders_tea": "Чай Строителя", - "item.create.chest_minecart_contraption": "Сундуко-вагонеточная штуковина", + "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_backtank": "UNLOCALIZED: Copper Backtank", + "item.create.copper_backtank": "Медный баллон", "item.create.copper_ingot": "Медный слиток", "item.create.copper_nugget": "Кусочек меди", "item.create.copper_sheet": "Медный лист", "item.create.crafter_slot_cover": "Крышка на слот крафтера", - "item.create.crushed_aluminum_ore": "Измельчённая алюминиевая руда", + "item.create.crafting_blueprint": "Создание чертежа", + "item.create.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", + "item.create.crushed_aluminum_ore": "Дроблёная алюминиевая руда", "item.create.crushed_brass": "Дроблёная латунь", "item.create.crushed_copper_ore": "Дроблёная медная руда", "item.create.crushed_gold_ore": "Дроблёная золотая руда", @@ -454,31 +494,35 @@ "item.create.crushed_osmium_ore": "Дроблёная осмиевая руда", "item.create.crushed_platinum_ore": "Дроблёная платиновая руда", "item.create.crushed_quicksilver_ore": "Дроблёная ртутная руда", - "item.create.crushed_silver_ore": "Дроблёная серебрянная руда", + "item.create.crushed_silver_ore": "Дроблёная серебряная руда", "item.create.crushed_tin_ore": "Дроблёная оловянная руда", "item.create.crushed_uranium_ore": "Дроблёная урановая руда", "item.create.crushed_zinc_ore": "Дроблёная цинковая руда", - "item.create.diving_boots": "UNLOCALIZED: Diving Boots", - "item.create.diving_helmet": "UNLOCALIZED: Diving Helmet", + "item.create.diving_boots": "Ботинки для дайвинга", + "item.create.diving_helmet": "Шлем для дайвинга", "item.create.dough": "Тесто", "item.create.electron_tube": "Электронная лампа", - "item.create.empty_blaze_burner": "Пустая горелека Всполоха", + "item.create.empty_blaze_burner": "Пустая горелка Всполоха", "item.create.empty_schematic": "Пустая схематика", "item.create.extendo_grip": "Удлинённая рука", "item.create.filter": "Фильтр", - "item.create.furnace_minecart_contraption": "Печно-вагонеточная штуковина", + "item.create.furnace_minecart_contraption": "Штуковина самоходной вагонетки", "item.create.goggles": "Инженерные очки", "item.create.golden_sheet": "Золотой лист", "item.create.handheld_worldshaper": "Ручной редактор мира", "item.create.honey_bucket": "Ведро мёда", "item.create.honeyed_apple": "Яблоко в меду", - "item.create.integrated_circuit": "Интегральная схема", + "item.create.incomplete_cogwheel": "Незаконченная шестерня", + "item.create.incomplete_large_cogwheel": "Незаконченная большая шестерня", + "item.create.incomplete_precision_mechanism": "Незаконченный механизм точности", "item.create.iron_sheet": "Железный лист", - "item.create.lapis_sheet": "Лазуритовый лист", + "item.create.linked_controller": "Контроллер связей", "item.create.minecart_contraption": "Вагонеточная штуковина", - "item.create.minecart_coupling": "Связыватель вагонеток", + "item.create.minecart_coupling": "Соединитель вагонеток", "item.create.polished_rose_quartz": "Полированный розовый кварц", + "item.create.potato_cannon": "Картофельная пушка", "item.create.powdered_obsidian": "Порошкообразный обсидиан", + "item.create.precision_mechanism": "Механизм точности", "item.create.propeller": "Пропеллер", "item.create.red_sand_paper": "Красная наждачная бумага", "item.create.refined_radiance": "Изысканное сияние", @@ -506,9 +550,9 @@ "advancement.create.andesite_alloy": "Повторение - мать учения", "advancement.create.andesite_alloy.desc": "Материалы Create имеют странные названия, одно из них - Андезитовый сплав", "advancement.create.its_alive": "Оно живое!", - "advancement.create.its_alive.desc": "Смастерите ваш первый кинетический компонент вращения.", + "advancement.create.its_alive.desc": "Смастерите ваш первый кинетический вращающийся компонент.", "advancement.create.shifting_gears": "Механизм переключения", - "advancement.create.shifting_gears.desc": "Подсоедините большую шестерню к шестерне, что позволит изменить скорость вращения.", + "advancement.create.shifting_gears.desc": "Подсоедините большую шестерню к обычной шестерне для изменения скорости вращения.", "advancement.create.overstressed": "Перегрузка", "advancement.create.overstressed.desc": "Столкнитесь с предельной перегрузкой лицом к лицу.", "advancement.create.belt": "Передайте за проезд!", @@ -524,9 +568,9 @@ "advancement.create.belt_funnel": "Болтающиеся воронки", "advancement.create.belt_funnel.desc": "Поместите воронку боком, сверху конвейера или депо, чтобы создать её специальный тип.", "advancement.create.belt_funnel_kiss": "Механический ужин", - "advancement.create.belt_funnel_kiss.desc": "Заставте две смонтированные на ремнях воронки поцеловаться.", + "advancement.create.belt_funnel_kiss.desc": "Заставьте две смонтированные на ремнях воронки поцеловаться.", "advancement.create.fan": "Механический маг воздуха", - "advancement.create.fan.desc": "Оседлайте поток воздуха от Венитлятора.", + "advancement.create.fan.desc": "Оседлайте поток воздуха от Вентилятора.", "advancement.create.fan_lava": "Геотермальный пространственный нагреватель", "advancement.create.fan_lava.desc": "Попадите в поток воздуха, плавящего вещи.", "advancement.create.fan_water": "Сумасшедшая мойка", @@ -536,19 +580,19 @@ "advancement.create.wrench": "Конфигурировать удобно", "advancement.create.wrench.desc": "Создайте гаечный ключ, чтобы помочь себе в создании изобретений.", "advancement.create.goggles": "Стресс-о-зрение", - "advancement.create.goggles.desc": "Создайте инженерные очки, чтобы получить больше кинетической информации о компонентах.", + "advancement.create.goggles.desc": "Создайте инженерные очки, чтобы получить больше информации о кинетике компонентов.", "advancement.create.speedometer": "Так быстро?", "advancement.create.speedometer.desc": "Поставьте и подключите спидометр. Посмотрите на спидометр через очки, чтобы прочитать точное значение.", "advancement.create.stressometer": "Так сильно?", - "advancement.create.stressometer.desc": "Поставьте и подключите динамометр. Посмотрите на динамометр через очки, чтобы прочитать точное значение.", + "advancement.create.stressometer.desc": "Поставьте и подключите стрессометр. Посмотрите на стрессометр через очки, чтобы прочитать точное значение.", "advancement.create.aesthetics": "Бах! Эстетично!", - "advancement.create.aesthetics.desc": "Разместите скобы на валу, трубе или шестерне.", + "advancement.create.aesthetics.desc": "Разместите скобы на вал, трубу или шестерню.", "advancement.create.reinforced": "Бах! Усилено!", "advancement.create.reinforced.desc": "Разместите подходящий блок корпуса на вал, трубу и конвейер.", - "advancement.create.water_wheel": "Гидравлика", + "advancement.create.water_wheel": "Обузданная гидравлика", "advancement.create.water_wheel.desc": "Поставьте водяное колесо и попытайтесь заставить его вращаться!", "advancement.create.chocolate_wheel": "Вкусная сила", - "advancement.create.chocolate_wheel.desc": "Зпустите водяное колесо с помощью раплавленного шоколада.", + "advancement.create.chocolate_wheel.desc": "Запустите водяное колесо с помощью расплавленного шоколада.", "advancement.create.lava_wheel": "Адское колесо", "advancement.create.lava_wheel.desc": "Это не должно было работать.", "advancement.create.cuckoo": "Уже?", @@ -561,12 +605,12 @@ "advancement.create.maxed_windmill.desc": "Соберите ветряную мельницу максимальной силы.", "advancement.create.andesite_casing": "Андезитовый век", "advancement.create.andesite_casing.desc": "Используйте немного андезитового сплава и дерева для создания корпуса.", - "advancement.create.mechanical_drill": "Стационарные выключатели", + "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.polished_rose_quartz.desc": "Используйте кусок наждачной бумаги, чтобы отполировать розовый кварц, пока он не станет глянцевым.", "advancement.create.electron_tube": "Бип бип", "advancement.create.electron_tube.desc": "Сделайте несколько электронных ламп, пригодных для изготовления менее примитивных машин.", "advancement.create.mechanical_saw": "Стационарная рубка", @@ -579,7 +623,7 @@ "advancement.create.blaze_burner.desc": "Получить Горелку Всполоха", "advancement.create.compact": "Автоматическое уплотнение", "advancement.create.compact.desc": "Используйте пресс и чашу для уплотнения некоторых предметов.", - "advancement.create.brass": "Действительный сплав", + "advancement.create.brass": "Реальный сплав", "advancement.create.brass.desc": "Используйте дроблёную медь и дроблёный цинк, чтобы создать немного латуни.", "advancement.create.brass_casing": "Бронзовый век", "advancement.create.brass_casing.desc": "Используйте только что полученную латунь и немного дерева, чтобы создать более продвинутый корпус.", @@ -595,7 +639,7 @@ "advancement.create.item_drain.desc": "Посмотрите как жидкость выкачивается из предмета, в Предметном осушителе.", "advancement.create.chained_item_drain": "Поехали!", "advancement.create.chained_item_drain.desc": "Наблюдайте за тем как предмет едет через несколько соединённых предметных осушителей.", - "advancement.create.glass_pipe": "Поточный шпион", + "advancement.create.glass_pipe": "Шпион за потоками", "advancement.create.glass_pipe.desc": "Наблюдайте через окно в трубе за тем как распространяется жидкость. Окно появится на трубе при использовании гаечного ключа.", "advancement.create.pipe_collision": "Никогда не скрещивайте потоки!", "advancement.create.pipe_collision.desc": "Наблюдайте за тем как две жидкости встречаются в вашей сети труб.", @@ -608,7 +652,7 @@ "advancement.create.infinite_lava": "Уничтожение ядра", "advancement.create.infinite_lava.desc": "Выкачивайте лаву из бассейна, считающегося бесконечным.", "advancement.create.infinite_chocolate": "Утопая в воображении", - "advancement.create.infinite_chocolate.desc": "Выкачивайте раславленный шоколад из резервуара, считающегося бесконечным.", + "advancement.create.infinite_chocolate.desc": "Выкачивайте расплавленный шоколад из резервуара, считающегося бесконечным.", "advancement.create.crafter": "Автоматизированная сборка", "advancement.create.crafter.desc": "Поставьте и подключите механический крафтер", "advancement.create.clockwork_bearing": "Хитрые часы", @@ -623,18 +667,18 @@ "advancement.create.flywheel.desc": "Успешно соедините двигатель с маховиком.", "advancement.create.overstress_flywheel": "Перенапряжение", "advancement.create.overstress_flywheel.desc": "Подайте слишком большую нагрузку на печной двигатель.", - "advancement.create.integrated_circuit": "Сложные вычисления", - "advancement.create.integrated_circuit.desc": "Создайте Интегральную схему.", + "advancement.create.precision_mechanism": "Сложные любопытства.", + "advancement.create.precision_mechanism.desc": "Создайте механизм точности.", "advancement.create.mechanical_arm": "Золотые руки!", - "advancement.create.mechanical_arm.desc": "Создайте Механическую руку, выбирете входы и выходы, установите в мире и запитайте. Затем смотрите как она делает за вас всю работу.", + "advancement.create.mechanical_arm.desc": "Создайте Механическую руку, выберите входы и выходы, установите в мире и запитайте. Затем смотрите как она делает за вас всю работу.", "advancement.create.musical_arm": "Сбацай что-нибудь!", "advancement.create.musical_arm.desc": "Посмотрите как механическая рука меняет пластинки.", - "advancement.create.arm_many_targets": "Организатор", + "advancement.create.arm_many_targets": "Организа-трон", "advancement.create.arm_many_targets.desc": "Запрограммируйте механическую руку на 10 и больше выходов.", - "advancement.create.arm_blaze_burner": "Поджигатель", + "advancement.create.arm_blaze_burner": "Поджигателе-трон", "advancement.create.arm_blaze_burner.desc": "Запрограммируйте механическую руку на кормление Горелки Всполоха.", "advancement.create.fist_bump": "Брось это, братан!", - "advancement.create.fist_bump.desc": "Сделайте два удара кулаком.", + "advancement.create.fist_bump.desc": "Сделайте два удара кулаками Автономных активаторов.", "advancement.create.crushing_wheel": "Пара гигантов", "advancement.create.crushing_wheel.desc": "Создайте несколько дробящих колес, чтобы более эффективно разрушать больше материалов.", "advancement.create.blaze_cake": "Сахарная лихорадка", @@ -649,9 +693,11 @@ "advancement.create.chromatic_age.desc": "Создайте блоки корпуса из света и тьмы.", "advancement.create.wand_of_symmetry": "Сияющие зеркала", "advancement.create.wand_of_symmetry.desc": "Создайте жезл симметрии.", - "advancement.create.extendo_grip": "Кипение!", + "advancement.create.extendo_grip": "Бойоиоинг!", "advancement.create.extendo_grip.desc": "Возьмите в руки удлинённую руку", - "advancement.create.dual_extendo_grip": "Окончательное выкипание", + "advancement.create.potato_cannon": "Свомп!", + "advancement.create.potato_cannon.desc": "Победите врага с помощью своей картофельной пушки!", + "advancement.create.dual_extendo_grip": "Время ультимативных пружин", "advancement.create.dual_extendo_grip.desc": "Две удлинённых руки для сверхчеловеческого охвата.", "advancement.create.eob": "Конец бета-версии", "advancement.create.eob.desc": "Ожидайте больше контента здесь в будущем. <3", @@ -663,15 +709,31 @@ "itemGroup.create.palettes": "Create: Декор", "death.attack.create.crush": "%1$s был передроблен", + "death.attack.create.crush.player": "%2$s столкнул %1$s в дробящие колёса", "death.attack.create.fan_fire": "%1$s был сожжен до смерти горячим воздухом", + "death.attack.create.fan_fire.player": "%2$s столкнул %1$s в коптильню", "death.attack.create.fan_lava": "%1$s был сожжен до смерти поклонником лавы", - "death.attack.create.mechanical_drill": "%1$s был пронзен с помощью механической дрели", + "death.attack.create.fan_lava.player": "%2$s столкнул %1$s в плавильню", + "death.attack.create.mechanical_drill": "%1$s был пронзён механической дрелью", + "death.attack.create.mechanical_drill.player": "%2$s толкнул %1$s под механическую дрель", "death.attack.create.mechanical_saw": "%1$s был разрезан пополам механической пилой", + "death.attack.create.mechanical_saw.player": "%2$s толкнул %1$s под механическую пилу", + "death.attack.create.potato_cannon": "%1$s был застрелен картофельной пушкой %2$s", + "death.attack.create.potato_cannon.item": "%1$s был застрелен %2$s при помощи «%3$s»", "death.attack.create.cuckoo_clock_explosion": "%1$s взорвали подделанные часы с кукушкой", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s был взорван подделанными часами с кукушкой", "create.block.deployer.damage_source_name": "автономным активатором", "create.block.cart_assembler.invalid": "Поместите сборщик вагонеток на блок рельс", + "create.menu.return": "Вернуться в меню", + "create.menu.configure": "Настроить...", + "create.menu.ponder_index": "Содержание размышлений", + "create.menu.only_ingame": "Доступно в меню Паузы", + "create.menu.project_page": "Страница проекта", + "create.menu.report_bugs": "Сообщите об ошибке", + "create.menu.support": "Поддержите нас", + "create.recipe.crushing": "Измельчение", "create.recipe.milling": "Помол", "create.recipe.fan_washing": "Массовая промывка", @@ -682,7 +744,7 @@ "create.recipe.fan_blasting.fan": "Вентилятор за текущей лавой", "create.recipe.pressing": "Прессование", "create.recipe.mixing": "Смешивание", - "create.recipe.deploying": "UNLOCALIZED: Deploying", + "create.recipe.deploying": "Автономная активация", "create.recipe.automatic_shapeless": "Автоматическая бесформенная сборка", "create.recipe.automatic_brewing": "Автоматическое смешивание", "create.recipe.packing": "Прессование", @@ -691,12 +753,23 @@ "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.sequenced_assembly": "Последовательная сборка", + "create.recipe.assembly.next": "Следующее: %1$s", + "create.recipe.assembly.step": "Шаг %1$s:", + "create.recipe.assembly.progress": "Прогресс: %1$s/%2$s", + "create.recipe.assembly.pressing": "Обработайте в Прессе", + "create.recipe.assembly.spout_filling_fluid": "Долейте %1$s", + "create.recipe.assembly.deploying_item": "Добавьте %1$s", + "create.recipe.assembly.cutting": "Разрежьте пилой", + "create.recipe.assembly.repeat": "Повторите последовательность %1$s раз", + "create.recipe.assembly.junk": "Случайный мусор", "create.recipe.processing.chance": "%1$s%% шанса", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "Не требует нагрева", "create.recipe.heat_requirement.heated": "Нагрето", "create.recipe.heat_requirement.superheated": "Перегрето", @@ -712,7 +785,7 @@ "create.generic.unit.seconds": "секунд", "create.generic.unit.minutes": "минут", "create.generic.unit.rpm": "об./мин.", - "create.generic.unit.stress": "Н*м", + "create.generic.unit.stress": "ен", "create.generic.unit.degrees": "°", "create.generic.unit.millibuckets": "%1$smB", "create.generic.clockwise": "По часовой стрелке", @@ -725,6 +798,7 @@ "create.action.discard": "Отказаться", "create.keyinfo.toolmenu": "Меню инструмента фокусировки", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "Имитация движения мыши вверх (в мире)", "create.keyinfo.scrolldown": "Имитация движения мыши вниз (в мире)", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "Нажмите Shift для быстрой прокрутки", "create.gui.toolmenu.focusKey": "Удерживайте [%1$s] для смены задач", "create.gui.toolmenu.cycle": "[Прокрутка] для переключения", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "Зеркало", "create.gui.symmetryWand.orientation": "Ориентация", @@ -749,15 +830,15 @@ "create.orientation.alongX": "Вдоль X", "create.gui.terrainzapper.title": "Ручной редактор мира", - "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": "Следование диагоналям", + "create.gui.terrainzapper.searchFuzzy": "Игнорировать границы материала", + "create.gui.terrainzapper.patternSection": "Шаблон", + "create.gui.terrainzapper.pattern.solid": "Сплошной", + "create.gui.terrainzapper.pattern.checkered": "Шахматный порядок", + "create.gui.terrainzapper.pattern.inversecheckered": "Обратный шахматный порядок", + "create.gui.terrainzapper.pattern.chance25": "25% заполнение", + "create.gui.terrainzapper.pattern.chance50": "50% заполнение", + "create.gui.terrainzapper.pattern.chance75": "75% заполнение", "create.gui.terrainzapper.placement": "Размещение", "create.gui.terrainzapper.placement.merged": "Слитый", "create.gui.terrainzapper.placement.attached": "Прикреплённый", @@ -766,8 +847,8 @@ "create.gui.terrainzapper.brush.cuboid": "Куб", "create.gui.terrainzapper.brush.sphere": "Сфера", "create.gui.terrainzapper.brush.cylinder": "Цилиндр", - "create.gui.terrainzapper.brush.surface": "UNLOCALIZED: Surface", - "create.gui.terrainzapper.brush.cluster": "UNLOCALIZED: Cluster", + "create.gui.terrainzapper.brush.surface": "Поверхность", + "create.gui.terrainzapper.brush.cluster": "Скопление", "create.gui.terrainzapper.tool": "Инструмент", "create.gui.terrainzapper.tool.fill": "Заполнить", "create.gui.terrainzapper.tool.place": "Поставить", @@ -777,12 +858,12 @@ "create.gui.terrainzapper.tool.flatten": "Выравнивание", "create.terrainzapper.shiftRightClickToSet": "ПКМ крадучись, чтобы выбрать форму", - "create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s", - "create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material", + "create.terrainzapper.usingBlock": "Используется: %1$s", + "create.terrainzapper.leftClickToSet": "Левый клик по блоку, что бы использовать материал", "create.minecart_coupling.two_couplings_max": "Вагонетки могут иметь только две связи", "create.minecart_coupling.unloaded": "Кажется, часть вашего поезда в незагруженных чанках", - "create.minecart_coupling.no_loops": "Связыватели не могут образовывать петлю", + "create.minecart_coupling.no_loops": "Соединители не могут образовывать петлю", "create.minecart_coupling.removed": "Убраны все связи между вагонетками", "create.minecart_coupling.too_far": "Вагонетки слишком далеко друг от друга", @@ -809,12 +890,12 @@ "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_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.at_current_speed": "При текущей скорости", "create.gui.goggles.pole_length": "Длина поршня", "create.gui.goggles.fluid_container": "Информация о жидкостном контейнере:", "create.gui.goggles.fluid_container.capacity": "Ёмкость: ", @@ -822,17 +903,17 @@ "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": "Штуковина состоит из слишком большого количества Блоков.\nТекущий максимум: %1$s", - "create.gui.assembly.exception.tooManyPistonPoles": "Слишком много Удлинителей прикреплено к этому Поршню.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "Слишком много Удлинителей прикреплено к этому поршню.\nТекущий максимум: %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.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.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": "Настраиваемый компаратор", @@ -844,7 +925,7 @@ "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": "Временная задержка", @@ -852,7 +933,7 @@ "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.descriptive": "Ожидать нового Импульса редстоун Сигнала", "create.gui.sequenced_gearshift.instruction.await": "Ожидать", "create.gui.sequenced_gearshift.speed": "Скорость, Направление", "create.gui.sequenced_gearshift.speed.forward": "Скорость ввода, вперед", @@ -877,11 +958,11 @@ "create.schematic.rotation.cw90": "По час. стрелке 90", "create.schematic.rotation.cw180": "По час. стрелке 180", "create.schematic.rotation.cw270": "По час. стрелке 270", - "create.schematic.mirror": "Зеркало", + "create.schematic.mirror": "Отразить", "create.schematic.mirror.none": "Нет", "create.schematic.mirror.frontBack": "Спереди-сзади", "create.schematic.mirror.leftRight": "Влево-вправо", - "create.schematic.tool.deploy": "Развернуть", + "create.schematic.tool.deploy": "Развёртывание", "create.schematic.tool.move": "Подвинуть XZ", "create.schematic.tool.movey": "Подвинуть Y", "create.schematic.tool.rotate": "Вращать", @@ -907,7 +988,7 @@ "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.0": "Переверните схему вдоль выбранной стороны.", "create.schematic.tool.flip.description.1": "Наведите курсор на схему и [CTRL] + прокрутка, чтобы перевернуть ее.", "create.schematic.tool.flip.description.2": "", "create.schematic.tool.flip.description.3": "", @@ -938,10 +1019,10 @@ "create.gui.schematicannon.option.skipMissing": "Пропускать отсутствующие блоки", "create.gui.schematicannon.option.skipTileEntities": "Защитить имущество", "create.gui.schematicannon.slot.gunpowder": "Добавьте порох чтобы запитать пушку", - "create.gui.schematicannon.slot.listPrinter": "Положите книгу чтобы создать список предметов для схематики", + "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.skipTileEntities.description": "Пушка не будет заменять блоки хранения, такие как сундуки.", "create.gui.schematicannon.option.dontReplaceSolid.description": "Пушка никогда не заменит целые блоки, только не целые и воздух.", "create.gui.schematicannon.option.replaceWithSolid.description": "Пушка будет заменять целый блок только в случае, если в схеме в этом месте расположен целый блок.", "create.gui.schematicannon.option.replaceWithAny.description": "Пушка будет заменять целые блоки, если в схеме в этом месте есть что-либо.", @@ -981,18 +1062,14 @@ "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.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "зачарован", "create.item_attributes.enchanted.inverted": "не зачарован", + "create.item_attributes.max_enchanted": "Зачаровано за максимальный уровень", + "create.item_attributes.max_enchanted.inverted": "Не зачаровано за максимальный уровень", + "create.item_attributes.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "повреждён", "create.item_attributes.damaged.inverted": "не повреждён", "create.item_attributes.badly_damaged": "сильно повреждён", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "не может быть надет", "create.item_attributes.furnace_fuel": "является топливом", "create.item_attributes.furnace_fuel.inverted": "не является топливом", + "create.item_attributes.washable": "можно промыть", + "create.item_attributes.washable.inverted": "нельзя промыть", + "create.item_attributes.crushable": "можно измельчить", + "create.item_attributes.crushable.inverted": "нельзя разместить", + "create.item_attributes.smeltable": "можно расплавить", + "create.item_attributes.smeltable.inverted": "нельзя расплавить", + "create.item_attributes.smokable": "можно прокоптить", + "create.item_attributes.smokable.inverted": "нельзя прокоптить", + "create.item_attributes.blastable": "плавится в доменной печи", + "create.item_attributes.blastable.inverted": "не плавится в доменной печи", + "create.item_attributes.shulker_level": "шалкер %1$s", + "create.item_attributes.shulker_level.inverted": "шалкер не %1$s", + "create.item_attributes.shulker_level.full": "полный", + "create.item_attributes.shulker_level.empty": "пустой", + "create.item_attributes.shulker_level.partial": "частично заполнен", "create.item_attributes.in_tag": "помечен %1$s", "create.item_attributes.in_tag.inverted": "не помечен %1$s", "create.item_attributes.in_item_group": "принадлежит %1$s", @@ -1013,14 +1105,12 @@ "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_author.inverted": "не подписана %1$s", "create.item_attributes.book_copy_original": "оригинал", "create.item_attributes.book_copy_original.inverted": "не оригинал", "create.item_attributes.book_copy_first": "копия первого порядка", @@ -1029,14 +1119,14 @@ "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.item_attributes.astralsorcery_constellation": "настроено на %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "не настроено на %1$s", + "create.item_attributes.astralsorcery_crystal": "имеет характеристики кристалла %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "не имеет характеристики кристалла %1$s", + "create.item_attributes.astralsorcery_perk_gem": "имеет характеристики перка %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "не имеет характеристики перка %1$s", "create.gui.attribute_filter.no_selected_attributes": "Атрибуты не выбраны", "create.gui.attribute_filter.selected_attributes": "Выбранные атрибуты:", @@ -1058,12 +1148,12 @@ "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": "Создаваемая нагрузка: %1$s", + "create.tooltip.stressImpact.low": "Низкая", + "create.tooltip.stressImpact.medium": "Средняя", + "create.tooltip.stressImpact.high": "Высокая", "create.tooltip.stressImpact.overstressed": "Перегрузка", - "create.tooltip.capacityProvided": "Ёмкостный крутящий момент: %1$s", + "create.tooltip.capacityProvided": "Допустимая нагрузка: %1$s", "create.tooltip.capacityProvided.low": "Маленький", "create.tooltip.capacityProvided.medium": "Средний", "create.tooltip.capacityProvided.high": "Большой", @@ -1076,34 +1166,55 @@ "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.target_not_valid": "Бросает до ближайшего блока (Неподходящая Цель)", + "create.weighted_ejector.no_target": "Бросает до ближайшего блока (Цель не была Выбрана)", "create.weighted_ejector.targeting": "Бросает до [%1$s,%2$s,%3$s]", - "create.weighted_ejector.stack_size": "Размер Бросаемого Стака", + "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.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.prefer_nearest": "Предпочтительно ближайшее", "create.tunnel.selection_mode.randomize": "Случайно", "create.tunnel.selection_mode.synchronize": "Синхронизировать входы", - "create.tooltip.chute.header": "Инвормация о желобе", + "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.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.tooltip.brass_tunnel.contains": "В данный момент раздает(выдает):", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "ПКМ, чтобы получить", + + "create.linked_controller.bind_mode": "Режим привязки активирован", + "create.linked_controller.press_keybind": "Нажмите %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, чтобы привязать эту частоту к соответствующей клавише", + "create.linked_controller.key_bound": "Частота привязана к %1$s", + "create.linked_controller.frequency_slot_1": "Клавиша: %1$s, Частота #1", + "create.linked_controller.frequency_slot_2": "Клавиша: %1$s, Частота #2", + + "create.crafting_blueprint.crafting_slot": "Слот для ингредиентов", + "create.crafting_blueprint.filter_items_viable": "Продвинутые фильтры предметов применимы", + "create.crafting_blueprint.display_slot": "Отображаемая ячейка", + "create.crafting_blueprint.inferred": "Производные от рецепта", + "create.crafting_blueprint.manually_assigned": "Назначен вручную", + "create.crafting_blueprint.secondary_display_slot": "Дополнительная отображаемая ячейка", + "create.crafting_blueprint.optional": "Опциональна", + + "create.potato_cannon.ammo.attack_damage": "%1$s урона от атаки", + "create.potato_cannon.ammo.reload_ticks": "%1$s тиков перезагрузки", + "create.potato_cannon.ammo.knockback": "%1$s отбрасывания", "create.hint.hose_pulley.title": "Безграничное снабжение", "create.hint.hose_pulley": "Целевой водный резервуар считается бесконечным.", @@ -1131,35 +1242,47 @@ "create.command.killTPSCommand.status.usage.1": "[Create]: используйте /killtps start <Время тика>, чтобы искусственно замедлить тик сервера", "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_too_big": "Эта вагонеточная штуковина кажется слишком большой, чтобы ее можно было поднять", + "create.contraption.minecart_contraption_illegal_pickup": "Мистическая сила связывает эту вагонеточную штуковину с миром", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "Намазывание слизи", - "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.contraption_disassemble": "Штуковина останавливается", + "create.subtitle.peculiar_bell_use": "Особенный колокол звонит", + "create.subtitle.mixing": "Шум смешивания", + "create.subtitle.mechanical_press_activation_belt": "Механический пресс делает «бонк»", + "create.subtitle.fwoomp": "Картофельная пушка делает «Свомп»", + "create.subtitle.worldshaper_place": "Ручной редактор мира делает «Зап»", + "create.subtitle.crushing_1": "Шум разрушения", + "create.subtitle.depot_slide": "Шелест предметов", + "create.subtitle.saw_activate_stone": "Активируется механическая пила", "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.funnel_flap": "Занавески воронок хлопают", "create.subtitle.schematicannon_finish": "Схематичная пушка закончила работу", - "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.haunted_bell_use": "Призрачный колокол звонит", + "create.subtitle.scroll_value": "Щелчки колеса прокрутки", + "create.subtitle.crafter_craft": "Крафтер создаёт", + "create.subtitle.controller_put": "Контроллер стучит", + "create.subtitle.cranking": "Вращается рукоятка", + "create.subtitle.wrench_remove": "Компонент ломается", + "create.subtitle.cogs": "Шестерни грохочут", + "create.subtitle.slime_added": "Намазывание слизи", + "create.subtitle.wrench_rotate": "Использован гаечный ключ", + "create.subtitle.potato_hit": "Овощ врезается", + "create.subtitle.saw_activate_wood": "Активируется механическая пила", + "create.subtitle.haunted_bell_convert": "Призрачный колокол пробуждается", + "create.subtitle.deployer_polish": "Автономный активатор полирует", + "create.subtitle.deny": "Отрицательный «Буп»", + "create.subtitle.controller_click": "Клики контроллера", + "create.subtitle.schematicannon_launch_block": "Выстрелы схематичной пушки", + "create.subtitle.copper_armor_equip": "Позвякивание снаряжения для дайвинга", + "create.subtitle.controller_take": "Кафедра опустошается", "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", + "create.subtitle.contraption_assemble": "Штуковина движется", + "create.subtitle.crafter_click": "Крафтер кликает", + "create.subtitle.depot_plop": "Предмет падает", + "create.subtitle.confirm": "Утвердительный «Динь»", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1173,88 +1296,21 @@ "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": "ДЕРЕВЯННАЯ СКОБА", "block.create.wooden_bracket.tooltip.summary": "_Украсьте_ ваши _валы, шестерни_ и _трубы_, используя уютное деревянное укрепление.", - "block.create.metal_bracket.tooltip": "METAL BRACKET", + "block.create.metal_bracket.tooltip": "МЕТАЛЛИЧЕСКАЯ СКОБА", "block.create.metal_bracket.tooltip.summary": "_Украсьте_ ваши _валы, шестерни_ и _трубы_, используя прочное индустриальное укрепление.", - "block.create.copper_casing.tooltip": "COPPER CASING", - "block.create.copper_casing.tooltip.summary": "Прочный машинный корпус для разнообразного использования. Безопасно для украшения.", - "block.create.copper_casing.tooltip.condition1": "При использовании на жидкостной трубе", - "block.create.copper_casing.tooltip.behaviour1": "Покрывает _жидкостную трубу_ _корпусом_. Трубы в корпусе _закрепят свои соединения_ и не будут соединятся с другими трубами, расположенными по соседству.", - - "block.create.encased_fluid_pipe.tooltip": "ENCASED FLUID PIPE", - "block.create.encased_fluid_pipe.tooltip.summary": "_Труба_ в _Медном корпусе_.", - - "block.create.seat.tooltip": "SEAT", + "block.create.seat.tooltip": "СИДЕНЬЕ", "block.create.seat.tooltip.summary": "Присядьте и насладитесь поездкой! Привязывает игроков к собранным _устройствам_. Отлично выглядит как простая мебель! Можно окрасить в разные цвета.", "block.create.seat.tooltip.condition1": "ПКМ по сиденью", - "block.create.seat.tooltip.behaviour1": "Сажает игрока на _Сиденье_. Нажмите _кнопку_ _приседания_ чтобы слезть.", + "block.create.seat.tooltip.behaviour1": "Сажает игрока на _Сиденье_. Нажмите _кнопку_ _приседания_ чтобы слезть (Shift по умолчанию).", - "item.create.blaze_cake.tooltip": "BLAZE CAKE", + "item.create.blaze_cake.tooltip": "ТОРТ ВСПОЛОХА", "item.create.blaze_cake.tooltip.summary": "Вкусное угощения для вашей трудяги _Горелки Всполоха_. Зажигает их всех!", - "block.create.fluid_pipe.tooltip": "FLUID PIPE", - "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": "HOSE PULLEY", - "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": "FLUID TANK", - "block.create.fluid_tank.tooltip.summary": "_Хранит_ ваши любимые _жидкости_. Скалируется в высоту и ширину.", - "block.create.fluid_tank.tooltip.condition1": "Правый клик с гаечным ключом", - "block.create.fluid_tank.tooltip.behaviour1": "Переключает опциональное отображение окна", - - "block.create.creative_fluid_tank.tooltip": "CREATIVE FLUID TANK", - "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": "FLUID VALVE", - "block.create.fluid_valve.tooltip.summary": "Останавливает поток жидкости по трубе.", - "block.create.fluid_valve.tooltip.condition1": "Контролируемый поток", - "block.create.fluid_valve.tooltip.behaviour1": "Приложенная _Вращательная сила_ заставит _клапан_ закрыться, останавливая поток _жидкости_. Измените направление _вращательной силы_, чтобы снова открыть клапан.", - - "block.create.mechanical_pump.tooltip": "MECHANICAL PUMP", - "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": "SMART FLUID PIPE", - "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": "SPOUT", - "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": "ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "Депо с решёткой, которое может выкачивать _жидкость_ из ваших _предметов_", - "block.create.item_drain.tooltip.condition1": "Транспортировка жидкости", - "block.create.item_drain.tooltip.behaviour1": "Когда _предмет с жидкостью_, такой как _ведро_ или _бутылочка_ вставлены с боку, предметный осушитель будет автоматически извлекать жидкость, в свой собственный _бак_. Предмет будет выброшен с противоположной стороны.", - - "item.create.wand_of_symmetry.tooltip": "SYMMETRY WAND", + "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": "Остаётся активным", @@ -1265,7 +1321,7 @@ "item.create.wand_of_symmetry.tooltip.control3": "ПКМ крадучись", "item.create.wand_of_symmetry.tooltip.action3": "Открывает _интерфейс_ _конфигурации_", - "item.create.handheld_worldshaper.tooltip": "HANDHELD WORLDSHAPER", + "item.create.handheld_worldshaper.tooltip": "РУЧНОЙ РЕДАКТОР МИРА", "item.create.handheld_worldshaper.tooltip.summary": "Удобный инструмент для создания _ландшафтов_ и _рельефа_ _местности_.", "item.create.handheld_worldshaper.tooltip.control1": "ЛКМ на блок", "item.create.handheld_worldshaper.tooltip.action1": "Устанавливает блоки, помещенные инструментом, в целевой блок.", @@ -1274,41 +1330,50 @@ "item.create.handheld_worldshaper.tooltip.control3": "ПКМ крадучись", "item.create.handheld_worldshaper.tooltip.action3": "Открывает _интерфейс_ _конфигурации_", - "item.create.tree_fertilizer.tooltip": "TREE FERTILIZER", + "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.extendo_grip.tooltip": "EXTENDO GRIP", + "item.create.extendo_grip.tooltip": "УДЛИНЕННАЯ РУКА", "item.create.extendo_grip.tooltip.summary": "Бойоиоинг! Значительно _увеличивает_ _досягаемость_ владельца.", "item.create.extendo_grip.tooltip.condition1": "Находясь в другой руке", - "item.create.extendo_grip.tooltip.behaviour1": "Увеличьте _расстояние_ _досягаемости_ предметов, используемых в _главной_ _руке_.", + "item.create.extendo_grip.tooltip.behaviour1": "Увеличивает _расстояние_ _досягаемости_ предметов, используемых в _главной_ _руке_.", + "item.create.extendo_grip.tooltip.condition2": "Когда надет Медный баллон", + "item.create.extendo_grip.tooltip.behaviour2": " _НЕ_ тратится _прочность_. Вместо этого будет тратиться _воздух_ из баллона.", - "item.create.filter.tooltip": "FILTER", + "item.create.potato_cannon.tooltip": "КАРТОФЕЛЬНАЯ ПУШКА", + "item.create.potato_cannon.tooltip.summary": "Свомп! Запускайте выращенные вами овощи в своих врагов. Может питаться от давления воздуха из _Медного_ _баллона_", + "item.create.potato_cannon.tooltip.condition1": "Нажимая ПКМ", + "item.create.potato_cannon.tooltip.behaviour1": "_Выстреливает_ подходящим предметом из вашего _инвентаря_.", + "item.create.potato_cannon.tooltip.condition2": "Когда надет Медный баллон", + "item.create.potato_cannon.tooltip.behaviour2": "_НЕ_ тратится _прочность_. Вместо этого будет тратиться _воздух_ из баллона.", + + "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": "ATTRIBUTE FILTER", + "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": "EMPTY SCHEMATIC", + "item.create.empty_schematic.tooltip": "ПУСТАЯ СХЕМАТИКА", "item.create.empty_schematic.tooltip.summary": "Используется в качестве ингредиента рецепта и для записи в _Схематичный столе_", - "item.create.schematic.tooltip": "SCHEMATIC", + "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": "SCHEMATIC AND QUILL", + "item.create.schematic_and_quill.tooltip": "СХЕМАТИКА И ПЕРО", "item.create.schematic_and_quill.tooltip.summary": "Используется для сохранения структуры в вашем мире в файл .nbt.", "item.create.schematic_and_quill.tooltip.condition1": "Шаг 1", "item.create.schematic_and_quill.tooltip.behaviour1": "Выберите две угловые точки, используя ПКМ.", @@ -1321,110 +1386,156 @@ "item.create.schematic_and_quill.tooltip.control3": "ПКМ крадучись", "item.create.schematic_and_quill.tooltip.action3": "_Сбрасывает_ и _удаляет_ выделение.", - "block.create.schematicannon.tooltip": "SCHEMATICANNON", + "block.create.schematicannon.tooltip": "СХЕМАТИЧНАЯ ПУШКА", "block.create.schematicannon.tooltip.summary": "_Ставит блоки_ для воссоздания _схематики_ в мире. Использует предметы из _соседнего_ _инвентаря_ и _порох_ в качестве _топлива_.", "block.create.schematicannon.tooltip.condition1": "ПКМ", "block.create.schematicannon.tooltip.behaviour1": "Открывает _Интерфейс_", - "block.create.schematic_table.tooltip": "SCHEMATIC TABLE", + "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": "GOGGLES", + "item.create.goggles.tooltip": "ИНЖЕНЕРНЫЕ ОЧКИ", "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.behaviour2": "Показывает подробную информацию о скорости или нагрузке сети, к которой подключён датчик.", "item.create.goggles.tooltip.condition3": "При взгляде на жидкостные контейнеры", "item.create.goggles.tooltip.behaviour3": "Показывает детализированную информацию о _Ёмкости_ блока и о хранящейся в нём хранится _Жидкости_.", - "item.create.wrench.tooltip": "WRENCH", + "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": "NOZZLE", + "block.create.nozzle.tooltip": "ФОРСУНКА", "block.create.nozzle.tooltip.summary": "Прикрепите к передней части _вентилятора_, чтобы распределить его влияние на сущностей _во_ _всех_ _направлениях_.", - "block.create.cuckoo_clock.tooltip": "CUCKOO CLOCK", + "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": "TURNTABLE", + "block.create.turntable.tooltip": "ПОВОРОТНЫЙ СТОЛ", "block.create.turntable.tooltip.summary": "Преобразует _силу_ _вращения_ прямиком в морскую болезнь.", - "block.create.portable_fluid_interface.tooltip": "PORTABLE FLUID INTERFACE", - "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.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", - "block.create.stockpile_switch.tooltip": "stockpile_switch", - "block.create.stockpile_switch.tooltip.summary": "Подаёт сигнал красного камня в зависимости от _заполниности_ _прикреплённого_ _ящика_.", + "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": "CONTENT OBSERVER", + "block.create.content_observer.tooltip": "НАБЛЮДАТЕЛЬ ЗА СОДЕРЖИМЫМ", "block.create.content_observer.tooltip.summary": "_Обнаруживает элементы_ внутри _контейнеров_ и _конвейеров_, соответствующие настроенному _фильтру_. Если наблюдаемый инвентарь, ремень или шланг содержит совпадающий элемент, этот компонент излучает сигнал красного камня. Когда наблюдаемая _ воронка передает_ соответствующий предмет, этот компонент испускает _импульс_.", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", - "block.create.adjustable_crate.tooltip": "ADJUSTABLE CRATE", - "block.create.adjustable_crate.tooltip.summary": "Этот контейнер для хранения позволяет вручную контролировать его емкость. Он может вместить до 16 стэков любого предмета. Поддерживает компараторы.", + "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": "THE ENDLESS CRATE", + "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": "CONTROLLER RAIL", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + + "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.controller_rail.tooltip.behaviour1": "_Ускоряет_ или _замедляет_ _прошедшие вагонетки_, на величину зависящую от _силы сигнала_. Распространяя сигнал красного камня на соседние контролирующие рельсы. Питание двух контролирующих рельс с разной мощностью приведет к тому, что дорожки между ними будут интерполировать свой сигнал.", - "item.create.sand_paper.tooltip": "SAND PAPER", + "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": "BUILDERS TEA", + "item.create.builders_tea.tooltip": "ЧАЙ СТРОИТЕЛЯ", "item.create.builders_tea.tooltip.summary": "Идеальный напиток для начала дня. _Мотивирует и насыщает_.", - "item.create.refined_radiance.tooltip": "REFINED RADIANCE", + "item.create.refined_radiance.tooltip": "ИЗЫСКАННОЕ СИЯНИЕ", "item.create.refined_radiance.tooltip.summary": "Хроматический материал, _добытый_ _из_ _поглощенного_ _света_.", + "item.create.refined_radiance.tooltip.condition1": "Работа в процессе", + "item.create.refined_radiance.tooltip.behaviour1": "Использование этого материала будет доступно в следующем обновлении.", - "item.create.shadow_steel.tooltip": "SHADOW STEEL", + "item.create.shadow_steel.tooltip": "ВОЗВРАЩЕНИЕ ПУСТОТЫ", "item.create.shadow_steel.tooltip.summary": "Хроматический материал, _добытый_ _в_ _пустоте_.", + "item.create.shadow_steel.tooltip.condition1": "Работа в процессе", + "item.create.shadow_steel.tooltip.behaviour1": "Использование этого материала будет доступно в следующем обновлении.", - "item.create.minecart_coupling.tooltip": "MINECART COUPLING", + "item.create.linked_controller.tooltip": "ПОДКЛЮЧАЕМЫЙ КОНТРОЛЛЕР", + "item.create.linked_controller.tooltip.summary": "Предоставляет _ручной_ _контроль_ над частотами _Беспроводного передатчика редстоун сигнала_, присвоенные его _шести_ кнопкам.", + "item.create.linked_controller.tooltip.condition1": "ПКМ", + "item.create.linked_controller.tooltip.behaviour1": "Включает контроллер. _Управление_ _движением_ перехвачено, пока он активен.", + "item.create.linked_controller.tooltip.condition2": "ПКМ крадучись", + "item.create.linked_controller.tooltip.behaviour2": "Открывает _интерфейс_ _конфигурации_.", + "item.create.linked_controller.tooltip.condition3": "ПКМ по приемнику сигнала редстоуна", + "item.create.linked_controller.tooltip.behaviour3": "Включает _режим привязки_, нажмите одну из _шести кнопок_, чтобы привязать его к _частоте передатчика_.", + "item.create.linked_controller.tooltip.condition4": "ПКМ по кафедре", + "item.create.linked_controller.tooltip.behaviour4": "Помещает контроллер на кафедру для удобства использования. (ПКМ крадучись, чтобы забрать его)", + + "item.create.diving_helmet.tooltip": "ШЛЕМ ДЛЯ ДАЙВИНГА", + "item.create.diving_helmet.tooltip.summary": "Вместе с _медным_ _баллоном_, позволяет владельцу _дышать _ _под водой_ в течение длительного времени.", + "item.create.diving_helmet.tooltip.condition1": "При ношении", + "item.create.diving_helmet.tooltip.behaviour1": "Даёт эффект _Водного Дыхания_, медленно тратя _воздух_ из баллона.", + + "item.create.copper_backtank.tooltip": "МЕДНЫЙ БАЛЛОН", + "item.create.copper_backtank.tooltip.summary": "_Носимый_ _резервуар_ для транспортировки воздуха под давлением.", + "item.create.copper_backtank.tooltip.condition1": "При ношении", + "item.create.copper_backtank.tooltip.behaviour1": "Обеспечивает подачу _воздуха_ под _давлением_ к оборудованию, которое в этом нуждается.", + "item.create.copper_backtank.tooltip.condition2": "При размещении и питании от кинетической энергии", + "item.create.copper_backtank.tooltip.behaviour2": "Собирает и сжимает воздух со скоростью, зависящей от скорости вращения.", + + "item.create.diving_boots.tooltip": "БОТИНКИ ДЛЯ ДАЙВИНГА", + "item.create.diving_boots.tooltip.summary": "Пара _тяжелых_ _ботинок_, позволяющая лучше передвигаться по океанскому дну.", + "item.create.diving_boots.tooltip.condition1": "При ношении", + "item.create.diving_boots.tooltip.behaviour1": "Владелец _тонет_ _быстрее_ и _не_ может _плавать_. Ботинки дают возможность _ходить_ и _прыгать_ под водой. На владельца также больше не влияют механические ремни (передвижение по конвейеру).", + + "item.create.crafting_blueprint.tooltip": "СОЗДАНИЕ ЧЕРТЕЖА", + "item.create.crafting_blueprint.tooltip.summary": "_Разместив_ на стене, его можно использовать для _определения_ _расположения_ _компонентов_ (блоков) для более простого ручного создания предметов. Каждый слот показывает Рецепт.", + "item.create.crafting_blueprint.condition1": "ПКМ по пустому слоту", + "item.create.crafting_blueprint.behaviour1": "Открывает меню _крафта_, позволяющее _настроить_ _рецепт_ и отображаемые предметы.", + "item.create.crafting_blueprint.condition2": "ПКМ по настроенному слоту", + "item.create.crafting_blueprint.behaviour2": "_Применяет_ _заданный_ _рецепт_ с подходящими ингредиентами, из вашего _инвентаря_. _Shift_, чтобы создать целого до _стака_ предметов..", + + "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 секунд. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Поверьте мне, это бесполезно.", - "create.tooltip.randomWipDescription6": "Используя этот пункт, вы тем самым соглашаетесь с нашим отказом от ответственности и соглашаетесь с его условиями.", - "create.tooltip.randomWipDescription7": "Этот, возможно, но не для тебя. Как насчет этого?", - "create.tooltip.randomWipDescription8": "Используя его, вы немедленно пожалеете о своем решении.", + "block.create.peculiar_bell.tooltip": "СТРАННЫЙ КОЛОКОЛ", + "block.create.peculiar_bell.tooltip.summary": "Декоративный _латунный колокол_. Установка его прямо над горящем _Огнем душ_ может вызвать побочные эффекты...с", + + "block.create.haunted_bell.tooltip": "ПРИЗРАЧНЫЙ КОЛОКОЛ", + "block.create.haunted_bell.tooltip.summary": "_Проклятый колокол_ населенный потерянными душами Нижнего мира.", + "block.create.haunted_bell.tooltip.condition1": "При ношении или при звоне", + "block.create.haunted_bell.tooltip.behaviour1": "Подсвечивает ближайшие _места без света_ на которых могут появляться _враждебные мобы_..", "_": "->------------------------] Ponder Content [------------------------<-", - "create.ponder.hold_to_ponder": "Удерживайте [%1$s] для Размышления", + "create.ponder.hold_to_ponder": "Удерживайте [%1$s] для размышления", "create.ponder.subject": "Субъект этой сцены", - "create.ponder.pondering": "Размышляем о...", + "create.ponder.pondering": "Размышляем о/об...", "create.ponder.identify_mode": "Режим Идентификации включён.\nУбрать паузу: [%1$s]", "create.ponder.associated": "Связанные статьи", "create.ponder.close": "Закрыть", @@ -1434,41 +1545,46 @@ "create.ponder.replay": "Воспроизвести снова", "create.ponder.think_back": "Подумать о предыдущем", "create.ponder.slow_text": "Удобное чтение", - "create.ponder.shared.movement_anchors": "С помощью Суперклея или Шасси, более крупные структуры могут быть сдивинуты.", - "create.ponder.shared.rpm32": "32 об./мин.", - "create.ponder.shared.sneak_and": "Красться +", - "create.ponder.shared.storage_on_contraption": "Присоединённые к Штуковине инвентари будут подбирать вещи автоматически", + "create.ponder.exit": "Выйти", + "create.ponder.welcome": "Добро пожаловать в размышления", + "create.ponder.categories": "Категории, доступные в Create", + "create.ponder.index_description": "Кликните по одной из иконок, чтобы узнать о связанных с ней предметах и блоках.", + "create.ponder.index_title": "Содержание размышлений", + "create.ponder.shared.rpm16": "16 об./мин.", "create.ponder.shared.behaviour_modify_wrench": "Это поведение может быть изменено Ключом", + "create.ponder.shared.storage_on_contraption": "Присоединённые к штуковине инвентари будут подбирать вещи автоматически", + "create.ponder.shared.sneak_and": "Красться +", "create.ponder.shared.rpm8": "8 об./мин.", "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm32": "32 об./мин.", "create.ponder.shared.rpm16_source": "Источник: 16 об./мин.", - "create.ponder.shared.rpm16": "16 об./мин.", - "create.ponder.tag.kinetic_sources": "Кинетические источники", - "create.ponder.tag.kinetic_sources.description": "Компоненты, генерирующие Силу Вращения", - "create.ponder.tag.contraption_actor": "UNLOCALIZED: Contraption Actors", - "create.ponder.tag.contraption_actor.description": "Компоненты, проявляющие особое поведение когда прикреплены к двигающейся штуковине", - "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": "Опоры Движения", - "create.ponder.tag.movement_anchor.description": "Компоненты, позволяющие создавать двигающиеся штуковины, оживляя прикрепленную структуру разными способами", - "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.shared.movement_anchors": "С помощью суперклея или шасси, более крупные структуры могут быть сдвинуты.", + "create.ponder.tag.redstone": "Логические компоненты", + "create.ponder.tag.redstone.description": "Компоненты, помогающие с конструированием редстоун схем", "create.ponder.tag.contraption_assembly": "Приспособления для присоединения блоков", "create.ponder.tag.contraption_assembly.description": "Инструменты и Компоненты используемые для сборки структур передвигаемых как движущиеся Штуковины", + "create.ponder.tag.fluids": "Жидкостные манипуляторы", + "create.ponder.tag.fluids.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.tag.windmill_sails": "Паруса для Подшипников ветряной мельницы", + "create.ponder.tag.windmill_sails.description": "Блоки, число которых увеличивает силу Ветряной мельницы. Каждый из этих блоков имеет одинаковую эффективность в деле.", + "create.ponder.tag.arm_targets": "Цели для Механической руки", + "create.ponder.tag.arm_targets.description": "Компоненты, которые могут быть выбраны входами или выходами для Механической руки", + "create.ponder.tag.kinetic_appliances": "Кинетические приборы", + "create.ponder.tag.kinetic_appliances.description": "Компоненты, использующие силу вращения", + "create.ponder.tag.kinetic_sources": "Кинетические источники", + "create.ponder.tag.kinetic_sources.description": "Компоненты, генерирующие силу вращения", + "create.ponder.tag.movement_anchor": "Опоры движения", + "create.ponder.tag.movement_anchor.description": "Компоненты, позволяющие создавать двигающиеся штуковины, оживляя прикрепленную структуру разными способами", + "create.ponder.tag.kinetic_relays": "Кинетические блоки", + "create.ponder.tag.kinetic_relays.description": "Компоненты, помогающие передавать силу вращения куда-нибудь", + "create.ponder.tag.contraption_actor": "Компоненты штуковин", + "create.ponder.tag.contraption_actor.description": "Компоненты, проявляющие особое поведение когда прикреплены к двигающейся штуковине", + "create.ponder.tag.creative": "Творческий режим", + "create.ponder.tag.creative.description": "Компоненты обычно недоступные в Режиме Выживания", + "create.ponder.tag.logistics": "Транспортировка предметов", + "create.ponder.tag.logistics.description": "Компоненты, помогающие перемещать предметы", "create.ponder.adjustable_pulse_repeater.header": "Управлении сигналами с помощью Регулируемого импульсного повторителя", "create.ponder.adjustable_pulse_repeater.text_1": "Регулируемые импульсные повторители испускают короткий импульс с задержкой", @@ -1482,628 +1598,750 @@ "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": "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.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_modes.text_3": "Если сборщик настроен на блокировку вращения, то ориентация штуковин никогда не изменится", + + "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": "В обоих случаях Цепные приводы в ряду всегда вращаются с 2x скоростью активированного Цепного механизма", + "create.ponder.chain_gearshift.text_5": "Используя аналоговые сигналы, это умножение может быть настроено более точно между 1 и 2", + "create.ponder.chain_gearshift.text_6": "12 об./мин.", + + "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": "Осмотр желобов в Инженерных очках открывает информацию о направлении движения", + "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": "Творческом жидкостном баке", + "create.ponder.creative_fluid_tank.text_1": "Творческий жидкостный бак может использоваться для обеспечения бесконечного запаса жидкости", + "create.ponder.creative_fluid_tank.text_2": "Щелкните ПКМ предметом, содержащим жидкость, чтобы настроить его", + "create.ponder.creative_fluid_tank.text_3": "Сети труб могут бесконечно вытягивать заданную жидкость из резервуара", + "create.ponder.creative_fluid_tank.text_4": "Любые жидкости, закачанные обратно в творческий жидкостный бак, будут уничтожены", + + "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": "Обработке элементов с помощью автономных активаторов", + "create.ponder.deployer_processing.text_1": "Держа подходящий предмет/инструмент, автономные активаторы могут обрабатывать предметы под собой", + "create.ponder.deployer_processing.text_2": "Принимаемые предметы можно бросить или положить на депо под автономным активатором", + "create.ponder.deployer_processing.text_3": "Когда предметы находятся на конвейере...", + "create.ponder.deployer_processing.text_4": "автономный активатор будет удерживать и обрабатывать их автоматически", + + "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.empty_blaze_burner.text_6": "Однако они не будут подходить для промышленного нагрева", + + "create.ponder.encased_fluid_pipe.header": "Обрамлении Жидкостных труб", + "create.ponder.encased_fluid_pipe.text_1": "Медный корпус можно использовать для украшения декорации труб.", + "create.ponder.encased_fluid_pipe.text_2": "Помимо того, что они скрываются, заключенные в обрамление трубы блокируются в текущем состоянии", + "create.ponder.encased_fluid_pipe.text_3": "Они больше не будут реагировать на добавление или удаление каких-либо соседних блоков", + + "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": "Перемещении жидкостей при помощи медных труб.", + "create.ponder.fluid_pipe_flow.text_1": "Жидкостные трубы могут соединять два или более источников и потребителей жидкости", + "create.ponder.fluid_pipe_flow.text_2": "При помощи гаечного ключа можно создать окно прямому отрезку трубы", + "create.ponder.fluid_pipe_flow.text_3": "Трубы с окнами не будут соединяться ни с какими другими рядом идущими отрезками труб", + "create.ponder.fluid_pipe_flow.text_4": "Приводимые в действие механическими помпами, трубы могут транспортировать жидкости", + "create.ponder.fluid_pipe_flow.text_5": "Сначала жидкость не выкачивается", + "create.ponder.fluid_pipe_flow.text_6": "Как только поток соединит концы, они постепенно перекачают свое содержимое", + "create.ponder.fluid_pipe_flow.text_7": "Таким образом, сами блоки труб никогда «физически» не содержат никакой жидкости", + + "create.ponder.fluid_pipe_interaction.header": "Опустошении и наполнении жидкостных контейнеров", + "create.ponder.fluid_pipe_interaction.text_1": "Концы сети труб могут взаимодействовать с различными блоками", + "create.ponder.fluid_pipe_interaction.text_2": "Любой блок с возможностью хранения жидкости может быть заполнен или опустошен", + "create.ponder.fluid_pipe_interaction.text_3": "Источники прямо перед открытым концом можно откачать...", + "create.ponder.fluid_pipe_interaction.text_4": "...в то время как выливание в незаполненное пространство может создать источники", + "create.ponder.fluid_pipe_interaction.text_5": "Трубы также могут извлекать жидкости непосредственно из нескольких других блоков", + + "create.ponder.fluid_tank_sizes.header": "Размерах жидкостного бака", + "create.ponder.fluid_tank_sizes.text_1": "Жидкостные баки можно объединить для увеличения общей вместимости", + "create.ponder.fluid_tank_sizes.text_2": "Их площадь основания может составлять до 3 блоков в ширину...", + "create.ponder.fluid_tank_sizes.text_3": "...и увеличиваются в высоту более чем на 30 дополнительных уровней", + "create.ponder.fluid_tank_sizes.text_4": "При помощи гаечного ключа можно создать окно на резервуаре", + + "create.ponder.fluid_tank_storage.header": "Хранении жидкостей в жидкостных баках", + "create.ponder.fluid_tank_storage.text_1": "Жидкостные баки можно использовать для хранения большого количества жидкости", + "create.ponder.fluid_tank_storage.text_2": "Трубы могут закачивать и выкачивать жидкости с любой стороны", + "create.ponder.fluid_tank_storage.text_3": "Содержащаяся жидкость может быть измерена с помощью компаратора", + "create.ponder.fluid_tank_storage.text_4": "Однако в режиме выживания жидкость нельзя добавлять или извлекать вручную", + "create.ponder.fluid_tank_storage.text_5": "Вы можете использовать чаши, предметные осушители и дозаторы для опустошения или наполнения содерж. жидкость предметов", + + "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": "Наполнении и осушении источников с помощью Шкива со шлангом", + "create.ponder.hose_pulley.text_1": "Шкивы со шлангом можно использовать для заполнения или осушения больших объёмов жидкости.", + "create.ponder.hose_pulley.text_2": "С помощью кинетической энергии можно регулировать длину шланга", + "create.ponder.hose_pulley.text_3": "Шкив сматывается, если обратить вращение", + "create.ponder.hose_pulley.text_4": "С противоположной стороны можно подключать трубы", + "create.ponder.hose_pulley.text_5": "Присоединённые сети труб могут либо подавать жидкость в шланг...", + "create.ponder.hose_pulley.text_6": "...либо вытягивать её, осушая водоем", + "create.ponder.hose_pulley.text_7": "Скорость заполнения и осушения шкивом полностью зависит от пропускной способности жидкостной сети", + + "create.ponder.hose_pulley_infinite.header": "Пассивном заполнении и осушении больших объёмов жидкости", + "create.ponder.hose_pulley_infinite.text_1": "При развертывании Шкива со шлангом в достаточно большой океан...", + "create.ponder.hose_pulley_infinite.text_2": "Он будет предоставлять/поглощать жидкости без влияния на источник", + "create.ponder.hose_pulley_infinite.text_3": "Сети труб могут неограниченно передавать жидкости из/в такие шкивы", + + "create.ponder.hose_pulley_level.header": "Уровне заполнения и осушения Шкива со шлангом", + "create.ponder.hose_pulley_level.text_1": "При полностью убранном рукаве шланга - он не может работать", + "create.ponder.hose_pulley_level.text_2": "Осушение происходит сверху вниз", + "create.ponder.hose_pulley_level.text_3": "Уровень поверхности окажется чуть ниже того места, где заканчивается шланг", + "create.ponder.hose_pulley_level.text_4": "Наполнение происходит снизу вверх", + "create.ponder.hose_pulley_level.text_5": "Заполняемый бассейн не будет наполняться выше уровня конца шланга", + + "create.ponder.item_drain.header": "Опустошении жидкостных резервуаров с помощью предметных осушителей", + "create.ponder.item_drain.text_1": "Предметные осушители могут извлекать жидкости из предметов", + "create.ponder.item_drain.text_2": "Щелкните ПКМ по нему, чтобы перелить в него жидкость из предмета в ваших руках", + "create.ponder.item_drain.text_3": "Когда предметы подаются со стороны...", + "create.ponder.item_drain.text_4": "...они переворачиваются, выливая содержащуюся в них жидкость", + "create.ponder.item_drain.text_5": "Сети труб теперь могут вытягивать жидкость из внутреннего хранилища осушителей", + + "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": "Транспортировке жидкости при помощи Механических помп", + "create.ponder.mechanical_pump_flow.text_1": "Механические помпы направляют поток в присоединённые сети из труб", + "create.ponder.mechanical_pump_flow.text_2": "Когда работает, стрелка указывает направление потока", + "create.ponder.mechanical_pump_flow.text_3": "Часть сети сзади теперь качает жидкости...", + "create.ponder.mechanical_pump_flow.text_4": "...в то время как часть сети спереди передаёт их наружу", + "create.ponder.mechanical_pump_flow.text_5": "Смена направления вращения изменяет направление потока", + "create.ponder.mechanical_pump_flow.text_6": "Используйте гаечный ключ, чтобы изменить направление помпы вручную", + + "create.ponder.mechanical_pump_speed.header": "Производительности механических помп", + "create.ponder.mechanical_pump_speed.text_1": "Независимо от скорости, Механические помпы оказывают влияние на трубы в радиусе 16 блоков", + "create.ponder.mechanical_pump_speed.text_2": "Ускорение подаваемого вращения изменяет скорость распространения потоков...", + "create.ponder.mechanical_pump_speed.text_3": "...также, как и скорость передачи жидкостей", + "create.ponder.mechanical_pump_speed.text_4": "Помпы могут объединять свою производительность в общих сетях труб", + "create.ponder.mechanical_pump_speed.text_5": "Изменение их направления может помочь сонаправить направление их потоков", + + "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.nixie_tube.text_3": "Щелкните ПКМ с красителем, чтобы изменить цвет их дисплея", + + "create.ponder.piston_pole.header": "Удлинителях Поршня", + "create.ponder.piston_pole.text_1": "Без присоединённых Удлинителей, Механический поршень не может двигаться", + "create.ponder.piston_pole.text_2": "Длина стержня, добавленного к его задней части, определяет Диапазон выдвижения.", + + "create.ponder.portable_fluid_interface.header": "Портативном жидкостном интерфейсе на штуковинах", + "create.ponder.portable_fluid_interface.text_1": "Жидкостные баки на движущихся штуковинах не могут быть доступны ни каким трубам", + "create.ponder.portable_fluid_interface.text_2": "Этот интерфейс может взаимодействовать с жидкостными баками без необходимости останавливать штуковину", + "create.ponder.portable_fluid_interface.text_3": "Установите второй с промежутком в 1 или 2 блока между ними", + "create.ponder.portable_fluid_interface.text_4": "Они установят соединение, когда встретятся", + "create.ponder.portable_fluid_interface.text_5": "Пока они соединены, стационарный интерфейс будет представлять собой ВСЕ баки на штуковине", + "create.ponder.portable_fluid_interface.text_6": "Теперь можно закачать жидкости...", + "create.ponder.portable_fluid_interface.text_7": "...или выкачать их из штуковины", + "create.ponder.portable_fluid_interface.text_8": "Если на какое-то время прекратится обмен содержимым - штуковина продолжит свой путь", + + "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": "Управлении сигналами при помощи Питаемого рычаг-переключателя", + "create.ponder.powered_toggle_latch.text_1": "Питаемый рычаг-переключатель - управляемый редстоуном рычаг", + "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": "Управлении жидкостным потоком с помощью Умных труб", + "create.ponder.smart_pipe.text_1": "Умные трубы могут помочь управлять потоками по типам жидкостей", + "create.ponder.smart_pipe.text_2": "Размещенные непосредственно у источника, они могут указывать тип извлекаемой жидкости", + "create.ponder.smart_pipe.text_3": "Просто щелкните ПКМ на слоте фильтра с любым предметом, содержащим нужную жидкость", + "create.ponder.smart_pipe.text_4": "И при размещении глубже по сети труб умные трубы будут пропускать только подходящие жидкости.", + + "create.ponder.speedometer.header": "Мониторинге Кинетической информации при помощи Спидометра", + "create.ponder.speedometer.text_1": "Спидометры отображают текущую скорость присоединённых компонентов", + "create.ponder.speedometer.text_2": "При ношении Инженерных очков игрок может получить более полную информацию от прибора", + "create.ponder.speedometer.text_3": "Компараторы могут испускать аналоговый Редстоун сигнал относительно измерений спидометра", + + "create.ponder.spout_filling.header": "Наполнении предметов при помощи дозатора", + "create.ponder.spout_filling.text_1": "Дозатор может заполнять подходящие предметы, расположенные под ним", + "create.ponder.spout_filling.text_2": "К содержимому дозатора невозможно получить доступ вручную.", + "create.ponder.spout_filling.text_3": "Вместо этого можно использовать трубы для подачи в него жидкостей", + "create.ponder.spout_filling.text_4": "Наполняемые предметы могут быть размещены на депо под дозатором", + "create.ponder.spout_filling.text_5": "Когда предметы подаются конвейером...", + "create.ponder.spout_filling.text_6": "Дозатор будет удерживать и обрабатывать их автоматически", + + "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": "При ношении Инженерных очков игрок может получить более полную информацию от прибора", + "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": "Управлении потоком жидкости с помощью вентилей", + "create.ponder.valve_pipe.text_1": "Жидкостные вентили помогают контролировать распространение жидкостей по сетям труб", + "create.ponder.valve_pipe.text_2": "Их входной вал контролирует, разрешена ли подача жидкости в данный момент", + "create.ponder.valve_pipe.text_3": "При вращении в направлении открытия - клапан откроется", + "create.ponder.valve_pipe.text_4": "Его можно снова закрыть, изменив направление входного вращения", + + "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/lang/unfinished/zh_cn.json b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json index 513325f0d..6e15adb82 100644 --- a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json +++ b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json @@ -3,8 +3,8 @@ "_": "->------------------------] Game Elements [------------------------<-", - "block.create.acacia_window": "金合欢窗户", - "block.create.acacia_window_pane": "金合欢窗户板", + "block.create.acacia_window": "金合欢木窗户", + "block.create.acacia_window_pane": "金合欢木窗户板", "block.create.adjustable_chain_gearshift": "可调节链式传动箱", "block.create.adjustable_crate": "可调节板条箱", "block.create.adjustable_pulse_repeater": "可调节脉冲中继器", @@ -26,14 +26,18 @@ "block.create.andesite_tunnel": "安山岩隧道", "block.create.basin": "工作盆", "block.create.belt": "传送带", - "block.create.birch_window": "白桦窗户", - "block.create.birch_window_pane": "白桦窗户板", + "block.create.birch_window": "白桦木窗户", + "block.create.birch_window_pane": "白桦木窗户板", + "block.create.black_nixie_tube": "黑色辉光管", "block.create.black_sail": "黑色风帆", "block.create.black_seat": "黑色坐垫", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "黑色阀门手轮", "block.create.blaze_burner": "烈焰人燃烧室", + "block.create.blue_nixie_tube": "蓝色辉光管", "block.create.blue_sail": "蓝色风帆", "block.create.blue_seat": "蓝色坐垫", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "蓝色阀门手轮", "block.create.brass_belt_funnel": "黄铜传送带漏斗", "block.create.brass_block": "黄铜块", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "黄铜传动杆箱", "block.create.brass_funnel": "黄铜漏斗", "block.create.brass_tunnel": "黄铜隧道", + "block.create.brown_nixie_tube": "棕色辉光管", "block.create.brown_sail": "棕色风帆", "block.create.brown_seat": "棕色坐垫", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "棕色阀门手轮", "block.create.cart_assembler": "矿车装配站", "block.create.chiseled_dark_scoria": "錾制深色熔渣", @@ -53,12 +59,12 @@ "block.create.chiseled_weathered_limestone": "錾制风化石灰岩", "block.create.chocolate": "巧克力", "block.create.chute": "溜槽", - "block.create.clockwork_bearing": "时钟轴承", + "block.create.clockwork_bearing": "发条轴承", "block.create.clutch": "离合器", "block.create.cogwheel": "齿轮", "block.create.content_observer": "物品侦测器", "block.create.controller_rail": "控制铁轨", - "block.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "block.create.copper_backtank": "Copper Backtank", "block.create.copper_block": "铜块", "block.create.copper_casing": "铜机壳", "block.create.copper_ore": "铜矿石", @@ -68,13 +74,15 @@ "block.create.creative_crate": "创造板条箱", "block.create.creative_fluid_tank": "创造流体储罐", "block.create.creative_motor": "创造马达", - "block.create.crimson_window": "绯红窗户", - "block.create.crimson_window_pane": "绯红窗户板", + "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_nixie_tube": "青色辉光管", "block.create.cyan_sail": "青色风帆", "block.create.cyan_seat": "青色坐垫", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "青色阀门手轮", "block.create.dark_oak_window": "深色橡木窗户", "block.create.dark_oak_window_pane": "深色橡木窗户板", @@ -179,20 +187,25 @@ "block.create.granite_cobblestone_stairs": "花岗岩圆石楼梯", "block.create.granite_cobblestone_wall": "花岗岩圆石墙", "block.create.granite_pillar": "竖纹花岗岩", + "block.create.gray_nixie_tube": "灰色辉光管", "block.create.gray_sail": "灰色风帆", "block.create.gray_seat": "灰色坐垫", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "灰色阀门手轮", + "block.create.green_nixie_tube": "绿色辉光管", "block.create.green_sail": "绿色风帆", "block.create.green_seat": "绿色坐垫", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "绿色阀门手轮", "block.create.hand_crank": "手摇曲柄", + "block.create.haunted_bell": "森魂钟", "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.jungle_window": "丛林木窗户", + "block.create.jungle_window_pane": "丛林木窗户板", "block.create.large_cogwheel": "大齿轮", "block.create.layered_andesite": "层叠安山岩", "block.create.layered_dark_scoria": "层叠深色熔渣", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "层叠石灰岩", "block.create.layered_scoria": "层叠熔渣", "block.create.layered_weathered_limestone": "层叠风化石灰岩", + "block.create.lectern_controller": "遥控器讲台", + "block.create.light_blue_nixie_tube": "淡蓝色辉光管", "block.create.light_blue_sail": "淡蓝色风帆", "block.create.light_blue_seat": "淡蓝色坐垫", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "淡蓝色阀门手轮", + "block.create.light_gray_nixie_tube": "淡灰色辉光管", "block.create.light_gray_sail": "淡灰色风帆", "block.create.light_gray_seat": "淡灰色坐垫", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "淡灰色阀门手轮", + "block.create.lime_nixie_tube": "黄绿色辉光管", "block.create.lime_sail": "黄绿色风帆", "block.create.lime_seat": "黄绿色坐垫", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "黄绿色阀门手轮", "block.create.limesand": "石灰沙", "block.create.limestone": "石灰岩", @@ -225,8 +245,10 @@ "block.create.limestone_pillar": "竖纹石灰岩", "block.create.linear_chassis": "机壳底盘", "block.create.lit_blaze_burner": "烈焰人燃烧室(已点燃)", + "block.create.magenta_nixie_tube": "品红色辉光管", "block.create.magenta_sail": "品红色风帆", "block.create.magenta_seat": "品红色坐垫", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "品红色阀门手轮", "block.create.mechanical_arm": "动力臂", "block.create.mechanical_bearing": "动力轴承", @@ -243,15 +265,15 @@ "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.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": "辉光管", @@ -260,18 +282,19 @@ "block.create.oak_window_pane": "橡木窗户板", "block.create.orange_sail": "橙色风帆", "block.create.orange_seat": "橙色坐垫", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "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.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": "安山岩铺路石楼梯", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "风化石灰岩铺路石台阶", "block.create.paved_weathered_limestone_stairs": "风化石灰岩铺路石楼梯", "block.create.paved_weathered_limestone_wall": "风化石灰岩铺路石墙", + "block.create.peculiar_bell": "奇异钟", + "block.create.pink_nixie_tube": "粉红色辉光管", "block.create.pink_sail": "粉红色风帆", "block.create.pink_seat": "粉红色坐垫", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "粉红色阀门手轮", "block.create.piston_extension_pole": "活塞杆", "block.create.polished_dark_scoria": "磨制深色熔渣", @@ -342,12 +368,16 @@ "block.create.powered_toggle_latch": "转换锁存器", "block.create.pulley_magnet": "滑轮磁铁", "block.create.pulse_repeater": "脉冲中继器", + "block.create.purple_nixie_tube": "紫色辉光管", "block.create.purple_sail": "紫色风帆", "block.create.purple_seat": "紫色坐垫", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "紫色阀门手轮", "block.create.radial_chassis": "旋转底盘", + "block.create.red_nixie_tube": "红色辉光管", "block.create.red_sail": "红色风帆", "block.create.red_seat": "红色坐垫", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "红色阀门手轮", "block.create.redstone_contact": "接触式红石信号发生器", "block.create.redstone_link": "无线红石信号终端", @@ -369,7 +399,7 @@ "block.create.scoria_cobblestone_stairs": "熔渣圆石楼梯", "block.create.scoria_cobblestone_wall": "熔渣圆石墙", "block.create.scoria_pillar": "竖纹熔渣", - "block.create.secondary_linear_chassis": "机壳底盘2号", + "block.create.secondary_linear_chassis": "机壳底盘 2 号", "block.create.sequenced_gearshift": "可编程齿轮箱", "block.create.shadow_steel_casing": "暗影机壳", "block.create.shaft": "传动杆", @@ -377,8 +407,8 @@ "block.create.smart_fluid_pipe": "智能流体管道", "block.create.speedometer": "速度表", "block.create.spout": "注液器", - "block.create.spruce_window": "云杉窗户", - "block.create.spruce_window_pane": "云杉窗户板", + "block.create.spruce_window": "云杉木窗户", + "block.create.spruce_window_pane": "云杉木窗户板", "block.create.sticker": "黏着器", "block.create.sticky_mechanical_piston": "黏性动力活塞", "block.create.stockpile_switch": "存量转换器", @@ -402,24 +432,32 @@ "block.create.weathered_limestone_cobblestone_wall": "风化石灰岩圆石墙", "block.create.weathered_limestone_pillar": "竖纹风化石灰岩", "block.create.weighted_ejector": "弹射置物台", + "block.create.white_nixie_tube": "白色辉光管", "block.create.white_sail": "白色风帆", "block.create.white_seat": "白色坐垫", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "白色阀门手轮", "block.create.windmill_bearing": "风车轴承", "block.create.wooden_bracket": "木质支架", + "block.create.yellow_nixie_tube": "黄色辉光管", "block.create.yellow_sail": "黄色风帆", "block.create.yellow_seat": "黄色坐垫", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "黄色阀门手轮", "block.create.zinc_block": "锌块", "block.create.zinc_ore": "锌矿石", + "enchantment.create.capacity": "扩容", + "enchantment.create.potato_recovery": "土豆回收", + "entity.create.contraption": "装置", + "entity.create.crafting_blueprint": "合成蓝图", "entity.create.gantry_contraption": "起重机装置", + "entity.create.potato_projectile": "被发射的土豆", "entity.create.seat": "坐垫", "entity.create.stationary_contraption": "固定装置", "entity.create.super_glue": "强力胶", - "fluid.create.milk": "牛奶", "fluid.create.potion": "药水", "fluid.create.tea": "茶", @@ -439,11 +477,13 @@ "item.create.chocolate_glazed_berries": "巧克力包层浆果", "item.create.chromatic_compound": "异彩化合物", "item.create.cinder_flour": "下界面粉", - "item.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "item.create.copper_backtank": "铜制背罐", "item.create.copper_ingot": "铜锭", "item.create.copper_nugget": "铜粒", "item.create.copper_sheet": "铜板", "item.create.crafter_slot_cover": "合成器盖板", + "item.create.crafting_blueprint": "合成蓝图", + "item.create.creative_blaze_cake": "创造模式烈焰蛋糕", "item.create.crushed_aluminum_ore": "粉碎铝矿石", "item.create.crushed_brass": "粉碎黄铜", "item.create.crushed_copper_ore": "粉碎铜矿石", @@ -458,8 +498,8 @@ "item.create.crushed_tin_ore": "粉碎锡矿石", "item.create.crushed_uranium_ore": "粉碎铀矿石", "item.create.crushed_zinc_ore": "粉碎锌矿石", - "item.create.diving_boots": "UNLOCALIZED: Diving Boots", - "item.create.diving_helmet": "UNLOCALIZED: Diving Helmet", + "item.create.diving_boots": "潜水靴", + "item.create.diving_helmet": "潜水头盔", "item.create.dough": "面团", "item.create.electron_tube": "电子管", "item.create.empty_blaze_burner": "空的烈焰人燃烧室", @@ -472,13 +512,17 @@ "item.create.handheld_worldshaper": "手持式环境塑形器", "item.create.honey_bucket": "蜂蜜桶", "item.create.honeyed_apple": "蜜渍苹果", - "item.create.integrated_circuit": "集成电路板", + "item.create.incomplete_cogwheel": "齿轮(半成品)", + "item.create.incomplete_large_cogwheel": "大齿轮(半成品)", + "item.create.incomplete_precision_mechanism": "精密构件(半成品)", "item.create.iron_sheet": "铁板", - "item.create.lapis_sheet": "青金石板", + "item.create.linked_controller": "无线红石遥控器", "item.create.minecart_contraption": "装配过的矿车", "item.create.minecart_coupling": "矿车连轴器", "item.create.polished_rose_quartz": "磨制玫瑰石英", + "item.create.potato_cannon": "土豆加农炮", "item.create.powdered_obsidian": "黑曜石粉末", + "item.create.precision_mechanism": "精密构件", "item.create.propeller": "扇叶", "item.create.red_sand_paper": "红沙砂纸", "item.create.refined_radiance": "光辉石", @@ -502,18 +546,18 @@ "_": "->------------------------] Advancements [------------------------<-", "advancement.create.root": "欢迎来到机械动力", - "advancement.create.root.desc": "是时候来制作一些超赞的机械结构了!", - "advancement.create.andesite_alloy": "头韵狂魔(Alliterations Aplenty)", + "advancement.create.root.desc": "是时候来制作一些超赞的机械装置了!", + "advancement.create.andesite_alloy": "头韵狂魔(Alliterations Aplenty)", "advancement.create.andesite_alloy.desc": "机械动力的材料名字都很古怪,安山合金(Andesite Alloy)就是其中之一。", "advancement.create.its_alive": "鲜活的机械生命", - "advancement.create.its_alive.desc": "首次激活齿轮结构的旋转。", + "advancement.create.its_alive.desc": "首次激活动力学组件。", "advancement.create.shifting_gears": "换挡,加速,起飞!", - "advancement.create.shifting_gears.desc": "将大齿轮连接到小齿轮上,可以改变结构的转速。", + "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": "躲起来!", "advancement.create.tunnel.desc": "用隧道装饰传送带。", "advancement.create.splitter_tunnel": "分而治之", "advancement.create.splitter_tunnel.desc": "用黄铜隧道设计一个分流器。", @@ -530,7 +574,7 @@ "advancement.create.fan_lava": "地热取暖", "advancement.create.fan_lava.desc": "被熔炼气流烤的酥脆。", "advancement.create.fan_water": "奇妙的洗涤流程", - "advancement.create.fan_water.desc": "被洗涤气流洗了个澡。", + "advancement.create.fan_water.desc": "在洗涤气流里洗了个澡。", "advancement.create.fan_smoke": "动力风箱", "advancement.create.fan_smoke.desc": "被烟熏气流熏得满脸黑。", "advancement.create.wrench": "细节调整", @@ -541,25 +585,25 @@ "advancement.create.speedometer.desc": "放置一个速度表,并且带上工程师护目镜来读取速度数据", "advancement.create.stressometer": "精密的应力控制", "advancement.create.stressometer.desc": "放置一个应力表,并且带上工程师护目镜来读取应力数据", - "advancement.create.aesthetics": "美观,即是一切!", + "advancement.create.aesthetics": "什么叫美学,这就叫美学!", "advancement.create.aesthetics.desc": "将支架放在传动杆,管道和齿轮上。", - "advancement.create.reinforced": "Boom~ 加强!", + "advancement.create.reinforced": "什么叫强化,这就叫强化!", "advancement.create.reinforced.desc": "在传动杆,管道和传送带上使用机壳加固。", - "advancement.create.water_wheel": "治水", + "advancement.create.water_wheel": "掌控水流", "advancement.create.water_wheel.desc": "放置一个水车并且让它开始旋转", - "advancement.create.chocolate_wheel": "味美动力", + "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.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": "安山时代", "advancement.create.andesite_casing.desc": "使用安山合金和木头来合成一个安山机壳", "advancement.create.mechanical_drill": "坚如磐石,势如破竹", "advancement.create.mechanical_drill.desc": "放置一个动力钻头并且为其供能", @@ -581,13 +625,13 @@ "advancement.create.compact.desc": "使用辊压机在工作盆中压缩一些物品", "advancement.create.brass": "真正的合金", "advancement.create.brass.desc": "使用粉碎锌矿石和粉碎铜矿石来制作粉碎黄铜", - "advancement.create.brass_casing": "黄铜纪元", + "advancement.create.brass_casing": "黄铜时代", "advancement.create.brass_casing.desc": "用黄铜和木头制作一个黄铜机壳", - "advancement.create.copper_casing": "铜之纪元", + "advancement.create.copper_casing": "铜器时代", "advancement.create.copper_casing.desc": "使用铜和木头制作一个铜制机壳", "advancement.create.spout": "哗啦啦", "advancement.create.spout.desc": "观察注液器灌满物品。", - "advancement.create.spout_potion": "全球啤酒厂", + "advancement.create.spout_potion": "环球酿造厂", "advancement.create.spout_potion.desc": "观察注液器注入药水到玻璃瓶。", "advancement.create.chocolate": "幻想世界", "advancement.create.chocolate.desc": "获取一桶熔融巧克力。", @@ -603,29 +647,29 @@ "advancement.create.pipe_spill.desc": "观察管道的开口端将流体排放或放置到世界中。", "advancement.create.hose_pulley": "工业泄漏", "advancement.create.hose_pulley.desc": "放下一个软管滑轮,观察它排干或填充一大片液体。", - "advancement.create.infinite_water": "排干海洋", + "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": "美梦不饶人", "advancement.create.infinite_chocolate.desc": "从大到足以被被视为无限的巧克力海中抽取巧克力。", "advancement.create.crafter": "自动化装配", "advancement.create.crafter.desc": "放置一些机械合成台并且为其供能", "advancement.create.clockwork_bearing": "巧械时钟", - "advancement.create.clockwork_bearing.desc": "组装安装在发条轴承上的结构。", + "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": "工程师的眼中钉", "advancement.create.speed_controller.desc": "放置一个转速控制器,这是换档的终极装置。", "advancement.create.flywheel": "工厂之心", "advancement.create.flywheel.desc": "将引擎成功连接到飞轮。", - "advancement.create.overstress_flywheel": "高压", + "advancement.create.overstress_flywheel": "压力山大", "advancement.create.overstress_flywheel.desc": "过载熔炉引擎。", - "advancement.create.integrated_circuit": "复杂运算", - "advancement.create.integrated_circuit.desc": "组装集成电路。", - "advancement.create.mechanical_arm": "忙碌的手!", + "advancement.create.precision_mechanism": "高新技术", + "advancement.create.precision_mechanism.desc": "装配一个精密构件。", + "advancement.create.mechanical_arm": "飞转的手!", "advancement.create.mechanical_arm.desc": "制作机械臂,选择输入和输出,放置并给予它动力,然后看着它为你完成所有工作。", "advancement.create.musical_arm": "没人能在我的 BGM 里打败我!", "advancement.create.musical_arm.desc": "使用动力臂播放唱片。", @@ -645,12 +689,14 @@ "advancement.create.shadow_steel.desc": "制作一些暗影钢", "advancement.create.refined_radiance": "明亮而启灵", "advancement.create.refined_radiance.desc": "制作一个光辉石", - "advancement.create.chromatic_age": "异彩纪元", + "advancement.create.chromatic_age": "异彩时代", "advancement.create.chromatic_age.desc": "创造出光与影的机壳。", "advancement.create.wand_of_symmetry": "简单的镜面几何学", "advancement.create.wand_of_symmetry.desc": "制作一个对称之杖", "advancement.create.extendo_grip": "biu biu biu!", "advancement.create.extendo_grip.desc": "获得一个伸缩机械手", + "advancement.create.potato_cannon": "Fwoomp!", + "advancement.create.potato_cannon.desc": "用土豆加农炮击杀一个生物。", "advancement.create.dual_extendo_grip": "biu——biu——biu——", "advancement.create.dual_extendo_grip.desc": "双持伸缩机械手,超人般的触碰距离。", "advancement.create.eob": "Beta 版结束", @@ -660,18 +706,34 @@ "_": "->------------------------] UI & Messages [------------------------<-", "itemGroup.create.base": "机械动力", - "itemGroup.create.palettes": "机械动力建筑方块", + "itemGroup.create.palettes": "机械动力丨建筑方块", "death.attack.create.crush": "%1$s被压扁了", + "death.attack.create.crush.player": "%1$s被%2$s推进了粉碎机", "death.attack.create.fan_fire": "%1$s试图接受热风的洗礼", + "death.attack.create.fan_fire.player": "%2$s给了%1$s一次热风的洗礼", "death.attack.create.fan_lava": "%1$s在接受热风的洗礼中浴火焚身", + "death.attack.create.fan_lava.player": "%1$s被%2$s火化了", "death.attack.create.mechanical_drill": "%1$s被钻头钻的坏掉了", + "death.attack.create.mechanical_drill.player": "%1$s因为%2$s和钻头来了一次亲密接触", "death.attack.create.mechanical_saw": "%1$s被圆锯切成了两截", + "death.attack.create.mechanical_saw.player": "%1$s被%2$s按在圆锯上切碎了", + "death.attack.create.potato_cannon": "%1$s被%2$s的土豆糊了一脸", + "death.attack.create.potato_cannon.item": "%1$s被%2$s用%3$s射死了", "death.attack.create.cuckoo_clock_explosion": "%1$s被布谷鸟钟炸得粉身碎骨", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s被布谷鸟钟炸得粉身碎骨", "create.block.deployer.damage_source_name": "二五仔机械手", "create.block.cart_assembler.invalid": "请将矿车装配器放置在铁轨上", + "create.menu.return": "返回上一级菜单", + "create.menu.configure": "配置...", + "create.menu.ponder_index": "思索内容清单", + "create.menu.only_ingame": "仅在游戏内暂停菜单中可用", + "create.menu.project_page": "在CurseForge上查看", + "create.menu.report_bugs": "报告Create的漏洞", + "create.menu.support": "支持我们", + "create.recipe.crushing": "粉碎", "create.recipe.milling": "研磨", "create.recipe.fan_washing": "批量洗涤", @@ -682,13 +744,13 @@ "create.recipe.fan_blasting.fan": "在熔岩后放置鼓风机", "create.recipe.pressing": "金属压片", "create.recipe.mixing": "混合搅拌", - "create.recipe.deploying": "UNLOCALIZED: Deploying", + "create.recipe.deploying": "使用", "create.recipe.automatic_shapeless": "自动搅拌", "create.recipe.automatic_brewing": "自动酿造", "create.recipe.packing": "压块塑形", "create.recipe.automatic_packing": "自动打包", - "create.recipe.sawing": "板材切割", - "create.recipe.mechanical_crafting": "自动合成", + "create.recipe.sawing": "切割", + "create.recipe.mechanical_crafting": "动力合成", "create.recipe.automatic_shaped": "自动合成", "create.recipe.block_cutting": "方块切割", "create.recipe.wood_cutting": "木材切割", @@ -696,7 +758,18 @@ "create.recipe.mystery_conversion": "神秘转化", "create.recipe.spout_filling": "注液", "create.recipe.draining": "分液", + "create.recipe.sequenced_assembly": "序列组装", + "create.recipe.assembly.next": "下一步:%1$s", + "create.recipe.assembly.step": "第%1$s步:", + "create.recipe.assembly.progress": "组装进度:%1$s/%2$s", + "create.recipe.assembly.pressing": "进行辊压", + "create.recipe.assembly.spout_filling_fluid": "注入%1$s", + "create.recipe.assembly.deploying_item": "安装%1$s", + "create.recipe.assembly.cutting": "用动力锯切割", + "create.recipe.assembly.repeat": "该序列需要重复 %1$s 次", + "create.recipe.assembly.junk": "随机废料", "create.recipe.processing.chance": "%1$s%%概率", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", "create.recipe.heat_requirement.none": "无需加热", "create.recipe.heat_requirement.heated": "加热", "create.recipe.heat_requirement.superheated": "超级加热", @@ -725,6 +798,7 @@ "create.action.discard": "放弃", "create.keyinfo.toolmenu": "工具菜单", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "(游戏中)向上鼠标滚轮", "create.keyinfo.scrolldown": "(游戏中)向下鼠标滚轮", @@ -732,9 +806,16 @@ "create.gui.scrollInput.scrollToModify": "滚动修改", "create.gui.scrollInput.scrollToAdjustAmount": "滚动修改数量", "create.gui.scrollInput.scrollToSelect": "滚动选择", - "create.gui.scrollInput.shiftScrollsFaster": "按住Shift滚动更快", + "create.gui.scrollInput.shiftScrollsFaster": "按住 Shift 滚动更快", "create.gui.toolmenu.focusKey": "按住 [%1$s] 鼠标滚轮选择", "create.gui.toolmenu.cycle": "[SCROLL] 循环", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "镜子类型", "create.gui.symmetryWand.orientation": "方向", @@ -749,15 +830,15 @@ "create.orientation.alongX": "以x轴对齐", "create.gui.terrainzapper.title": "手持式环境塑形器", - "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": "对角线延伸", + "create.gui.terrainzapper.searchFuzzy": "忽略质料分界", + "create.gui.terrainzapper.patternSection": "样式", + "create.gui.terrainzapper.pattern.solid": "填满", + "create.gui.terrainzapper.pattern.checkered": "棋盘格", + "create.gui.terrainzapper.pattern.inversecheckered": "反转棋盘格", + "create.gui.terrainzapper.pattern.chance25": "随机填充 25%", + "create.gui.terrainzapper.pattern.chance50": "随机填充 50%", + "create.gui.terrainzapper.pattern.chance75": "随机填充 75%", "create.gui.terrainzapper.placement": "放置模式", "create.gui.terrainzapper.placement.merged": "结合", "create.gui.terrainzapper.placement.attached": "依附", @@ -766,8 +847,8 @@ "create.gui.terrainzapper.brush.cuboid": "矩形体", "create.gui.terrainzapper.brush.sphere": "球体", "create.gui.terrainzapper.brush.cylinder": "圆柱体", - "create.gui.terrainzapper.brush.surface": "UNLOCALIZED: Surface", - "create.gui.terrainzapper.brush.cluster": "UNLOCALIZED: Cluster", + "create.gui.terrainzapper.brush.surface": "表面", + "create.gui.terrainzapper.brush.cluster": "簇状", "create.gui.terrainzapper.tool": "填充类型", "create.gui.terrainzapper.tool.fill": "填充", "create.gui.terrainzapper.tool.place": "复写", @@ -776,9 +857,9 @@ "create.gui.terrainzapper.tool.overlay": "覆盖", "create.gui.terrainzapper.tool.flatten": "平整", - "create.terrainzapper.shiftRightClickToSet": "Shift+鼠标右击以设置塑形类型", - "create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s", - "create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material", + "create.terrainzapper.shiftRightClickToSet": "按住 Shift 右击以设置塑形类型", + "create.terrainzapper.usingBlock": "使用:%1$s", + "create.terrainzapper.leftClickToSet": "鼠标左击一个方块以设置填充材料", "create.minecart_coupling.two_couplings_max": "矿车无法被连接两个以上的矿车连轴器", "create.minecart_coupling.unloaded": "有一部分火车存在于未加载区块中", @@ -794,20 +875,20 @@ "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": "始终面朝前进方向", "create.contraptions.cart_movement_mode.rotate_paused": "矿车转向时机器停止工作", - "create.contraptions.cart_movement_mode.rotation_locked": "装置方向保持不变", + "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.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.firstFrequency": "UNLOCALIZED: Freq. #1", + "create.logistics.secondFrequency": "UNLOCALIZED: Freq. #2", "create.logistics.filter.apply": "已将过滤应用于%1$s。", "create.logistics.filter.apply_click_again": "已将过滤应用于%1$s,再次点击可将手持物品数量复制到过滤器上。", "create.logistics.filter.apply_count": "已将提取数量应用至过滤器。", @@ -818,13 +899,13 @@ "create.gui.goggles.pole_length": "活塞杆长度:", "create.gui.goggles.fluid_container": "流体容器信息:", "create.gui.goggles.fluid_container.capacity": "容量:", - "create.gui.assembly.exception": "无法组装该结构:", + "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": "结构中的方块数量过多。\n配置中的最大数量限制为:%1$s", - "create.gui.assembly.exception.tooManyPistonPoles": "活塞加装的活塞杆数量过多。\n配置中的最大数量限制为:%1$s", + "create.gui.assembly.exception.chunkNotLoaded": "位于 [%1$s,%2$s,%3$s] 的方块未处于加载区块", + "create.gui.assembly.exception.structureTooLarge": "装置中的方块数量过多。", + "create.gui.assembly.exception.tooManyPistonPoles": "活塞加装的活塞杆数量过多。", "create.gui.assembly.exception.noPistonPoles": "活塞缺失部分活塞杆", - "create.gui.assembly.exception.not_enough_sails": "相接的结构所包含的类风帆方块的数量不足。%1$s\n最低需要 %2$s 个方块", + "create.gui.assembly.exception.not_enough_sails": "相接的结构所包含的类风帆方块的数量不足。%1$s", "create.gui.gauge.info_header": "仪表信息:", "create.gui.speedometer.title": "旋转速度", "create.gui.stressometer.title": "网络应力", @@ -863,7 +944,7 @@ "create.schematicAndQuill.dimensions": "蓝图尺寸:%1$sx%2$sx%3$s", "create.schematicAndQuill.firstPos": "第一个位置。", "create.schematicAndQuill.secondPos": "第二个位置。", - "create.schematicAndQuill.noTarget": "按住Ctrl选择空气方块。", + "create.schematicAndQuill.noTarget": "按住 Ctrl 选择空气方块。", "create.schematicAndQuill.abort": "删除选择。", "create.schematicAndQuill.title": "蓝图名:", "create.schematicAndQuill.convert": "立即保存并部署", @@ -889,18 +970,18 @@ "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.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.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.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.1": "按住 Ctrl 鼠标滚动旋转90度", "create.schematic.tool.rotate.description.2": "", "create.schematic.tool.rotate.description.3": "", "create.schematic.tool.print.description.0": "立即将结构放置在世界上", @@ -908,7 +989,7 @@ "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.1": "指向蓝图,然后按住 Ctrl 鼠标滚动将其翻转。", "create.schematic.tool.flip.description.2": "", "create.schematic.tool.flip.description.3": "", @@ -935,7 +1016,7 @@ "create.gui.schematicannon.option.replaceWithSolid": "用固体方块替换工作区域内的方块", "create.gui.schematicannon.option.replaceWithAny": "用任何方块替换工作区域内的方块", "create.gui.schematicannon.option.replaceWithEmpty": "用空气替换工作区域内的方块", - "create.gui.schematicannon.option.skipMissing": "绕过缺少的方块", + "create.gui.schematicannon.option.skipMissing": "跳过缺少的方块", "create.gui.schematicannon.option.skipTileEntities": "保护存储方块", "create.gui.schematicannon.slot.gunpowder": "向蓝图加农炮添加火药以提供动力", "create.gui.schematicannon.slot.listPrinter": "在此处放置书以打印蓝图所需的材料清单", @@ -947,17 +1028,17 @@ "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.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.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": "清除方块中", @@ -966,7 +1047,7 @@ "create.schematicannon.status.schematicExpired": "蓝图文件已过期", "create.materialChecklist": "材料清单", - "create.materialChecklist.blocksNotLoaded": "*免责声明* \n\n由于未加载相关区块,材料清单可能不正确。", + "create.materialChecklist.blocksNotLoaded": "*免责声明* ", "create.gui.filter.deny_list": "黑名单", "create.gui.filter.deny_list.description": "只通过不在黑名单中的物品,如果黑名单为空,所有物品都可以通过", @@ -981,18 +1062,14 @@ "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.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "已被附魔", "create.item_attributes.enchanted.inverted": "未被附魔", + "create.item_attributes.max_enchanted": "已达到最高附魔等级", + "create.item_attributes.max_enchanted.inverted": "并未达到最高附魔等级", + "create.item_attributes.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "已损坏", "create.item_attributes.damaged.inverted": "未损坏", "create.item_attributes.badly_damaged": "严重受损", @@ -1003,20 +1080,33 @@ "create.item_attributes.equipable.inverted": "不可装备", "create.item_attributes.furnace_fuel": "可作为燃料", "create.item_attributes.furnace_fuel.inverted": "不可作为燃料", + "create.item_attributes.washable": "可被洗涤", + "create.item_attributes.washable.inverted": "不可被洗涤", + "create.item_attributes.crushable": "可被粉碎", + "create.item_attributes.crushable.inverted": "不可被粉碎", + "create.item_attributes.smeltable": "可被熔炉烧制", + "create.item_attributes.smeltable.inverted": "不可被熔炉烧制", + "create.item_attributes.smokable": "可被烟熏", + "create.item_attributes.smokable.inverted": "不可被烟熏", + "create.item_attributes.blastable": "可被高炉冶炼", + "create.item_attributes.blastable.inverted": "不可被高炉冶炼", + "create.item_attributes.shulker_level": "潜影盒是%1$s的", + "create.item_attributes.shulker_level.inverted": "潜影盒不是%1$s的", + "create.item_attributes.shulker_level.full": "满", + "create.item_attributes.shulker_level.empty": "空", + "create.item_attributes.shulker_level.partial": "部分填充", "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.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_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编写", @@ -1029,17 +1119,17 @@ "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.item_attributes.astralsorcery_constellation": "与%1$s共鸣", + "create.item_attributes.astralsorcery_constellation.inverted": "不与%1$s共鸣", + "create.item_attributes.astralsorcery_crystal": "有水晶石属性%1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "没有水晶石属性%1$s", + "create.item_attributes.astralsorcery_perk_gem": "带有有星能力属性%1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "不带有星能力属性%1$s", - "create.gui.attribute_filter.no_selected_attributes": "没有标记任何属性", - "create.gui.attribute_filter.selected_attributes": "已选择的属性:", + "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": "任意匹配白名单(任何)", @@ -1071,14 +1161,14 @@ "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.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.targeting": "弹射至 [%1$s,%2$s,%3$s]", "create.weighted_ejector.stack_size": "弹射物品堆数量", "create.logistics.when_multiple_outputs_available": "当多个输出可用时", @@ -1104,13 +1194,34 @@ "create.tooltip.chute.fans_pull_up": "鼓风机从上方进行吸引", "create.tooltip.chute.fans_pull_down": "鼓风机从下方进行吸引", "create.tooltip.chute.contains": "内含物品:%1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "目前分配:", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "鼠标右击取出", + + "create.linked_controller.bind_mode": "绑定模式激活", + "create.linked_controller.press_keybind": "按下%1$s、%2$s、%3$s、%4$s、%5$s或%6$s,可以将该频率绑定到按下的按键上。", + "create.linked_controller.key_bound": "该频率已绑定到%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": "原料槽", + "create.crafting_blueprint.filter_items_viable": "可以使用过滤器", + "create.crafting_blueprint.display_slot": "展示槽", + "create.crafting_blueprint.inferred": "已根据合成配方自动设定", + "create.crafting_blueprint.manually_assigned": "手动设定", + "create.crafting_blueprint.secondary_display_slot": "次要展示槽", + "create.crafting_blueprint.optional": "可选", + + "create.potato_cannon.ammo.attack_damage": "%1$s 攻击伤害", + "create.potato_cannon.ammo.reload_ticks": "%1$s 装弹时间(Ticks)", + "create.potato_cannon.ammo.knockback": "%1$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.empty_bearing": "_空手右击_轴承,可以将你新建造的结构_接到_轴承上。", "create.hint.full_deployer.title": "机械手物品溢出", "create.hint.full_deployer": "_机械手_包含_过剩的物品,_需要被_提取。你需要_使用_料斗,__漏斗_或其他方法将溢出释放出来。", @@ -1124,42 +1235,54 @@ "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]: 服务器恢复到正常速度 :D", - "create.command.killTPSCommand.status.usage.0": "[Create]: 用 /killtps stop 来让服务器的TPS速度变回正常", - "create.command.killTPSCommand.status.usage.1": "[Create]: 用 /killtps start 来手动降低服务器TPS速度", + "create.command.killTPSCommand.status.slowed_by.0": "[Create]: 服务器现在的 TPS 速度被降低为 %s ms :o", + "create.command.killTPSCommand.status.slowed_by.1": "[Create]: 服务器现在的 TPS 速度被降低为 >:)", + "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": "这一矿车装置似乎太大了,无法变为拾捡状态", + "create.contraption.minecart_contraption_illegal_pickup": "一股神秘的力量将这一装置与世界牢牢绑定在了一起。", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "粘液:挤碎声", - "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.contraption_disassemble": "结构:停止移动", + "create.subtitle.peculiar_bell_use": "奇异钟:鸣响", + "create.subtitle.mixing": "搅拌器:搅拌声", + "create.subtitle.mechanical_press_activation_belt": "辊压机:撞击传送带", + "create.subtitle.fwoomp": "土豆加农炮:发射", + "create.subtitle.worldshaper_place": "环境塑型器:放置方块", + "create.subtitle.crushing_1": "磨碎声", + "create.subtitle.depot_slide": "物品:滑入", + "create.subtitle.saw_activate_stone": "动力锯:切割", "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.funnel_flap": "漏斗:垂帘碰撞", "create.subtitle.schematicannon_finish": "蓝图加农炮:叮", - "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.haunted_bell_use": "森魂钟:鸣响", + "create.subtitle.scroll_value": "拨码输入:咔哒", + "create.subtitle.crafter_craft": "动力合成器:合成中", + "create.subtitle.controller_put": "遥控器:放进讲台", + "create.subtitle.cranking": "手摇曲柄:转动", + "create.subtitle.wrench_remove": "组件:被破坏", + "create.subtitle.cogs": "齿轮:嘎吱作响", + "create.subtitle.slime_added": "粘液:挤碎声", + "create.subtitle.wrench_rotate": "扳手:拧动", + "create.subtitle.potato_hit": "土豆:击中", + "create.subtitle.saw_activate_wood": "动力锯:切割", + "create.subtitle.haunted_bell_convert": "奇异钟:转化", + "create.subtitle.deployer_polish": "机械手:打磨物品", + "create.subtitle.deny": "提示声:出错", + "create.subtitle.controller_click": "遥控器:按下按钮", + "create.subtitle.schematicannon_launch_block": "蓝图加农炮:发射", + "create.subtitle.copper_armor_equip": "潜水装备:铿锵", + "create.subtitle.controller_take": "讲台:取走物品", "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", + "create.subtitle.contraption_assemble": "结构:开始移动", + "create.subtitle.crafter_click": "动力合成器:咔哒声", + "create.subtitle.depot_plop": "物品:着地", + "create.subtitle.confirm": "提示声:接受", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1179,81 +1302,14 @@ "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": "会使得玩家坐在_坐垫_上,L-Shift可离开_坐垫_。", + "block.create.seat.tooltip.behaviour1": "会使得玩家坐在_坐垫_上,按下左 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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Places a window on the pipe if available", - - "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": "当在快捷栏时", @@ -1283,6 +1339,15 @@ "item.create.extendo_grip.tooltip.summary": "biubiubiu! 大幅度_增加了_使用者的_触碰距离_。", "item.create.extendo_grip.tooltip.condition1": "放置于副手栏时", "item.create.extendo_grip.tooltip.behaviour1": "增加_主手_所使用物品的_接触距离_。", + "item.create.extendo_grip.tooltip.condition2": "当装备铜制背罐时", + "item.create.extendo_grip.tooltip.behaviour2": "使用罐中_气压_来_抵消_伸缩机械手的_耐久_损耗。", + + "item.create.potato_cannon.tooltip": "土豆加农炮", + "item.create.potato_cannon.tooltip.summary": "噗!把你亲手栽培的蔬菜砸向你的敌人。可以使用_铜制背罐_供能。", + "item.create.potato_cannon.tooltip.condition1": "当右击时", + "item.create.potato_cannon.tooltip.behaviour1": "_发射_你_物品栏_中任一可作为弹药的物品。", + "item.create.potato_cannon.tooltip.condition2": "当装备铜制背罐时", + "item.create.potato_cannon.tooltip.behaviour2": "使用罐中_气压_来_抵消_土豆加农炮的_耐久_损耗。", "item.create.filter.tooltip": "过滤器", "item.create.filter.tooltip.summary": "可用于_精确_控制物流设备的_输出_以及_输入_,使得通过的物品流与_一组_物品或者数个_相嵌套的过滤器_相匹配。", @@ -1323,8 +1388,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": "When R-Clicked", + "block.create.schematicannon.tooltip.behaviour1": "Opens the _Interface_", "block.create.schematic_table.tooltip": "蓝图桌", "block.create.schematic_table.tooltip.summary": "将保存的蓝图图写入_空白蓝图_", @@ -1358,12 +1423,14 @@ "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.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", "block.create.stockpile_switch.tooltip": "存量转换器", "block.create.stockpile_switch.tooltip.summary": "根据连接的容器中_储存物品_的数量切换红石信号强度。自带有过滤槽,与_比较器_不同的是,你可以配置_存量转换器_信号反转的_阈值_。", @@ -1372,17 +1439,26 @@ "block.create.content_observer.tooltip": "物品侦测器", "block.create.content_observer.tooltip.summary": "检测_容器_和_传送带_中过滤器匹配的物品。当在_物品栏_,_传送带_或者_溜槽所容物_中侦测到匹配的物品时,此组件将发出_红石信号_。当观察到的漏斗_转移匹配的物品_时,此组件将发出_红石脉冲_。", + "block.create.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "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.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": "任何从容器中_提取_的物品都是_无限量的_,而任何_放置_到容器中的物品都会被_送入虚空_", + "item.create.creative_blaze_cake.tooltip": "创造蛋糕", + "item.create.creative_blaze_cake.tooltip.summary": "为_烈焰人燃烧室_特制的小食,可以让你_控制燃烧室的热量等级_。吃下这个蛋糕之后,烈焰人燃烧室将_不再耗尽燃料_。", + "item.create.creative_blaze_cake.tooltip.condition1": "对着烈焰人燃烧室使用", + "item.create.creative_blaze_cake.tooltip.behaviour1": "_锁定_烈焰人燃烧室的热量等级。如果再次使用,会使得燃烧室的热量等级开始_循环_变化。", + "block.create.controller_rail.tooltip": "控制铁轨", "block.create.controller_rail.tooltip.summary": "一种_汇流的,受红石信号影响的_铁轨,可以_较好地控制_经过矿车的_移动速度_。", "block.create.controller_rail.tooltip.condition1": "通入红石信号时时", @@ -1394,30 +1470,65 @@ "item.create.sand_paper.tooltip.behaviour1": "打磨_副手_上或者_准心所指_的物品。", "item.create.builders_tea.tooltip": "建造工茶饮", - "item.create.builders_tea.tooltip.summary": "饮下这杯完美茶饮,开启神清气爽的一天。可以回复_饥饿值_并获得_急迫_效果。", + "item.create.builders_tea.tooltip.summary": "饮下这杯完美茶饮,开启神清气爽的一天。可以恢复_饥饿值_并获得_急迫_效果。", "item.create.refined_radiance.tooltip": "光辉石", "item.create.refined_radiance.tooltip.summary": "一种用_光辉_锻造的化合物材料。", + "item.create.refined_radiance.tooltip.condition1": "尚未完工", + "item.create.refined_radiance.tooltip.behaviour1": "该材料在未来可能会有更多的用途。", "item.create.shadow_steel.tooltip": "暗影钢", "item.create.shadow_steel.tooltip.summary": "一种用_虚空_锻造的化合物材料。", + "item.create.shadow_steel.tooltip.condition1": "尚未完工", + "item.create.shadow_steel.tooltip.behaviour1": "该材料在未来可能会有更多的用途。", + + "item.create.linked_controller.tooltip": "无线红石遥控器", + "item.create.linked_controller.tooltip.summary": "提供_六个_可以绑定_无线红石_频道的按钮,用于_遥控_附近的_无线红石信号终端_。", + "item.create.linked_controller.tooltip.condition1": "右击时", + "item.create.linked_controller.tooltip.behaviour1": "_拿起_或_放下_遥控器。拿起遥控器时,_控制移动_将被用来_操作遥控器_,而不是移动玩家。", + "item.create.linked_controller.tooltip.condition2": "潜行右击时", + "item.create.linked_controller.tooltip.behaviour2": "打开手动_配置界面_。", + "item.create.linked_controller.tooltip.condition3": "右击无线红石信号终端时", + "item.create.linked_controller.tooltip.behaviour3": "启用_绑定模式_,按下_六个按键_中的一个,即可将此按键与_无线红石信号终端的频率_绑定。", + "item.create.linked_controller.tooltip.condition4": "右击讲台时", + "item.create.linked_controller.tooltip.behaviour4": "将遥控器放在讲台上以便使用(潜行右击来取回遥控器)。", + + "item.create.diving_helmet.tooltip": "潜水头盔", + "item.create.diving_helmet.tooltip.summary": "与_铜制背罐_配合使用,为穿戴者提供在_水下_行动一段时间所需的_空气_。", + "item.create.diving_helmet.tooltip.condition1": "戴在头上时", + "item.create.diving_helmet.tooltip.behaviour1": "提供_水下呼吸_效果。缓慢消耗背罐中的_压缩空气_。", + + "item.create.copper_backtank.tooltip": "铜制背罐", + "item.create.copper_backtank.tooltip.summary": "一个可以_背在背上_的_铜罐_,用于携带一定量的压缩空气。", + "item.create.copper_backtank.tooltip.condition1": "背在背上时", + "item.create.copper_backtank.tooltip.behaviour1": "为其他需要_压缩空气_的装备提供所需的空气。", + "item.create.copper_backtank.tooltip.condition2": "当放下并接入动力时", + "item.create.copper_backtank.tooltip.behaviour2": "基于转速从周围环境中_收集_并_加压空气_。", + + "item.create.diving_boots.tooltip": "潜水靴", + "item.create.diving_boots.tooltip.summary": "一双_沉重的靴子_,让穿戴者可以更方便的探索海底。", + "item.create.diving_boots.tooltip.condition1": "穿在脚上时", + "item.create.diving_boots.tooltip.behaviour1": "穿戴者_下沉更快_并_无法游泳_。穿戴者可以在水下_行走_和_跳跃_。穿戴者不会被_传送带_移走。", + + "item.create.crafting_blueprint.tooltip": "合成蓝图", + "item.create.crafting_blueprint.tooltip.summary": "_放在_墙上,便可用它来设置特定的_原料排布_,以便更快地制作物品。每个格子都可以设定一个配方。", + "item.create.crafting_blueprint.condition1": "当右击空的格子时", + "item.create.crafting_blueprint.behaviour1": "打开一个_配方设置界面_,用于_设置_一个_合成配方_以及展示的物品。", + "item.create.crafting_blueprint.condition2": "当右击设置好的格子时", + "item.create.crafting_blueprint.behaviour2": "使用_物品栏_中的物品制作_设置的配方_。_潜行_可以一次合成_一组_。", "item.create.minecart_coupling.tooltip": "矿车连轴器", - "item.create.minecart_coupling.tooltip.summary": "将多个_矿车_或运输结构链接在一起,构成雄伟的火车。", + "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": "试试就逝世。", + "block.create.peculiar_bell.tooltip": "奇异钟", + "block.create.peculiar_bell.tooltip.summary": "装饰用的_黄铜质钟_。放在_灵魂火_的正上方可能会产生意料之外的后果......", + + "block.create.haunted_bell.tooltip": "森魂钟", + "block.create.haunted_bell.tooltip.summary": "_被诅咒_的钟,来自下界的迷失的灵魂缠绕于其上。", + "block.create.haunted_bell.tooltip.condition1": "当手持或鸣响时", + "block.create.haunted_bell.tooltip.behaviour1": "标识出附近可能生成_敌对生物_的_亮度不足_之处。", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1434,41 +1545,46 @@ "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.exit": "退出", + "create.ponder.welcome": "欢迎来到思索界面", + "create.ponder.categories": "机械动力中包含的条目", + "create.ponder.index_description": "点击一个图标来查看相关的物品和方块。", + "create.ponder.index_title": "思索索引", + "create.ponder.shared.rpm16": "16 RPM", "create.ponder.shared.behaviour_modify_wrench": "可以用扳手调整它的行为。", + "create.ponder.shared.storage_on_contraption": "与装置相接的存储空间,会自动将装置遇到的掉落物拾取到空间内。", + "create.ponder.shared.sneak_and": "潜行 +", "create.ponder.shared.rpm8": "8 RPM", "create.ponder.shared.ctrl_and": "Ctrl +", - "create.ponder.shared.rpm16_source": "动力源:16 R", - "create.ponder.shared.rpm16": "16 RPM", - "create.ponder.tag.kinetic_sources": "动力源", - "create.ponder.tag.kinetic_sources.description": "能够发生动力的组件。", - "create.ponder.tag.contraption_actor": "装置执行组件", - "create.ponder.tag.contraption_actor.description": "能在移动的装置上执行特殊功能的组件", - "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": "运动源泉", - "create.ponder.tag.movement_anchor.description": "有了它,运动装置才得以可能,它可以以数种方式使相接的结构运动起来。", - "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.shared.rpm32": "32 RPM", + "create.ponder.shared.rpm16_source": "动力源:16 RPM", + "create.ponder.shared.movement_anchors": "有了底盘和强力胶,移动起大型结构轻轻松松。", "create.ponder.tag.redstone": "逻辑组件", "create.ponder.tag.redstone.description": "这些组件会在红石工程中发挥大用处。", + "create.ponder.tag.contraption_assembly": "方块连接功能", + "create.ponder.tag.contraption_assembly.description": "将各个组件连接以便同时运动的工具以及组件", "create.ponder.tag.fluids": "流体操纵器械", "create.ponder.tag.fluids.description": "这些组件可以用于传递流体,以及利用流体进行工作。", + "create.ponder.tag.decoration": "装饰", + "create.ponder.tag.decoration.description": "装饰是这些组件的常见用法。", + "create.ponder.tag.windmill_sails": "风车轴承的帆", + "create.ponder.tag.windmill_sails.description": "在进行风车组装时会被算入风车旋转力的方块,这些方块的效能都是一样的。", + "create.ponder.tag.arm_targets": "机械臂的工作目标", + "create.ponder.tag.arm_targets.description": "该组件可做为机械臂的输入或者输出点。", + "create.ponder.tag.kinetic_appliances": "动力设备", + "create.ponder.tag.kinetic_appliances.description": "这些组件可以利用旋转力进行工作。", + "create.ponder.tag.kinetic_sources": "动力源", + "create.ponder.tag.kinetic_sources.description": "能够发生动力的组件。", + "create.ponder.tag.movement_anchor": "运动源泉", + "create.ponder.tag.movement_anchor.description": "有了它,运动装置才得以可能,它可以以数种方式使相接的结构运动起来。", + "create.ponder.tag.kinetic_relays": "动力方块", + "create.ponder.tag.kinetic_relays.description": "用于传递旋转力的组件。", + "create.ponder.tag.contraption_actor": "装置执行组件", + "create.ponder.tag.contraption_actor.description": "能在移动的装置上执行特殊功能的组件", + "create.ponder.tag.creative": "创造模式", + "create.ponder.tag.creative.description": "总有些东西是生存模式得不到的。", + "create.ponder.tag.logistics": "物品运输", + "create.ponder.tag.logistics.description": "该组件可以协助物品运输", "create.ponder.adjustable_pulse_repeater.header": "使用可调节脉冲中继器控制信号发送", "create.ponder.adjustable_pulse_repeater.text_1": "可调节脉冲中继器在一段延时之后会发出一道短时脉冲", @@ -1505,7 +1621,7 @@ "create.ponder.basin.text_9": "若是加装过滤,那么你便无需担心会将未被处理的物品抽取出来了", "create.ponder.bearing_modes.header": "动力轴承的运动模式", - "create.ponder.bearing_modes.text_1": "当结构停止时,轴承会控制结构以特定的角度停在最近的与格相对齐之处", + "create.ponder.bearing_modes.text_1": "停止时,轴承会控制结构以特定的角度停在最近的与格相对齐之处", "create.ponder.bearing_modes.text_2": "你可以调整整个结构永不方块化,或者仅在结构的起始位置方块化", "create.ponder.belt_casing.header": "带机壳的传送带", @@ -1568,19 +1684,20 @@ "create.ponder.brass_tunnel_modes.text_8": "“最近优先”会将物品优先送入距离输入口更近的输出口", "create.ponder.brass_tunnel_modes.text_9": "“随机”会随机选择一个输出口,一次性送入所有物品", - "create.ponder.cart_assembler.header": "使用矿车装配站组装运动结构", + "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.header": "组装连接运输装置", "create.ponder.cart_assembler_dual.text_1": "若两个装配矿车分享了同一个结构", - "create.ponder.cart_assembler_dual.text_2": "给其中的任意一方的矿车装配站通入红石信号,都会创建出连接装置", + "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_modes.text_2": "矿车装置上的箭头表明了哪一侧是“前面”", + "create.ponder.cart_assembler_modes.text_3": "如果装配站的配置为“旋转锁定”,那么装置的方向将不会改变", "create.ponder.cart_assembler_rails.header": "另外几种矿车以及铁轨", "create.ponder.cart_assembler_rails.text_1": "放置在普通轨道上的矿车装配站并不会影响路过矿车装置的运动", @@ -1611,12 +1728,12 @@ "create.ponder.chute_upward.text_2": "佩戴工程师护目镜时,你可以看见物品的移动方向", "create.ponder.chute_upward.text_3": "在溜槽“被挡住的”底端,物品只能从侧边进行提取或输入", - "create.ponder.clockwork_bearing.header": "使用时钟轴承来移动结构", - "create.ponder.clockwork_bearing.text_1": "时钟轴承黏附其正前方的方块", + "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_5": "右击可以激活/停止结构运动", "create.ponder.clockwork_bearing.text_6": "在时针前方可添加第二个结构", "create.ponder.clockwork_bearing.text_7": "请确保这两个结构没有互相被例如强力胶等方式黏附", "create.ponder.clockwork_bearing.text_8": "第二个结构将会作为分针进行旋转", @@ -1634,6 +1751,12 @@ "create.ponder.cogwheel.text_1": "齿轮会将动力传递至临近的齿轮", "create.ponder.cogwheel.text_2": "以此方式连接的齿轮,旋转方向相反", + "create.ponder.creative_fluid_tank.header": "创造流体储罐", + "create.ponder.creative_fluid_tank.text_1": "创造流体储罐可以提供无限量的流体", + "create.ponder.creative_fluid_tank.text_2": "使用一个含有流体的容器右击它,即可指定它提供特定的流体", + "create.ponder.creative_fluid_tank.text_3": "流体管道可以从中无限提取指定的流体", + "create.ponder.creative_fluid_tank.text_4": "任何被输入创造流体储罐的液体都将被销毁", + "create.ponder.creative_motor.header": "使用创造马达发生旋转", "create.ponder.creative_motor.text_1": "创造马达不仅能够手动调配输出旋转力,而且体积相当小巧", "create.ponder.creative_motor.text_2": "对其背侧面板滚动滑轮,可以改变马达的输出旋转转速", @@ -1662,7 +1785,7 @@ "create.ponder.deployer.text_9": "以及攻击生物", "create.ponder.deployer_contraption.header": "在装置上使用机械手", - "create.ponder.deployer_contraption.text_1": "当机械手在移动的结构上时...", + "create.ponder.deployer_contraption.text_1": "当机械手在移动的装置上时...", "create.ponder.deployer_contraption.text_2": "机械手会对每一个经过的方块使用装置中任意容器内的物品", "create.ponder.deployer_contraption.text_3": "可以通过过滤槽来指定其从存储空间中抽取的物品", @@ -1670,6 +1793,12 @@ "create.ponder.deployer_modes.text_1": "在默认情况下,机械手模仿玩家的右击交互", "create.ponder.deployer_modes.text_2": "使用扳手可以将模式调整为模仿玩家的左击交互", + "create.ponder.deployer_processing.header": "使用机械手处理物品", + "create.ponder.deployer_processing.text_1": "当机械手持有合适的物品时,它可以自动处理下方的物品", + "create.ponder.deployer_processing.text_2": "物品可以被丢在机械手下方,或放在置物台上", + "create.ponder.deployer_processing.text_3": "当传送带上的物品经过机械手下方时...", + "create.ponder.deployer_processing.text_4": "...机械手会使物品停下,然后处理这个物品", + "create.ponder.deployer_redstone.header": "使用红石控制机械手", "create.ponder.deployer_redstone.text_1": "当被红石充能时,机械手会停止工作", "create.ponder.deployer_redstone.text_2": "在停止工作前,机械手会完成当前正在进行的工作周期", @@ -1686,7 +1815,13 @@ "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.empty_blaze_burner.text_5": "你可以使用注入了灵魂的物品转化这种火焰", + "create.ponder.empty_blaze_burner.text_6": "但是,没有烈焰人,这样的火焰并不足以用于工业级加热工作", + + "create.ponder.encased_fluid_pipe.header": "流体管道箱", + "create.ponder.encased_fluid_pipe.text_1": "铜机壳可以用于装饰流体管道", + "create.ponder.encased_fluid_pipe.text_2": "除了遮掩流体管道之外,装箱的流体管道将不会改变其连接状态", + "create.ponder.encased_fluid_pipe.text_3": "它将不会对旁边新增加或移除的管道做出反应", "create.ponder.fan_direction.header": "鼓风机的气流", "create.ponder.fan_direction.text_1": "鼓风机使用旋转力来制造气流", @@ -1706,6 +1841,35 @@ "create.ponder.fan_source.text_1": "如鼓风机的扇叶向下朝着热源放置,鼓风机可以借此产生旋转力", "create.ponder.fan_source.text_2": "当鼓风机接受红石信号后,它便会向外供给旋转力", + "create.ponder.fluid_pipe_flow.header": "使用管道运输流体", + "create.ponder.fluid_pipe_flow.text_1": "流体管道可以用于连接两个或多个流体容器", + "create.ponder.fluid_pipe_flow.text_2": "使用扳手,可以为直管道安装观察窗", + "create.ponder.fluid_pipe_flow.text_3": "带有观察窗的管道不会建立侧向管道连接", + "create.ponder.fluid_pipe_flow.text_4": "使用动力泵,流体管道可以传输流体", + "create.ponder.fluid_pipe_flow.text_5": "一开始,流体不会真正地被抽出", + "create.ponder.fluid_pipe_flow.text_6": "只有当管道内的液体流彻底连通之后,流体才会开始逐渐从一个容器中转移到另一个", + "create.ponder.fluid_pipe_flow.text_7": "这意味着流体管道本身并不真正存储任何流体", + + "create.ponder.fluid_pipe_interaction.header": "抽取和填充流体容器", + "create.ponder.fluid_pipe_interaction.text_1": "流体管道的末端可以与许多种容器连接", + "create.ponder.fluid_pipe_interaction.text_2": "任何可以容纳流体的容器都可以被填充或从中抽取", + "create.ponder.fluid_pipe_interaction.text_3": "开放的管道口可以吸走流体源方块...", + "create.ponder.fluid_pipe_interaction.text_4": "...或者将流体源排放出来", + "create.ponder.fluid_pipe_interaction.text_5": "管道也可以从许多种其他方块中直接抽取流体", + + "create.ponder.fluid_tank_sizes.header": "流体储罐的大小", + "create.ponder.fluid_tank_sizes.text_1": "流体储罐可以多格连接,提供更大的存储量", + "create.ponder.fluid_tank_sizes.text_2": "流体储罐最大横截面为 3x3...", + "create.ponder.fluid_tank_sizes.text_3": "...并且可以超过 30 格高", + "create.ponder.fluid_tank_sizes.text_4": "使用扳手可以打开或关闭观察窗", + + "create.ponder.fluid_tank_storage.header": "使用流体储罐存储流体", + "create.ponder.fluid_tank_storage.text_1": "流体储罐可以存储大量的流体", + "create.ponder.fluid_tank_storage.text_2": "流体管道可以在流体储罐的任何一面将流体输入/输出", + "create.ponder.fluid_tank_storage.text_3": "使用比较器可以检测储罐中的流体储量", + "create.ponder.fluid_tank_storage.text_4": "在生存模式中,无法直接用容器向储罐中存入流体,或是取出流体", + "create.ponder.fluid_tank_storage.text_5": "要装满/倒空流体容器,可以使用工作盆,分液池或注液器。", + "create.ponder.flywheel.header": "使用飞轮来产生旋转力", "create.ponder.flywheel.text_1": "飞轮和熔炉引擎必须配套使用,方可产生旋转力", "create.ponder.flywheel.text_2": "如此产生的旋转力具有非常大的应力值", @@ -1760,8 +1924,8 @@ "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.gantry_shaft.text_1": "起重机杆组成了起重机系统的基础。与其相接的载物器可以沿着杆进行移动。", + "create.ponder.gantry_shaft.text_2": "起重机系统可以移动与其相接的方块。", "create.ponder.gearbox.header": "使用十字齿轮箱传递旋转力", "create.ponder.gearbox.text_1": "更改旋转轴,很容易使得整个旋转体系变得臃肿不堪", @@ -1779,6 +1943,34 @@ "create.ponder.hand_crank.text_3": "它产生的转速相对较高", "create.ponder.hand_crank.text_4": "潜行长按右键可以顺时针旋转它", + "create.ponder.hose_pulley.header": "使用软管滑轮抽取或排放流体", + "create.ponder.hose_pulley.text_1": "软管滑轮可以用于方便地对一个较大区域进行抽取液体或填满液体的操作", + "create.ponder.hose_pulley.text_2": "通过输入动力可以调节软管末端的高度", + "create.ponder.hose_pulley.text_3": "翻转动力输入的方向可以收起软管", + "create.ponder.hose_pulley.text_4": "管道可以连接在另一侧", + "create.ponder.hose_pulley.text_5": "连接的管道可以将流体输入到软管滑轮中,软管会在下方排出口处放置流体源...", + "create.ponder.hose_pulley.text_6": "...或者提供吸力来抽取世界中的流体", + "create.ponder.hose_pulley.text_7": "软管滑轮的抽取/排放速度取决于连接管道中流体的流速", + + "create.ponder.hose_pulley_infinite.header": "被动抽取或排放从大体量流体中", + "create.ponder.hose_pulley_infinite.text_1": "当软管被放进足够大的流体中时...", + "create.ponder.hose_pulley_infinite.text_2": "...它在抽取或排放液体时将不会影响流体源", + "create.ponder.hose_pulley_infinite.text_3": "可以从这些软管滑轮中无限量地抽取或向其排放流体", + + "create.ponder.hose_pulley_level.header": "软管滑轮的排水/抽水机制", + "create.ponder.hose_pulley_level.text_1": "当软管彻底收回时,软管滑轮无法工作。", + "create.ponder.hose_pulley_level.text_2": "抽取流体的顺序为从上到下", + "create.ponder.hose_pulley_level.text_3": "流体表面最终将会被抽取到刚好低于软管开口", + "create.ponder.hose_pulley_level.text_4": "填充流体的顺序为从下到上", + "create.ponder.hose_pulley_level.text_5": "流体最多只能被填充至软管开口所在的高度", + + "create.ponder.item_drain.header": "使用分液池提取物品中的流体", + "create.ponder.item_drain.text_1": "分液池可以提取物品中的流体", + "create.ponder.item_drain.text_2": "右击可以将手持物品中的流体倒入分液池中", + "create.ponder.item_drain.text_3": "当物品从侧面输入时...", + "create.ponder.item_drain.text_4": "...物品将会经过分液池顶部,并在此过程中将其包含的液体排入分液池内", + "create.ponder.item_drain.text_5": "流体管道可以从分液池中抽取液体", + "create.ponder.large_cogwheel.header": "使用大齿轮传递旋转力", "create.ponder.large_cogwheel.text_1": "大齿轮可以以特定的角度相互连接", "create.ponder.large_cogwheel.text_2": "可以利用大齿轮变更旋转轴向", @@ -1889,18 +2081,33 @@ "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.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.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.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": "使用动力泵传输流体", + "create.ponder.mechanical_pump_flow.text_1": "动力泵可以控制管道网络中的流体", + "create.ponder.mechanical_pump_flow.text_2": "当接入动力时,其上的箭头指示流体流向", + "create.ponder.mechanical_pump_flow.text_3": "泵后的管道网络正在抽取流体...", + "create.ponder.mechanical_pump_flow.text_4": "...而泵前的网络则把这些液体排到世界当中", + "create.ponder.mechanical_pump_flow.text_5": "反转动力方向将会改变流体流向", + "create.ponder.mechanical_pump_flow.text_6": "使用扳手可以手动改变动力泵的朝向", + + "create.ponder.mechanical_pump_speed.header": "动力泵的传输机制", + "create.ponder.mechanical_pump_speed.text_1": "动力泵的压力最多沿管线传递 16 格,与输入动力无关", + "create.ponder.mechanical_pump_speed.text_2": "提高输入动力,可以加快流的蔓延速度...", + "create.ponder.mechanical_pump_speed.text_3": "...以及流体的传输速度", + "create.ponder.mechanical_pump_speed.text_4": "同一管道网络中的多个并联动力泵,它们的传输量可以叠加", + "create.ponder.mechanical_pump_speed.text_5": "使泵的传输方向相互交替,可以方便地控制流体流向", + "create.ponder.mechanical_saw_breaker.header": "使用动力锯伐木", "create.ponder.mechanical_saw_breaker.text_1": "向其通入旋转力后,动力锯可以直接砍伐掉它面前的树木", "create.ponder.mechanical_saw_breaker.text_2": "想要一次性砍掉整棵树,锯子必须破坏掉树与地面连接的最后一个方块", @@ -1912,7 +2119,7 @@ "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_3": "锯子可以与传送带放置在一条直线上,相互配合工作", "create.ponder.mechanical_saw_processing.text_4": "若输入原料有多种可能产物,你可以用动力锯上的过滤槽指定只产出某种产物", "create.ponder.mechanical_saw_processing.text_5": "若没有使用过滤槽,动力锯会在各产物中按顺序循环输出", @@ -1925,21 +2132,32 @@ "create.ponder.nixie_tube.header": "使用辉光管", "create.ponder.nixie_tube.text_1": "通入红石信号后,辉光管会显示出红石信号的强度", - "create.ponder.nixie_tube.text_2": "使用命名牌在铁砧上为其命名,可以自定义它的显示文本", + "create.ponder.nixie_tube.text_2": "在着它使用更改过名称的命名牌,可以自定义它的显示文本", + "create.ponder.nixie_tube.text_3": "使用染料右击,便可更改辉光管的显示颜色", "create.ponder.piston_pole.header": "活塞延长杆", "create.ponder.piston_pole.text_1": "若无相接的延长杆,动力活塞无法移动其他方块", "create.ponder.piston_pole.text_2": "在其背面安装的延长杆长度,决定了活塞的推动范围", + "create.ponder.portable_fluid_interface.header": "装置流体交换", + "create.ponder.portable_fluid_interface.text_1": "管道无法与运动装置内的流体储罐直接交互", + "create.ponder.portable_fluid_interface.text_2": "这一组件可以在不停止装置的情况下与装置内的流体存储进行交互", + "create.ponder.portable_fluid_interface.text_3": "放置第二个接口时,记得要与装置接口相隔 1 格或者 2 格的距离", + "create.ponder.portable_fluid_interface.text_4": "当它们彼此经过时,它们会连接在一起", + "create.ponder.portable_fluid_interface.text_5": "连接状态下,固定侧接口便会作为整个装置的流体存储代理", + "create.ponder.portable_fluid_interface.text_6": "流体可被泵入到装置内....", + "create.ponder.portable_fluid_interface.text_7": "...或是从装置中抽取出来", + "create.ponder.portable_fluid_interface.text_8": "如果一小段时间内没有流体交换,接口将会断开连接,然后装置重新开始运动", + "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_6": "物品可被输入到装置内...", "create.ponder.portable_storage_interface.text_7": "...或是从装置中提取出来", - "create.ponder.portable_storage_interface.text_8": "物品交换完毕后,装置仍然会停留在原地一小会,然后才会继续前行", + "create.ponder.portable_storage_interface.text_8": "如果一小段时间内没有物品交换,接口将会断开连接,然后装置重新开始运动", "create.ponder.portable_storage_interface_redstone.header": "红石控制", "create.ponder.portable_storage_interface_redstone.text_1": "通入红石信号可以阻止固定侧接口的连接行为", @@ -2028,16 +2246,30 @@ "create.ponder.smart_chute.text_3": "使用鼠标滚轮可以指定被过滤的物品数量", "create.ponder.smart_chute.text_4": "通入红石信号,智能溜槽将会完全暂停工作", + "create.ponder.smart_pipe.header": "使用智能流体管道控制流体流动", + "create.ponder.smart_pipe.text_1": "智能流体管道可以限制通过它的流体种类", + "create.ponder.smart_pipe.text_2": "当紧邻流体源放置时,管道只会抽取设置的流体种类", + "create.ponder.smart_pipe.text_3": "使用任何包含流体的容器右击过滤槽,可以标记过滤的流体", + "create.ponder.smart_pipe.text_4": "当放在管道网络中时,只有匹配过滤器的流体才能通过此管道", + "create.ponder.speedometer.header": "使用速度表来监测转速", "create.ponder.speedometer.text_1": "速度表能显示相接组件的转速", "create.ponder.speedometer.text_2": "当佩戴工程师护目镜时,可以看到仪表所显示的更详细的数据", "create.ponder.speedometer.text_3": "红石比较器可以根据速度表的数值输出不同强弱的红石信号", + "create.ponder.spout_filling.header": "使用注液器填充物品", + "create.ponder.spout_filling.text_1": "注液器可以将流体装入下方经过且可以接受该流体的物品", + "create.ponder.spout_filling.text_2": "注液器的流体存储无法直接手动交互", + "create.ponder.spout_filling.text_3": "使用管道可以将流体输入到注液器内", + "create.ponder.spout_filling.text_4": "输入的物品可以被放置在其下方的置物台上", + "create.ponder.spout_filling.text_5": "当传送带上的物品经过注液器下方时...", + "create.ponder.spout_filling.text_6": "注液器会使物品停下,然后自动处理这一物品", + "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.stabilized_bearings.text_4": "这种情况下,它所黏着的子装置的垂直朝向也不会改变", "create.ponder.sticker.header": "使用黏着器来黏附方块", "create.ponder.sticker.text_1": "你可以用红石信号来控制黏着器的行为", @@ -2064,6 +2296,12 @@ "create.ponder.valve_handle.text_4": "潜行右击可使它顺时针旋转", "create.ponder.valve_handle.text_5": "可以通过染色来美化阀门手轮", + "create.ponder.valve_pipe.header": "使用阀门管道控制液体流", + "create.ponder.valve_pipe.text_1": "阀门管道可以控制管道网络中流体的蔓延", + "create.ponder.valve_pipe.text_2": "通过其上的传动杆输入动力可以控制它的开关", + "create.ponder.valve_pipe.text_3": "提供向“打开”方向的旋转力会打开阀门,使得流体可以通过", + "create.ponder.valve_pipe.text_4": "提供另一方向的旋转力可以关闭阀门,阻止流体通过", + "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..bf3e75b3b 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: 58", "_": "->------------------------] Game Elements [------------------------<-", @@ -28,12 +28,16 @@ "block.create.belt": "輸送帶", "block.create.birch_window": "白樺木窗戶", "block.create.birch_window_pane": "白樺木窗戶片", + "block.create.black_nixie_tube": "黑色真空管", "block.create.black_sail": "黑色風帆", "block.create.black_seat": "黑色坐墊", + "block.create.black_toolbox": "UNLOCALIZED: Black Toolbox", "block.create.black_valve_handle": "黑色閥門開關", "block.create.blaze_burner": "烈焰使者動力爐", + "block.create.blue_nixie_tube": "藍色真空管", "block.create.blue_sail": "藍色風帆", "block.create.blue_seat": "藍色坐墊", + "block.create.blue_toolbox": "UNLOCALIZED: Blue Toolbox", "block.create.blue_valve_handle": "藍色閥門開關", "block.create.brass_belt_funnel": "黃銅輸送帶漏斗", "block.create.brass_block": "黃銅磚", @@ -41,8 +45,10 @@ "block.create.brass_encased_shaft": "黃銅傳動軸箱", "block.create.brass_funnel": "黃銅漏斗", "block.create.brass_tunnel": "黃銅物品隧道", + "block.create.brown_nixie_tube": "棕色真空管", "block.create.brown_sail": "棕色風帆", "block.create.brown_seat": "棕色坐墊", + "block.create.brown_toolbox": "UNLOCALIZED: Brown Toolbox", "block.create.brown_valve_handle": "棕色閥門開關", "block.create.cart_assembler": "礦車裝修站", "block.create.chiseled_dark_scoria": "鏨製黑火成岩", @@ -58,7 +64,7 @@ "block.create.cogwheel": "齒輪", "block.create.content_observer": "物品偵測器", "block.create.controller_rail": "控制鐵軌", - "block.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "block.create.copper_backtank": "銅製後背包", "block.create.copper_block": "銅磚", "block.create.copper_casing": "銅機殼", "block.create.copper_ore": "銅礦石", @@ -73,8 +79,10 @@ "block.create.crushing_wheel": "粉碎輪", "block.create.crushing_wheel_controller": "粉碎輪控制器", "block.create.cuckoo_clock": "布穀鳥鐘", + "block.create.cyan_nixie_tube": "青色真空管", "block.create.cyan_sail": "藍綠色風帆", "block.create.cyan_seat": "藍綠色坐墊", + "block.create.cyan_toolbox": "UNLOCALIZED: Cyan Toolbox", "block.create.cyan_valve_handle": "藍綠色閥門開關", "block.create.dark_oak_window": "黑橡木窗戶", "block.create.dark_oak_window_pane": "黑橡木窗戶片", @@ -165,8 +173,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": "玻璃液體管道", @@ -179,13 +187,18 @@ "block.create.granite_cobblestone_stairs": "碎花崗岩樓梯", "block.create.granite_cobblestone_wall": "碎花崗岩牆", "block.create.granite_pillar": "豎紋花崗岩", + "block.create.gray_nixie_tube": "灰色真空管", "block.create.gray_sail": "灰色風帆", "block.create.gray_seat": "灰色坐墊", + "block.create.gray_toolbox": "UNLOCALIZED: Gray Toolbox", "block.create.gray_valve_handle": "灰色閥門開關", + "block.create.green_nixie_tube": "綠色真空管", "block.create.green_sail": "綠色風帆", "block.create.green_seat": "綠色坐墊", + "block.create.green_toolbox": "UNLOCALIZED: Green Toolbox", "block.create.green_valve_handle": "綠色閥門開關", "block.create.hand_crank": "手搖把手", + "block.create.haunted_bell": "靈魂鐘", "block.create.honey": "蜂蜜", "block.create.horizontal_framed_glass": "豎直邊框玻璃", "block.create.horizontal_framed_glass_pane": "豎直邊框玻璃片", @@ -203,14 +216,21 @@ "block.create.layered_limestone": "疊層石灰岩", "block.create.layered_scoria": "疊層火成岩", "block.create.layered_weathered_limestone": "疊層風化石灰岩", + "block.create.lectern_controller": "講台遙控器", + "block.create.light_blue_nixie_tube": "亮藍色真空管", "block.create.light_blue_sail": "淡藍色風帆", "block.create.light_blue_seat": "淡藍色坐墊", + "block.create.light_blue_toolbox": "UNLOCALIZED: Light Blue Toolbox", "block.create.light_blue_valve_handle": "淡藍色閥門開關", + "block.create.light_gray_nixie_tube": "亮灰色真空管", "block.create.light_gray_sail": "淡灰色風帆", "block.create.light_gray_seat": "淡灰色坐墊", + "block.create.light_gray_toolbox": "UNLOCALIZED: Light Gray Toolbox", "block.create.light_gray_valve_handle": "淡灰色閥門開關", + "block.create.lime_nixie_tube": "淺綠色真空管", "block.create.lime_sail": "黃綠色風帆", "block.create.lime_seat": "黃綠色坐墊", + "block.create.lime_toolbox": "UNLOCALIZED: Lime Toolbox", "block.create.lime_valve_handle": "黃綠色閥門開關", "block.create.limesand": "石灰沙", "block.create.limestone": "石灰岩", @@ -225,8 +245,10 @@ "block.create.limestone_pillar": "豎紋石灰岩", "block.create.linear_chassis": "機殼底盤", "block.create.lit_blaze_burner": "烈焰使者動力爐(已啟動)", + "block.create.magenta_nixie_tube": "洋紅色真空管", "block.create.magenta_sail": "洋紅色風帆", "block.create.magenta_seat": "洋紅色坐墊", + "block.create.magenta_toolbox": "UNLOCALIZED: Magenta Toolbox", "block.create.magenta_valve_handle": "洋紅色閥門開關", "block.create.mechanical_arm": "機械手臂", "block.create.mechanical_bearing": "機械軸承", @@ -260,6 +282,7 @@ "block.create.oak_window_pane": "橡木窗戶片", "block.create.orange_sail": "橙色風帆", "block.create.orange_seat": "橙色坐墊", + "block.create.orange_toolbox": "UNLOCALIZED: Orange Toolbox", "block.create.orange_valve_handle": "橙色閥門開關", "block.create.ornate_iron_window": "華麗鐵窗戶", "block.create.ornate_iron_window_pane": "華麗鐵窗戶片", @@ -308,8 +331,11 @@ "block.create.paved_weathered_limestone_slab": "風化石灰岩鋪路石半磚", "block.create.paved_weathered_limestone_stairs": "風化石灰岩鋪路石樓梯", "block.create.paved_weathered_limestone_wall": "風化石灰岩鋪路石牆", + "block.create.peculiar_bell": "黃銅鐘", + "block.create.pink_nixie_tube": "粉紅色真空管", "block.create.pink_sail": "粉紅色風帆", "block.create.pink_seat": "粉紅色坐墊", + "block.create.pink_toolbox": "UNLOCALIZED: Pink Toolbox", "block.create.pink_valve_handle": "粉紅色閥門開關", "block.create.piston_extension_pole": "活塞桿", "block.create.polished_dark_scoria": "磨製黑火成岩", @@ -342,12 +368,16 @@ "block.create.powered_toggle_latch": "T型正反器", "block.create.pulley_magnet": "滑輪磁鐵", "block.create.pulse_repeater": "脈衝中繼器", + "block.create.purple_nixie_tube": "紫色真空管", "block.create.purple_sail": "紫色風帆", "block.create.purple_seat": "紫色坐墊", + "block.create.purple_toolbox": "UNLOCALIZED: Purple Toolbox", "block.create.purple_valve_handle": "紫色閥門開關", "block.create.radial_chassis": "旋轉底盤", + "block.create.red_nixie_tube": "紅色真空管", "block.create.red_sail": "紅色風帆", "block.create.red_seat": "紅色坐墊", + "block.create.red_toolbox": "UNLOCALIZED: Red Toolbox", "block.create.red_valve_handle": "紅色閥門開關", "block.create.redstone_contact": "接觸式紅石訊號產生器", "block.create.redstone_link": "無限紅石訊號機", @@ -373,15 +403,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,25 +431,33 @@ "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_nixie_tube": "白色真空管", "block.create.white_sail": "白色風帆", "block.create.white_seat": "白色坐墊", + "block.create.white_toolbox": "UNLOCALIZED: White Toolbox", "block.create.white_valve_handle": "白色閥門開關", "block.create.windmill_bearing": "風車軸承", "block.create.wooden_bracket": "木製支架", + "block.create.yellow_nixie_tube": "黃色真空管", "block.create.yellow_sail": "黃色風帆", "block.create.yellow_seat": "黃色坐墊", + "block.create.yellow_toolbox": "UNLOCALIZED: Yellow Toolbox", "block.create.yellow_valve_handle": "黃色閥門開關", "block.create.zinc_block": "鋅磚", "block.create.zinc_ore": "鋅礦石", + "enchantment.create.capacity": "容量", + "enchantment.create.potato_recovery": "馬鈴薯恢復", + "entity.create.contraption": "結構", - "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "entity.create.crafting_blueprint": "合成藍圖", + "entity.create.gantry_contraption": "門式結構", + "entity.create.potato_projectile": "馬鈴薯彈藥", "entity.create.seat": "坐墊", "entity.create.stationary_contraption": "固定結構", "entity.create.super_glue": "強力膠", - "fluid.create.milk": "牛奶", "fluid.create.potion": "藥水", "fluid.create.tea": "茶", @@ -436,14 +474,16 @@ "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", + "item.create.copper_backtank": "銅製後背包", "item.create.copper_ingot": "銅錠", "item.create.copper_nugget": "銅粒", "item.create.copper_sheet": "銅板", "item.create.crafter_slot_cover": "合成器蓋板", + "item.create.crafting_blueprint": "合成藍圖", + "item.create.creative_blaze_cake": "UNLOCALIZED: Creative Blaze Cake", "item.create.crushed_aluminum_ore": "碎狀鋁礦石", "item.create.crushed_brass": "碎狀黃銅", "item.create.crushed_copper_ore": "碎狀銅礦石", @@ -458,8 +498,8 @@ "item.create.crushed_tin_ore": "碎狀錫礦石", "item.create.crushed_uranium_ore": "碎狀鈾礦石", "item.create.crushed_zinc_ore": "碎狀鋅礦石", - "item.create.diving_boots": "UNLOCALIZED: Diving Boots", - "item.create.diving_helmet": "UNLOCALIZED: Diving Helmet", + "item.create.diving_boots": "潛水鞋", + "item.create.diving_helmet": "潛水頭盔", "item.create.dough": "麵團", "item.create.electron_tube": "真空管", "item.create.empty_blaze_burner": "空的烈焰使者動力爐", @@ -471,14 +511,18 @@ "item.create.golden_sheet": "金板", "item.create.handheld_worldshaper": "地形雕塑器", "item.create.honey_bucket": "蜂蜜桶", - "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", - "item.create.integrated_circuit": "IC板", + "item.create.honeyed_apple": "蜂蜜蘋果", + "item.create.incomplete_cogwheel": "未完成的小齒輪", + "item.create.incomplete_large_cogwheel": "未完成的大齒輪", + "item.create.incomplete_precision_mechanism": "未完成的精確控制器", "item.create.iron_sheet": "鐵板", - "item.create.lapis_sheet": "青金石板", + "item.create.linked_controller": "遙控器", "item.create.minecart_contraption": "裝修過的礦車", "item.create.minecart_coupling": "礦車連結器", "item.create.polished_rose_quartz": "磨製玫瑰石英", + "item.create.potato_cannon": "馬鈴薯大砲", "item.create.powdered_obsidian": "黑曜石粉末", + "item.create.precision_mechanism": " 精確控制器", "item.create.propeller": "扇葉", "item.create.red_sand_paper": "紅砂紙", "item.create.refined_radiance": "光輝石", @@ -488,13 +532,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 +553,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 +580,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": "超級加固!", @@ -623,8 +667,8 @@ "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.precision_mechanism": "複雜的好奇心", + "advancement.create.precision_mechanism.desc": "組裝一個精確控制器", "advancement.create.mechanical_arm": "忙碌的手!", "advancement.create.mechanical_arm.desc": "製作機械手臂,選擇輸入和輸出,放置並給它動能; 然後看著它完成所有你交代的工作。", "advancement.create.musical_arm": "沒人能在我的BGM裡打敗我!", @@ -632,8 +676,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": "製作一對能更快粉碎物品的粉碎輪", @@ -651,6 +695,8 @@ "advancement.create.wand_of_symmetry.desc": "製作一個對稱杖", "advancement.create.extendo_grip": "piu piu piu!", "advancement.create.extendo_grip.desc": "拿到一個伸縮機械手", + "advancement.create.potato_cannon": "噗~碰", + "advancement.create.potato_cannon.desc": "用馬鈴薯大砲擊殺一隻怪物", "advancement.create.dual_extendo_grip": "piu——piu——piu——", "advancement.create.dual_extendo_grip.desc": "雙持伸縮機械手進一步加長觸碰距離", "advancement.create.eob": "Beta版結束", @@ -663,15 +709,31 @@ "itemGroup.create.palettes": "動力機械建築與裝飾方塊", "death.attack.create.crush": "%1$s被壓扁了", + "death.attack.create.crush.player": "%1$s 被 %2$s 打包丟進粉碎輪", "death.attack.create.fan_fire": "%1$s想接受熱風的洗禮", + "death.attack.create.fan_fire.player": "%1$s 被 %2$s 推入火坑", "death.attack.create.fan_lava": "%1$s想接受熱風的洗禮但走火入魔", + "death.attack.create.fan_lava.player": "%1$s 被 %2$s 推進岩漿", "death.attack.create.mechanical_drill": "%1$s被鑽頭鑽爆腦袋", + "death.attack.create.mechanical_drill.player": "%1$s 被 %2$s 當成礦物放在鑽頭前面而死", "death.attack.create.mechanical_saw": "%1$s被鋸切成了兩半", + "death.attack.create.mechanical_saw.player": "%1$s 被 %2$s 鋸掉了", + "death.attack.create.potato_cannon": "%1$s 被 %2$s 的馬鈴薯大砲餵飽了", + "death.attack.create.potato_cannon.item": "%1$s 被 %2$s 用馬鈴薯大砲塞了滿肚子 %3$s", "death.attack.create.cuckoo_clock_explosion": "%1$s 被布穀鳥鐘炸得粉身碎骨", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s 被布穀鳥鐘炸得粉身碎骨", "create.block.deployer.damage_source_name": "機械手", "create.block.cart_assembler.invalid": "將您的礦車裝修站放在鐵軌上", + "create.menu.return": "回到選單", + "create.menu.configure": "設定", + "create.menu.ponder_index": "示範目錄", + "create.menu.only_ingame": "UNLOCALIZED: Available in the Pause Menu", + "create.menu.project_page": "專案頁面", + "create.menu.report_bugs": "回報問題", + "create.menu.support": "支持我們", + "create.recipe.crushing": "粉碎", "create.recipe.milling": "研磨", "create.recipe.fan_washing": "批次洗滌", @@ -691,14 +753,25 @@ "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.sequenced_assembly": "排序中的步驟", + "create.recipe.assembly.next": "下一步:%1$s", + "create.recipe.assembly.step": "步驟 %1$s:", + "create.recipe.assembly.progress": "進度:%1$s/%2$s", + "create.recipe.assembly.pressing": "UNLOCALIZED: Process in Press", + "create.recipe.assembly.spout_filling_fluid": "注入:%1$s", + "create.recipe.assembly.deploying_item": "使用:%1$s", + "create.recipe.assembly.cutting": "用鋸子切", + "create.recipe.assembly.repeat": "重複 %1$s 次", + "create.recipe.assembly.junk": "有機率得到垃圾", "create.recipe.processing.chance": "%1$s%%概率", - "create.recipe.heat_requirement.none": "不需加熱", - "create.recipe.heat_requirement.heated": "加熱", + "create.recipe.deploying.not_consumed": "UNLOCALIZED: Not Consumed", + "create.recipe.heat_requirement.none": "不需要加熱", + "create.recipe.heat_requirement.heated": "普通加熱", "create.recipe.heat_requirement.superheated": "超級加熱", "create.generic.range": "範圍", @@ -712,8 +785,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": "逆時鐘方向", @@ -725,6 +798,7 @@ "create.action.discard": "放棄", "create.keyinfo.toolmenu": "選單", + "create.keyinfo.toolbelt": "UNLOCALIZED: Access Nearby Toolboxes", "create.keyinfo.scrollup": "(遊戲中)向上滑鼠滾輪", "create.keyinfo.scrolldown": "(遊戲中)向下滑鼠滾輪", @@ -735,6 +809,13 @@ "create.gui.scrollInput.shiftScrollsFaster": "按住Shift滾動更快", "create.gui.toolmenu.focusKey": "按住 [%1$s] 滑鼠滾輪選擇", "create.gui.toolmenu.cycle": "[SCROLL] 循環", + + "create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s", + "create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range", + "create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item", + "create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes", + "create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox", + "create.gui.symmetryWand.mirrorType": "鏡子類型", "create.gui.symmetryWand.orientation": "方向", @@ -749,15 +830,15 @@ "create.orientation.alongX": "以x軸對齊", "create.gui.terrainzapper.title": "地形雕塑器", - "create.gui.terrainzapper.searchDiagonal": "UNLOCALIZED: Follow Diagonals", - "create.gui.terrainzapper.searchFuzzy": "UNLOCALIZED: Ignore Material Borders", + "create.gui.terrainzapper.searchDiagonal": "跟隨對角線", + "create.gui.terrainzapper.searchFuzzy": "忽略材質邊界", "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.pattern.solid": "填滿", + "create.gui.terrainzapper.pattern.checkered": "棋盤狀", + "create.gui.terrainzapper.pattern.inversecheckered": "反轉棋盤狀", + "create.gui.terrainzapper.pattern.chance25": "隨機填滿 25% 的面積", + "create.gui.terrainzapper.pattern.chance50": "隨機填滿 50% 的面積", + "create.gui.terrainzapper.pattern.chance75": "隨機填滿 75% 的面積", "create.gui.terrainzapper.placement": "放置模式", "create.gui.terrainzapper.placement.merged": "結合", "create.gui.terrainzapper.placement.attached": "依附", @@ -766,8 +847,8 @@ "create.gui.terrainzapper.brush.cuboid": "矩形體", "create.gui.terrainzapper.brush.sphere": "球體", "create.gui.terrainzapper.brush.cylinder": "圓柱體", - "create.gui.terrainzapper.brush.surface": "UNLOCALIZED: Surface", - "create.gui.terrainzapper.brush.cluster": "UNLOCALIZED: Cluster", + "create.gui.terrainzapper.brush.surface": "表面", + "create.gui.terrainzapper.brush.cluster": "群組", "create.gui.terrainzapper.tool": "填充類型", "create.gui.terrainzapper.tool.fill": "填充", "create.gui.terrainzapper.tool.place": "覆寫", @@ -777,8 +858,8 @@ "create.gui.terrainzapper.tool.flatten": "平整", "create.terrainzapper.shiftRightClickToSet": "Shift+滑鼠右鍵 以設定雕塑類型", - "create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s", - "create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material", + "create.terrainzapper.usingBlock": "使用:%1$s", + "create.terrainzapper.leftClickToSet": "左鍵點擊方塊可以設定材質", "create.minecart_coupling.two_couplings_max": "礦車無法被連接兩個以上的礦車連結器", "create.minecart_coupling.unloaded": "有一部份礦車存在於未讀取區塊中", @@ -813,18 +894,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 +922,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": "兩倍速,正向", @@ -981,18 +1062,14 @@ "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.fluid_container": "UNLOCALIZED: can store fluids", + "create.item_attributes.fluid_container.inverted": "UNLOCALIZED: cannot store fluids", "create.item_attributes.enchanted": "已被附魔", "create.item_attributes.enchanted.inverted": "未被附魔", + "create.item_attributes.max_enchanted": "已達到最高附魔等級", + "create.item_attributes.max_enchanted.inverted": "未達到最高附魔等級", + "create.item_attributes.renamed": "UNLOCALIZED: has a custom name", + "create.item_attributes.renamed.inverted": "UNLOCALIZED: does not have a custom name", "create.item_attributes.damaged": "已損壞", "create.item_attributes.damaged.inverted": "未損壞", "create.item_attributes.badly_damaged": "嚴重受損", @@ -1003,6 +1080,21 @@ "create.item_attributes.equipable.inverted": "不可裝備", "create.item_attributes.furnace_fuel": "是燃料", "create.item_attributes.furnace_fuel.inverted": "不是燃料", + "create.item_attributes.washable": "可被篩洗", + "create.item_attributes.washable.inverted": "不可被篩洗", + "create.item_attributes.crushable": "可被粉碎", + "create.item_attributes.crushable.inverted": "不可被粉碎", + "create.item_attributes.smeltable": "可被熔爐融煉", + "create.item_attributes.smeltable.inverted": "不可被熔爐融煉", + "create.item_attributes.smokable": "可被煙熏", + "create.item_attributes.smokable.inverted": "不可被煙熏", + "create.item_attributes.blastable": "可被高爐融煉", + "create.item_attributes.blastable.inverted": "不可被高爐融煉", + "create.item_attributes.shulker_level": "界伏盒是 %1$s", + "create.item_attributes.shulker_level.inverted": "界伏盒不是 %1$s", + "create.item_attributes.shulker_level.full": "滿的", + "create.item_attributes.shulker_level.empty": "空的", + "create.item_attributes.shulker_level.partial": "有裝東西但沒滿", "create.item_attributes.in_tag": "標籤是%1$s", "create.item_attributes.in_tag.inverted": "標籤不是%1$s", "create.item_attributes.in_item_group": "屬於%1$s", @@ -1011,10 +1103,8 @@ "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.has_fluid": "包含%1$s", "create.item_attributes.has_fluid.inverted": "不包含%1$s", "create.item_attributes.has_name": "有自定義名稱%1$s", @@ -1029,14 +1119,14 @@ "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.item_attributes.astralsorcery_constellation": "與%1$s調諧", + "create.item_attributes.astralsorcery_constellation.inverted": "未與%1$s調諧", + "create.item_attributes.astralsorcery_crystal": "具有晶體屬性%1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "不具有晶體屬性%1$s", + "create.item_attributes.astralsorcery_perk_gem": "具有特殊屬性%1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "不具有特殊屬性%1$s", "create.gui.attribute_filter.no_selected_attributes": "沒有標記任何屬性", "create.gui.attribute_filter.selected_attributes": "已選擇的屬性:", @@ -1050,8 +1140,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 +1165,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 +1193,43 @@ "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.tooltip.brass_tunnel.contains": "正在處理", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "右鍵取回", - "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": "綁定模式", + "create.linked_controller.press_keybind": "按 %1$s, %2$s, %3$s, %4$s, %5$s 或 %6$s 來綁定這個頻率到對應按鍵上", + "create.linked_controller.key_bound": "頻率綁定到 %1$s 鍵", + "create.linked_controller.frequency_slot_1": "按鍵:%1$s 頻道 #1", + "create.linked_controller.frequency_slot_2": "按鍵:%1$s 頻道 #2", + + "create.crafting_blueprint.crafting_slot": "材料格", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "顯示格", + "create.crafting_blueprint.inferred": "根據配方推論", + "create.crafting_blueprint.manually_assigned": "手動設定", + "create.crafting_blueprint.secondary_display_slot": "次要顯示格", + "create.crafting_blueprint.optional": "可選的", + + "create.potato_cannon.ammo.attack_damage": "%1$s 攻擊傷害", + "create.potato_cannon.ammo.reload_ticks": "%1$s 攻擊速度", + "create.potato_cannon.ammo.knockback": "%1$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.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 +1242,45 @@ "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": "一股神秘的力量將這個礦車結構與世界綁在一起", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "黏液擠壓", - "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.contraption_disassemble": "結構停止", + "create.subtitle.peculiar_bell_use": "黃銅鐘聲", + "create.subtitle.mixing": "攪拌機噪音", + "create.subtitle.mechanical_press_activation_belt": "液壓機工作", + "create.subtitle.fwoomp": "馬鈴薯大砲發射", + "create.subtitle.worldshaper_place": "地形塑造器發射聲", + "create.subtitle.crushing_1": "粉碎機咀嚼聲", + "create.subtitle.depot_slide": "物品滑動聲", + "create.subtitle.saw_activate_stone": "機械鋸子聲", "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.funnel_flap": "UNLOCALIZED: Funnel flaps", "create.subtitle.schematicannon_finish": "藍圖大炮完成任務", - "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.haunted_bell_use": "靈魂鐘敲響", + "create.subtitle.scroll_value": "滾動輸入聲", + "create.subtitle.crafter_craft": "機械合成器合成聲", + "create.subtitle.controller_put": "遙控器放置聲", + "create.subtitle.cranking": "手搖把手轉動聲", + "create.subtitle.wrench_remove": "零件移除聲", + "create.subtitle.cogs": "齒輪隆隆聲", + "create.subtitle.slime_added": "黏液擠壓", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.potato_hit": "食物撞擊聲", + "create.subtitle.saw_activate_wood": "機械鋸子運作聲", + "create.subtitle.haunted_bell_convert": "靈魂鐘轉化聲", + "create.subtitle.deployer_polish": "機械手拋光聲", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "遙控器按鍵聲", + "create.subtitle.schematicannon_launch_block": "藍圖大炮發射", + "create.subtitle.copper_armor_equip": "潛水裝裝備聲", + "create.subtitle.controller_take": "拿下遙控器", "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.contraption_assemble": "結構移動", + "create.subtitle.crafter_click": "機械合成器工作聲", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1179,14 +1302,6 @@ "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": "對坐墊右鍵", @@ -1195,65 +1310,6 @@ "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": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Places a window on the pipe if available", - - "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": "當在熱鍵欄時", @@ -1263,7 +1319,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 +1328,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": "適用來常見樹木的快速肥料", @@ -1283,13 +1339,22 @@ "item.create.extendo_grip.tooltip.summary": "biubiubiu! 大幅度_增加了_使用者的_觸碰距離_。", "item.create.extendo_grip.tooltip.condition1": "放置於副手欄時", "item.create.extendo_grip.tooltip.behaviour1": "大幅增加_主手_的觸碰距離,與_主手_的伸縮機械手攜同使用,可進一步增加_觸碰距離_。", + "item.create.extendo_grip.tooltip.condition2": "當裝備銅製後背包時", + "item.create.extendo_grip.tooltip.behaviour2": "_不會消耗耐久_ 但是會抽取銅製後背包裡的_壓縮空氣_", + + "item.create.potato_cannon.tooltip": "馬鈴薯大砲", + "item.create.potato_cannon.tooltip.summary": "噗~碰!用你種的蔬菜來攻擊敵人。可以用_銅製後背包_的壓縮空氣驅動", + "item.create.potato_cannon.tooltip.condition1": "當點擊右鍵時", + "item.create.potato_cannon.tooltip.behaviour1": "從_物品欄_中_發射_一顆彈藥", + "item.create.potato_cannon.tooltip.condition2": "當裝備銅製後背包時", + "item.create.potato_cannon.tooltip.behaviour2": "_不會消耗耐久_ 但是會抽取銅製後背包裡的_壓縮空氣_", "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 +1367,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 +1388,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 +1399,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": "一種常用的工具,能夠調整_動能_的_方向_、_配置_等。", @@ -1358,31 +1423,42 @@ "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.toolbox.tooltip": "UNLOCALIZED: TOOLBOX", + "block.create.toolbox.tooltip.summary": "UNLOCALIZED: Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "UNLOCALIZED: When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "UNLOCALIZED: _Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "UNLOCALIZED: When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "UNLOCALIZED: _Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "UNLOCALIZED: When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "UNLOCALIZED: Opens the _Container Interface_.", - "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.content_observer.tooltip.condition1": "UNLOCALIZED: When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "UNLOCALIZED: Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "UNLOCALIZED: When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "UNLOCALIZED: Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "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": "這個容器可以給臨近的_藍圖大炮_提供無限物品以及燃料 (創造專用物品)", "block.create.creative_crate.tooltip.condition1": "當標記了物品時", "block.create.creative_crate.tooltip.behaviour1": "容器將會從虛空中提供_無限量_的標記物品,並且任何放置到容器中的物品都會被_送入虛空_", + "item.create.creative_blaze_cake.tooltip": "UNLOCALIZED: CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "UNLOCALIZED: A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "UNLOCALIZED: R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "UNLOCALIZED: _Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "控制鐵軌", "block.create.controller_rail.tooltip.summary": "單向電動導軌,能夠精細控制礦車的移動速度。", "block.create.controller_rail.tooltip.condition1": "被紅石激活時", @@ -1393,717 +1469,879 @@ "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": "工作進度", + "item.create.refined_radiance.tooltip.behaviour1": "在未來的更新中會更新更多用途", "item.create.shadow_steel.tooltip": "暗影鋼", "item.create.shadow_steel.tooltip.summary": "一種用_虛空_鍛造的化合物材料。", + "item.create.shadow_steel.tooltip.condition1": "工作進度", + "item.create.shadow_steel.tooltip.behaviour1": "在未來的更新中會更新更多用途", + + "item.create.linked_controller.tooltip": "遙控器", + "item.create.linked_controller.tooltip.summary": "提供_六個_連接到相對應_按鍵_的_無線紅石訊號機_ _手持的控制_", + "item.create.linked_controller.tooltip.condition1": "點擊右鍵時", + "item.create.linked_controller.tooltip.behaviour1": "_切換_遙控器,當遙控器啟動時你會失去_移動控制_", + "item.create.linked_controller.tooltip.condition2": "當右鍵時", + "item.create.linked_controller.tooltip.behaviour2": "打開_設定面板_", + "item.create.linked_controller.tooltip.condition3": "當對無線紅石訊號機點右鍵時", + "item.create.linked_controller.tooltip.behaviour3": "開啟_綁定模式_。按_六個控制鍵_的其中一個來綁定_頻率_到遙控器上", + "item.create.linked_controller.tooltip.condition4": "當對講台按右鍵時", + "item.create.linked_controller.tooltip.behaviour4": "把遙控器放到講台上,可以更方便的控制它。(蹲下右鍵取回)", + + "item.create.diving_helmet.tooltip": "潛水頭盔", + "item.create.diving_helmet.tooltip.summary": "和_銅製後背包_一起裝備時可以延長在_水下呼吸_的時間", + "item.create.diving_helmet.tooltip.condition1": "當裝備時", + "item.create.diving_helmet.tooltip.behaviour1": "提昇_水下呼吸效果_,會緩慢的抽取銅製後背包中的_壓縮空氣_", + + "item.create.copper_backtank.tooltip": "銅製後背包", + "item.create.copper_backtank.tooltip.summary": "可裝備的氣罐,用來攜帶壓縮空氣", + "item.create.copper_backtank.tooltip.condition1": "當裝備時", + "item.create.copper_backtank.tooltip.behaviour1": "提供_壓縮空氣_給需要的裝備", + "item.create.copper_backtank.tooltip.condition2": "當放置時,由轉動來補充驅動", + "item.create.copper_backtank.tooltip.behaviour2": "旋轉的速度決定收集_壓縮空氣_的速率", + + "item.create.diving_boots.tooltip": "潛水鞋", + "item.create.diving_boots.tooltip.summary": "一雙_沈重的鞋子_,提供更好的水下移動", + "item.create.diving_boots.tooltip.condition1": "當裝備時", + "item.create.diving_boots.tooltip.behaviour1": "你可以在水下走得更快而且可以跳躍,但是不能游泳。穿著者不會被輸送帶移動。", + + "item.create.crafting_blueprint.tooltip": "合成藍圖", + "item.create.crafting_blueprint.tooltip.summary": "可以被放置在牆上、地上和天花板。指定一個合成配方,你可以更快速的合成物品。每一格代表一個合成配方", + "item.create.crafting_blueprint.condition1": "右鍵點擊空格", + "item.create.crafting_blueprint.behaviour1": "打開_合成界面_讓你_指定配方_和要顯示的物品", + "item.create.crafting_blueprint.condition2": "右鍵點擊編輯過的格子", + "item.create.crafting_blueprint.behaviour2": "根據_物品欄_內的物品_使用_這個_配方_合成。_蹲下_點擊可以一次合成_一組_的物品", "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": "用了就死定了。", + "block.create.peculiar_bell.tooltip": "黃銅鐘", + "block.create.peculiar_bell.tooltip.summary": "一個裝飾性的_鐘_,放在_靈魂火_正上方會有意想不到的副作用", + + "block.create.haunted_bell.tooltip": "靈魂鐘", + "block.create.haunted_bell.tooltip.summary": "一個受到地獄亡魂_詛咒的鐘_", + "block.create.haunted_bell.tooltip.condition1": "當拿者或是被敲響時", + "block.create.haunted_bell.tooltip.behaviour1": "標示附近_不夠亮_、會生成_敵對生物_的地方", "_": "->------------------------] 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.exit": "離開", + "create.ponder.welcome": "歡迎來到教學", + "create.ponder.categories": "Create 中的分類", + "create.ponder.index_description": "點擊其中一個圖像查看和他相關的物品以及方塊", + "create.ponder.index_title": "教學首頁", + "create.ponder.shared.rpm16": "16 RPM", + "create.ponder.shared.behaviour_modify_wrench": "使用扳手來調整這個動作", + "create.ponder.shared.storage_on_contraption": "與結構相連的儲物空間會自動撿取物品", + "create.ponder.shared.sneak_and": "潛行 +", + "create.ponder.shared.rpm8": "8 RPM", + "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm32": "32 RPM", + "create.ponder.shared.rpm16_source": "轉速: 16 RPM", + "create.ponder.shared.movement_anchors": "有了機殼底盤和強力膠就可以移動大型結構", + "create.ponder.tag.redstone": "邏輯控制裝置", + "create.ponder.tag.redstone.description": "這些裝置會在紅石電路中發揮用處", + "create.ponder.tag.contraption_assembly": "方塊連接物件", + "create.ponder.tag.contraption_assembly.description": "此物件用於連接各個零件以便組成一個成品", + "create.ponder.tag.fluids": "液體控制裝置", + "create.ponder.tag.fluids.description": "這些裝置可傳輸並利用液體", + "create.ponder.tag.decoration": "裝飾", + "create.ponder.tag.decoration.description": "這些零件通常用於裝飾", + "create.ponder.tag.windmill_sails": "風車軸承的帆", + "create.ponder.tag.windmill_sails.description": "建造風車時用於產生動能的帆,每個帆對風車產生的效果都是同等的", + "create.ponder.tag.arm_targets": "機械手臂的目標物", + "create.ponder.tag.arm_targets.description": "該裝置可作為機械手臂的工作目標", + "create.ponder.tag.kinetic_appliances": "動能利用裝置", + "create.ponder.tag.kinetic_appliances.description": "這些裝置利用動能運作", + "create.ponder.tag.kinetic_sources": "動能產生裝置", + "create.ponder.tag.kinetic_sources.description": "該裝置能夠產生動能", + "create.ponder.tag.movement_anchor": "運動錨點", + "create.ponder.tag.movement_anchor.description": "允許建立移動裝置的元件,以各種方式為連接的結構設置動畫", + "create.ponder.tag.kinetic_relays": "動能傳遞方塊", + "create.ponder.tag.kinetic_relays.description": "該裝置用於傳遞動能", + "create.ponder.tag.contraption_actor": "特殊方塊", + "create.ponder.tag.contraption_actor.description": "附加到移動裝置上時表現出特殊行為的方塊", + "create.ponder.tag.creative": "創造模式", + "create.ponder.tag.creative.description": "該裝置無法在生存模式中獲得", + "create.ponder.tag.logistics": "傳輸物品", + "create.ponder.tag.logistics.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_modes.text_3": "如果在裝修站鎖定其方向,則結構方向不會隨礦車方向改變", + + "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": "創造液體除存罐", + "create.ponder.creative_fluid_tank.text_1": "創造液體除存罐可以提供無限的液體", + "create.ponder.creative_fluid_tank.text_2": "拿著一個液體物品點擊可以設定它", + "create.ponder.creative_fluid_tank.text_3": "現在管線網路可以無限制的從它抽取液體", + "create.ponder.creative_fluid_tank.text_4": "任何被抽進創造液體除存罐的液體都會消失", + + "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": "用機器手處理物品", + "create.ponder.deployer_processing.text_1": "拿著適當物品的機器手可以處理下面的物品", + "create.ponder.deployer_processing.text_2": "待處理的物品可以是掉落狀態或是被放在置物台上", + "create.ponder.deployer_processing.text_3": "當物品被放在輸送帶上時...", + "create.ponder.deployer_processing.text_4": "機器手會抓住他並且自動處理", + + "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.empty_blaze_burner.text_6": "但是,這樣的熱源不足以給機器提加工供足夠的熱量", + + "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": "始用銅製管道來移動液體", + "create.ponder.fluid_pipe_flow.text_1": "液體管可以連接兩個或更多的液體來源與目標", + "create.ponder.fluid_pipe_flow.text_2": "使用扳手可以在一段直管線上開窗戶", + "create.ponder.fluid_pipe_flow.text_3": "有窗戶的管線側面不會連接到其他管線", + "create.ponder.fluid_pipe_flow.text_4": "機械幫浦可以讓管線運輸液體", + "create.ponder.fluid_pipe_flow.text_5": "一開始不會有液體被抽出來", + "create.ponder.fluid_pipe_flow.text_6": "直到兩端被連接起來,才會有液體被抽過去", + "create.ponder.fluid_pipe_flow.text_7": "因此,管線裡不會『物理上的』含有液體", + + "create.ponder.fluid_pipe_interaction.header": "抽取並填滿液體罐", + "create.ponder.fluid_pipe_interaction.text_1": "管線網路的終端可以和很多東西互動", + "create.ponder.fluid_pipe_interaction.text_2": "任何有意體容量的方塊都可以被抽取和填滿", + "create.ponder.fluid_pipe_interaction.text_3": "在開放端口前的液體源方塊可以被抽走", + "create.ponder.fluid_pipe_interaction.text_4": "當液體被排放出來時會產生新的液體源方塊", + "create.ponder.fluid_pipe_interaction.text_5": "管線也可以直接從其他方塊中抽取流體", + + "create.ponder.fluid_tank_sizes.header": "液體罐的尺寸", + "create.ponder.fluid_tank_sizes.text_1": "可以組合液體罐以增加總容量", + "create.ponder.fluid_tank_sizes.text_2": "底部最多可以是 3x3 的正方形 ......", + "create.ponder.fluid_tank_sizes.text_3": "...... 最多可以堆疊 30 層", + "create.ponder.fluid_tank_sizes.text_4": "扳手可以用來開關窗戶", + + "create.ponder.fluid_tank_storage.header": "在液體罐中儲存液體", + "create.ponder.fluid_tank_storage.text_1": "液體罐中可儲存大量的液體", + "create.ponder.fluid_tank_storage.text_2": "管線體網路可以從任何一邊抽取或是輸入液體", + "create.ponder.fluid_tank_storage.text_3": "紅石比較器可以輸出液體容量", + "create.ponder.fluid_tank_storage.text_4": "但是,在生存模式你不能直接存入、取出液體", + "create.ponder.fluid_tank_storage.text_5": "你可以用作業盆、分液池或液體灌注器和管線網路互動", + + "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": "使用軟管滑輪抽取、填滿液體", + "create.ponder.hose_pulley.text_1": "軟管滑輪可以用來抽取、填滿大量的液體", + "create.ponder.hose_pulley.text_2": "你可以透過輸入轉動來控制軟管的高度", + "create.ponder.hose_pulley.text_3": "反轉時可以收回軟管", + "create.ponder.hose_pulley.text_4": "另一邊可以連接管線", + "create.ponder.hose_pulley.text_5": "相連的管線網路可以提供液體 ......", + "create.ponder.hose_pulley.text_6": "...... 或是從池子裡抽取液體", + "create.ponder.hose_pulley.text_7": "抽取或填滿的速度取決於管線系統的吞吐量", + + "create.ponder.hose_pulley_infinite.header": "被動填充和排放大量液體", + "create.ponder.hose_pulley_infinite.text_1": "將軟管滑輪接觸到足夠大的海洋中時 ......", + "create.ponder.hose_pulley_infinite.text_2": "海洋會被視為無限液體源", + "create.ponder.hose_pulley_infinite.text_3": "管線網路可以無限的抽取、排放液體到海洋中而不影響海洋", + + "create.ponder.hose_pulley_level.header": "軟管滑輪抽取、填滿水平面", + "create.ponder.hose_pulley_level.text_1": "完全縮回時,軟管滑輪無法操作", + "create.ponder.hose_pulley_level.text_2": "抽取工作將由上而下進行", + "create.ponder.hose_pulley_level.text_3": "水平面將停在軟管末端的正下方", + "create.ponder.hose_pulley_level.text_4": "而填充工作將由下而上進行將由上而下進行", + "create.ponder.hose_pulley_level.text_5": "水平面不會超過軟管末端", + + "create.ponder.item_drain.header": "使用分液池清空液體容器", + "create.ponder.item_drain.text_1": "分液池可以從液體容器中清空抽取液體", + "create.ponder.item_drain.text_2": "點擊右鍵可以把你手上的液體倒進去", + "create.ponder.item_drain.text_3": "當從旁邊輸入物品 ......", + "create.ponder.item_drain.text_4": "...... 他會從上方滑過,並清空裡面的液體", + "create.ponder.item_drain.text_5": "現在液體網路可以抽取分液池中的液體了", + + "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": "使用機械幫浦抽運送液體", + "create.ponder.mechanical_pump_flow.text_1": "機械幫浦為與其連接的管線提供動力", + "create.ponder.mechanical_pump_flow.text_2": "轉動時,箭頭指向液體的方向", + "create.ponder.mechanical_pump_flow.text_3": "在他後面的網路現在可以抽取液體 ......", + "create.ponder.mechanical_pump_flow.text_4": "...... 當前面的網絡向外傳輸時", + "create.ponder.mechanical_pump_flow.text_5": "反轉輸入的動力可以反轉液體的方向", + "create.ponder.mechanical_pump_flow.text_6": "扳手可以手動調整方向", + + "create.ponder.mechanical_pump_speed.header": "機械幫浦的吞吐量", + "create.ponder.mechanical_pump_speed.text_1": "無論轉速如何,機械幫浦都只能影響相連的 16 個方塊以內的管線", + "create.ponder.mechanical_pump_speed.text_2": "加快旋轉速度會改變液動傳播的速度 ......", + "create.ponder.mechanical_pump_speed.text_3": "...... 以及流體轉移的速度", + "create.ponder.mechanical_pump_speed.text_4": "在同一個管線網路中機械幫浦可以結合他們的吞吐量", + "create.ponder.mechanical_pump_speed.text_5": "改變它們的方向可以對齊它們的流動方向", + + "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.nixie_tube.text_3": "使用染料右鍵點擊可以上色", + + "create.ponder.piston_pole.header": "活塞延長杆", + "create.ponder.piston_pole.text_1": "若無相接的延長杆,動力活塞無法移動其他方塊", + "create.ponder.piston_pole.text_2": "在其背面安裝的延長杆長度,決定了活塞的推動範圍", + + "create.ponder.portable_fluid_interface.header": "移動式液體口", + "create.ponder.portable_fluid_interface.text_1": "任何管道線都無法與移動裝置上的液體罐連接", + "create.ponder.portable_fluid_interface.text_2": "該元件可以與液體罐相互作用,而無需停止裝置", + "create.ponder.portable_fluid_interface.text_3": "放置第二個,中間間隔 1 或 2 個方塊", + "create.ponder.portable_fluid_interface.text_4": "每當他們擦身而過時,他們就會建立聯繫", + "create.ponder.portable_fluid_interface.text_5": "啟用時,移動式液體口將代表裝置上的『所有』水箱", + "create.ponder.portable_fluid_interface.text_6": "現在可以輸入液體 ......", + "create.ponder.portable_fluid_interface.text_7": "...... 或從裝置中抽取", + "create.ponder.portable_fluid_interface.text_8": "一段時間沒有液體交換後,裝置將繼續前進", + + "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": "使用智慧液體管道控制液體", + "create.ponder.smart_pipe.text_1": "智慧液體管道可以按照液體類型控制液體流", + "create.ponder.smart_pipe.text_2": "當直接放置在源頭時,他們可以指定要提取的液體類型", + "create.ponder.smart_pipe.text_3": "只需用包含所需液體的任何項目右鍵點擊其過濾槽", + "create.ponder.smart_pipe.text_4": "在管網裡時,智慧液體管道只會讓匹配的液體經過", + + "create.ponder.speedometer.header": "使用速度計來監測轉速", + "create.ponder.speedometer.text_1": "速度計能顯示相接組件的轉速", + "create.ponder.speedometer.text_2": "當佩戴MR護目鏡時,可以看到儀表所顯示的更詳細的數據", + "create.ponder.speedometer.text_3": "紅石比較器可以根據速度計的數值輸出不同強弱的紅石訊號", + + "create.ponder.spout_filling.header": "使用液體灌注器填充物品", + "create.ponder.spout_filling.text_1": "液體灌注器可以填充下方的液體容器", + "create.ponder.spout_filling.text_2": "無法手動接觸液體灌注器中的液體", + "create.ponder.spout_filling.text_3": "管道可用於為其提供液體", + "create.ponder.spout_filling.text_4": "輸入物品可以是掉落狀態或是被放在置物台上", + "create.ponder.spout_filling.text_5": "當物品放在輸送帶上時 ......", + "create.ponder.spout_filling.text_6": "液體灌注器會停下他並且自動填滿", + + "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": "使用液體閥門控制液體流量", + "create.ponder.valve_pipe.text_1": "閥門管道有助於控制通過管線網路傳播的液體", + "create.ponder.valve_pipe.text_2": "用轉動輸入控制現在是否允許液體通過", + "create.ponder.valve_pipe.text_3": "打開方向旋轉,液體閥門將會打開", + "create.ponder.valve_pipe.text_4": "反方向的旋轉會關閉閥門", + + "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/block/black_nixie_tube.json b/src/generated/resources/assets/create/models/block/black_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/black_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/black_toolbox.json b/src/generated/resources/assets/create/models/block/black_toolbox.json new file mode 100644 index 000000000..59daf9193 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/black_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/black" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/blue_nixie_tube.json b/src/generated/resources/assets/create/models/block/blue_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/blue_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/blue_toolbox.json b/src/generated/resources/assets/create/models/block/blue_toolbox.json new file mode 100644 index 000000000..e141edb75 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/blue_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/blue" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brown_nixie_tube.json b/src/generated/resources/assets/create/models/block/brown_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brown_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brown_toolbox.json b/src/generated/resources/assets/create/models/block/brown_toolbox.json new file mode 100644 index 000000000..c7ff0f084 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brown_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/brown" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cyan_nixie_tube.json b/src/generated/resources/assets/create/models/block/cyan_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cyan_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cyan_toolbox.json b/src/generated/resources/assets/create/models/block/cyan_toolbox.json new file mode 100644 index 000000000..66340a4fb --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cyan_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/cyan" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/gray_nixie_tube.json b/src/generated/resources/assets/create/models/block/gray_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/gray_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/gray_toolbox.json b/src/generated/resources/assets/create/models/block/gray_toolbox.json new file mode 100644 index 000000000..78ba376ab --- /dev/null +++ b/src/generated/resources/assets/create/models/block/gray_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/gray" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/green_nixie_tube.json b/src/generated/resources/assets/create/models/block/green_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/green_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/green_toolbox.json b/src/generated/resources/assets/create/models/block/green_toolbox.json new file mode 100644 index 000000000..75b87c951 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/green_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/green" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/haunted_bell_ceiling.json b/src/generated/resources/assets/create/models/block/haunted_bell_ceiling.json new file mode 100644 index 000000000..8953c2bde --- /dev/null +++ b/src/generated/resources/assets/create/models/block/haunted_bell_ceiling.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bell_base/block_ceiling" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/haunted_bell_double_wall.json b/src/generated/resources/assets/create/models/block/haunted_bell_double_wall.json new file mode 100644 index 000000000..b3a17b341 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/haunted_bell_double_wall.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bell_base/block_double_wall" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/haunted_bell_floor.json b/src/generated/resources/assets/create/models/block/haunted_bell_floor.json new file mode 100644 index 000000000..987b55e26 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/haunted_bell_floor.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bell_base/block_floor" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/haunted_bell_single_wall.json b/src/generated/resources/assets/create/models/block/haunted_bell_single_wall.json new file mode 100644 index 000000000..a6bacf266 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/haunted_bell_single_wall.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bell_base/block_single_wall" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_blue_nixie_tube.json b/src/generated/resources/assets/create/models/block/light_blue_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_blue_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_blue_toolbox.json b/src/generated/resources/assets/create/models/block/light_blue_toolbox.json new file mode 100644 index 000000000..ac9c5d68f --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_blue_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/light_blue" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_gray_nixie_tube.json b/src/generated/resources/assets/create/models/block/light_gray_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_gray_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_gray_toolbox.json b/src/generated/resources/assets/create/models/block/light_gray_toolbox.json new file mode 100644 index 000000000..7da3d2d4c --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_gray_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/light_gray" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/lime_nixie_tube.json b/src/generated/resources/assets/create/models/block/lime_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/lime_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/lime_toolbox.json b/src/generated/resources/assets/create/models/block/lime_toolbox.json new file mode 100644 index 000000000..cf66d6f6d --- /dev/null +++ b/src/generated/resources/assets/create/models/block/lime_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/lime" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/magenta_nixie_tube.json b/src/generated/resources/assets/create/models/block/magenta_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/magenta_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/magenta_toolbox.json b/src/generated/resources/assets/create/models/block/magenta_toolbox.json new file mode 100644 index 000000000..8981c46a8 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/magenta_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/magenta" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/nixie_tube.json b/src/generated/resources/assets/create/models/block/nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/orange_toolbox.json b/src/generated/resources/assets/create/models/block/orange_toolbox.json new file mode 100644 index 000000000..564b8c9bd --- /dev/null +++ b/src/generated/resources/assets/create/models/block/orange_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/orange" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/peculiar_bell_ceiling.json b/src/generated/resources/assets/create/models/block/peculiar_bell_ceiling.json new file mode 100644 index 000000000..8953c2bde --- /dev/null +++ b/src/generated/resources/assets/create/models/block/peculiar_bell_ceiling.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bell_base/block_ceiling" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/peculiar_bell_double_wall.json b/src/generated/resources/assets/create/models/block/peculiar_bell_double_wall.json new file mode 100644 index 000000000..b3a17b341 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/peculiar_bell_double_wall.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bell_base/block_double_wall" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/peculiar_bell_floor.json b/src/generated/resources/assets/create/models/block/peculiar_bell_floor.json new file mode 100644 index 000000000..987b55e26 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/peculiar_bell_floor.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bell_base/block_floor" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/peculiar_bell_single_wall.json b/src/generated/resources/assets/create/models/block/peculiar_bell_single_wall.json new file mode 100644 index 000000000..a6bacf266 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/peculiar_bell_single_wall.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bell_base/block_single_wall" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/pink_nixie_tube.json b/src/generated/resources/assets/create/models/block/pink_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/pink_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/pink_toolbox.json b/src/generated/resources/assets/create/models/block/pink_toolbox.json new file mode 100644 index 000000000..77b96dcf4 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/pink_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/pink" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/purple_nixie_tube.json b/src/generated/resources/assets/create/models/block/purple_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/purple_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/purple_toolbox.json b/src/generated/resources/assets/create/models/block/purple_toolbox.json new file mode 100644 index 000000000..2e259f635 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/purple_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/purple" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/red_nixie_tube.json b/src/generated/resources/assets/create/models/block/red_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/red_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/red_toolbox.json b/src/generated/resources/assets/create/models/block/red_toolbox.json new file mode 100644 index 000000000..417bf8f09 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/red_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/red" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/white_nixie_tube.json b/src/generated/resources/assets/create/models/block/white_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/white_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/white_toolbox.json b/src/generated/resources/assets/create/models/block/white_toolbox.json new file mode 100644 index 000000000..5556f26f3 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/white_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/white" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/yellow_nixie_tube.json b/src/generated/resources/assets/create/models/block/yellow_nixie_tube.json new file mode 100644 index 000000000..79f550f05 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/yellow_nixie_tube.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/nixie_tube/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/yellow_toolbox.json b/src/generated/resources/assets/create/models/block/yellow_toolbox.json new file mode 100644 index 000000000..d5c59a497 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/yellow_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/block", + "textures": { + "0": "create:block/toolbox/yellow" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/black_toolbox.json b/src/generated/resources/assets/create/models/item/black_toolbox.json new file mode 100644 index 000000000..ed1bd5883 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/black_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/black" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/blue_toolbox.json b/src/generated/resources/assets/create/models/item/blue_toolbox.json new file mode 100644 index 000000000..1f5d6b34a --- /dev/null +++ b/src/generated/resources/assets/create/models/item/blue_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/blue" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brown_toolbox.json b/src/generated/resources/assets/create/models/item/brown_toolbox.json new file mode 100644 index 000000000..44db1ecef --- /dev/null +++ b/src/generated/resources/assets/create/models/item/brown_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/brown" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/integrated_circuit.json b/src/generated/resources/assets/create/models/item/crafting_blueprint.json similarity index 57% rename from src/generated/resources/assets/create/models/item/integrated_circuit.json rename to src/generated/resources/assets/create/models/item/crafting_blueprint.json index e06638fff..94ec8d07a 100644 --- a/src/generated/resources/assets/create/models/item/integrated_circuit.json +++ b/src/generated/resources/assets/create/models/item/crafting_blueprint.json @@ -1,6 +1,6 @@ { "parent": "minecraft:item/generated", "textures": { - "layer0": "create:item/integrated_circuit" + "layer0": "create:item/crafting_blueprint" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/lapis_sheet.json b/src/generated/resources/assets/create/models/item/creative_blaze_cake.json similarity index 56% rename from src/generated/resources/assets/create/models/item/lapis_sheet.json rename to src/generated/resources/assets/create/models/item/creative_blaze_cake.json index bf1867e80..810fb81b9 100644 --- a/src/generated/resources/assets/create/models/item/lapis_sheet.json +++ b/src/generated/resources/assets/create/models/item/creative_blaze_cake.json @@ -1,6 +1,6 @@ { "parent": "minecraft:item/generated", "textures": { - "layer0": "create:item/lapis_sheet" + "layer0": "create:item/creative_blaze_cake" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cyan_toolbox.json b/src/generated/resources/assets/create/models/item/cyan_toolbox.json new file mode 100644 index 000000000..f07294c53 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cyan_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/cyan" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/gray_toolbox.json b/src/generated/resources/assets/create/models/item/gray_toolbox.json new file mode 100644 index 000000000..96bf28443 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/gray_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/gray" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/green_toolbox.json b/src/generated/resources/assets/create/models/item/green_toolbox.json new file mode 100644 index 000000000..c515a6cc8 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/green_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/green" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/haunted_bell.json b/src/generated/resources/assets/create/models/item/haunted_bell.json new file mode 100644 index 000000000..c0f602bc8 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/haunted_bell.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/haunted_bell" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/incomplete_precision_mechanism.json b/src/generated/resources/assets/create/models/item/incomplete_precision_mechanism.json new file mode 100644 index 000000000..a8d39ded4 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/incomplete_precision_mechanism.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/incomplete_precision_mechanism" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/light_blue_toolbox.json b/src/generated/resources/assets/create/models/item/light_blue_toolbox.json new file mode 100644 index 000000000..ccd30ddd0 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/light_blue_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/light_blue" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/light_gray_toolbox.json b/src/generated/resources/assets/create/models/item/light_gray_toolbox.json new file mode 100644 index 000000000..a04fb3e8d --- /dev/null +++ b/src/generated/resources/assets/create/models/item/light_gray_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/light_gray" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/lime_toolbox.json b/src/generated/resources/assets/create/models/item/lime_toolbox.json new file mode 100644 index 000000000..8f78bdb3e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/lime_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/lime" + } +} \ 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/models/item/magenta_toolbox.json b/src/generated/resources/assets/create/models/item/magenta_toolbox.json new file mode 100644 index 000000000..67c24fd1c --- /dev/null +++ b/src/generated/resources/assets/create/models/item/magenta_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/magenta" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/orange_toolbox.json b/src/generated/resources/assets/create/models/item/orange_toolbox.json new file mode 100644 index 000000000..da7b8046e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/orange_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/orange" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/peculiar_bell.json b/src/generated/resources/assets/create/models/item/peculiar_bell.json new file mode 100644 index 000000000..4cc9e1942 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/peculiar_bell.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/peculiar_bell" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/pink_toolbox.json b/src/generated/resources/assets/create/models/item/pink_toolbox.json new file mode 100644 index 000000000..f470337b3 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/pink_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/pink" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/potato_cannon.json b/src/generated/resources/assets/create/models/item/potato_cannon.json new file mode 100644 index 000000000..0767486a0 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/potato_cannon.json @@ -0,0 +1,3 @@ +{ + "parent": "create:item/potato_cannon/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/precision_mechanism.json b/src/generated/resources/assets/create/models/item/precision_mechanism.json new file mode 100644 index 000000000..18694533b --- /dev/null +++ b/src/generated/resources/assets/create/models/item/precision_mechanism.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/precision_mechanism" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/purple_toolbox.json b/src/generated/resources/assets/create/models/item/purple_toolbox.json new file mode 100644 index 000000000..4bfd8fcc4 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/purple_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/purple" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/red_toolbox.json b/src/generated/resources/assets/create/models/item/red_toolbox.json new file mode 100644 index 000000000..6c45eb23b --- /dev/null +++ b/src/generated/resources/assets/create/models/item/red_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/red" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/white_toolbox.json b/src/generated/resources/assets/create/models/item/white_toolbox.json new file mode 100644 index 000000000..7666c29fa --- /dev/null +++ b/src/generated/resources/assets/create/models/item/white_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/white" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/yellow_toolbox.json b/src/generated/resources/assets/create/models/item/yellow_toolbox.json new file mode 100644 index 000000000..156703b47 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/yellow_toolbox.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/item", + "textures": { + "0": "create:block/toolbox/yellow" + } +} \ 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..5e22450ae 100644 --- a/src/generated/resources/assets/create/sounds.json +++ b/src/generated/resources/assets/create/sounds.json @@ -49,6 +49,33 @@ ], "subtitle": "create.subtitle.contraption_disassemble" }, + "controller_click": { + "sounds": [ + { + "name": "minecraft:entity.item_frame.add_item", + "type": "event" + } + ], + "subtitle": "create.subtitle.controller_click" + }, + "controller_put": { + "sounds": [ + { + "name": "minecraft:item.book.put", + "type": "event" + } + ], + "subtitle": "create.subtitle.controller_put" + }, + "controller_take": { + "sounds": [ + { + "name": "minecraft:entity.item_frame.remove_item", + "type": "event" + } + ], + "subtitle": "create.subtitle.controller_take" + }, "copper_armor_equip": { "sounds": [ { @@ -101,6 +128,31 @@ } ] }, + "crushing_1": { + "sounds": [ + { + "name": "minecraft:block.netherrack.hit", + "type": "event" + } + ], + "subtitle": "create.subtitle.crushing_1" + }, + "crushing_2": { + "sounds": [ + { + "name": "minecraft:block.gravel.place", + "type": "event" + } + ] + }, + "crushing_3": { + "sounds": [ + { + "name": "minecraft:block.netherite_block.break", + "type": "event" + } + ] + }, "deny": { "sounds": [ { @@ -154,6 +206,24 @@ } ] }, + "fwoomp": { + "sounds": [ + "create:fwoomp" + ], + "subtitle": "create.subtitle.fwoomp" + }, + "haunted_bell_convert": { + "sounds": [ + "create:haunted_bell_convert" + ], + "subtitle": "create.subtitle.haunted_bell_convert" + }, + "haunted_bell_use": { + "sounds": [ + "create:haunted_bell_use" + ], + "subtitle": "create.subtitle.haunted_bell_use" + }, "mechanical_press_activation": { "sounds": [ { @@ -205,6 +275,50 @@ } ] }, + "peculiar_bell_use": { + "sounds": [ + { + "name": "minecraft:block.bell.use", + "type": "event" + } + ], + "subtitle": "create.subtitle.peculiar_bell_use" + }, + "potato_hit": { + "sounds": [ + { + "name": "minecraft:entity.item_frame.break", + "type": "event" + } + ], + "subtitle": "create.subtitle.potato_hit" + }, + "potato_hit_compounded_1": { + "sounds": [ + { + "name": "minecraft:block.weeping_vines.break", + "type": "event" + } + ] + }, + "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" + }, "schematicannon_finish": { "sounds": [ { diff --git a/src/generated/resources/data/create/advancements/integrated_circuit_eob.json b/src/generated/resources/data/create/advancements/clockwork_component_eob.json similarity index 85% rename from src/generated/resources/data/create/advancements/integrated_circuit_eob.json rename to src/generated/resources/data/create/advancements/clockwork_component_eob.json index 858b7e963..667bb88c4 100644 --- a/src/generated/resources/data/create/advancements/integrated_circuit_eob.json +++ b/src/generated/resources/data/create/advancements/clockwork_component_eob.json @@ -1,5 +1,5 @@ { - "parent": "create:integrated_circuit", + "parent": "create:precision_mechanism", "display": { "icon": { "item": "minecraft:oak_sapling" @@ -21,7 +21,7 @@ "conditions": { "items": [ { - "item": "create:integrated_circuit" + "item": "create:precision_mechanism" } ] } diff --git a/src/generated/resources/data/create/advancements/dual_extendo_grip.json b/src/generated/resources/data/create/advancements/dual_extendo_grip.json index d8effe72f..63c805ca0 100644 --- a/src/generated/resources/data/create/advancements/dual_extendo_grip.json +++ b/src/generated/resources/data/create/advancements/dual_extendo_grip.json @@ -2,7 +2,8 @@ "parent": "create:extendo_grip", "display": { "icon": { - "item": "create:extendo_grip" + "item": "create:extendo_grip", + "nbt": "{Damage:0}" }, "title": { "translate": "advancement.create.dual_extendo_grip" diff --git a/src/generated/resources/data/create/advancements/extendo_grip.json b/src/generated/resources/data/create/advancements/extendo_grip.json index b4d7b88b1..bb4882b2b 100644 --- a/src/generated/resources/data/create/advancements/extendo_grip.json +++ b/src/generated/resources/data/create/advancements/extendo_grip.json @@ -1,8 +1,9 @@ { - "parent": "create:crafter", + "parent": "create:precision_mechanism", "display": { "icon": { - "item": "create:extendo_grip" + "item": "create:extendo_grip", + "nbt": "{Damage:0}" }, "title": { "translate": "advancement.create.extendo_grip" diff --git a/src/generated/resources/data/create/advancements/potato_cannon.json b/src/generated/resources/data/create/advancements/potato_cannon.json new file mode 100644 index 000000000..9e1da2e5e --- /dev/null +++ b/src/generated/resources/data/create/advancements/potato_cannon.json @@ -0,0 +1,30 @@ +{ + "parent": "create:precision_mechanism", + "display": { + "icon": { + "item": "create:potato_cannon", + "nbt": "{Damage:0}" + }, + "title": { + "translate": "advancement.create.potato_cannon" + }, + "description": { + "translate": "advancement.create.potato_cannon.desc" + }, + "frame": "goal", + "show_toast": true, + "announce_to_chat": true, + "hidden": false + }, + "criteria": { + "0": { + "trigger": "create:potato_kill", + "conditions": {} + } + }, + "requirements": [ + [ + "0" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/integrated_circuit.json b/src/generated/resources/data/create/advancements/precision_mechanism.json similarity index 62% rename from src/generated/resources/data/create/advancements/integrated_circuit.json rename to src/generated/resources/data/create/advancements/precision_mechanism.json index ea773a430..a39f61f11 100644 --- a/src/generated/resources/data/create/advancements/integrated_circuit.json +++ b/src/generated/resources/data/create/advancements/precision_mechanism.json @@ -1,14 +1,14 @@ { - "parent": "create:crafter", + "parent": "create:deployer", "display": { "icon": { - "item": "create:integrated_circuit" + "item": "create:precision_mechanism" }, "title": { - "translate": "advancement.create.integrated_circuit" + "translate": "advancement.create.precision_mechanism" }, "description": { - "translate": "advancement.create.integrated_circuit.desc" + "translate": "advancement.create.precision_mechanism.desc" }, "frame": "task", "show_toast": true, @@ -21,7 +21,7 @@ "conditions": { "items": [ { - "item": "create:integrated_circuit" + "item": "create:precision_mechanism" } ] } 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.base/crafting/curiosities/black_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/black_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..25384d9d0 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/black_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/black_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/black_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/black_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/black_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..8efffc110 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/black_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/black_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/black_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/blue_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/blue_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..8d387311e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/blue_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/blue_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/blue_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/blue_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/blue_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..1ed9b3d01 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/blue_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/blue_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/blue_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox.json new file mode 100644 index 000000000..8c43e9d44 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/brown_toolbox" + ] + }, + "criteria": { + "has_item": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "forge:plates/gold" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/brown_toolbox" + } + } + }, + "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/curiosities/brown_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..dbef931eb --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/brown_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/brown_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..66b5bb27b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/brown_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/brown_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/brown_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/cyan_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/cyan_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..5ee432ba8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/cyan_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/cyan_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/cyan_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/cyan_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/cyan_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..818722d03 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/cyan_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/cyan_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/cyan_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/gray_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/gray_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..b1378cb8b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/gray_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/gray_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/gray_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/gray_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/gray_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..225623bc6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/gray_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/gray_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/gray_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/green_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/green_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..bea6b3d8f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/green_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/green_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/green_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/green_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/green_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..9b293b778 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/green_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/green_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/green_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_blue_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_blue_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..3c0308480 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_blue_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/light_blue_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/light_blue_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_blue_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_blue_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..7cadae543 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_blue_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/light_blue_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/light_blue_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_gray_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_gray_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..fcc3da6f0 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_gray_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/light_gray_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/light_gray_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_gray_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_gray_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..2d7e2ec59 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/light_gray_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/light_gray_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/light_gray_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/lime_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/lime_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..f81ed7f9b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/lime_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/lime_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/lime_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/lime_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/lime_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..6c1da665a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/lime_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/lime_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/lime_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/magenta_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/magenta_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..f8aabffcd --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/magenta_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/magenta_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/magenta_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/magenta_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/magenta_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..e91b28d1b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/magenta_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/magenta_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/magenta_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/orange_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/orange_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..baf71df3b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/orange_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/orange_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/orange_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/orange_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/orange_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..e2913f6ce --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/orange_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/orange_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/orange_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/peculiar_bell.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/peculiar_bell.json new file mode 100644 index 000000000..e0c6e6747 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/peculiar_bell.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/peculiar_bell" + ] + }, + "criteria": { + "has_item": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "forge:ingots/brass" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/peculiar_bell" + } + } + }, + "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/curiosities/pink_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/pink_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..9a7f2e402 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/pink_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/pink_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/pink_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/pink_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/pink_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..50506ecae --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/pink_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/pink_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/pink_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/purple_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/purple_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..de7832688 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/purple_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/purple_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/purple_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/purple_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/purple_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..216566ae4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/purple_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/purple_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/purple_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/red_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/red_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..8f0940397 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/red_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/red_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/red_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/red_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/red_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..dd4198e8d --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/red_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/red_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/red_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/white_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/white_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..92e4c0882 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/white_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/white_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/white_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/white_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/white_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..462d402e6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/white_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/white_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/white_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/yellow_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/yellow_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..d1b0d7776 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/yellow_toolbox_from_main_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/yellow_toolbox_from_main_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/yellow_toolbox_from_main_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/yellow_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/yellow_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..f257e60f6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/curiosities/yellow_toolbox_from_other_toolbox.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/curiosities/yellow_toolbox_from_other_toolbox" + ] + }, + "criteria": { + "has_toolbox": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "create:toolboxes" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/curiosities/yellow_toolbox_from_other_toolbox" + } + } + }, + "requirements": [ + [ + "has_toolbox", + "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/advancements/speed_controller.json b/src/generated/resources/data/create/advancements/speed_controller.json index 694246452..38632e7d1 100644 --- a/src/generated/resources/data/create/advancements/speed_controller.json +++ b/src/generated/resources/data/create/advancements/speed_controller.json @@ -1,5 +1,5 @@ { - "parent": "create:integrated_circuit", + "parent": "create:precision_mechanism", "display": { "icon": { "item": "create:rotation_speed_controller" diff --git a/src/generated/resources/data/create/loot_tables/blocks/black_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/black_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/black_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/black_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/black_toolbox.json new file mode 100644 index 000000000..0eb8a43f3 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/black_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:black_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/blue_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/blue_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/blue_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/blue_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/blue_toolbox.json new file mode 100644 index 000000000..a7b223542 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/blue_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:blue_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/brown_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/brown_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/brown_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/brown_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/brown_toolbox.json new file mode 100644 index 000000000..e84f83f1e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/brown_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:brown_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copper_backtank.json b/src/generated/resources/data/create/loot_tables/blocks/copper_backtank.json index b5466bfc9..d1903f132 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/copper_backtank.json +++ b/src/generated/resources/data/create/loot_tables/blocks/copper_backtank.json @@ -21,6 +21,17 @@ "op": "replace" } ] + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Enchantments", + "target": "Enchantments", + "op": "replace" + } + ] } ], "name": "create:copper_backtank" diff --git a/src/generated/resources/data/create/loot_tables/blocks/cyan_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/cyan_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/cyan_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/cyan_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/cyan_toolbox.json new file mode 100644 index 000000000..bad83e82e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/cyan_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:cyan_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file 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/gray_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/gray_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/gray_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/gray_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/gray_toolbox.json new file mode 100644 index 000000000..07541bf8e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/gray_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:gray_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/green_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/green_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/green_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/green_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/green_toolbox.json new file mode 100644 index 000000000..5cbc865a5 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/green_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:green_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/haunted_bell.json b/src/generated/resources/data/create/loot_tables/blocks/haunted_bell.json new file mode 100644 index 000000000..ec8bd3826 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/haunted_bell.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:haunted_bell" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/lectern_controller.json b/src/generated/resources/data/create/loot_tables/blocks/lectern_controller.json new file mode 100644 index 000000000..6e9c3e84c --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/lectern_controller.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:lectern" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/light_blue_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/light_blue_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/light_blue_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/light_blue_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/light_blue_toolbox.json new file mode 100644 index 000000000..d4fabb3c5 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/light_blue_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:light_blue_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/light_gray_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/light_gray_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/light_gray_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/light_gray_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/light_gray_toolbox.json new file mode 100644 index 000000000..062539366 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/light_gray_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:light_gray_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/lime_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/lime_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/lime_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/lime_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/lime_toolbox.json new file mode 100644 index 000000000..0761f4697 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/lime_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:lime_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file 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/magenta_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/magenta_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/magenta_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/magenta_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/magenta_toolbox.json new file mode 100644 index 000000000..34eac7d29 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/magenta_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:magenta_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/orange_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/orange_toolbox.json new file mode 100644 index 000000000..22ebc019b --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/orange_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:orange_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/peculiar_bell.json b/src/generated/resources/data/create/loot_tables/blocks/peculiar_bell.json new file mode 100644 index 000000000..fd37d00df --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/peculiar_bell.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:peculiar_bell" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/pink_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/pink_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/pink_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/pink_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/pink_toolbox.json new file mode 100644 index 000000000..8ee137fce --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/pink_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:pink_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/purple_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/purple_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/purple_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/purple_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/purple_toolbox.json new file mode 100644 index 000000000..ff7977799 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/purple_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:purple_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/red_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/red_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/red_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/red_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/red_toolbox.json new file mode 100644 index 000000000..086d5361d --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/red_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:red_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file 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/loot_tables/blocks/white_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/white_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/white_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/white_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/white_toolbox.json new file mode 100644 index 000000000..31e955723 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/white_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:white_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/yellow_nixie_tube.json b/src/generated/resources/data/create/loot_tables/blocks/yellow_nixie_tube.json new file mode 100644 index 000000000..68e7a85d0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/yellow_nixie_tube.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:nixie_tube" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/yellow_toolbox.json b/src/generated/resources/data/create/loot_tables/blocks/yellow_toolbox.json new file mode 100644 index 000000000..ab79ef612 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/yellow_toolbox.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Inventory", + "target": "Inventory", + "op": "replace" + } + ] + } + ], + "name": "create:yellow_toolbox" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file 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/compacting/honey.json b/src/generated/resources/data/create/recipes/compacting/honey.json new file mode 100644 index 000000000..4a036ce31 --- /dev/null +++ b/src/generated/resources/data/create/recipes/compacting/honey.json @@ -0,0 +1,14 @@ +{ + "type": "create:compacting", + "ingredients": [ + { + "fluidTag": "forge:honey", + "amount": 1000 + } + ], + "results": [ + { + "item": "minecraft:honey_block" + } + ] +} \ 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/crafting/curiosities/black_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/black_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..c50b64af4 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/black_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/black" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:black_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/black_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/black_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..9527f380a --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/black_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/black" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:black_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/blue_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/blue_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..7c0bf6cf7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/blue_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/blue" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:blue_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/blue_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/blue_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..27736017e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/blue_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/blue" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:blue_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox.json new file mode 100644 index 000000000..6d6361a8d --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + " C ", + "SWS", + " L " + ], + "key": { + "S": { + "tag": "forge:plates/gold" + }, + "C": { + "item": "create:cogwheel" + }, + "W": { + "tag": "forge:chests/wooden" + }, + "L": { + "tag": "forge:leather" + } + }, + "result": { + "item": "create:brown_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..0db80fc97 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/brown" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:brown_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..28aac0823 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/brown_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/brown" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:brown_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/cyan_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/cyan_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..749e020e8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/cyan_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/cyan" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:cyan_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/cyan_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/cyan_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..11841f982 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/cyan_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/cyan" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:cyan_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/gray_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/gray_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..450b7e4b8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/gray_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/gray" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:gray_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/gray_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/gray_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..8d721bf4f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/gray_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/gray" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:gray_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/green_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/green_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..28858a501 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/green_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/green" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:green_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/green_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/green_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..24526bce9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/green_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/green" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:green_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/light_blue_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/light_blue_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..75621af2b --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/light_blue_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/light_blue" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:light_blue_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/light_blue_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/light_blue_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..6afefc1b3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/light_blue_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/light_blue" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:light_blue_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/light_gray_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/light_gray_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..371d47432 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/light_gray_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/light_gray" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:light_gray_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/light_gray_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/light_gray_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..cc48c4376 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/light_gray_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/light_gray" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:light_gray_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/lime_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/lime_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..b86ba9427 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/lime_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/lime" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:lime_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/lime_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/lime_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..f2bb6e189 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/lime_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/lime" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:lime_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/magenta_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/magenta_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..a8842ade0 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/magenta_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/magenta" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:magenta_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/magenta_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/magenta_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..5593479ad --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/magenta_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/magenta" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:magenta_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/orange_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/orange_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..f0b01517c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/orange_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/orange" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:orange_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/orange_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/orange_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..82180b384 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/orange_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/orange" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:orange_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/peculiar_bell.json b/src/generated/resources/data/create/recipes/crafting/curiosities/peculiar_bell.json new file mode 100644 index 000000000..93c17704e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/peculiar_bell.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "I", + "P" + ], + "key": { + "I": { + "tag": "forge:storage_blocks/brass" + }, + "P": { + "tag": "forge:plates/brass" + } + }, + "result": { + "item": "create:peculiar_bell" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/pink_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/pink_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..351ae6db5 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/pink_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/pink" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:pink_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/pink_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/pink_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..24da6b4c5 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/pink_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/pink" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:pink_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/purple_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/purple_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..252f414e7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/purple_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/purple" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:purple_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/purple_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/purple_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..aa4fed224 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/purple_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/purple" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:purple_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/red_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/red_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..ebb27082c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/red_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/red" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:red_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/red_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/red_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..6bfbff76e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/red_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/red" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:red_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/white_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/white_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..62f9b0f56 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/white_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/white" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:white_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/white_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/white_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..0ef96c2d4 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/white_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/white" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:white_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/yellow_toolbox_from_main_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/yellow_toolbox_from_main_toolbox.json new file mode 100644 index 000000000..1cfded44a --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/yellow_toolbox_from_main_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/yellow" + }, + "-": { + "item": "create:brown_toolbox" + } + }, + "result": { + "item": "create:yellow_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/yellow_toolbox_from_other_toolbox.json b/src/generated/resources/data/create/recipes/crafting/curiosities/yellow_toolbox_from_other_toolbox.json new file mode 100644 index 000000000..dfbdcc356 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/yellow_toolbox_from_other_toolbox.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "#", + "-" + ], + "key": { + "#": { + "tag": "forge:dyes/yellow" + }, + "-": { + "tag": "create:toolboxes" + } + }, + "result": { + "item": "create:yellow_toolbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/mechanical_arm.json b/src/generated/resources/data/create/recipes/crafting/kinetics/mechanical_arm.json index b92394fe0..5a64f5c23 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/mechanical_arm.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/mechanical_arm.json @@ -2,18 +2,15 @@ "type": "minecraft:crafting_shaped", "pattern": [ "LLA", - "LR ", - "ICI" + "L ", + "IC " ], "key": { "L": { "tag": "forge:plates/brass" }, - "R": { - "item": "create:cogwheel" - }, "I": { - "item": "create:electron_tube" + "item": "create:precision_mechanism" }, "A": { "item": "create:andesite_alloy" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/rotation_speed_controller.json b/src/generated/resources/data/create/recipes/crafting/kinetics/rotation_speed_controller.json index f25765247..76a4949f5 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/rotation_speed_controller.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/rotation_speed_controller.json @@ -6,7 +6,7 @@ ], "key": { "B": { - "item": "create:integrated_circuit" + "item": "create:precision_mechanism" }, "C": { "item": "create:brass_casing" diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_acacia_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_acacia_log.json index c04b56b51..45e306432 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_acacia_log.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_acacia_log.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:acacia_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_acacia_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_acacia_wood.json index b13377f88..f8a1c75d7 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_acacia_wood.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_acacia_wood.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:acacia_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_birch_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_birch_log.json index 367c77dda..d494dce0c 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_birch_log.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_birch_log.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:birch_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_birch_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_birch_wood.json index e47607e25..bcfa77df8 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_birch_wood.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_birch_wood.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:birch_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_crimson_hyphae.json b/src/generated/resources/data/create/recipes/cutting/stripped_crimson_hyphae.json index bffc17ab3..ae2ccba5a 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_crimson_hyphae.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_crimson_hyphae.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:crimson_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_crimson_stem.json b/src/generated/resources/data/create/recipes/cutting/stripped_crimson_stem.json index 144c34ee4..27c8c26d9 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_crimson_stem.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_crimson_stem.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:crimson_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_log.json index 926996581..09992fa45 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_log.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_log.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:dark_oak_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_wood.json index 7df760eb5..78ee9957a 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_wood.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_wood.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:dark_oak_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_jungle_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_jungle_log.json index f4cfbdb15..0d1b99dc1 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_jungle_log.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_jungle_log.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:jungle_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_jungle_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_jungle_wood.json index 2cbc87f06..127315498 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_jungle_wood.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_jungle_wood.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:jungle_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_oak_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_oak_log.json index 9fe00f52d..e2dcb8771 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_oak_log.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_oak_log.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:oak_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_oak_wood.json index c761dbfd7..47fad8bd1 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_oak_wood.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_oak_wood.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:oak_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_spruce_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_spruce_log.json index 7bec71d4e..29f3afac1 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_spruce_log.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_spruce_log.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:spruce_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_spruce_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_spruce_wood.json index 45f30b64b..06838e98a 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_spruce_wood.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_spruce_wood.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:spruce_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_warped_hyphae.json b/src/generated/resources/data/create/recipes/cutting/stripped_warped_hyphae.json index 9dbd508c5..4cf788d2f 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_warped_hyphae.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_warped_hyphae.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:warped_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_warped_stem.json b/src/generated/resources/data/create/recipes/cutting/stripped_warped_stem.json index 47fd80d74..454a05cbb 100644 --- a/src/generated/resources/data/create/recipes/cutting/stripped_warped_stem.json +++ b/src/generated/resources/data/create/recipes/cutting/stripped_warped_stem.json @@ -8,8 +8,8 @@ "results": [ { "item": "minecraft:warped_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ 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/emptying/milk_bucket.json b/src/generated/resources/data/create/recipes/emptying/milk_bucket.json deleted file mode 100644 index be95f4c33..000000000 --- a/src/generated/resources/data/create/recipes/emptying/milk_bucket.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "create:emptying", - "ingredients": [ - { - "item": "minecraft:milk_bucket" - } - ], - "results": [ - { - "item": "minecraft:bucket" - }, - { - "fluid": "create:milk", - "amount": 1000 - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/filling/milk_bucket.json b/src/generated/resources/data/create/recipes/filling/milk_bucket.json deleted file mode 100644 index ab968ec8d..000000000 --- a/src/generated/resources/data/create/recipes/filling/milk_bucket.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "create:filling", - "ingredients": [ - { - "item": "minecraft:bucket" - }, - { - "fluidTag": "forge:milk", - "amount": 1000 - } - ], - "results": [ - { - "item": "minecraft:milk_bucket" - } - ] -} \ 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/mechanical_crafting/crushing_wheel.json b/src/generated/resources/data/create/recipes/mechanical_crafting/crushing_wheel.json index a8c1170ec..34ad9ea72 100644 --- a/src/generated/resources/data/create/recipes/mechanical_crafting/crushing_wheel.json +++ b/src/generated/resources/data/create/recipes/mechanical_crafting/crushing_wheel.json @@ -21,5 +21,6 @@ "result": { "item": "create:crushing_wheel", "count": 2 - } + }, + "acceptMirrored": false } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mechanical_crafting/extendo_grip.json b/src/generated/resources/data/create/recipes/mechanical_crafting/extendo_grip.json index 37d2eeae5..2d69859ee 100644 --- a/src/generated/resources/data/create/recipes/mechanical_crafting/extendo_grip.json +++ b/src/generated/resources/data/create/recipes/mechanical_crafting/extendo_grip.json @@ -12,7 +12,7 @@ "tag": "forge:ingots/brass" }, "R": { - "item": "create:cogwheel" + "item": "create:precision_mechanism" }, "H": { "item": "create:brass_hand" @@ -23,5 +23,6 @@ }, "result": { "item": "create:extendo_grip" - } + }, + "acceptMirrored": false } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mechanical_crafting/flywheel.json b/src/generated/resources/data/create/recipes/mechanical_crafting/flywheel.json index 010b2fbae..dee9cffd7 100644 --- a/src/generated/resources/data/create/recipes/mechanical_crafting/flywheel.json +++ b/src/generated/resources/data/create/recipes/mechanical_crafting/flywheel.json @@ -15,5 +15,6 @@ }, "result": { "item": "create:flywheel" - } + }, + "acceptMirrored": true } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mechanical_crafting/furnace_engine.json b/src/generated/resources/data/create/recipes/mechanical_crafting/furnace_engine.json index 45765aebe..3842209f0 100644 --- a/src/generated/resources/data/create/recipes/mechanical_crafting/furnace_engine.json +++ b/src/generated/resources/data/create/recipes/mechanical_crafting/furnace_engine.json @@ -26,5 +26,6 @@ }, "result": { "item": "create:furnace_engine" - } + }, + "acceptMirrored": true } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mechanical_crafting/integrated_circuit.json b/src/generated/resources/data/create/recipes/mechanical_crafting/integrated_circuit.json deleted file mode 100644 index 68a5323da..000000000 --- a/src/generated/resources/data/create/recipes/mechanical_crafting/integrated_circuit.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "create:mechanical_crafting", - "pattern": [ - " L ", - "RRQRR", - " CCC " - ], - "key": { - "L": { - "item": "create:lapis_sheet" - }, - "R": { - "tag": "forge:dusts/redstone" - }, - "Q": { - "item": "create:polished_rose_quartz" - }, - "C": { - "tag": "forge:nuggets/gold" - } - }, - "result": { - "item": "create:integrated_circuit" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mechanical_crafting/potato_cannon.json b/src/generated/resources/data/create/recipes/mechanical_crafting/potato_cannon.json new file mode 100644 index 000000000..a21d9bd04 --- /dev/null +++ b/src/generated/resources/data/create/recipes/mechanical_crafting/potato_cannon.json @@ -0,0 +1,25 @@ +{ + "type": "create:mechanical_crafting", + "pattern": [ + "LRSSS", + "CC " + ], + "key": { + "L": { + "item": "create:andesite_alloy" + }, + "R": { + "item": "create:precision_mechanism" + }, + "S": { + "item": "create:fluid_pipe" + }, + "C": { + "tag": "forge:ingots/copper" + } + }, + "result": { + "item": "create:potato_cannon" + }, + "acceptMirrored": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/milling/beetroot.json b/src/generated/resources/data/create/recipes/milling/beetroot.json new file mode 100644 index 000000000..740896026 --- /dev/null +++ b/src/generated/resources/data/create/recipes/milling/beetroot.json @@ -0,0 +1,19 @@ +{ + "type": "create:milling", + "ingredients": [ + { + "item": "minecraft:beetroot" + } + ], + "results": [ + { + "item": "minecraft:red_dye", + "count": 2 + }, + { + "item": "minecraft:beetroot_seeds", + "chance": 0.1 + } + ], + "processingTime": 70 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/milling/sea_pickle.json b/src/generated/resources/data/create/recipes/milling/sea_pickle.json new file mode 100644 index 000000000..93769b17d --- /dev/null +++ b/src/generated/resources/data/create/recipes/milling/sea_pickle.json @@ -0,0 +1,19 @@ +{ + "type": "create:milling", + "ingredients": [ + { + "item": "minecraft:sea_pickle" + } + ], + "results": [ + { + "item": "minecraft:lime_dye", + "count": 2 + }, + { + "item": "minecraft:green_dye", + "chance": 0.1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mixing/chocolate_melting.json b/src/generated/resources/data/create/recipes/mixing/chocolate_melting.json new file mode 100644 index 000000000..eb4529be1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/mixing/chocolate_melting.json @@ -0,0 +1,15 @@ +{ + "type": "create:mixing", + "ingredients": [ + { + "item": "create:bar_of_chocolate" + } + ], + "results": [ + { + "fluid": "create:chocolate", + "amount": 250 + } + ], + "heatRequirement": "heated" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mixing/dough_by_mixing.json b/src/generated/resources/data/create/recipes/mixing/dough_by_mixing.json new file mode 100644 index 000000000..79d9a710a --- /dev/null +++ b/src/generated/resources/data/create/recipes/mixing/dough_by_mixing.json @@ -0,0 +1,18 @@ +{ + "type": "create:mixing", + "ingredients": [ + { + "item": "create:wheat_flour" + }, + { + "fluid": "minecraft:water", + "nbt": {}, + "amount": 1000 + } + ], + "results": [ + { + "item": "create:dough" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mixing/honey.json b/src/generated/resources/data/create/recipes/mixing/honey.json new file mode 100644 index 000000000..cfc7abf8c --- /dev/null +++ b/src/generated/resources/data/create/recipes/mixing/honey.json @@ -0,0 +1,15 @@ +{ + "type": "create:mixing", + "ingredients": [ + { + "item": "minecraft:honey_block" + } + ], + "results": [ + { + "fluid": "create:honey", + "amount": 1000 + } + ], + "heatRequirement": "heated" +} \ 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/lapis_block.json b/src/generated/resources/data/create/recipes/pressing/lapis_block.json deleted file mode 100644 index 7551fecd2..000000000 --- a/src/generated/resources/data/create/recipes/pressing/lapis_block.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "create:pressing", - "ingredients": [ - { - "item": "minecraft:lapis_block" - } - ], - "results": [ - { - "item": "create:lapis_sheet" - } - ] -} \ No newline at end of file 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/sequenced_assembly/cogwheel.json b/src/generated/resources/data/create/recipes/sequenced_assembly/cogwheel.json new file mode 100644 index 000000000..3815a5bdc --- /dev/null +++ b/src/generated/resources/data/create/recipes/sequenced_assembly/cogwheel.json @@ -0,0 +1,65 @@ +{ + "type": "create:sequenced_assembly", + "ingredient": { + "item": "create:andesite_alloy" + }, + "transitionalItem": { + "item": "create:incomplete_cogwheel" + }, + "sequence": [ + { + "type": "create:deploying", + "ingredients": [ + { + "item": "create:incomplete_cogwheel" + }, + { + "tag": "minecraft:wooden_buttons" + } + ], + "results": [ + { + "item": "create:incomplete_cogwheel" + } + ] + }, + { + "type": "create:cutting", + "ingredients": [ + { + "item": "create:incomplete_cogwheel" + } + ], + "results": [ + { + "item": "create:incomplete_cogwheel" + } + ], + "processingTime": 50 + } + ], + "results": [ + { + "item": "create:cogwheel", + "count": 12, + "chance": 32.0 + }, + { + "item": "create:andesite_alloy", + "chance": 2.0 + }, + { + "item": "minecraft:andesite" + }, + { + "item": "create:large_cogwheel" + }, + { + "item": "minecraft:stick" + }, + { + "item": "minecraft:iron_nugget" + } + ], + "loops": 4 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/sequenced_assembly/large_cogwheel.json b/src/generated/resources/data/create/recipes/sequenced_assembly/large_cogwheel.json new file mode 100644 index 000000000..6c80cc515 --- /dev/null +++ b/src/generated/resources/data/create/recipes/sequenced_assembly/large_cogwheel.json @@ -0,0 +1,81 @@ +{ + "type": "create:sequenced_assembly", + "ingredient": { + "item": "create:andesite_alloy" + }, + "transitionalItem": { + "item": "create:incomplete_large_cogwheel" + }, + "sequence": [ + { + "type": "create:deploying", + "ingredients": [ + { + "item": "create:incomplete_large_cogwheel" + }, + { + "tag": "minecraft:planks" + } + ], + "results": [ + { + "item": "create:incomplete_large_cogwheel" + } + ] + }, + { + "type": "create:deploying", + "ingredients": [ + { + "item": "create:incomplete_large_cogwheel" + }, + { + "tag": "minecraft:wooden_buttons" + } + ], + "results": [ + { + "item": "create:incomplete_large_cogwheel" + } + ] + }, + { + "type": "create:cutting", + "ingredients": [ + { + "item": "create:incomplete_large_cogwheel" + } + ], + "results": [ + { + "item": "create:incomplete_large_cogwheel" + } + ], + "processingTime": 50 + } + ], + "results": [ + { + "item": "create:large_cogwheel", + "count": 6, + "chance": 32.0 + }, + { + "item": "create:andesite_alloy", + "chance": 2.0 + }, + { + "item": "minecraft:andesite" + }, + { + "item": "create:cogwheel" + }, + { + "item": "minecraft:stick" + }, + { + "item": "minecraft:iron_nugget" + } + ], + "loops": 3 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/sequenced_assembly/precision_mechanism.json b/src/generated/resources/data/create/recipes/sequenced_assembly/precision_mechanism.json new file mode 100644 index 000000000..c130de722 --- /dev/null +++ b/src/generated/resources/data/create/recipes/sequenced_assembly/precision_mechanism.json @@ -0,0 +1,96 @@ +{ + "type": "create:sequenced_assembly", + "ingredient": { + "tag": "forge:plates/gold" + }, + "transitionalItem": { + "item": "create:incomplete_precision_mechanism" + }, + "sequence": [ + { + "type": "create:deploying", + "ingredients": [ + { + "item": "create:incomplete_precision_mechanism" + }, + { + "item": "create:cogwheel" + } + ], + "results": [ + { + "item": "create:incomplete_precision_mechanism" + } + ] + }, + { + "type": "create:deploying", + "ingredients": [ + { + "item": "create:incomplete_precision_mechanism" + }, + { + "item": "create:large_cogwheel" + } + ], + "results": [ + { + "item": "create:incomplete_precision_mechanism" + } + ] + }, + { + "type": "create:deploying", + "ingredients": [ + { + "item": "create:incomplete_precision_mechanism" + }, + { + "tag": "forge:nuggets/iron" + } + ], + "results": [ + { + "item": "create:incomplete_precision_mechanism" + } + ] + } + ], + "results": [ + { + "item": "create:precision_mechanism", + "chance": 120.0 + }, + { + "item": "create:golden_sheet", + "chance": 8.0 + }, + { + "item": "create:andesite_alloy", + "chance": 8.0 + }, + { + "item": "create:cogwheel", + "chance": 5.0 + }, + { + "item": "create:shaft", + "chance": 2.0 + }, + { + "item": "create:crushed_gold_ore", + "chance": 2.0 + }, + { + "item": "minecraft:gold_nugget", + "chance": 2.0 + }, + { + "item": "minecraft:iron_ingot" + }, + { + "item": "minecraft:clock" + } + ], + "loops": 5 +} \ 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..4cc8d6e48 100644 --- a/src/generated/resources/data/create/tags/blocks/brittle.json +++ b/src/generated/resources/data/create/tags/blocks/brittle.json @@ -24,7 +24,10 @@ "create:pulley_magnet", "create:furnace_engine", "create:redstone_link", + "create:peculiar_bell", + "create:haunted_bell", "#minecraft:doors", + "#minecraft:beds", "minecraft:flower_pot", "minecraft:bell", "minecraft:cocoa" diff --git a/src/generated/resources/data/create/tags/blocks/fan_transparent.json b/src/generated/resources/data/create/tags/blocks/fan_transparent.json index 5e6279801..6c8dfd4aa 100644 --- a/src/generated/resources/data/create/tags/blocks/fan_transparent.json +++ b/src/generated/resources/data/create/tags/blocks/fan_transparent.json @@ -5,6 +5,8 @@ "create:lit_blaze_burner", "create:sail_frame", "#minecraft:fences", - "minecraft:iron_bars" + "minecraft:iron_bars", + "minecraft:campfire", + "minecraft:soul_campfire" ] } \ No newline at end of file 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/create/tags/blocks/toolboxes.json b/src/generated/resources/data/create/tags/blocks/toolboxes.json new file mode 100644 index 000000000..1d7b0be45 --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/toolboxes.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "create:white_toolbox", + "create:orange_toolbox", + "create:magenta_toolbox", + "create:light_blue_toolbox", + "create:yellow_toolbox", + "create:lime_toolbox", + "create:pink_toolbox", + "create:gray_toolbox", + "create:light_gray_toolbox", + "create:cyan_toolbox", + "create:purple_toolbox", + "create:blue_toolbox", + "create:brown_toolbox", + "create:green_toolbox", + "create:red_toolbox", + "create:black_toolbox" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/wrench_pickup.json b/src/generated/resources/data/create/tags/blocks/wrench_pickup.json new file mode 100644 index 000000000..c3da555b0 --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/wrench_pickup.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "#minecraft:rails", + "#minecraft:buttons", + "#minecraft:pressure_plates", + "minecraft:redstone_wire", + "minecraft:redstone_torch", + "minecraft:repeater", + "minecraft:lever", + "minecraft:comparator", + "minecraft:observer", + "minecraft:redstone_wall_torch", + "minecraft:piston", + "minecraft:sticky_piston", + "minecraft:tripwire", + "minecraft:tripwire_hook", + "minecraft:daylight_detector", + "minecraft:target" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/sandpaper.json b/src/generated/resources/data/create/tags/items/sandpaper.json new file mode 100644 index 000000000..acab7913a --- /dev/null +++ b/src/generated/resources/data/create/tags/items/sandpaper.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "create:sand_paper", + "create:red_sand_paper" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/toolboxes.json b/src/generated/resources/data/create/tags/items/toolboxes.json new file mode 100644 index 000000000..1d7b0be45 --- /dev/null +++ b/src/generated/resources/data/create/tags/items/toolboxes.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "create:white_toolbox", + "create:orange_toolbox", + "create:magenta_toolbox", + "create:light_blue_toolbox", + "create:yellow_toolbox", + "create:lime_toolbox", + "create:pink_toolbox", + "create:gray_toolbox", + "create:light_gray_toolbox", + "create:cyan_toolbox", + "create:purple_toolbox", + "create:blue_toolbox", + "create:brown_toolbox", + "create:green_toolbox", + "create:red_toolbox", + "create:black_toolbox" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/upright_on_belt.json b/src/generated/resources/data/create/tags/items/upright_on_belt.json index 0aa3286d8..76dfebfa3 100644 --- a/src/generated/resources/data/create/tags/items/upright_on_belt.json +++ b/src/generated/resources/data/create/tags/items/upright_on_belt.json @@ -3,11 +3,13 @@ "values": [ "create:blaze_cake_base", "create:blaze_cake", + "create:creative_blaze_cake", "create:builders_tea", "minecraft:glass_bottle", "minecraft:potion", "minecraft:splash_potion", "minecraft:lingering_potion", - "minecraft:honey_bottle" + "minecraft:honey_bottle", + "minecraft:cake" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/cobblestone.json b/src/generated/resources/data/forge/tags/blocks/cobblestone.json new file mode 100644 index 000000000..4a5c2c1fb --- /dev/null +++ b/src/generated/resources/data/forge/tags/blocks/cobblestone.json @@ -0,0 +1,14 @@ +{ + "replace": false, + "values": [ + "create:granite_cobblestone", + "create:diorite_cobblestone", + "create:andesite_cobblestone", + "create:limestone_cobblestone", + "create:weathered_limestone_cobblestone", + "create:dolomite_cobblestone", + "create:gabbro_cobblestone", + "create:scoria_cobblestone", + "create:dark_scoria_cobblestone" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/forge/tags/items/stone.json b/src/generated/resources/data/forge/tags/blocks/stone.json similarity index 100% rename from src/main/resources/data/forge/tags/items/stone.json rename to src/generated/resources/data/forge/tags/blocks/stone.json index 2b4996602..5a5395c1f 100644 --- a/src/main/resources/data/forge/tags/items/stone.json +++ b/src/generated/resources/data/forge/tags/blocks/stone.json @@ -5,10 +5,10 @@ "create:polished_limestone", "create:weathered_limestone", "create:polished_weathered_limestone", - "create:gabbro", - "create:polished_gabbro", "create:dolomite", "create:polished_dolomite", + "create:gabbro", + "create:polished_gabbro", "create:scoria", "create:polished_scoria", "create:dark_scoria", diff --git a/src/main/resources/data/forge/tags/blocks/wg_stone.json b/src/generated/resources/data/forge/tags/blocks/wg_stone.json similarity index 100% rename from src/main/resources/data/forge/tags/blocks/wg_stone.json rename to src/generated/resources/data/forge/tags/blocks/wg_stone.json index d49e3fbd6..39e5fd569 100644 --- a/src/main/resources/data/forge/tags/blocks/wg_stone.json +++ b/src/generated/resources/data/forge/tags/blocks/wg_stone.json @@ -3,8 +3,8 @@ "values": [ "create:limestone", "create:weathered_limestone", - "create:gabbro", "create:dolomite", + "create:gabbro", "create:natural_scoria" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/fluids/milk.json b/src/generated/resources/data/forge/tags/fluids/milk.json deleted file mode 100644 index 6860027e8..000000000 --- a/src/generated/resources/data/forge/tags/fluids/milk.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "replace": false, - "values": [ - "create:flowing_milk", - "create:milk" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/plates/lapis_lazuli.json b/src/generated/resources/data/forge/tags/items/buckets/honey.json similarity index 61% rename from src/generated/resources/data/forge/tags/items/plates/lapis_lazuli.json rename to src/generated/resources/data/forge/tags/items/buckets/honey.json index b9f6147a1..215063f0f 100644 --- a/src/generated/resources/data/forge/tags/items/plates/lapis_lazuli.json +++ b/src/generated/resources/data/forge/tags/items/buckets/honey.json @@ -1,6 +1,6 @@ { "replace": false, "values": [ - "create:lapis_sheet" + "create:honey_bucket" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/plates.json b/src/generated/resources/data/forge/tags/items/plates.json index 3ba58600a..c294488df 100644 --- a/src/generated/resources/data/forge/tags/items/plates.json +++ b/src/generated/resources/data/forge/tags/items/plates.json @@ -4,7 +4,6 @@ "create:copper_sheet", "create:brass_sheet", "create:iron_sheet", - "create:golden_sheet", - "create:lapis_sheet" + "create:golden_sheet" ] } \ No newline at end of file diff --git a/src/main/resources/data/forge/tags/blocks/stone.json b/src/generated/resources/data/forge/tags/items/stone.json similarity index 100% rename from src/main/resources/data/forge/tags/blocks/stone.json rename to src/generated/resources/data/forge/tags/items/stone.json index 2b4996602..5a5395c1f 100644 --- a/src/main/resources/data/forge/tags/blocks/stone.json +++ b/src/generated/resources/data/forge/tags/items/stone.json @@ -5,10 +5,10 @@ "create:polished_limestone", "create:weathered_limestone", "create:polished_weathered_limestone", - "create:gabbro", - "create:polished_gabbro", "create:dolomite", "create:polished_dolomite", + "create:gabbro", + "create:polished_gabbro", "create:scoria", "create:polished_scoria", "create:dark_scoria", 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..e1624bb5c 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -3,14 +3,14 @@ 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; +import net.minecraft.item.DyeColor; import net.minecraft.util.Direction; -import net.minecraft.util.ResourceLocation; public class AllBlockPartials { @@ -93,22 +93,30 @@ public class AllBlockPartials { SPOUT_TOP = get("spout/top"), SPOUT_MIDDLE = get("spout/middle"), SPOUT_BOTTOM = get("spout/bottom"), + PECULIAR_BELL = get("peculiar_bell"), HAUNTED_BELL = get("haunted_bell"), + + TOOLBOX_DRAWER = get("toolbox/drawer"), + SPEED_CONTROLLER_BRACKET = get("rotation_speed_controller/bracket"), 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"), + 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") + COUPLING_CONNECTOR = getEntity("minecart_coupling/connector"); - ; - - public static final Map> PIPE_ATTACHMENTS = new HashMap<>(); + public static final Map> PIPE_ATTACHMENTS = + new HashMap<>(); + public static final Map TOOLBOX_LIDS = new HashMap<>(); public static final Map BLAZES = new HashMap<>(); static { @@ -122,26 +130,29 @@ public class AllBlockPartials { Map map = new HashMap<>(); for (Direction d : Iterate.directions) { String asId = Lang.asId(type.name()); - map.put(d, get("fluid_pipe/" + asId + "/" + Lang.asId(d.getString()))); + map.put(d, get("fluid_pipe/" + asId + "/" + Lang.asId(d.getSerializedName()))); } PIPE_ATTACHMENTS.put(type, map); } for (BlazeBurnerBlock.HeatLevel heat : BlazeBurnerBlock.HeatLevel.values()) { if (heat == BlazeBurnerBlock.HeatLevel.NONE) continue; - BLAZES.put(heat, get("blaze_burner/blaze/" + heat.getString())); + BLAZES.put(heat, get("blaze_burner/blaze/" + heat.getSerializedName())); } + for (DyeColor color : DyeColor.values()) + TOOLBOX_LIDS.put(color, get("toolbox/lid/" + Lang.asId(color.name()))); } private static PartialModel getEntity(String path) { - return new PartialModel(new ResourceLocation(Create.ID, "entity/" + path)); + return new PartialModel(Create.asResource("entity/" + path)); } private static PartialModel get(String path) { - return new PartialModel(new ResourceLocation(Create.ID, "block/" + path)); + return new PartialModel(Create.asResource("block/" + path)); } - public static void clientInit() { + public static void init() { // init static fields } + } diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 472b8e8a2..a7e176e76 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -9,12 +9,12 @@ 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; import com.simibubi.create.content.contraptions.base.CasingBlock; +import com.simibubi.create.content.contraptions.components.AssemblyOperatorBlockItem; +import com.simibubi.create.content.contraptions.components.actors.BellMovementBehaviour; import com.simibubi.create.content.contraptions.components.actors.DrillBlock; import com.simibubi.create.content.contraptions.components.actors.DrillMovementBehaviour; import com.simibubi.create.content.contraptions.components.actors.HarvesterBlock; @@ -41,7 +41,6 @@ import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBloc import com.simibubi.create.content.contraptions.components.flywheel.FlywheelGenerator; import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineBlock; import com.simibubi.create.content.contraptions.components.millstone.MillstoneBlock; -import com.simibubi.create.content.contraptions.components.mixer.BasinOperatorBlockItem; import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerBlock; import com.simibubi.create.content.contraptions.components.motor.CreativeMotorBlock; import com.simibubi.create.content.contraptions.components.motor.CreativeMotorGenerator; @@ -116,6 +115,10 @@ 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.bell.HauntedBellBlock; +import com.simibubi.create.content.curiosities.bell.HauntedBellMovementBehaviour; +import com.simibubi.create.content.curiosities.bell.PeculiarBellBlock; +import com.simibubi.create.content.curiosities.toolbox.ToolboxBlock; 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; @@ -155,10 +158,12 @@ import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock; import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkGenerator; import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchBlock; +import com.simibubi.create.content.logistics.item.LecternControllerBlock; import com.simibubi.create.content.schematics.block.SchematicTableBlock; import com.simibubi.create.content.schematics.block.SchematicannonBlock; +import com.simibubi.create.foundation.block.BlockStressDefaults; +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; import com.simibubi.create.foundation.data.BlockStateGen; import com.simibubi.create.foundation.data.BuilderTransformers; @@ -166,6 +171,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 +209,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 +221,17 @@ 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.lootTable(); + IBuilder survivesExplosion = SurvivesExplosion.survivesExplosion(); + lt.add(block, builder.withPool(LootPool.lootPool() + .when(survivesExplosion) + .setRolls(ConstantRange.exactly(1)) + .add(ItemLootEntry.lootTableItem(AllBlocks.SCHEMATICANNON.get() + .asItem()) + .apply(CopyNbt.copyData(CopyNbt.Source.BLOCK_ENTITY) + .copy("Options", "BlockEntityTag.Options"))))); + }) .item() .transform(customItemModel()) .register(); @@ -235,7 +252,7 @@ public class AllBlocks { public static final BlockEntry SHAFT = REGISTRATE.block("shaft", ShaftBlock::new) .initialProperties(SharedProperties::stone) - .transform(StressConfigDefaults.setNoImpact()) + .transform(BlockStressDefaults.setNoImpact()) .blockstate(BlockStateGen.axisBlockProvider(false)) .onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new)) .simpleItem() @@ -243,7 +260,7 @@ public class AllBlocks { public static final BlockEntry COGWHEEL = REGISTRATE.block("cogwheel", CogWheelBlock::small) .initialProperties(SharedProperties::stone) - .transform(StressConfigDefaults.setNoImpact()) + .transform(BlockStressDefaults.setNoImpact()) .properties(p -> p.sound(SoundType.WOOD)) .blockstate(BlockStateGen.axisBlockProvider(false)) .onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new)) @@ -255,7 +272,7 @@ public class AllBlocks { REGISTRATE.block("large_cogwheel", CogWheelBlock::large) .initialProperties(SharedProperties::stone) .properties(p -> p.sound(SoundType.WOOD)) - .transform(StressConfigDefaults.setNoImpact()) + .transform(BlockStressDefaults.setNoImpact()) .blockstate(BlockStateGen.axisBlockProvider(false)) .onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new)) .item(CogwheelBlockItem::new) @@ -274,11 +291,11 @@ public class AllBlocks { public static final BlockEntry GEARBOX = REGISTRATE.block("gearbox", GearboxBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) - .transform(StressConfigDefaults.setNoImpact()) + .properties(AbstractBlock.Properties::noOcclusion) + .transform(BlockStressDefaults.setNoImpact()) .onRegister(CreateRegistrate.connectedTextures(new EncasedCTBehaviour(AllSpriteShifts.ANDESITE_CASING))) .onRegister(CreateRegistrate.casingConnectivity((block, cc) -> cc.make(block, AllSpriteShifts.ANDESITE_CASING, - (s, f) -> f.getAxis() == s.get(GearboxBlock.AXIS)))) + (s, f) -> f.getAxis() == s.getValue(GearboxBlock.AXIS)))) .blockstate((c, p) -> axisBlock(c, p, $ -> AssetLookup.partialBaseModel(c, p), true)) .item() .transform(customItemModel()) @@ -286,8 +303,8 @@ public class AllBlocks { public static final BlockEntry CLUTCH = REGISTRATE.block("clutch", ClutchBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) - .transform(StressConfigDefaults.setNoImpact()) + .properties(AbstractBlock.Properties::noOcclusion) + .transform(BlockStressDefaults.setNoImpact()) .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, AssetLookup.forPowered(c, p))) .item() .transform(customItemModel()) @@ -295,8 +312,8 @@ public class AllBlocks { public static final BlockEntry GEARSHIFT = REGISTRATE.block("gearshift", GearshiftBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) - .transform(StressConfigDefaults.setNoImpact()) + .properties(AbstractBlock.Properties::noOcclusion) + .transform(BlockStressDefaults.setNoImpact()) .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, AssetLookup.forPowered(c, p))) .item() .transform(customItemModel()) @@ -305,8 +322,8 @@ public class AllBlocks { public static final BlockEntry ENCASED_CHAIN_DRIVE = REGISTRATE.block("encased_chain_drive", EncasedBeltBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) - .transform(StressConfigDefaults.setNoImpact()) + .properties(AbstractBlock.Properties::noOcclusion) + .transform(BlockStressDefaults.setNoImpact()) .blockstate((c, p) -> new EncasedBeltGenerator((state, suffix) -> p.models() .getExistingFile(p.modLoc("block/" + c.getName() + "/" + suffix))).generate(c, p)) .item() @@ -316,10 +333,10 @@ public class AllBlocks { public static final BlockEntry ADJUSTABLE_CHAIN_GEARSHIFT = REGISTRATE.block("adjustable_chain_gearshift", AdjustablePulleyBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) - .transform(StressConfigDefaults.setNoImpact()) + .properties(AbstractBlock.Properties::noOcclusion) + .transform(BlockStressDefaults.setNoImpact()) .blockstate((c, p) -> new EncasedBeltGenerator((state, suffix) -> { - String powered = state.get(AdjustablePulleyBlock.POWERED) ? "_powered" : ""; + String powered = state.getValue(AdjustablePulleyBlock.POWERED) ? "_powered" : ""; return p.models() .withExistingParent(c.getName() + "_" + suffix + powered, p.modLoc("block/encased_chain_drive/" + suffix)) @@ -332,11 +349,11 @@ public class AllBlocks { .register(); public static final BlockEntry BELT = REGISTRATE.block("belt", BeltBlock::new) - .initialProperties(SharedProperties.beltMaterial, MaterialColor.GRAY) - .properties(p -> p.sound(SoundType.CLOTH)) - .properties(p -> p.hardnessAndResistance(0.8F)) + .initialProperties(SharedProperties.beltMaterial, MaterialColor.COLOR_GRAY) + .properties(p -> p.sound(SoundType.WOOL)) + .properties(p -> p.strength(0.8F)) .blockstate(new BeltGenerator()::generate) - .transform(StressConfigDefaults.setImpact(1.0)) + .transform(BlockStressDefaults.setImpact(1.0)) .onRegister(CreateRegistrate.blockModel(() -> BeltModel::new)) .register(); @@ -345,7 +362,7 @@ public class AllBlocks { .initialProperties(SharedProperties::stone) .tag(AllBlockTags.SAFE_NBT.tag) .blockstate(new CreativeMotorGenerator()::generate) - .transform(StressConfigDefaults.setCapacity(16384.0)) + .transform(BlockStressDefaults.setCapacity(16384.0)) .item() .properties(p -> p.rarity(Rarity.EPIC)) .transform(customItemModel()) @@ -353,19 +370,19 @@ public class AllBlocks { public static final BlockEntry WATER_WHEEL = REGISTRATE.block("water_wheel", WaterWheelBlock::new) .initialProperties(SharedProperties::wooden) - .properties(AbstractBlock.Properties::nonOpaque) - .blockstate(BlockStateGen.horizontalWheelProvider(false)) - .addLayer(() -> RenderType::getCutoutMipped) - .transform(StressConfigDefaults.setCapacity(16.0)) + .properties(AbstractBlock.Properties::noOcclusion) + .blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(false)) + .addLayer(() -> RenderType::cutoutMipped) + .transform(BlockStressDefaults.setCapacity(16.0)) .simpleItem() .register(); public static final BlockEntry ENCASED_FAN = REGISTRATE.block("encased_fan", EncasedFanBlock::new) .initialProperties(SharedProperties::stone) .blockstate(BlockStateGen.directionalBlockProvider(true)) - .addLayer(() -> RenderType::getCutoutMipped) - .transform(StressConfigDefaults.setCapacity(16.0)) - .transform(StressConfigDefaults.setImpact(2.0)) + .addLayer(() -> RenderType::cutoutMipped) + .transform(BlockStressDefaults.setCapacity(16.0)) + .transform(BlockStressDefaults.setImpact(2.0)) .item() .transform(customItemModel()) .register(); @@ -374,7 +391,7 @@ public class AllBlocks { .initialProperties(SharedProperties::stone) .tag(AllBlockTags.BRITTLE.tag) .blockstate(BlockStateGen.directionalBlockProvider(true)) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item() .transform(customItemModel()) .register(); @@ -382,14 +399,14 @@ public class AllBlocks { public static final BlockEntry TURNTABLE = REGISTRATE.block("turntable", TurntableBlock::new) .initialProperties(SharedProperties::wooden) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.standardModel(c, p))) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .simpleItem() .register(); public static final BlockEntry HAND_CRANK = REGISTRATE.block("hand_crank", HandCrankBlock::new) .initialProperties(SharedProperties::wooden) .blockstate(BlockStateGen.directionalBlockProvider(true)) - .transform(StressConfigDefaults.setCapacity(8.0)) + .transform(BlockStressDefaults.setCapacity(8.0)) .tag(AllBlockTags.BRITTLE.tag) .onRegister(ItemUseOverrides::addBlock) .item() @@ -411,7 +428,7 @@ public class AllBlocks { public static final BlockEntry MILLSTONE = REGISTRATE.block("millstone", MillstoneBlock::new) .initialProperties(SharedProperties::stone) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .item() .transform(customItemModel()) .register(); @@ -419,10 +436,10 @@ public class AllBlocks { public static final BlockEntry CRUSHING_WHEEL = REGISTRATE.block("crushing_wheel", CrushingWheelBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(BlockStateGen.axisBlockProvider(false)) - .addLayer(() -> RenderType::getCutoutMipped) - .transform(StressConfigDefaults.setImpact(8.0)) + .addLayer(() -> RenderType::cutoutMipped) + .transform(BlockStressDefaults.setImpact(8.0)) .simpleItem() .register(); @@ -439,27 +456,27 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_PRESS = REGISTRATE.block("mechanical_press", MechanicalPressBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .transform(StressConfigDefaults.setImpact(8.0)) - .item(BasinOperatorBlockItem::new) + .transform(BlockStressDefaults.setImpact(8.0)) + .item(AssemblyOperatorBlockItem::new) .transform(customItemModel()) .register(); public static final BlockEntry MECHANICAL_MIXER = REGISTRATE.block("mechanical_mixer", MechanicalMixerBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) - .addLayer(() -> RenderType::getCutoutMipped) - .transform(StressConfigDefaults.setImpact(4.0)) - .item(BasinOperatorBlockItem::new) + .addLayer(() -> RenderType::cutoutMipped) + .transform(BlockStressDefaults.setImpact(4.0)) + .item(AssemblyOperatorBlockItem::new) .transform(customItemModel()) .register(); public static final BlockEntry BASIN = REGISTRATE.block("basin", BasinBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.sound(SoundType.NETHERITE)) + .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .blockstate(new BasinGenerator()::generate) .onRegister(addMovementBehaviour(new BasinMovementBehaviour())) .item() @@ -469,10 +486,10 @@ public class AllBlocks { public static final BlockEntry BLAZE_BURNER = REGISTRATE.block("blaze_burner", BlazeBurnerBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.luminance($ -> 12)) - .addLayer(() -> RenderType::getCutoutMipped) + .properties(p -> p.lightLevel(BlazeBurnerBlock::getLight)) + .addLayer(() -> RenderType::cutoutMipped) .tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.FAN_HEATERS.tag) - .loot((lt, block) -> lt.registerLootTable(block, BlazeBurnerBlock.buildLootTable())) + .loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable())) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .item(BlazeBurnerBlockItem::withBlaze) .model(AssetLookup.customBlockItemModel("blaze_burner", "block_with_blaze")) @@ -482,12 +499,18 @@ public class AllBlocks { public static final BlockEntry LIT_BLAZE_BURNER = REGISTRATE.block("lit_blaze_burner", LitBlazeBurnerBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.luminance($ -> 12)) - .addLayer(() -> RenderType::getCutoutMipped) + .properties(p -> p.lightLevel(LitBlazeBurnerBlock::getLight)) + .addLayer(() -> RenderType::cutoutMipped) .tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.FAN_HEATERS.tag) - .loot((lt, block) -> lt.registerDropping(block, AllItems.EMPTY_BLAZE_BURNER.get())) - .blockstate((c, p) -> p.simpleBlock(c.getEntry(), p.models() - .getExistingFile(p.modLoc("block/blaze_burner/block_with_fire")))) + .loot((lt, block) -> lt.dropOther(block, AllItems.EMPTY_BLAZE_BURNER.get())) + .blockstate((c, p) -> p.getVariantBuilder(c.get()) + .forAllStates(state -> ConfiguredModel.builder() + .modelFile(p.models() + .getExistingFile(p.modLoc("block/blaze_burner/" + + (state.getValue(LitBlazeBurnerBlock.FLAME_TYPE) == LitBlazeBurnerBlock.FlameType.SOUL + ? "block_with_soul_fire" + : "block_with_fire")))) + .build())) .register(); public static final BlockEntry DEPOT = REGISTRATE.block("depot", DepotBlock::new) @@ -500,17 +523,17 @@ public class AllBlocks { public static final BlockEntry WEIGHTED_EJECTOR = REGISTRATE.block("weighted_ejector", EjectorBlock::new) .initialProperties(SharedProperties::stone) - .properties(Block.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p), 180)) - .transform(StressConfigDefaults.setImpact(2.0)) + .transform(BlockStressDefaults.setImpact(2.0)) .item(EjectorItem::new) .transform(customItemModel()) .register(); public static final BlockEntry CHUTE = REGISTRATE.block("chute", ChuteBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.sound(SoundType.NETHERITE)) - .addLayer(() -> RenderType::getCutoutMipped) + .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) + .addLayer(() -> RenderType::cutoutMipped) .blockstate(new ChuteGenerator()::generate) .item(ChuteItem::new) .transform(customItemModel("_", "block")) @@ -518,7 +541,7 @@ public class AllBlocks { public static final BlockEntry SMART_CHUTE = REGISTRATE.block("smart_chute", SmartChuteBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.sound(SoundType.NETHERITE)) + .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p))) .item() .transform(customItemModel("_", "block")) @@ -526,7 +549,7 @@ public class AllBlocks { public static final BlockEntry SPEEDOMETER = REGISTRATE.block("speedometer", GaugeBlock::speed) .initialProperties(SharedProperties::wooden) - .transform(StressConfigDefaults.setNoImpact()) + .transform(BlockStressDefaults.setNoImpact()) .blockstate(new GaugeGenerator()::generate) .item() .transform(ModelGen.customItemModel("gauge", "_", "item")) @@ -534,7 +557,7 @@ public class AllBlocks { public static final BlockEntry STRESSOMETER = REGISTRATE.block("stressometer", GaugeBlock::stress) .initialProperties(SharedProperties::wooden) - .transform(StressConfigDefaults.setNoImpact()) + .transform(BlockStressDefaults.setNoImpact()) .blockstate(new GaugeGenerator()::generate) .item() .transform(ModelGen.customItemModel("gauge", "_", "item")) @@ -565,30 +588,31 @@ public class AllBlocks { public static final BlockEntry ENCASED_FLUID_PIPE = REGISTRATE.block("encased_fluid_pipe", EncasedPipeBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(Block.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(BlockStateGen.encasedPipe()) .onRegister(CreateRegistrate.connectedTextures(new EncasedCTBehaviour(AllSpriteShifts.COPPER_CASING))) .onRegister(CreateRegistrate.casingConnectivity((block, cc) -> cc.make(block, AllSpriteShifts.COPPER_CASING, - (s, f) -> !s.get(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(f))))) + (s, f) -> !s.getValue(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(f))))) .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) - .loot((p, b) -> p.registerDropping(b, FLUID_PIPE.get())) + .loot((p, b) -> p.dropOther(b, FLUID_PIPE.get())) .register(); public static final BlockEntry GLASS_FLUID_PIPE = REGISTRATE.block("glass_fluid_pipe", GlassFluidPipeBlock::new) .initialProperties(SharedProperties::softMetal) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, s -> p.models() - .getExistingFile(p.modLoc("block/fluid_pipe/window" + (s.get(GlassFluidPipeBlock.ALT) ? "_alt" : ""))))) + .getExistingFile( + p.modLoc("block/fluid_pipe/window" + (s.getValue(GlassFluidPipeBlock.ALT) ? "_alt" : ""))))) .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) - .loot((p, b) -> p.registerDropping(b, FLUID_PIPE.get())) + .loot((p, b) -> p.dropOther(b, FLUID_PIPE.get())) .register(); public static final BlockEntry MECHANICAL_PUMP = REGISTRATE.block("mechanical_pump", PumpBlock::new) .initialProperties(SharedProperties::softMetal) .blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(true)) .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .item() .transform(customItemModel()) .register(); @@ -606,7 +630,7 @@ public class AllBlocks { .initialProperties(SharedProperties::softMetal) .blockstate((c, p) -> BlockStateGen.directionalAxisBlock(c, p, (state, vertical) -> AssetLookup.partialBaseModel(c, p, vertical ? "vertical" : "horizontal", - state.get(FluidValveBlock.ENABLED) ? "open" : "closed"))) + state.getValue(FluidValveBlock.ENABLED) ? "open" : "closed"))) .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) .item() .transform(customItemModel()) @@ -617,31 +641,26 @@ public class AllBlocks { .transform(BuilderTransformers.valveHandle(null)) .register(); - public static final Vector> DYED_VALVE_HANDLES = - new Vector<>(DyeColor.values().length); - - static { - for (DyeColor colour : DyeColor.values()) { - String colourName = colour.getString(); - DYED_VALVE_HANDLES.add(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()); - } - } + public static final DyedBlockList DYED_VALVE_HANDLES = new DyedBlockList<>(colour -> { + String colourName = colour.getSerializedName(); + return REGISTRATE.block(colourName + "_valve_handle", ValveHandleBlock::dyed) + .transform(BuilderTransformers.valveHandle(colour)) + .recipe((c, p) -> ShapedRecipeBuilder.shaped(c.get()) + .pattern("#") + .pattern("-") + .define('#', DyeHelper.getTagOfDye(colour)) + .define('-', AllItemTags.VALVE_HANDLES.tag) + .unlockedBy("has_valve", RegistrateRecipeProvider.hasItem(AllItemTags.VALVE_HANDLES.tag)) + .save(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) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(new FluidTankGenerator()::generate) .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard)) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item(FluidTankItem::new) .model(AssetLookup.customBlockItemModel("_", "block_single_window")) .build() @@ -651,10 +670,10 @@ public class AllBlocks { REGISTRATE.block("creative_fluid_tank", FluidTankBlock::creative) .initialProperties(SharedProperties::softMetal) .tag(AllBlockTags.SAFE_NBT.tag) - .properties(Block.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(new FluidTankGenerator("creative_")::generate) .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::creative)) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item(FluidTankItem::new) .properties(p -> p.rarity(Rarity.EPIC)) .model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/fluid_tank/block_single_window")) @@ -667,14 +686,14 @@ public class AllBlocks { public static final BlockEntry HOSE_PULLEY = REGISTRATE.block("hose_pulley", HosePulleyBlock::new) .initialProperties(SharedProperties::softMetal) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .item() .transform(customItemModel()) .register(); public static final BlockEntry ITEM_DRAIN = REGISTRATE.block("item_drain", ItemDrainBlock::new) .initialProperties(SharedProperties::softMetal) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.standardModel(c, p))) .simpleItem() .register(); @@ -682,8 +701,8 @@ public class AllBlocks { public static final BlockEntry SPOUT = REGISTRATE.block("spout", SpoutBlock::new) .initialProperties(SharedProperties::softMetal) .blockstate((ctx, prov) -> prov.simpleBlock(ctx.getEntry(), AssetLookup.partialBaseModel(ctx, prov))) - .addLayer(() -> RenderType::getCutoutMipped) - .item(BasinOperatorBlockItem::new) + .addLayer(() -> RenderType::cutoutMipped) + .item(AssemblyOperatorBlockItem::new) .transform(customItemModel()) .register(); @@ -720,16 +739,16 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_PISTON_HEAD = REGISTRATE.block("mechanical_piston_head", MechanicalPistonHeadBlock::new) .initialProperties(() -> Blocks.PISTON_HEAD) - .loot((p, b) -> p.registerDropping(b, PISTON_EXTENSION_POLE.get())) + .loot((p, b) -> p.dropOther(b, PISTON_EXTENSION_POLE.get())) .blockstate((c, p) -> BlockStateGen.directionalBlockIgnoresWaterlogged(c, p, state -> p.models() - .getExistingFile(p.modLoc("block/mechanical_piston/" + state.get(MechanicalPistonHeadBlock.TYPE) - .getString() + "/head")))) + .getExistingFile(p.modLoc("block/mechanical_piston/" + state.getValue(MechanicalPistonHeadBlock.TYPE) + .getSerializedName() + "/head")))) .register(); public static final BlockEntry GANTRY_CARRIAGE = REGISTRATE.block("gantry_carriage", GantryCarriageBlock::new) .initialProperties(SharedProperties::stone) - .properties(Block.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(BlockStateGen.directionalAxisBlockProvider()) .item() .transform(customItemModel()) @@ -739,11 +758,11 @@ public class AllBlocks { REGISTRATE.block("gantry_shaft", GantryShaftBlock::new) .initialProperties(SharedProperties::stone) .blockstate((c, p) -> p.directionalBlock(c.get(), s -> { - boolean isPowered = s.get(GantryShaftBlock.POWERED); - boolean isFlipped = s.get(GantryShaftBlock.FACING) + boolean isPowered = s.getValue(GantryShaftBlock.POWERED); + boolean isFlipped = s.getValue(GantryShaftBlock.FACING) .getAxisDirection() == AxisDirection.NEGATIVE; - String partName = s.get(GantryShaftBlock.PART) - .getString(); + String partName = s.getValue(GantryShaftBlock.PART) + .getSerializedName(); String flipped = isFlipped ? "_flipped" : ""; String powered = isPowered ? "_powered" : ""; ModelFile existing = AssetLookup.partialBaseModel(c, p, partName); @@ -761,14 +780,14 @@ public class AllBlocks { public static final BlockEntry WINDMILL_BEARING = REGISTRATE.block("windmill_bearing", WindmillBearingBlock::new) .transform(BuilderTransformers.bearing("windmill", "gearbox", true)) - .transform(StressConfigDefaults.setCapacity(512.0)) + .transform(BlockStressDefaults.setCapacity(512.0)) .tag(AllBlockTags.SAFE_NBT.tag) .register(); public static final BlockEntry MECHANICAL_BEARING = REGISTRATE.block("mechanical_bearing", MechanicalBearingBlock::new) .transform(BuilderTransformers.bearing("mechanical", "gearbox", false)) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .tag(AllBlockTags.SAFE_NBT.tag) .onRegister(addMovementBehaviour(new StabilizedBearingMovementBehaviour())) .register(); @@ -776,7 +795,7 @@ public class AllBlocks { public static final BlockEntry CLOCKWORK_BEARING = REGISTRATE.block("clockwork_bearing", ClockworkBearingBlock::new) .transform(BuilderTransformers.bearing("clockwork", "brass_gearbox", false)) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .tag(AllBlockTags.SAFE_NBT.tag) .register(); @@ -784,15 +803,15 @@ public class AllBlocks { .initialProperties(SharedProperties::stone) .tag(AllBlockTags.SAFE_NBT.tag) .blockstate(BlockStateGen.horizontalAxisBlockProvider(true)) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .item() .transform(customItemModel()) .register(); public static final BlockEntry ROPE = REGISTRATE.block("rope", PulleyBlock.RopeBlock::new) - .initialProperties(SharedProperties.beltMaterial, MaterialColor.BROWN) + .initialProperties(SharedProperties.beltMaterial, MaterialColor.COLOR_BROWN) .tag(AllBlockTags.BRITTLE.tag) - .properties(p -> p.sound(SoundType.CLOTH)) + .properties(p -> p.sound(SoundType.WOOL)) .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() .getExistingFile(p.modLoc("block/rope_pulley/" + c.getName())))) .register(); @@ -808,9 +827,9 @@ public class AllBlocks { public static final BlockEntry CART_ASSEMBLER = REGISTRATE.block("cart_assembler", CartAssemblerBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(BlockStateGen.cartAssembler()) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .tag(BlockTags.RAILS, AllBlockTags.SAFE_NBT.tag) .item(CartAssemblerBlockItem::new) .transform(customItemModel()) @@ -819,9 +838,9 @@ public class AllBlocks { public static final BlockEntry REINFORCED_RAIL = REGISTRATE.block("reinforced_rail", ReinforcedRailBlock::new) .initialProperties(SharedProperties::stone) - .properties(AbstractBlock.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(BlockStateGen.reinforcedRail()) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .tag(BlockTags.RAILS) .item() .model((c, p) -> p.blockItem(() -> c.getEntry() @@ -833,8 +852,8 @@ public class AllBlocks { REGISTRATE.block("controller_rail", ControllerRailBlock::new) .initialProperties(() -> Blocks.POWERED_RAIL) .blockstate(new ControllerRailGenerator()::generate) - .addLayer(() -> RenderType::getCutoutMipped) - .onRegister(CreateRegistrate.blockColors(() -> AllColorHandlers::getRedstonePower)) + .addLayer(() -> RenderType::cutoutMipped) + .color(() -> ColorHandlers::getRedstonePower) .tag(BlockTags.RAILS) .item() .model((c, p) -> p.generated(c, Create.asResource("block/" + c.getName()))) @@ -882,8 +901,8 @@ public class AllBlocks { public static final BlockEntry STICKER = REGISTRATE.block("sticker", StickerBlock::new) .initialProperties(SharedProperties::stone) - .properties(Block.Properties::nonOpaque) - .addLayer(() -> RenderType::getCutoutMipped) + .properties(AbstractBlock.Properties::noOcclusion) + .addLayer(() -> RenderType::cutoutMipped) .blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.forPowered(c, p))) .item() .transform(customItemModel()) @@ -892,7 +911,7 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_DRILL = REGISTRATE.block("mechanical_drill", DrillBlock::new) .initialProperties(SharedProperties::stone) .blockstate(BlockStateGen.directionalBlockProvider(true)) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .onRegister(addMovementBehaviour(new DrillMovementBehaviour())) .item() .transform(customItemModel()) @@ -901,9 +920,9 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_SAW = REGISTRATE.block("mechanical_saw", SawBlock::new) .initialProperties(SharedProperties::stone) .blockstate(new SawGenerator()::generate) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .onRegister(addMovementBehaviour(new SawMovementBehaviour())) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item() .transform(customItemModel()) .register(); @@ -911,9 +930,9 @@ public class AllBlocks { public static final BlockEntry DEPLOYER = REGISTRATE.block("deployer", DeployerBlock::new) .initialProperties(SharedProperties::stone) .blockstate(BlockStateGen.directionalAxisBlockProvider()) - .transform(StressConfigDefaults.setImpact(4.0)) + .transform(BlockStressDefaults.setImpact(4.0)) .onRegister(addMovementBehaviour(new DeployerMovementBehaviour())) - .item() + .item(AssemblyOperatorBlockItem::new) .transform(customItemModel()) .register(); @@ -940,7 +959,7 @@ public class AllBlocks { .initialProperties(SharedProperties::stone) .onRegister(addMovementBehaviour(new HarvesterMovementBehaviour())) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item() .transform(customItemModel()) .register(); @@ -953,87 +972,75 @@ public class AllBlocks { .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() - .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()) - .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()) - .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(); - } - } + public static final DyedBlockList SEATS = new DyedBlockList<>(colour -> { + String colourName = colour.getSerializedName(); + 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.shaped(c.get()) + .pattern("#") + .pattern("-") + .define('#', DyeHelper.getWoolOfDye(colour)) + .define('-', ItemTags.WOODEN_SLABS) + .unlockedBy("has_wool", RegistrateRecipeProvider.hasItem(ItemTags.WOOL)) + .save(p, Create.asResource("crafting/kinetics/" + c.getName())); + ShapedRecipeBuilder.shaped(c.get()) + .pattern("#") + .pattern("-") + .define('#', DyeHelper.getTagOfDye(colour)) + .define('-', AllItemTags.SEATS.tag) + .unlockedBy("has_seat", RegistrateRecipeProvider.hasItem(AllItemTags.SEATS.tag)) + .save(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_seat")); + }) + .onRegisterAfter(Item.class, v -> TooltipHelper.referTo(v, "block.create.brown_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) + .properties(AbstractBlock.Properties::noOcclusion) .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]; - public static final BlockEntry SAIL = REGISTRATE.block("white_sail", p -> SailBlock.withCanvas(p)) .initialProperties(SharedProperties::wooden) - .properties(Block.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .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)) - .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)))) - .tag(AllBlockTags.WINDMILL_SAILS.tag) - .tag(AllBlockTags.SAILS.tag) - .loot((p, b) -> p.registerDropping(b, SAIL.get())) - .register(); + public static final DyedBlockList DYED_SAILS = new DyedBlockList<>(colour -> { + if (colour == DyeColor.WHITE) { + return SAIL; } - } + String colourName = colour.getSerializedName(); + return REGISTRATE.block(colourName + "_sail", p -> SailBlock.withCanvas(p)) + .properties(AbstractBlock.Properties::noOcclusion) + .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)))) + .tag(AllBlockTags.WINDMILL_SAILS.tag) + .tag(AllBlockTags.SAILS.tag) + .loot((p, b) -> p.dropOther(b, SAIL.get())) + .register(); + }); public static final BlockEntry ANDESITE_CASING = REGISTRATE.block("andesite_casing", CasingBlock::new) .transform(BuilderTransformers.casing(AllSpriteShifts.ANDESITE_CASING)) @@ -1056,18 +1063,18 @@ public class AllBlocks { public static final BlockEntry REFINED_RADIANCE_CASING = REGISTRATE.block("refined_radiance_casing", CasingBlock::new) .transform(BuilderTransformers.casing(AllSpriteShifts.REFINED_RADIANCE_CASING)) - .properties(p -> p.luminance($ -> 12)) + .properties(p -> p.lightLevel($ -> 12)) .lang("Radiant Casing") .register(); public static final BlockEntry MECHANICAL_CRAFTER = REGISTRATE.block("mechanical_crafter", MechanicalCrafterBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(AbstractBlock.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .transform(StressConfigDefaults.setImpact(2.0)) + .transform(BlockStressDefaults.setImpact(2.0)) .onRegister(CreateRegistrate.connectedTextures(new CrafterCTBehaviour())) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item() .transform(customItemModel()) .register(); @@ -1076,8 +1083,8 @@ public class AllBlocks { REGISTRATE.block("sequenced_gearshift", SequencedGearshiftBlock::new) .initialProperties(SharedProperties::stone) .tag(AllBlockTags.SAFE_NBT.tag) - .properties(AbstractBlock.Properties::nonOpaque) - .transform(StressConfigDefaults.setNoImpact()) + .properties(AbstractBlock.Properties::noOcclusion) + .transform(BlockStressDefaults.setNoImpact()) .blockstate(new SequencedGearshiftGenerator()::generate) .item() .transform(customItemModel()) @@ -1085,8 +1092,8 @@ public class AllBlocks { public static final BlockEntry FLYWHEEL = REGISTRATE.block("flywheel", FlywheelBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(AbstractBlock.Properties::nonOpaque) - .transform(StressConfigDefaults.setNoImpact()) + .properties(AbstractBlock.Properties::noOcclusion) + .transform(BlockStressDefaults.setNoImpact()) .blockstate(new FlywheelGenerator()::generate) .item() .transform(customItemModel()) @@ -1097,7 +1104,7 @@ public class AllBlocks { .initialProperties(SharedProperties::softMetal) .tag(AllBlockTags.BRITTLE.tag) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .transform(StressConfigDefaults.setCapacity(1024.0)) + .transform(BlockStressDefaults.setCapacity(1024.0)) .item() .transform(customItemModel()) .register(); @@ -1106,7 +1113,7 @@ public class AllBlocks { REGISTRATE.block("rotation_speed_controller", SpeedControllerBlock::new) .initialProperties(SharedProperties::softMetal) .tag(AllBlockTags.SAFE_NBT.tag) - .transform(StressConfigDefaults.setNoImpact()) + .transform(BlockStressDefaults.setNoImpact()) .blockstate(BlockStateGen.horizontalAxisBlockProvider(true)) .item() .transform(customItemModel()) @@ -1123,9 +1130,9 @@ public class AllBlocks { .blockstate((c, p) -> p.getVariantBuilder(c.get()) .forAllStates(s -> ConfiguredModel.builder() .modelFile(AssetLookup.partialBaseModel(c, p)) - .rotationX(s.get(ArmBlock.CEILING) ? 180 : 0) + .rotationX(s.getValue(ArmBlock.CEILING) ? 180 : 0) .build())) - .transform(StressConfigDefaults.setImpact(8.0)) + .transform(BlockStressDefaults.setImpact(2.0)) .item(ArmItem::new) .transform(customItemModel()) .register(); @@ -1146,7 +1153,7 @@ public class AllBlocks { .initialProperties(SharedProperties::stone) .tag(AllBlockTags.SAFE_NBT.tag) .blockstate(new BeltFunnelGenerator("andesite", new ResourceLocation("block/polished_andesite"))::generate) - .loot((p, b) -> p.registerDropping(b, ANDESITE_FUNNEL.get())) + .loot((p, b) -> p.dropOther(b, ANDESITE_FUNNEL.get())) .register(); public static final BlockEntry BRASS_FUNNEL = @@ -1165,7 +1172,7 @@ public class AllBlocks { .initialProperties(SharedProperties::softMetal) .tag(AllBlockTags.SAFE_NBT.tag) .blockstate(new BeltFunnelGenerator("brass", Create.asResource("block/brass_block"))::generate) - .loot((p, b) -> p.registerDropping(b, BRASS_FUNNEL.get())) + .loot((p, b) -> p.dropOther(b, BRASS_FUNNEL.get())) .register(); public static final BlockEntry ANDESITE_TUNNEL = @@ -1206,21 +1213,35 @@ public class AllBlocks { .tag(AllBlockTags.SAFE_NBT.tag) .register(); - public static final BlockEntry NIXIE_TUBE = REGISTRATE.block("nixie_tube", NixieTubeBlock::new) - .initialProperties(SharedProperties::softMetal) - .properties(p -> p.luminance($ -> 5)) - .blockstate(new NixieTubeGenerator()::generate) - .addLayer(() -> RenderType::getTranslucent) - .item() - .transform(customItemModel()) - .register(); + public static final BlockEntry ORANGE_NIXIE_TUBE = + REGISTRATE.block("nixie_tube", p -> new NixieTubeBlock(p, DyeColor.ORANGE)) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.lightLevel($ -> 5)) + .blockstate(new NixieTubeGenerator()::generate) + .addLayer(() -> RenderType::translucent) + .item() + .transform(customItemModel()) + .register(); + + public static final DyedBlockList NIXIE_TUBES = new DyedBlockList<>(colour -> { + if (colour == DyeColor.ORANGE) + return ORANGE_NIXIE_TUBE; + String colourName = colour.getSerializedName(); + return REGISTRATE.block(colourName + "_nixie_tube", p -> new NixieTubeBlock(p, colour)) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.lightLevel($ -> 5)) + .blockstate(new NixieTubeGenerator()::generate) + .loot((p, b) -> p.dropOther(b, ORANGE_NIXIE_TUBE.get())) + .addLayer(() -> RenderType::translucent) + .register(); + }); public static final BlockEntry REDSTONE_LINK = REGISTRATE.block("redstone_link", RedstoneLinkBlock::new) .initialProperties(SharedProperties::wooden) .tag(AllBlockTags.BRITTLE.tag, AllBlockTags.SAFE_NBT.tag) .blockstate(new RedstoneLinkGenerator()::generate) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item() .transform(customItemModel("_", "transmitter")) .register(); @@ -1239,7 +1260,7 @@ public class AllBlocks { REGISTRATE.block("pulse_repeater", PulseRepeaterBlock::new) .initialProperties(() -> Blocks.REPEATER) .blockstate(new PulseRepeaterGenerator()::generate) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item() .transform(customItemModel("diodes", "pulse_repeater")) .register(); @@ -1259,7 +1280,7 @@ public class AllBlocks { .initialProperties(() -> Blocks.REPEATER) .tag(AllBlockTags.SAFE_NBT.tag) .blockstate(new AdjustableRepeaterGenerator()::generate) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item() .model(AbstractDiodeGenerator.diodeItemModel(true)) .build() @@ -1269,7 +1290,7 @@ public class AllBlocks { REGISTRATE.block("powered_latch", PoweredLatchBlock::new) .initialProperties(() -> Blocks.REPEATER) .blockstate(new PoweredLatchGenerator()::generate) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .simpleItem() .register(); @@ -1277,11 +1298,19 @@ public class AllBlocks { REGISTRATE.block("powered_toggle_latch", ToggleLatchBlock::new) .initialProperties(() -> Blocks.REPEATER) .blockstate(new ToggleLatchGenerator()::generate) - .addLayer(() -> RenderType::getCutoutMipped) + .addLayer(() -> RenderType::cutoutMipped) .item() .transform(customItemModel("diodes", "latch_off")) .register(); + public static final BlockEntry LECTERN_CONTROLLER = + REGISTRATE.block("lectern_controller", LecternControllerBlock::new) + .initialProperties(() -> Blocks.LECTERN) + .blockstate((c, p) -> p.horizontalBlock(c.get(), p.models() + .getExistingFile(p.mcLoc("block/lectern")))) + .loot((lt, block) -> lt.dropOther(block, Blocks.LECTERN)) + .register(); + // Curiosities static { @@ -1292,21 +1321,84 @@ public class AllBlocks { REGISTRATE.block("copper_backtank", CopperBacktankBlock::new) .initialProperties(SharedProperties::softMetal) .blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) - .addLayer(() -> RenderType::getCutoutMipped) - .transform(StressConfigDefaults.setImpact(4.0)) + .addLayer(() -> RenderType::cutoutMipped) + .transform(BlockStressDefaults.setImpact(4.0)) .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(AllItems.COPPER_BACKTANK.get()) - .acceptFunction(CopyName.builder(CopyName.Source.BLOCK_ENTITY)) - .acceptFunction(CopyNbt.func_215881_a(CopyNbt.Source.BLOCK_ENTITY) - .func_216056_a("Air", "Air"))))); + Builder builder = LootTable.lootTable(); + IBuilder survivesExplosion = SurvivesExplosion.survivesExplosion(); + lt.add(block, builder.withPool(LootPool.lootPool() + .when(survivesExplosion) + .setRolls(ConstantRange.exactly(1)) + .add(ItemLootEntry.lootTableItem(AllItems.COPPER_BACKTANK.get()) + .apply(CopyName.copyName(CopyName.Source.BLOCK_ENTITY)) + .apply(CopyNbt.copyData(CopyNbt.Source.BLOCK_ENTITY) + .copy("Air", "Air")) + .apply(CopyNbt.copyData(CopyNbt.Source.BLOCK_ENTITY) + .copy("Enchantments", "Enchantments"))))); }) .register(); + public static final BlockEntry PECULIAR_BELL = + REGISTRATE.block("peculiar_bell", PeculiarBellBlock::new) + .transform(BuilderTransformers.bell()) + .onRegister(addMovementBehaviour(new BellMovementBehaviour())) + .register(); + + public static final BlockEntry HAUNTED_BELL = + REGISTRATE.block("haunted_bell", HauntedBellBlock::new) + .transform(BuilderTransformers.bell()) + .onRegister(addMovementBehaviour(new HauntedBellMovementBehaviour())) + .register(); + + public static final DyedBlockList TOOLBOXES = new DyedBlockList<>(colour -> { + String colourName = colour.getSerializedName(); + return REGISTRATE.block(colourName + "_toolbox", p -> new ToolboxBlock(p, colour)) + .initialProperties(SharedProperties::wooden) + .properties(p -> p.sound(SoundType.WOOD)) + .addLayer(() -> RenderType::cutoutMipped) + .loot((lt, block) -> { + Builder builder = LootTable.lootTable(); + IBuilder survivesExplosion = SurvivesExplosion.survivesExplosion(); + lt.add(block, builder.withPool(LootPool.lootPool() + .when(survivesExplosion) + .setRolls(ConstantRange.exactly(1)) + .add(ItemLootEntry.lootTableItem(block) + .apply(CopyName.copyName(CopyName.Source.BLOCK_ENTITY)) + .apply(CopyNbt.copyData(CopyNbt.Source.BLOCK_ENTITY) + .copy("Inventory", "Inventory"))))); + }) + .blockstate((c, p) -> { + p.horizontalBlock(c.get(), p.models() + .withExistingParent(colourName + "_toolbox", p.modLoc("block/toolbox/block")) + .texture("0", p.modLoc("block/toolbox/" + colourName))); + }) + .recipe((c, p) -> { + ShapedRecipeBuilder.shaped(c.get()) + .pattern("#") + .pattern("-") + .define('#', DyeHelper.getTagOfDye(colour)) + .define('-', AllItemTags.TOOLBOXES.tag) + .unlockedBy("has_toolbox", RegistrateRecipeProvider.hasItem(AllItemTags.TOOLBOXES.tag)) + .save(p, Create.asResource("crafting/curiosities/" + c.getName() + "_from_other_toolbox")); + + ShapedRecipeBuilder.shaped(c.get()) + .pattern("#") + .pattern("-") + .define('#', DyeHelper.getTagOfDye(colour)) + .define('-', ToolboxBlock.getMainBox()) + .unlockedBy("has_toolbox", RegistrateRecipeProvider.hasItem(AllItemTags.TOOLBOXES.tag)) + .save(p, Create.asResource("crafting/curiosities/" + c.getName() + "_from_main_toolbox")); + }) + .onRegisterAfter(Item.class, v -> TooltipHelper.referTo(v, "block.create.toolbox")) + .tag(AllBlockTags.TOOLBOXES.tag) + .item() + .model((c, p) -> p.withExistingParent(colourName + "_toolbox", p.modLoc("block/toolbox/item")) + .texture("0", p.modLoc("block/toolbox/" + colourName))) + .tag(AllItemTags.TOOLBOXES.tag) + .build() + .register(); + }); + // Materials static { diff --git a/src/main/java/com/simibubi/create/AllColorHandlers.java b/src/main/java/com/simibubi/create/AllColorHandlers.java deleted file mode 100644 index f8d86596d..000000000 --- a/src/main/java/com/simibubi/create/AllColorHandlers.java +++ /dev/null @@ -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..79e5745f3 100644 --- a/src/main/java/com/simibubi/create/AllContainerTypes.java +++ b/src/main/java/com/simibubi/create/AllContainerTypes.java @@ -1,7 +1,13 @@ package com.simibubi.create; +import com.simibubi.create.content.curiosities.toolbox.ToolboxContainer; +import com.simibubi.create.content.curiosities.toolbox.ToolboxScreen; +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 +16,45 @@ 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); + + public static final ContainerEntry TOOLBOX = + register("toolbox", ToolboxContainer::new, () -> ToolboxScreen::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/AllEnchantments.java b/src/main/java/com/simibubi/create/AllEnchantments.java new file mode 100644 index 000000000..eae8bf6e0 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllEnchantments.java @@ -0,0 +1,32 @@ +package com.simibubi.create; + +import com.simibubi.create.content.curiosities.armor.CapacityEnchantment; +import com.simibubi.create.content.curiosities.weapons.PotatoRecoveryEnchantment; +import com.simibubi.create.foundation.data.CreateRegistrate; +import com.tterrag.registrate.util.entry.RegistryEntry; + +import net.minecraft.enchantment.Enchantment.Rarity; +import net.minecraft.enchantment.EnchantmentType; +import net.minecraft.inventory.EquipmentSlotType; + +public class AllEnchantments { + + private static final CreateRegistrate REGISTRATE = Create.registrate(); + + public static final RegistryEntry POTATO_RECOVERY = REGISTRATE.object("potato_recovery") + .enchantment(EnchantmentType.BOW, PotatoRecoveryEnchantment::new) + .addSlots(EquipmentSlotType.MAINHAND, EquipmentSlotType.OFFHAND) + .lang("Potato Recovery") + .rarity(Rarity.UNCOMMON) + .register(); + + public static final RegistryEntry CAPACITY = REGISTRATE.object("capacity") + .enchantment(EnchantmentType.ARMOR_CHEST, CapacityEnchantment::new) + .addSlots(EquipmentSlotType.CHEST) + .lang("Capacity") + .rarity(Rarity.COMMON) + .register(); + + 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..c67800ab2 100644 --- a/src/main/java/com/simibubi/create/AllEntityTypes.java +++ b/src/main/java/com/simibubi/create/AllEntityTypes.java @@ -7,49 +7,64 @@ 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.content.curiosities.weapons.PotatoProjectileEntity; +import com.simibubi.create.content.curiosities.weapons.PotatoProjectileRenderer; +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.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 POTATO_PROJECTILE = + register("potato_projectile", PotatoProjectileEntity::new, () -> PotatoProjectileRenderer::new, + EntityClassification.MISC, 4, 20, true, false, PotatoProjectileEntity::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() + return (CreateEntityBuilder) Create.registrate() .entity(id, factory, group) .properties(b -> b.setTrackingRange(range) .setUpdateInterval(updateFrequency) @@ -57,18 +72,10 @@ public class AllEntityTypes { .properties(propertyBuilder) .properties(b -> { if (immuneToFire) - b.immuneToFire(); + b.fireImmune(); }) - .register(); + .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..5cc52de55 100644 --- a/src/main/java/com/simibubi/create/AllFluids.java +++ b/src/main/java/com/simibubi/create/AllFluids.java @@ -2,12 +2,13 @@ package com.simibubi.create; import javax.annotation.Nullable; +import com.simibubi.create.AllTags.AllFluidTags; import com.simibubi.create.content.contraptions.fluids.VirtualFluid; 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,50 +26,42 @@ 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 final FluidEntry POTION = + REGISTRATE.virtualFluid("potion", PotionFluidAttributes::new, PotionFluid::new) + .lang(f -> "fluid.create.potion", "Potion") + .register(); + + public static final 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 final FluidEntry HONEY = + REGISTRATE.standardFluid("honey", NoColorFluidAttributes::new) + .lang(f -> "fluid.create.honey", "Honey") + .attributes(b -> b.viscosity(2000) + .density(1400)) + .properties(p -> p.levelDecreasePerBlock(2) + .tickRate(25) + .slopeFindDistance(3) + .explosionResistance(100f)) + .tag(AllFluidTags.HONEY.tag) + .bucket() + .tag(AllTags.forgeItemTag("buckets/honey")) + .build() + .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() - .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() - .properties(p -> p.maxStackSize(1)) - .build() - .register(); + public static final FluidEntry CHOCOLATE = + REGISTRATE.standardFluid("chocolate", NoColorFluidAttributes::new) + .lang(f -> "fluid.create.chocolate", "Chocolate") + .tag(AllTags.forgeFluidTag("chocolate")) + .attributes(b -> b.viscosity(1500) + .density(1400)) + .properties(p -> p.levelDecreasePerBlock(2) + .tickRate(25) + .slopeFindDistance(3) + .explosionResistance(100f)) + .register(); // Load this class @@ -78,20 +71,20 @@ 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()); + RenderTypeLookup.setRenderLayer(fluid, RenderType.translucent()); + RenderTypeLookup.setRenderLayer(fluid.getSource(), RenderType.translucent()); } @Nullable public static BlockState getLavaInteraction(FluidState fluidState) { - Fluid fluid = fluidState.getFluid(); - if (fluid.isEquivalentTo(HONEY.get())) + Fluid fluid = fluidState.getType(); + if (fluid.isSame(HONEY.get())) return fluidState.isSource() ? AllPaletteBlocks.LIMESTONE.getDefaultState() : AllPaletteBlocks.LIMESTONE_VARIANTS.registeredBlocks.get(0) .getDefaultState(); - if (fluid.isEquivalentTo(CHOCOLATE.get())) + if (fluid.isSame(CHOCOLATE.get())) return fluidState.isSource() ? AllPaletteBlocks.SCORIA.getDefaultState() : AllPaletteBlocks.SCORIA_VARIANTS.registeredBlocks.get(0) .getDefaultState(); @@ -114,5 +107,5 @@ public class AllFluids { } } - + } diff --git a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java new file mode 100644 index 000000000..7848d908e --- /dev/null +++ b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java @@ -0,0 +1,66 @@ +package com.simibubi.create; + +import java.util.HashMap; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.content.contraptions.components.deployer.DeployerMovingInteraction; +import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.DoorMovingInteraction; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.LeverMovingInteraction; +import com.simibubi.create.content.contraptions.components.structureMovement.interaction.TrapdoorMovingInteraction; + +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.util.ResourceLocation; + +public class AllInteractionBehaviours { + private static final HashMap> INTERACT_BEHAVIOURS = + new HashMap<>(); + + public static void addInteractionBehaviour(ResourceLocation loc, Supplier behaviour) { + if (INTERACT_BEHAVIOURS.containsKey(loc)) + Create.LOGGER.warn("Interaction behaviour for " + loc.toString() + " was overridden"); + INTERACT_BEHAVIOURS.put(loc, behaviour); + } + + public static void addInteractionBehaviour(Block block, Supplier behaviour) { + addInteractionBehaviour(block.getRegistryName(), behaviour); + } + + @Nullable + public static MovingInteractionBehaviour of(ResourceLocation loc) { + return (INTERACT_BEHAVIOURS.get(loc) == null) ? null + : INTERACT_BEHAVIOURS.get(loc) + .get(); + } + + @Nullable + public static MovingInteractionBehaviour of(Block block) { + return of(block.getRegistryName()); + } + + public static boolean contains(Block block) { + return INTERACT_BEHAVIOURS.containsKey(block.getRegistryName()); + } + + static void register() { + addInteractionBehaviour(Blocks.LEVER.getRegistryName(), LeverMovingInteraction::new); + addInteractionBehaviour(AllBlocks.DEPLOYER.getId(), DeployerMovingInteraction::new); + + // TODO: Scan registry for instanceof (-> modded door support) + + for (Block trapdoor : ImmutableList.of(Blocks.ACACIA_TRAPDOOR, Blocks.OAK_TRAPDOOR, Blocks.DARK_OAK_TRAPDOOR, + Blocks.SPRUCE_TRAPDOOR, Blocks.JUNGLE_TRAPDOOR, Blocks.BIRCH_TRAPDOOR, Blocks.WARPED_TRAPDOOR, + Blocks.CRIMSON_TRAPDOOR)) { + addInteractionBehaviour(trapdoor.getRegistryName(), TrapdoorMovingInteraction::new); + } + + for (Block door : ImmutableList.of(Blocks.ACACIA_DOOR, Blocks.OAK_DOOR, Blocks.DARK_OAK_DOOR, + Blocks.SPRUCE_DOOR, Blocks.JUNGLE_DOOR, Blocks.BIRCH_DOOR, Blocks.WARPED_DOOR, Blocks.CRIMSON_DOOR)) { + addInteractionBehaviour(door.getRegistryName(), DoorMovingInteraction::new); + } + } +} diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index 2d13ad744..90a9e2030 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -3,7 +3,6 @@ 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.content.AllSections.CURIOSITIES; import static com.simibubi.create.content.AllSections.KINETICS; @@ -17,11 +16,12 @@ import com.simibubi.create.content.contraptions.components.structureMovement.mou import com.simibubi.create.content.contraptions.components.structureMovement.train.MinecartCouplingItem; import com.simibubi.create.content.contraptions.goggles.GogglesItem; import com.simibubi.create.content.contraptions.goggles.GogglesModel; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyItem; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlockItem; import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorItem; import com.simibubi.create.content.contraptions.relays.gearbox.VerticalGearboxItem; import com.simibubi.create.content.contraptions.wrench.WrenchItem; -import com.simibubi.create.content.contraptions.wrench.WrenchModel; +import com.simibubi.create.content.contraptions.wrench.WrenchItemRenderer; import com.simibubi.create.content.curiosities.BuildersTeaItem; import com.simibubi.create.content.curiosities.ChromaticCompoundColor; import com.simibubi.create.content.curiosities.ChromaticCompoundItem; @@ -34,13 +34,18 @@ import com.simibubi.create.content.curiosities.armor.CopperBacktankItem; 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.symmetry.client.SymmetryWandItemRenderer; +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.ExtendoGripItemRenderer; import com.simibubi.create.content.curiosities.tools.SandPaperItem; -import com.simibubi.create.content.curiosities.tools.SandPaperItemRenderer.SandPaperModel; +import com.simibubi.create.content.curiosities.tools.SandPaperItemRenderer; +import com.simibubi.create.content.curiosities.weapons.PotatoCannonItem; +import com.simibubi.create.content.curiosities.weapons.PotatoCannonItemRenderer; import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperItem; -import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperModel; +import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperItemRenderer; +import com.simibubi.create.content.logistics.item.LinkedControllerItem; +import com.simibubi.create.content.logistics.item.LinkedControllerItemRenderer; 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 +61,14 @@ 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; +import net.minecraftforge.common.Tags; public class AllItems { private static final CreateRegistrate REGISTRATE = Create.registrate() - .itemGroup(() -> Create.baseCreativeTab); + .itemGroup(() -> Create.BASE_CREATIVE_TAB); // Schematics @@ -73,8 +80,23 @@ public class AllItems { CINDER_FLOUR = ingredient("cinder_flour"), POWDERED_OBSIDIAN = ingredient("powdered_obsidian"), ROSE_QUARTZ = ingredient("rose_quartz"), POLISHED_ROSE_QUARTZ = ingredient("polished_rose_quartz"), PROPELLER = ingredient("propeller"), WHISK = ingredient("whisk"), BRASS_HAND = ingredient("brass_hand"), - CRAFTER_SLOT_COVER = ingredient("crafter_slot_cover"), ELECTRON_TUBE = ingredient("electron_tube"), - INTEGRATED_CIRCUIT = ingredient("integrated_circuit"); + CRAFTER_SLOT_COVER = ingredient("crafter_slot_cover"), ELECTRON_TUBE = ingredient("electron_tube"); + + public static final ItemEntry INCOMPLETE_PRECISION_MECHANISM = + REGISTRATE.item("incomplete_precision_mechanism", SequencedAssemblyItem::new) + .register(); + + public static final ItemEntry PRECISION_MECHANISM = ingredient("precision_mechanism"); + + public static final ItemEntry INCOMPLETE_COGWHEEL = + REGISTRATE.item("incomplete_cogwheel", SequencedAssemblyItem::new) + .model(AssetLookup.existingItemModel()) + .register(); + + public static final ItemEntry INCOMPLETE_LARGE_COGWHEEL = + REGISTRATE.item("incomplete_large_cogwheel", SequencedAssemblyItem::new) + .model(AssetLookup.existingItemModel()) + .register(); public static final ItemEntry BLAZE_CAKE_BASE = REGISTRATE.item("blaze_cake_base", HiddenIngredientItem::new) @@ -83,36 +105,43 @@ public class AllItems { public static final ItemEntry BLAZE_CAKE = REGISTRATE.item("blaze_cake", CombustibleItem::new) .tag(AllItemTags.UPRIGHT_ON_BELT.tag) + .onRegister(i -> i.setBurnTime(6400)) + .register(); + + public static final ItemEntry CREATIVE_BLAZE_CAKE = REGISTRATE.item("creative_blaze_cake", CombustibleItem::new) + .properties(p -> p.rarity(Rarity.EPIC)) + .tag(AllItemTags.UPRIGHT_ON_BELT.tag) + .onRegister(i -> i.setBurnTime(Integer.MAX_VALUE)) .register(); public static final ItemEntry BAR_OF_CHOCOLATE = REGISTRATE.item("bar_of_chocolate", Item::new) - .properties(p -> p.food(new Food.Builder().hunger(6) - .saturation(0.3F) + .properties(p -> p.food(new Food.Builder().nutrition(6) + .saturationMod(0.3F) .build())) .lang("Bar of Chocolate") .register(); public static final ItemEntry SWEET_ROLL = REGISTRATE.item("sweet_roll", Item::new) - .properties(p -> p.food(new Food.Builder().hunger(6) - .saturation(0.8F) + .properties(p -> p.food(new Food.Builder().nutrition(6) + .saturationMod(0.8F) .build())) .register(); public static final ItemEntry CHOCOLATE_BERRIES = REGISTRATE.item("chocolate_glazed_berries", Item::new) - .properties(p -> p.food(new Food.Builder().hunger(7) - .saturation(0.8F) + .properties(p -> p.food(new Food.Builder().nutrition(7) + .saturationMod(0.8F) .build())) .register(); public static final ItemEntry HONEYED_APPLE = REGISTRATE.item("honeyed_apple", Item::new) - .properties(p -> p.food(new Food.Builder().hunger(8) - .saturation(0.8F) + .properties(p -> p.food(new Food.Builder().nutrition(8) + .saturationMod(0.8F) .build())) .register(); public static final ItemEntry BUILDERS_TEA = REGISTRATE.item("builders_tea", BuildersTeaItem::new) .tag(AllItemTags.UPRIGHT_ON_BELT.tag) - .properties(p -> p.maxStackSize(16)) + .properties(p -> p.stacksTo(16)) .lang("Builder's Tea") .register(); @@ -125,7 +154,7 @@ public class AllItems { REGISTRATE.item("chromatic_compound", ChromaticCompoundItem::new) .properties(p -> p.rarity(Rarity.UNCOMMON)) .model(AssetLookup.existingItemModel()) - .onRegister(CreateRegistrate.itemColors(() -> ChromaticCompoundColor::new)) + .color(() -> ChromaticCompoundColor::new) .register(); public static final ItemEntry SHADOW_STEEL = REGISTRATE.item("shadow_steel", ShadowSteelItem::new) @@ -138,18 +167,17 @@ public class AllItems { .register(); public static final ItemEntry COPPER_NUGGET = - taggedIngredient("copper_nugget", forgeItemTag("nuggets/copper"), NUGGETS.tag), - ZINC_NUGGET = taggedIngredient("zinc_nugget", forgeItemTag("nuggets/zinc"), NUGGETS.tag), - BRASS_NUGGET = taggedIngredient("brass_nugget", forgeItemTag("nuggets/brass"), NUGGETS.tag), + taggedIngredient("copper_nugget", forgeItemTag("nuggets/copper"), Tags.Items.NUGGETS), + ZINC_NUGGET = taggedIngredient("zinc_nugget", forgeItemTag("nuggets/zinc"), Tags.Items.NUGGETS), + BRASS_NUGGET = taggedIngredient("brass_nugget", forgeItemTag("nuggets/brass"), Tags.Items.NUGGETS), 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), - LAPIS_SHEET = taggedIngredient("lapis_sheet", forgeItemTag("plates/lapis_lazuli"), PLATES.tag), + GOLDEN_SHEET = taggedIngredient("golden_sheet", forgeItemTag("plates/gold"), PLATES.tag, ItemTags.PIGLIN_LOVED), 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); @@ -182,7 +210,7 @@ public class AllItems { .register(); public static final ItemEntry GOGGLES = REGISTRATE.item("goggles", GogglesItem::new) - .properties(p -> p.maxStackSize(1)) + .properties(p -> p.stacksTo(1)) .onRegister(CreateRegistrate.itemModel(() -> GogglesModel::new)) .lang("Engineer's Goggles") .register(); @@ -194,40 +222,27 @@ public class AllItems { 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)) + .transform(CreateRegistrate.customRenderedItem(() -> SandPaperItemRenderer::new)) + .tag(AllTags.AllItemTags.SANDPAPER.tag) .register(); public static final ItemEntry RED_SAND_PAPER = REGISTRATE.item("red_sand_paper", SandPaperItem::new) - .transform(CreateRegistrate.customRenderedItem(() -> SandPaperModel::new)) + .transform(CreateRegistrate.customRenderedItem(() -> SandPaperItemRenderer::new)) + .tag(AllTags.AllItemTags.SANDPAPER.tag) .onRegister(s -> TooltipHelper.referTo(s, SAND_PAPER)) .register(); public static final ItemEntry WRENCH = REGISTRATE.item("wrench", WrenchItem::new) - .properties(p -> p.maxStackSize(1)) - .transform(CreateRegistrate.customRenderedItem(() -> WrenchModel::new)) + .properties(p -> p.stacksTo(1)) + .transform(CreateRegistrate.customRenderedItem(() -> WrenchItemRenderer::new)) .model(AssetLookup.itemModelWithPartials()) .register(); - public static final ItemEntry EXTENDO_GRIP = REGISTRATE.item("extendo_grip", ExtendoGripItem::new) - .transform(CreateRegistrate.customRenderedItem(() -> ExtendoGripModel::new)) - .model(AssetLookup.itemModelWithPartials()) - .register(); - - public static final ItemEntry WAND_OF_SYMMETRY = - REGISTRATE.item("wand_of_symmetry", SymmetryWandItem::new) - .transform(CreateRegistrate.customRenderedItem(() -> SymmetryWandModel::new)) - .model(AssetLookup.itemModelWithPartials()) - .register(); - - public static final ItemEntry WORLDSHAPER = - REGISTRATE.item("handheld_worldshaper", WorldshaperItem::new) - .properties(p -> p.rarity(Rarity.EPIC)) - .transform(CreateRegistrate.customRenderedItem(() -> WorldshaperModel::new)) - .lang("Creative Worldshaper") - .model(AssetLookup.itemModelWithPartials()) - .register(); - public static final ItemEntry MINECART_CONTRAPTION = REGISTRATE.item("minecart_contraption", MinecartContraptionItem::rideable) .register(); @@ -240,27 +255,45 @@ public class AllItems { REGISTRATE.item("chest_minecart_contraption", MinecartContraptionItem::chest) .register(); - // Logistics - - static { - REGISTRATE.startSection(LOGISTICS); - } - - public static final ItemEntry FILTER = REGISTRATE.item("filter", FilterItem::regular) - .model(AssetLookup.existingItemModel()) - .register(); - - public static final ItemEntry ATTRIBUTE_FILTER = - REGISTRATE.item("attribute_filter", FilterItem::attribute) - .model(AssetLookup.existingItemModel()) - .register(); - // Curiosities static { REGISTRATE.startSection(CURIOSITIES); } + public static final ItemEntry LINKED_CONTROLLER = + REGISTRATE.item("linked_controller", LinkedControllerItem::new) + .properties(p -> p.stacksTo(1)) + .transform(CreateRegistrate.customRenderedItem(() -> LinkedControllerItemRenderer::new)) + .model(AssetLookup.itemModelWithPartials()) + .register(); + + public static final ItemEntry POTATO_CANNON = + REGISTRATE.item("potato_cannon", PotatoCannonItem::new) + .properties(p -> p.stacksTo(1)) + .transform(CreateRegistrate.customRenderedItem(() -> PotatoCannonItemRenderer::new)) + .model(AssetLookup.itemModelWithPartials()) + .register(); + + public static final ItemEntry EXTENDO_GRIP = REGISTRATE.item("extendo_grip", ExtendoGripItem::new) + .transform(CreateRegistrate.customRenderedItem(() -> ExtendoGripItemRenderer::new)) + .model(AssetLookup.itemModelWithPartials()) + .register(); + + public static final ItemEntry WAND_OF_SYMMETRY = + REGISTRATE.item("wand_of_symmetry", SymmetryWandItem::new) + .transform(CreateRegistrate.customRenderedItem(() -> SymmetryWandItemRenderer::new)) + .model(AssetLookup.itemModelWithPartials()) + .register(); + + public static final ItemEntry WORLDSHAPER = + REGISTRATE.item("handheld_worldshaper", WorldshaperItem::new) + .properties(p -> p.rarity(Rarity.EPIC)) + .transform(CreateRegistrate.customRenderedItem(() -> WorldshaperItemRenderer::new)) + .lang("Creative Worldshaper") + .model(AssetLookup.itemModelWithPartials()) + .register(); + public static final ItemEntry COPPER_BACKTANK = @@ -279,6 +312,21 @@ public class AllItems { REGISTRATE.item("tree_fertilizer", TreeFertilizerItem::new) .register(); + // Logistics + + static { + REGISTRATE.startSection(LOGISTICS); + } + + public static final ItemEntry FILTER = REGISTRATE.item("filter", FilterItem::regular) + .model(AssetLookup.existingItemModel()) + .register(); + + public static final ItemEntry ATTRIBUTE_FILTER = + REGISTRATE.item("attribute_filter", FilterItem::attribute) + .model(AssetLookup.existingItemModel()) + .register(); + // Schematics static { @@ -286,16 +334,16 @@ public class AllItems { } public static final ItemEntry EMPTY_SCHEMATIC = REGISTRATE.item("empty_schematic", Item::new) - .properties(p -> p.maxStackSize(1)) + .properties(p -> p.stacksTo(1)) .register(); public static final ItemEntry SCHEMATIC_AND_QUILL = REGISTRATE.item("schematic_and_quill", SchematicAndQuillItem::new) - .properties(p -> p.maxStackSize(1)) + .properties(p -> p.stacksTo(1)) .register(); public static final ItemEntry SCHEMATIC = REGISTRATE.item("schematic", SchematicItem::new) - .properties(p -> p.maxStackSize(1)) + .properties(p -> p.stacksTo(1)) .register(); // Shortcuts @@ -305,11 +353,10 @@ public class AllItems { .register(); } - @SuppressWarnings("unused") - private static ItemEntry hiddenIngredient(String name) { - return REGISTRATE.item(name, HiddenIngredientItem::new) - .register(); - } +// private static ItemEntry hiddenIngredient(String name) { +// return REGISTRATE.item(name, HiddenIngredientItem::new) +// .register(); +// } @SafeVarargs private static ItemEntry taggedIngredient(String name, ITag.INamedTag... tags) { diff --git a/src/main/java/com/simibubi/create/AllKeys.java b/src/main/java/com/simibubi/create/AllKeys.java index d997811b2..e323ba47c 100644 --- a/src/main/java/com/simibubi/create/AllKeys.java +++ b/src/main/java/com/simibubi/create/AllKeys.java @@ -9,7 +9,9 @@ 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), + TOOLBELT("toolbelt", GLFW.GLFW_KEY_LEFT_ALT), ; @@ -41,24 +43,24 @@ public enum AllKeys { public boolean isPressed() { if (!modifiable) return isKeyDown(key); - return keybind.isKeyDown(); + return keybind.isDown(); } public String getBoundKey() { - return keybind.getBoundKeyLocalizedText() + return keybind.getTranslatedKeyMessage() .getString() .toUpperCase(); } public int getBoundCode() { return keybind.getKey() - .getKeyCode(); + .getValue(); } public static boolean isKeyDown(int key) { return GLFW.glfwGetKey(Minecraft.getInstance() .getWindow() - .getHandle(), key) != 0; + .getWindow(), key) != 0; } public static boolean ctrlDown() { 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/AllParticleTypes.java b/src/main/java/com/simibubi/create/AllParticleTypes.java index 03726b2ef..d2ceade86 100644 --- a/src/main/java/com/simibubi/create/AllParticleTypes.java +++ b/src/main/java/com/simibubi/create/AllParticleTypes.java @@ -9,6 +9,8 @@ import com.simibubi.create.content.contraptions.particle.CubeParticleData; import com.simibubi.create.content.contraptions.particle.HeaterParticleData; import com.simibubi.create.content.contraptions.particle.ICustomParticleData; import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData; +import com.simibubi.create.content.curiosities.bell.SoulBaseParticle; +import com.simibubi.create.content.curiosities.bell.SoulParticle; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.client.Minecraft; @@ -31,8 +33,11 @@ public enum AllParticleTypes { CUBE(CubeParticleData::new), FLUID_PARTICLE(FluidParticleData::new), BASIN_FLUID(FluidParticleData::new), - FLUID_DRIP(FluidParticleData::new) - + FLUID_DRIP(FluidParticleData::new), + SOUL(SoulParticle.Data::new), + SOUL_BASE(SoulBaseParticle.Data::new), + SOUL_PERIMETER(SoulParticle.PerimeterData::new), + SOUL_EXPANDING_PERIMETER(SoulParticle.ExpandingPerimeterData::new) ; private ParticleEntry entry; @@ -49,7 +54,7 @@ public enum AllParticleTypes { @OnlyIn(Dist.CLIENT) public static void registerFactories(ParticleFactoryRegisterEvent event) { - ParticleManager particles = Minecraft.getInstance().particles; + ParticleManager particles = Minecraft.getInstance().particleEngine; for (AllParticleTypes particle : values()) particle.entry.registerFactory(particles); } diff --git a/src/main/java/com/simibubi/create/AllRecipeTypes.java b/src/main/java/com/simibubi/create/AllRecipeTypes.java index c21740132..0ec2ecdf3 100644 --- a/src/main/java/com/simibubi/create/AllRecipeTypes.java +++ b/src/main/java/com/simibubi/create/AllRecipeTypes.java @@ -14,13 +14,14 @@ import com.simibubi.create.content.contraptions.components.mixer.MixingRecipe; import com.simibubi.create.content.contraptions.components.press.PressingRecipe; import com.simibubi.create.content.contraptions.components.saw.CuttingRecipe; import com.simibubi.create.content.contraptions.fluids.actors.FillingRecipe; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipeSerializer; import com.simibubi.create.content.contraptions.processing.BasinRecipe; import com.simibubi.create.content.contraptions.processing.EmptyingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeFactory; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeSerializer; import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import net.minecraft.inventory.IInventory; import net.minecraft.item.crafting.IRecipe; @@ -32,73 +33,98 @@ import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import net.minecraftforge.event.RegistryEvent; -public enum AllRecipeTypes { +public enum AllRecipeTypes implements IRecipeTypeInfo { MECHANICAL_CRAFTING(MechanicalCraftingRecipe.Serializer::new), - CONVERSION(processingSerializer(ConversionRecipe::new)), - CRUSHING(processingSerializer(CrushingRecipe::new)), - CUTTING(processingSerializer(CuttingRecipe::new)), - MILLING(processingSerializer(MillingRecipe::new)), - BASIN(processingSerializer(BasinRecipe::new)), - MIXING(processingSerializer(MixingRecipe::new)), - COMPACTING(processingSerializer(CompactingRecipe::new)), - PRESSING(processingSerializer(PressingRecipe::new)), - SANDPAPER_POLISHING(processingSerializer(SandPaperPolishingRecipe::new)), - SPLASHING(processingSerializer(SplashingRecipe::new)), - DEPLOYING(processingSerializer(DeployerApplicationRecipe::new)), - FILLING(processingSerializer(FillingRecipe::new)), - EMPTYING(processingSerializer(EmptyingRecipe::new)), + CONVERSION(ConversionRecipe::new), + CRUSHING(CrushingRecipe::new), + CUTTING(CuttingRecipe::new), + MILLING(MillingRecipe::new), + BASIN(BasinRecipe::new), + MIXING(MixingRecipe::new), + COMPACTING(CompactingRecipe::new), + PRESSING(PressingRecipe::new), + SANDPAPER_POLISHING(SandPaperPolishingRecipe::new), + SPLASHING(SplashingRecipe::new), + DEPLOYING(DeployerApplicationRecipe::new), + FILLING(FillingRecipe::new), + EMPTYING(EmptyingRecipe::new), + SEQUENCED_ASSEMBLY(SequencedAssemblyRecipeSerializer::new), ; - public IRecipeSerializer serializer; - public Supplier> supplier; - public IRecipeType> type; + private ResourceLocation id; + private Supplier> serializerSupplier; + private Supplier> typeSupplier; + private IRecipeSerializer serializer; + private IRecipeType type; - AllRecipeTypes(Supplier> supplier) { - this(supplier, null); + AllRecipeTypes(Supplier> serializerSupplier, Supplier> typeSupplier) { + this.id = Create.asResource(Lang.asId(name())); + this.serializerSupplier = serializerSupplier; + this.typeSupplier = typeSupplier; } - AllRecipeTypes(Supplier> supplier, - IRecipeType> existingType) { - this.supplier = supplier; - this.type = existingType; + AllRecipeTypes(Supplier> serializerSupplier, IRecipeType existingType) { + this(serializerSupplier, () -> existingType); } - public static void register(RegistryEvent.Register> event) { - ShapedRecipe.setCraftingSize(9, 9); - - for (AllRecipeTypes r : AllRecipeTypes.values()) { - if (r.type == null) - r.type = customType(Lang.asId(r.name())); - - r.serializer = r.supplier.get(); - ResourceLocation location = new ResourceLocation(Create.ID, Lang.asId(r.name())); - event.getRegistry() - .register(r.serializer.setRegistryName(location)); - } + AllRecipeTypes(Supplier> serializerSupplier) { + this.id = Create.asResource(Lang.asId(name())); + this.serializerSupplier = serializerSupplier; + this.typeSupplier = () -> simpleType(id); } - private static > IRecipeType customType(String id) { - return Registry.register(Registry.RECIPE_TYPE, new ResourceLocation(Create.ID, id), new IRecipeType() { - public String toString() { - return Create.ID + ":" + id; - } - }); + AllRecipeTypes(ProcessingRecipeFactory processingFactory) { + this(processingSerializer(processingFactory)); } - private static Supplier> processingSerializer( - ProcessingRecipeFactory> factory) { - return () -> new ProcessingRecipeSerializer<>(factory); + @Override + public ResourceLocation getId() { + return id; } @SuppressWarnings("unchecked") + @Override + public > T getSerializer() { + return (T) serializer; + } + + @SuppressWarnings("unchecked") + @Override public > T getType() { return (T) type; } public > Optional find(C inv, World world) { return world.getRecipeManager() - .getRecipe(getType(), inv, world); + .getRecipeFor(getType(), inv, world); } + + public static void register(RegistryEvent.Register> event) { + ShapedRecipe.setCraftingSize(9, 9); + + for (AllRecipeTypes r : AllRecipeTypes.values()) { + r.serializer = r.serializerSupplier.get(); + r.type = r.typeSupplier.get(); + r.serializer.setRegistryName(r.id); + event.getRegistry() + .register(r.serializer); + } + } + + private static Supplier> processingSerializer(ProcessingRecipeFactory factory) { + return () -> new ProcessingRecipeSerializer<>(factory); + } + + public static > IRecipeType simpleType(ResourceLocation id) { + String stringId = id.toString(); + return Registry.register(Registry.RECIPE_TYPE, id, new IRecipeType() { + @Override + public String toString() { + return stringId; + } + }); + } + } diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index 6ffb1c167..09bfd18cc 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -87,6 +87,7 @@ public class AllShapes { .forHorizontal(NORTH), FLUID_VALVE = shape(3, -1, 3, 13, 17, 13).add(2, 2, 2, 14, 14, 14) .forAxis(), + TOOLBOX = shape(1, 0, 4, 15, 9, 12).forHorizontal(NORTH), SMART_FLUID_PIPE_FLOOR = shape(4, 4, 0, 12, 12, 16).add(3, 3, 3, 13, 13, 13) .add(5, 13, 3, 11, 14, 11) .add(5, 14, 4, 11, 15, 10) @@ -108,16 +109,25 @@ public class AllShapes { PUMP = shape(2, 0, 2, 14, 5, 14).add(4, 0, 4, 12, 16, 12) .add(3, 12, 3, 13, 16, 13) .forDirectional(Direction.UP), - CRUSHING_WHEEL_CONTROLLER_COLLISION = shape(0, 0, 0, 16, 13, 16).forDirectional(Direction.DOWN) + CRUSHING_WHEEL_CONTROLLER_COLLISION = shape(0, 0, 0, 16, 13, 16).forDirectional(Direction.DOWN), + + BELL_FLOOR = shape(0, 0, 5, 16, 11, 11).add(3, 1, 3, 13, 13, 13) + .forHorizontal(SOUTH), + BELL_WALL = shape(5, 5, 8, 11, 11, 16).add(3, 1, 3, 13, 13, 13) + .forHorizontal(SOUTH), + BELL_DOUBLE_WALL = shape(5, 5, 0, 11, 11, 16).add(3, 1, 3, 13, 13, 13) + .forHorizontal(SOUTH), + BELL_CEILING = shape(0, 5, 5, 16, 16, 11).add(3, 1, 3, 13, 13, 13) + .forHorizontal(SOUTH) ; // Internally Shared Shapes private static final VoxelShape - PISTON_HEAD = Blocks.PISTON_HEAD.getDefaultState() - .with(DirectionalBlock.FACING, UP) - .with(PistonHeadBlock.SHORT, true) + PISTON_HEAD = Blocks.PISTON_HEAD.defaultBlockState() + .setValue(DirectionalBlock.FACING, UP) + .setValue(PistonHeadBlock.SHORT, true) .getShape(null, null), PISTON_EXTENDED = shape(CASING_12PX.get(UP)).add(FOUR_VOXEL_POLE.get(Axis.Y)) .build(), @@ -151,7 +161,7 @@ public class AllShapes { HEATER_BLOCK_SPECIAL_COLLISION_SHAPE = shape(0, 0, 0, 16, 4, 16).build(), CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 16, 16), SEAT = cuboid(0, 0, 0, 16, 8, 16), SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16), - MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12) + MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.block()).erase(4, 0, 4, 12, 16, 12) .build(), TURNTABLE_SHAPE = shape(1, 4, 1, 15, 8, 15).add(5, 0, 5, 11, 4, 11) .build(), @@ -229,60 +239,60 @@ public class AllShapes { } private static VoxelShape cuboid(double x1, double y1, double z1, double x2, double y2, double z2) { - return Block.makeCuboidShape(x1, y1, z1, x2, y2, z2); + return Block.box(x1, y1, z1, x2, y2, z2); } - private static class Builder { - VoxelShape shape; + public static class Builder { + + private VoxelShape shape; public Builder(VoxelShape shape) { this.shape = shape; } - Builder add(VoxelShape shape) { + public Builder add(VoxelShape shape) { this.shape = VoxelShapes.or(this.shape, shape); return this; } - Builder add(double x1, double y1, double z1, double x2, double y2, double z2) { + public Builder add(double x1, double y1, double z1, double x2, double y2, double z2) { return add(cuboid(x1, y1, z1, x2, y2, z2)); } - Builder erase(double x1, double y1, double z1, double x2, double y2, double z2) { - this.shape = - VoxelShapes.combineAndSimplify(shape, cuboid(x1, y1, z1, x2, y2, z2), IBooleanFunction.ONLY_FIRST); + public Builder erase(double x1, double y1, double z1, double x2, double y2, double z2) { + this.shape = VoxelShapes.join(shape, cuboid(x1, y1, z1, x2, y2, z2), IBooleanFunction.ONLY_FIRST); return this; } - VoxelShape build() { + public VoxelShape build() { return shape; } - VoxelShaper build(BiFunction factory, Direction direction) { + public VoxelShaper build(BiFunction factory, Direction direction) { return factory.apply(shape, direction); } - VoxelShaper build(BiFunction factory, Axis axis) { + public VoxelShaper build(BiFunction factory, Axis axis) { return factory.apply(shape, axis); } - VoxelShaper forDirectional(Direction direction) { + public VoxelShaper forDirectional(Direction direction) { return build(VoxelShaper::forDirectional, direction); } - VoxelShaper forAxis() { + public VoxelShaper forAxis() { return build(VoxelShaper::forAxis, Axis.Y); } - VoxelShaper forHorizontalAxis() { + public VoxelShaper forHorizontalAxis() { return build(VoxelShaper::forHorizontalAxis, Axis.Z); } - VoxelShaper forHorizontal(Direction direction) { + public VoxelShaper forHorizontal(Direction direction) { return build(VoxelShaper::forHorizontal, direction); } - VoxelShaper forDirectional() { + public VoxelShaper forDirectional() { return forDirectional(UP); } diff --git a/src/main/java/com/simibubi/create/AllSoundEvents.java b/src/main/java/com/simibubi/create/AllSoundEvents.java index bec9744d2..0dbe9ba98 100644 --- a/src/main/java/com/simibubi/create/AllSoundEvents.java +++ b/src/main/java/com/simibubi/create/AllSoundEvents.java @@ -10,7 +10,6 @@ import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Pair; @@ -25,6 +24,7 @@ import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.registries.IForgeRegistry; @@ -36,78 +36,78 @@ public class AllSoundEvents { public static final SoundEntry SCHEMATICANNON_LAUNCH_BLOCK = create("schematicannon_launch_block").subtitle("Schematicannon fires") - .playExisting(SoundEvents.ENTITY_GENERIC_EXPLODE, .1f, 1.1f) + .playExisting(SoundEvents.GENERIC_EXPLODE, .1f, 1.1f) .category(SoundCategory.BLOCKS) .build(), SCHEMATICANNON_FINISH = create("schematicannon_finish").subtitle("Schematicannon dings") - .playExisting(SoundEvents.BLOCK_NOTE_BLOCK_BELL, 1, .7f) + .playExisting(SoundEvents.NOTE_BLOCK_BELL, 1, .7f) .category(SoundCategory.BLOCKS) .build(), DEPOT_SLIDE = create("depot_slide").subtitle("Item slides") - .playExisting(SoundEvents.BLOCK_SAND_BREAK, .125f, 1.5f) + .playExisting(SoundEvents.SAND_BREAK, .125f, 1.5f) .category(SoundCategory.BLOCKS) .build(), DEPOT_PLOP = create("depot_plop").subtitle("Item lands") - .playExisting(SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, .25f, 1.25f) + .playExisting(SoundEvents.ITEM_FRAME_ADD_ITEM, .25f, 1.25f) .category(SoundCategory.BLOCKS) .build(), - FUNNEL_FLAP = create("funnel_flap").subtitle("Funnel Flaps") - .playExisting(SoundEvents.ENTITY_ITEM_FRAME_ROTATE_ITEM, .125f, 1.5f) - .playExisting(SoundEvents.BLOCK_WOOL_BREAK, .0425f, .75f) + FUNNEL_FLAP = create("funnel_flap").subtitle("Funnel flaps") + .playExisting(SoundEvents.ITEM_FRAME_ROTATE_ITEM, .125f, 1.5f) + .playExisting(SoundEvents.WOOL_BREAK, .0425f, .75f) .category(SoundCategory.BLOCKS) .build(), SLIME_ADDED = create("slime_added").subtitle("Slime squishes") - .playExisting(SoundEvents.BLOCK_SLIME_BLOCK_PLACE) + .playExisting(SoundEvents.SLIME_BLOCK_PLACE) .category(SoundCategory.BLOCKS) .build(), MECHANICAL_PRESS_ACTIVATION = create("mechanical_press_activation").subtitle("Mechanical Press clangs") - .playExisting(SoundEvents.BLOCK_ANVIL_LAND, .125f, 1f) - .playExisting(SoundEvents.ENTITY_ITEM_BREAK, .5f, 1f) + .playExisting(SoundEvents.ANVIL_LAND, .125f, 1f) + .playExisting(SoundEvents.ITEM_BREAK, .5f, 1f) .category(SoundCategory.BLOCKS) .build(), MECHANICAL_PRESS_ACTIVATION_ON_BELT = create("mechanical_press_activation_belt").subtitle("Mechanical Press bonks") - .playExisting(SoundEvents.BLOCK_WOOL_HIT, .75f, 1f) - .playExisting(SoundEvents.ENTITY_ITEM_BREAK, .15f, .75f) + .playExisting(SoundEvents.WOOL_HIT, .75f, 1f) + .playExisting(SoundEvents.ITEM_BREAK, .15f, .75f) .category(SoundCategory.BLOCKS) .build(), - MIXING = create("mixing").subtitle("Mixing Noises") - .playExisting(SoundEvents.BLOCK_GILDED_BLACKSTONE_BREAK, .125f, .5f) - .playExisting(SoundEvents.BLOCK_NETHERRACK_BREAK, .125f, .5f) + MIXING = create("mixing").subtitle("Mixing noises") + .playExisting(SoundEvents.GILDED_BLACKSTONE_BREAK, .125f, .5f) + .playExisting(SoundEvents.NETHERRACK_BREAK, .125f, .5f) .category(SoundCategory.BLOCKS) .build(), CRANKING = create("cranking").subtitle("Hand Crank turns") - .playExisting(SoundEvents.BLOCK_WOOD_PLACE, .075f, .5f) - .playExisting(SoundEvents.BLOCK_WOODEN_BUTTON_CLICK_OFF, .025f, .5f) + .playExisting(SoundEvents.WOOD_PLACE, .075f, .5f) + .playExisting(SoundEvents.WOODEN_BUTTON_CLICK_OFF, .025f, .5f) .category(SoundCategory.BLOCKS) .build(), WORLDSHAPER_PLACE = create("worldshaper_place").subtitle("Worldshaper zaps") - .playExisting(SoundEvents.BLOCK_NOTE_BLOCK_BASEDRUM) + .playExisting(SoundEvents.NOTE_BLOCK_BASEDRUM) .category(SoundCategory.PLAYERS) .build(), SCROLL_VALUE = create("scroll_value").subtitle("Scroll-input clicks") - .playExisting(SoundEvents.BLOCK_NOTE_BLOCK_HAT, .124f, 1f) + .playExisting(SoundEvents.NOTE_BLOCK_HAT, .124f, 1f) .category(SoundCategory.PLAYERS) .build(), CONFIRM = create("confirm").subtitle("Affirmative ding") - .playExisting(SoundEvents.BLOCK_NOTE_BLOCK_BELL, 0.5f, 0.8f) + .playExisting(SoundEvents.NOTE_BLOCK_BELL, 0.5f, 0.8f) .category(SoundCategory.PLAYERS) .build(), DENY = create("deny").subtitle("Declining boop") - .playExisting(SoundEvents.BLOCK_NOTE_BLOCK_BASS, 1f, 0.5f) + .playExisting(SoundEvents.NOTE_BLOCK_BASS, 1f, 0.5f) .category(SoundCategory.PLAYERS) .build(), @@ -115,51 +115,114 @@ public class AllSoundEvents { .category(SoundCategory.BLOCKS) .build(), + FWOOMP = create("fwoomp").subtitle("Potato Launcher fwoomps") + .category(SoundCategory.PLAYERS) + .build(), + + POTATO_HIT = create("potato_hit").subtitle("Vegetable impacts") + .playExisting(SoundEvents.ITEM_FRAME_BREAK, .75f, .75f) + .playExisting(SoundEvents.WEEPING_VINES_BREAK, .75f, 1.25f) + .category(SoundCategory.PLAYERS) + .build(), + CONTRAPTION_ASSEMBLE = create("contraption_assemble").subtitle("Contraption moves") - .playExisting(SoundEvents.BLOCK_WOODEN_TRAPDOOR_OPEN, .5f, .5f) - .playExisting(SoundEvents.BLOCK_CHEST_OPEN, .045f, .74f) + .playExisting(SoundEvents.WOODEN_TRAPDOOR_OPEN, .5f, .5f) + .playExisting(SoundEvents.CHEST_OPEN, .045f, .74f) .category(SoundCategory.BLOCKS) .build(), CONTRAPTION_DISASSEMBLE = create("contraption_disassemble").subtitle("Contraption stops") - .playExisting(SoundEvents.BLOCK_IRON_TRAPDOOR_CLOSE, .35f, .75f) + .playExisting(SoundEvents.IRON_TRAPDOOR_CLOSE, .35f, .75f) .category(SoundCategory.BLOCKS) .build(), WRENCH_ROTATE = create("wrench_rotate").subtitle("Wrench used") - .playExisting(SoundEvents.BLOCK_WOODEN_TRAPDOOR_CLOSE, .25f, 1.25f) + .playExisting(SoundEvents.WOODEN_TRAPDOOR_CLOSE, .25f, 1.25f) .category(SoundCategory.BLOCKS) .build(), WRENCH_REMOVE = create("wrench_remove").subtitle("Component breaks") - .playExisting(SoundEvents.ENTITY_ITEM_PICKUP, .25f, .75f) - .playExisting(SoundEvents.BLOCK_NETHERITE_BLOCK_HIT, .25f, .75f) + .playExisting(SoundEvents.ITEM_PICKUP, .25f, .75f) + .playExisting(SoundEvents.NETHERITE_BLOCK_HIT, .25f, .75f) .category(SoundCategory.BLOCKS) .build(), CRAFTER_CLICK = create("crafter_click").subtitle("Crafter clicks") - .playExisting(SoundEvents.BLOCK_NETHERITE_BLOCK_HIT, .25f, 1) - .playExisting(SoundEvents.BLOCK_WOODEN_TRAPDOOR_OPEN, .125f, 1) + .playExisting(SoundEvents.NETHERITE_BLOCK_HIT, .25f, 1) + .playExisting(SoundEvents.WOODEN_TRAPDOOR_OPEN, .125f, 1) .category(SoundCategory.BLOCKS) .build(), CRAFTER_CRAFT = create("crafter_craft").subtitle("Crafter crafts") - .playExisting(SoundEvents.ENTITY_ITEM_BREAK, .125f, .75f) + .playExisting(SoundEvents.ITEM_BREAK, .125f, .75f) .category(SoundCategory.BLOCKS) .build(), COPPER_ARMOR_EQUIP = create("copper_armor_equip").subtitle("Diving equipment clinks") - .playExisting(SoundEvents.ITEM_ARMOR_EQUIP_GOLD, 1f, 1f) + .playExisting(SoundEvents.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.ITEM_FRAME_ADD_ITEM, .35f, 1f) + .category(SoundCategory.BLOCKS) + .build(), + + CONTROLLER_PUT = create("controller_put").subtitle("Controller thumps") + .playExisting(SoundEvents.BOOK_PUT, 1f, 1f) + .category(SoundCategory.BLOCKS) + .build(), + + CONTROLLER_TAKE = create("controller_take").subtitle("Lectern empties") + .playExisting(SoundEvents.ITEM_FRAME_REMOVE_ITEM, 1f, 1f) + .category(SoundCategory.BLOCKS) + .build(), + + SAW_ACTIVATE_WOOD = create("saw_activate_wood").subtitle("Mechanical Saw activates") + .playExisting(SoundEvents.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(), + BLAZE_MUNCH = create("blaze_munch").subtitle("Blaze Burner munches") - .playExisting(SoundEvents.ENTITY_GENERIC_EAT, .5f, 1f) + .playExisting(SoundEvents.GENERIC_EAT, .5f, 1f) + .category(SoundCategory.BLOCKS) + .build(), + + CRUSHING_1 = create("crushing_1").subtitle("Crushing noises") + .playExisting(SoundEvents.NETHERRACK_HIT) + .category(SoundCategory.BLOCKS) + .build(), + + CRUSHING_2 = create("crushing_2").noSubtitle() + .playExisting(SoundEvents.GRAVEL_PLACE) + .category(SoundCategory.BLOCKS) + .build(), + + CRUSHING_3 = create("crushing_3").noSubtitle() + .playExisting(SoundEvents.NETHERITE_BLOCK_BREAK) + .category(SoundCategory.BLOCKS) + .build(), + + PECULIAR_BELL_USE = create("peculiar_bell_use").subtitle("Peculiar Bell tolls") + .playExisting(SoundEvents.BELL_BLOCK) + .category(SoundCategory.BLOCKS) + .build(), + + HAUNTED_BELL_CONVERT = create("haunted_bell_convert").subtitle("Haunted Bell awakens") + .category(SoundCategory.BLOCKS) + .build(), + + HAUNTED_BELL_USE = create("haunted_bell_use").subtitle("Haunted Bell tolls") .category(SoundCategory.BLOCKS) .build(); @@ -172,16 +235,17 @@ public class AllSoundEvents { for (SoundEntry entry : entries.values()) entry.register(registry); } - + public static void prepare() { for (SoundEntry entry : entries.values()) entry.prepare(); } - public static JsonElement provideLangEntries() { + public static JsonObject provideLangEntries() { JsonObject object = new JsonObject(); for (SoundEntry entry : entries.values()) - object.addProperty(entry.getSubtitleKey(), entry.getSubtitle()); + if (entry.hasSubtitle()) + object.addProperty(entry.getSubtitleKey(), entry.getSubtitle()); return object; } @@ -196,7 +260,7 @@ public class AllSoundEvents { // return; // if (soundLocation.getPath().contains("_compounded_") // event.setResultSound(); -// +// // } private static class SoundEntryProvider implements IDataProvider { @@ -208,7 +272,7 @@ public class AllSoundEvents { } @Override - public void act(DirectoryCache cache) throws IOException { + public void run(DirectoryCache cache) throws IOException { generate(generator.getOutputFolder(), cache); } @@ -257,6 +321,11 @@ public class AllSoundEvents { this.subtitle = subtitle; return this; } + + public SoundEntryBuilder noSubtitle() { + this.subtitle = null; + return this; + } public SoundEntryBuilder category(SoundCategory category) { this.category = category; @@ -312,6 +381,10 @@ public class AllSoundEvents { public ResourceLocation getLocation() { return Create.asResource(id); } + + public boolean hasSubtitle() { + return subtitle != null; + } public String getSubtitle() { return subtitle; @@ -335,17 +408,25 @@ public class AllSoundEvents { public void playFrom(Entity entity, float volume, float pitch) { if (!entity.isSilent()) - play(entity.world, null, entity.getBlockPos(), volume, pitch); + play(entity.level, null, entity.blockPosition(), volume, pitch); } public void play(World world, PlayerEntity entity, BlockPos pos, float volume, float pitch) { play(world, entity, pos.getX(), pos.getY(), pos.getZ(), volume, pitch); } - abstract void play(World world, PlayerEntity entity, double x, double y, double z, float volume, float pitch); + public void play(World world, PlayerEntity entity, Vector3d pos, float volume, float pitch) { + play(world, entity, pos.x(), pos.y(), pos.z(), volume, pitch); + } + + public abstract void play(World world, PlayerEntity entity, double x, double y, double z, float volume, float pitch); public void playAt(World world, BlockPos pos, float volume, float pitch, boolean fade) { - playAt(world, pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, volume, pitch, fade); + playAt(world, pos.getX() + .5, pos.getY() + .5, pos.getZ() + .5, volume, pitch, fade); + } + + public void playAt(World world, Vector3d pos, float volume, float pitch, boolean fade) { + playAt(world, pos.x(), pos.y(), pos.z(), volume, pitch, fade); } public abstract void playAt(World world, double x, double y, double z, float volume, float pitch, boolean fade); @@ -363,7 +444,7 @@ public class AllSoundEvents { this.wrappedEvents = wrappedEvents; compiledEvents = Lists.newArrayList(); } - + @Override public void prepare() { for (int i = 0; i < wrappedEvents.size(); i++) { @@ -376,7 +457,7 @@ public class AllSoundEvents { @Override public void register(IForgeRegistry registry) { - for (Pair> pair : compiledEvents) + for (Pair> pair : compiledEvents) registry.register(pair.getFirst()); } @@ -398,19 +479,19 @@ public class AllSoundEvents { JsonArray list = new JsonArray(); JsonObject s = new JsonObject(); s.addProperty("name", pair.getFirst() - .getName() + .getLocation() .toString()); s.addProperty("type", "event"); list.add(s); entry.add("sounds", list); - if (i == 0) + if (i == 0 && hasSubtitle()) entry.addProperty("subtitle", getSubtitleKey()); json.add(getIdOf(i), entry); } } @Override - void play(World world, PlayerEntity entity, double x, double y, double z, float volume, float pitch) { + public void play(World world, PlayerEntity entity, double x, double y, double z, float volume, float pitch) { for (Pair> pair : compiledEvents) { Couple volPitch = pair.getSecond(); world.playSound(entity, x, y, z, pair.getFirst(), category, volPitch.getFirst() * volume, @@ -422,7 +503,7 @@ public class AllSoundEvents { public void playAt(World world, double x, double y, double z, float volume, float pitch, boolean fade) { for (Pair> pair : compiledEvents) { Couple volPitch = pair.getSecond(); - world.playSound(x, y, z, pair.getFirst(), category, volPitch.getFirst() * volume, + world.playLocalSound(x, y, z, pair.getFirst(), category, volPitch.getFirst() * volume, volPitch.getSecond() * pitch, fade); } } @@ -435,7 +516,7 @@ public class AllSoundEvents { public CustomSoundEntry(String id, String subtitle, SoundCategory category) { super(id, subtitle, category); } - + @Override public void prepare() { ResourceLocation location = getLocation(); @@ -463,13 +544,13 @@ public class AllSoundEvents { } @Override - void play(World world, PlayerEntity entity, double x, double y, double z, float volume, float pitch) { + public void play(World world, PlayerEntity entity, double x, double y, double z, float volume, float pitch) { world.playSound(entity, x, y, z, event, category, volume, pitch); } @Override public void playAt(World world, double x, double y, double z, float volume, float pitch, boolean fade) { - world.playSound(x, y, z, event, category, volume, pitch, fade); + world.playLocalSound(x, y, z, event, category, volume, pitch, fade); } } diff --git a/src/main/java/com/simibubi/create/AllSpecialTextures.java b/src/main/java/com/simibubi/create/AllSpecialTextures.java index d3b95fe85..4a0117b8f 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"), @@ -21,13 +18,13 @@ public enum AllSpecialTextures { private ResourceLocation location; private AllSpecialTextures(String filename) { - location = new ResourceLocation(Create.ID, ASSET_PATH + filename); + location = Create.asResource(ASSET_PATH + filename); } public void bind() { Minecraft.getInstance() .getTextureManager() - .bindTexture(location); + .bind(location); } public ResourceLocation getLocation() { diff --git a/src/main/java/com/simibubi/create/AllSpriteShifts.java b/src/main/java/com/simibubi/create/AllSpriteShifts.java index 224d852a7..dfae3fdd4 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,15 +78,19 @@ public class AllSpriteShifts { // private static void populateMaps() { - WoodType.stream() - .forEach(woodType -> WOODEN_WINDOWS.put(woodType, vertical("palettes/" + woodType.getName() + "_window"))); + 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.name() + "_window"))); for (PaletteStoneVariants paletteStoneVariants : PaletteStoneVariants.values()) { String variantName = Lang.asId(paletteStoneVariants.name()); 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)); @@ -93,7 +98,7 @@ public class AllSpriteShifts { } for (DyeColor color : DyeColor.values()) { - String id = color.getString(); + String id = color.getSerializedName(); DYED_BELTS.put(color, SpriteShifter.get("block/belt", "block/belt/" + id + "_scroll")); DYED_OFFSET_BELTS.put(color, SpriteShifter.get("block/belt_offset", "block/belt/" + id + "_scroll")); DYED_DIAGONAL_BELTS.put(color, 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..62a7af3ed 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -7,7 +7,6 @@ import static com.simibubi.create.AllTags.NameSpace.TIC; import java.util.function.Function; import com.simibubi.create.foundation.data.CreateRegistrate; -import com.simibubi.create.foundation.utility.EmptyNamedTag; import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.builders.ItemBuilder; @@ -27,77 +26,187 @@ import net.minecraft.tags.FluidTags; import net.minecraft.tags.ITag; import net.minecraft.tags.ItemTags; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.ModList; +import net.minecraftforge.common.Tags; public class AllTags { + private static final CreateRegistrate REGISTRATE = Create.registrate() - .itemGroup(() -> Create.baseCreativeTab); + .itemGroup(() -> Create.BASE_CREATIVE_TAB); + + public static ITag.INamedTag tag(Function> wrapperFactory, String namespace, + String path) { + return wrapperFactory.apply(new ResourceLocation(namespace, path)); + } + + public static ITag.INamedTag forgeTag(Function> wrapperFactory, String path) { + return tag(wrapperFactory, "forge", path); + } + + public static ITag.INamedTag forgeBlockTag(String path) { + return forgeTag(BlockTags::createOptional, path); + } + + public static ITag.INamedTag forgeItemTag(String path) { + return forgeTag(ItemTags::createOptional, path); + } + + public static ITag.INamedTag forgeFluidTag(String path) { + return forgeTag(FluidTags::createOptional, path); + } public static NonNullFunction, ItemBuilder>> tagBlockAndItem( - String tagName) { - return b -> b.tag(forgeBlockTag(tagName)) + String path) { + return b -> b.tag(forgeBlockTag(path)) .item() - .tag(forgeItemTag(tagName)); + .tag(forgeItemTag(path)); } - public static ITag.INamedTag forgeBlockTag(String name) { - return forgeTag(BlockTags::makeWrapperTag, name); - } + public enum NameSpace { - public static ITag.INamedTag forgeItemTag(String name) { - return forgeTag(ItemTags::makeWrapperTag, name); - } - - public static ITag.INamedTag forgeFluidTag(String name) { - return forgeTag(FluidTags::makeWrapperTag, name); - } - - public static ITag.INamedTag forgeTag(Function> wrapperFactory, String name) { - return tag(wrapperFactory, "forge", name); - } - - public static ITag.INamedTag tag(Function> wrapperFactory, String domain, - String name) { - return wrapperFactory.apply(new ResourceLocation(domain, name).toString()); - } - - public static enum NameSpace { - - MOD(Create.ID), FORGE("forge"), MC("minecraft"), TIC("tconstruct") + MOD(Create.ID, false, true), + FORGE("forge"), + TIC("tconstruct") ; - String id; + public final String id; + public final boolean optionalDefault; + public final boolean alwaysDatagenDefault; - private NameSpace(String id) { + NameSpace(String id) { + this(id, true, false); + } + + NameSpace(String id, boolean optionalDefault, boolean alwaysDatagenDefault) { this.id = id; + this.optionalDefault = optionalDefault; + this.alwaysDatagenDefault = alwaysDatagenDefault; } + } - public static enum AllItemTags { - CRUSHED_ORES(MOD), - SEATS(MOD), - VALVE_HANDLES(MOD), - UPRIGHT_ON_BELT(MOD), - CREATE_INGOTS(MOD), - BEACON_PAYMENT(FORGE), - INGOTS(FORGE), - NUGGETS(FORGE), - PLATES(FORGE), - COBBLESTONE(FORGE) + public enum AllBlockTags { + + BRITTLE, + FAN_HEATERS, + FAN_TRANSPARENT, + SAFE_NBT, + SAILS, + SEATS, + TOOLBOXES, + VALVE_HANDLES, + WINDMILL_SAILS, + WINDOWABLE, + WRENCH_PICKUP, + + WG_STONE(FORGE), + + SLIMY_LOGS(TIC), ; - public ITag.INamedTag tag; + public final ITag.INamedTag tag; - private AllItemTags(NameSpace namespace) { - this(namespace, ""); + AllBlockTags() { + this(MOD); } - private AllItemTags(NameSpace namespace, String path) { - tag = ItemTags.makeWrapperTag( - new ResourceLocation(namespace.id, (path.isEmpty() ? "" : path + "/") + Lang.asId(name())).toString()); - REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, prov -> prov.getOrCreateTagBuilder(tag)); + AllBlockTags(NameSpace namespace) { + this(namespace, namespace.optionalDefault, namespace.alwaysDatagenDefault); + } + + AllBlockTags(NameSpace namespace, String path) { + this(namespace, path, namespace.optionalDefault, namespace.alwaysDatagenDefault); + } + + AllBlockTags(NameSpace namespace, boolean optional, boolean alwaysDatagen) { + this(namespace, null, optional, alwaysDatagen); + } + + AllBlockTags(NameSpace namespace, String path, boolean optional, boolean alwaysDatagen) { + ResourceLocation id = new ResourceLocation(namespace.id, path == null ? Lang.asId(name()) : path); + if (optional) { + tag = BlockTags.createOptional(id); + } else { + tag = BlockTags.bind(id.toString()); + } + if (alwaysDatagen) { + REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, prov -> prov.tag(tag)); + } + } + + public boolean matches(Block block) { + return tag.contains(block.getBlock()); + } + + public boolean matches(BlockState state) { + return matches(state.getBlock()); + } + + public void add(Block... values) { + REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, prov -> prov.tag(tag) + .add(values)); + } + + public void includeIn(ITag.INamedTag parent) { + REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, prov -> prov.tag(parent) + .addTag(tag)); + } + + public void includeIn(AllBlockTags parent) { + includeIn(parent.tag); + } + + public void includeAll(ITag.INamedTag child) { + REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, prov -> prov.tag(tag) + .addTag(child)); + } + + } + + public enum AllItemTags { + + CREATE_INGOTS, + CRUSHED_ORES, + SANDPAPER, + SEATS, + TOOLBOXES, + UPRIGHT_ON_BELT, + VALVE_HANDLES, + + BEACON_PAYMENT(FORGE), + PLATES(FORGE) + + ; + + public final ITag.INamedTag tag; + + AllItemTags() { + this(MOD); + } + + AllItemTags(NameSpace namespace) { + this(namespace, namespace.optionalDefault, namespace.alwaysDatagenDefault); + } + + AllItemTags(NameSpace namespace, String path) { + this(namespace, path, namespace.optionalDefault, namespace.alwaysDatagenDefault); + } + + AllItemTags(NameSpace namespace, boolean optional, boolean alwaysDatagen) { + this(namespace, null, optional, alwaysDatagen); + } + + AllItemTags(NameSpace namespace, String path, boolean optional, boolean alwaysDatagen) { + ResourceLocation id = new ResourceLocation(namespace.id, path == null ? Lang.asId(name()) : path); + if (optional) { + tag = ItemTags.createOptional(id); + } else { + tag = ItemTags.bind(id.toString()); + } + if (alwaysDatagen) { + REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, prov -> prov.tag(tag)); + } } public boolean matches(ItemStack stack) { @@ -105,119 +214,119 @@ public class AllTags { } public void add(Item... values) { - REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, prov -> prov.getOrCreateTagBuilder(tag) + REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, prov -> prov.tag(tag) .add(values)); } + public void includeIn(ITag.INamedTag parent) { + REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, prov -> prov.tag(parent) + .addTag(tag)); + } + public void includeIn(AllItemTags parent) { - REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, prov -> prov.getOrCreateTagBuilder(parent.tag) - .addTag(tag)); - } - } - - public static enum AllFluidTags { - NO_INFINITE_DRAINING - - ; - - public ITag.INamedTag tag; - - private AllFluidTags() { - this(MOD, ""); + includeIn(parent.tag); } - private AllFluidTags(NameSpace namespace) { - this(namespace, ""); - } - - private AllFluidTags(NameSpace namespace, String path) { - tag = FluidTags.createOptional( - new ResourceLocation(namespace.id, (path.isEmpty() ? "" : path + "/") + Lang.asId(name()))); - } - - public boolean matches(Fluid fluid) { - return fluid != null && fluid.isIn(tag); - } - - static void loadClass() {} - } - - public static enum AllBlockTags { - WINDMILL_SAILS, - FAN_HEATERS, - WINDOWABLE, - NON_MOVABLE, - BRITTLE, - SEATS, - SAILS, - VALVE_HANDLES, - FAN_TRANSPARENT, - SAFE_NBT, - SLIMY_LOGS(TIC) - - ; - - public ITag.INamedTag tag; - - private AllBlockTags() { - this(MOD, ""); - } - - private AllBlockTags(NameSpace namespace) { - this(namespace, ""); - } - - private AllBlockTags(NameSpace namespace, String path) { - ResourceLocation id = - new ResourceLocation(namespace.id, (path.isEmpty() ? "" : path + "/") + Lang.asId(name())); - if (ModList.get() - .isLoaded(namespace.id)) { - tag = BlockTags.makeWrapperTag(id.toString()); - REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, prov -> prov.getOrCreateTagBuilder(tag)); - } else { - tag = new EmptyNamedTag<>(id); - } - } - - public boolean matches(BlockState block) { - return tag.contains(block.getBlock()); - } - - public void includeIn(AllBlockTags parent) { - REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, prov -> prov.getOrCreateTagBuilder(parent.tag) - .addTag(tag)); - } - - public void includeAll(ITag.INamedTag child) { - REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, prov -> prov.getOrCreateTagBuilder(tag) + public void includeAll(ITag.INamedTag child) { + REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, prov -> prov.tag(tag) .addTag(child)); } - public void add(Block... values) { - REGISTRATE.addDataGenerator(ProviderType.BLOCK_TAGS, prov -> prov.getOrCreateTagBuilder(tag) + } + + public enum AllFluidTags { + + NO_INFINITE_DRAINING(MOD, true, false), + + HONEY(FORGE) + + ; + + public final ITag.INamedTag tag; + + AllFluidTags() { + this(MOD); + } + + AllFluidTags(NameSpace namespace) { + this(namespace, namespace.optionalDefault, namespace.alwaysDatagenDefault); + } + + AllFluidTags(NameSpace namespace, String path) { + this(namespace, path, namespace.optionalDefault, namespace.alwaysDatagenDefault); + } + + AllFluidTags(NameSpace namespace, boolean optional, boolean alwaysDatagen) { + this(namespace, null, optional, alwaysDatagen); + } + + AllFluidTags(NameSpace namespace, String path, boolean optional, boolean alwaysDatagen) { + ResourceLocation id = new ResourceLocation(namespace.id, path == null ? Lang.asId(name()) : path); + if (optional) { + tag = FluidTags.createOptional(id); + } else { + tag = FluidTags.bind(id.toString()); + } + if (alwaysDatagen) { + REGISTRATE.addDataGenerator(ProviderType.FLUID_TAGS, prov -> prov.tag(tag)); + } + } + + public boolean matches(Fluid fluid) { + return fluid != null && fluid.is(tag); + } + + public void add(Fluid... values) { + REGISTRATE.addDataGenerator(ProviderType.FLUID_TAGS, prov -> prov.tag(tag) .add(values)); } + + public void includeIn(ITag.INamedTag parent) { + REGISTRATE.addDataGenerator(ProviderType.FLUID_TAGS, prov -> prov.tag(parent) + .addTag(tag)); + } + + public void includeIn(AllFluidTags parent) { + includeIn(parent.tag); + } + + public void includeAll(ITag.INamedTag child) { + REGISTRATE.addDataGenerator(ProviderType.FLUID_TAGS, prov -> prov.tag(tag) + .addTag(child)); + } + + private static void loadClass() {} + } public static void register() { + AllFluidTags.loadClass(); + AllItemTags.CREATE_INGOTS.includeIn(AllItemTags.BEACON_PAYMENT); - AllItemTags.CREATE_INGOTS.includeIn(AllItemTags.INGOTS); + AllItemTags.CREATE_INGOTS.includeIn(Tags.Items.INGOTS); AllItemTags.UPRIGHT_ON_BELT.add(Items.GLASS_BOTTLE, Items.POTION, Items.SPLASH_POTION, Items.LINGERING_POTION, - Items.HONEY_BOTTLE); + Items.HONEY_BOTTLE, Items.CAKE); 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); - AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS); + AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS, Blocks.CAMPFIRE, Blocks.SOUL_CAMPFIRE); AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE, Blocks.SOUL_FIRE, Blocks.SOUL_CAMPFIRE); AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS); - AllFluidTags.loadClass(); + AllBlockTags.WRENCH_PICKUP.includeAll(BlockTags.RAILS); + AllBlockTags.WRENCH_PICKUP.includeAll(BlockTags.BUTTONS); + AllBlockTags.WRENCH_PICKUP.includeAll(BlockTags.PRESSURE_PLATES); + AllBlockTags.WRENCH_PICKUP.add(Blocks.REDSTONE_WIRE, Blocks.REDSTONE_TORCH, Blocks.REPEATER, Blocks.LEVER, + Blocks.COMPARATOR, Blocks.OBSERVER, Blocks.REDSTONE_WALL_TORCH, Blocks.PISTON, Blocks.STICKY_PISTON, + Blocks.TRIPWIRE, Blocks.TRIPWIRE_HOOK, Blocks.DAYLIGHT_DETECTOR, Blocks.TARGET); } + } diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 329786289..c707584e6 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -1,5 +1,6 @@ package com.simibubi.create; +import com.simibubi.create.content.contraptions.base.CutoutRotatingInstance; import com.simibubi.create.content.contraptions.base.HalfShaftInstance; import com.simibubi.create.content.contraptions.base.HorizontalHalfShaftInstance; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; @@ -119,6 +120,11 @@ 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.bell.BellRenderer; +import com.simibubi.create.content.curiosities.bell.HauntedBellTileEntity; +import com.simibubi.create.content.curiosities.bell.PeculiarBellTileEntity; +import com.simibubi.create.content.curiosities.toolbox.ToolboxRenderer; +import com.simibubi.create.content.curiosities.toolbox.ToolboxTileEntity; 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; @@ -152,12 +158,13 @@ import com.simibubi.create.content.logistics.block.redstone.NixieTubeRenderer; import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity; import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkTileEntity; import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity; +import com.simibubi.create.content.logistics.item.LecternControllerRenderer; +import com.simibubi.create.content.logistics.item.LecternControllerTileEntity; import com.simibubi.create.content.schematics.block.SchematicTableTileEntity; 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 +253,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(); @@ -485,7 +492,7 @@ public class AllTileEntities { public static final TileEntityEntry CRUSHING_WHEEL = Create.registrate() .tileEntity("crushing_wheel", CrushingWheelTileEntity::new) - .instance(() -> SingleRotatingInstance::new) + .instance(() -> CutoutRotatingInstance::new) .validBlocks(AllBlocks.CRUSHING_WHEEL) .renderer(() -> KineticTileEntityRenderer::new) .register(); @@ -499,7 +506,7 @@ public class AllTileEntities { public static final TileEntityEntry WATER_WHEEL = Create.registrate() .tileEntity("water_wheel", WaterWheelTileEntity::new) - .instance(() -> SingleRotatingInstance::new) + .instance(() -> CutoutRotatingInstance::new) .validBlocks(AllBlocks.WATER_WHEEL) .renderer(() -> KineticTileEntityRenderer::new) .register(); @@ -594,7 +601,8 @@ public class AllTileEntities { public static final TileEntityEntry NIXIE_TUBE = Create.registrate() .tileEntity("nixie_tube", NixieTubeTileEntity::new) - .validBlocks(AllBlocks.NIXIE_TUBE) + .validBlocks(AllBlocks.ORANGE_NIXIE_TUBE) + .validBlocks(AllBlocks.NIXIE_TUBES.toArray()) .renderer(() -> NixieTubeRenderer::new) .register(); @@ -657,7 +665,15 @@ public class AllTileEntities { .validBlocks(AllBlocks.ADJUSTABLE_PULSE_REPEATER) .renderer(() -> AdjustableRepeaterRenderer::new) .register(); - + + public static final TileEntityEntry LECTERN_CONTROLLER = + Create.registrate() + .tileEntity("lectern_controller", LecternControllerTileEntity::new) + .validBlocks(AllBlocks.LECTERN_CONTROLLER) + .renderer(() -> LecternControllerRenderer::new) + .register(); + + // Curiosities public static final TileEntityEntry COPPER_BACKTANK = Create.registrate() .tileEntity("copper_backtank", CopperBacktankTileEntity::new) .instance(() -> CopperBacktankInstance::new) @@ -665,5 +681,23 @@ public class AllTileEntities { .renderer(() -> CopperBacktankRenderer::new) .register(); + public static final TileEntityEntry PECULIAR_BELL = Create.registrate() + .tileEntity("peculiar_bell", PeculiarBellTileEntity::new) + .validBlocks(AllBlocks.PECULIAR_BELL) + .renderer(() -> BellRenderer::new) + .register(); + + public static final TileEntityEntry HAUNTED_BELL = Create.registrate() + .tileEntity("cursed_bell", HauntedBellTileEntity::new) + .validBlocks(AllBlocks.HAUNTED_BELL) + .renderer(() -> BellRenderer::new) + .register(); + + public static final TileEntityEntry TOOLBOX = Create.registrate() + .tileEntity("toolbox", ToolboxTileEntity::new) + .validBlocks(AllBlocks.TOOLBOXES.toArray()) + .renderer(() -> ToolboxRenderer::new) + .register(); + public static void register() {} } diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index c62a11acb..24393754d 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -7,9 +7,12 @@ import org.apache.logging.log4j.Logger; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; import com.simibubi.create.content.CreateItemGroup; import com.simibubi.create.content.contraptions.TorquePropagator; +import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineModifiers; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; +import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes; import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; import com.simibubi.create.content.palettes.AllPaletteBlocks; import com.simibubi.create.content.palettes.PalettesItemGroup; @@ -25,13 +28,13 @@ import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.data.LangMerger; import com.simibubi.create.foundation.data.recipe.MechanicalCraftingRecipeGen; import com.simibubi.create.foundation.data.recipe.ProcessingRecipeGen; +import com.simibubi.create.foundation.data.recipe.SequencedAssemblyRecipeGen; import com.simibubi.create.foundation.data.recipe.StandardRecipeGen; import com.simibubi.create.foundation.networking.AllPackets; 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; @@ -40,11 +43,13 @@ import net.minecraft.util.SoundEvent; import net.minecraft.world.gen.feature.Feature; import net.minecraft.world.gen.placement.Placement; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.BiomeLoadingEvent; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.GatherDataEvent; @@ -55,28 +60,32 @@ 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.2e"; - 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() + 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(); + onCtor(); + } + + public static void onCtor() { + ModLoadingContext modLoadingContext = ModLoadingContext.get(); AllSoundEvents.prepare(); AllBlocks.register(); @@ -84,70 +93,76 @@ public class Create { AllFluids.register(); AllTags.register(); AllPaletteBlocks.register(); + AllContainerTypes.register(); AllEntityTypes.register(); AllTileEntities.register(); AllMovementBehaviours.register(); + AllInteractionBehaviours.register(); AllWorldFeatures.register(); + AllEnchantments.register(); + FurnaceEngineModifiers.register(); + AllConfigs.register(modLoadingContext); + BlockSpoutingBehaviour.register(); + + ForgeMod.enableMilkFluid(); + + 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); + modEventBus.addListener(EventPriority.LOWEST, Create::gatherData); - AllConfigs.register(); - random = new Random(); + forgeEventBus.addListener(EventPriority.HIGH, Create::onBiomeLoad); + forgeEventBus.register(CHUNK_UTIL); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.addClientListeners(modEventBus)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus)); } 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); - AllPackets.registerPackets(); - AllTriggers.register(); + SchematicInstances.register(); + BuiltinPotatoProjectileTypes.register(); + + CHUNK_UTIL.init(); event.enqueueWork(() -> { + AllTriggers.register(); SchematicProcessor.register(); AllWorldFeatures.registerFeatures(); }); } + public static void gatherData(GatherDataEvent event) { + DataGenerator gen = event.getGenerator(); + gen.addProvider(new AllAdvancements(gen)); + gen.addProvider(new LangMerger(gen)); + gen.addProvider(AllSoundEvents.provider(gen)); + gen.addProvider(new StandardRecipeGen(gen)); + gen.addProvider(new MechanicalCraftingRecipeGen(gen)); + gen.addProvider(new SequencedAssemblyRecipeGen(gen)); + ProcessingRecipeGen.registerAll(gen); + } + public static void onBiomeLoad(BiomeLoadingEvent event) { AllWorldFeatures.reload(event); } public static CreateRegistrate registrate() { - return registrate.get(); + 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)); - gen.addProvider(new LangMerger(gen)); - gen.addProvider(AllSoundEvents.provider(gen)); - gen.addProvider(new StandardRecipeGen(gen)); - gen.addProvider(new MechanicalCraftingRecipeGen(gen)); - ProcessingRecipeGen.registerAll(gen); - } - } diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 635998c39..e9177402e 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -1,51 +1,36 @@ package com.simibubi.create; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import javax.annotation.Nullable; - import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.contraptions.components.structureMovement.render.SBBContraptionManager; import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivity; import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer; +import com.simibubi.create.content.curiosities.bell.SoulPulseEffectHandler; +import com.simibubi.create.content.curiosities.weapons.PotatoCannonRenderHandler; +import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler; import com.simibubi.create.content.schematics.ClientSchematicLoader; import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler; import com.simibubi.create.content.schematics.client.SchematicHandler; import com.simibubi.create.events.ClientEvents; -import com.simibubi.create.foundation.ResourceReloadHandler; -import com.simibubi.create.foundation.block.render.CustomBlockModels; +import com.simibubi.create.foundation.ClientResourceReloadListener; 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.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.AllMaterialSpecs; +import com.simibubi.create.foundation.render.CreateContexts; 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.ModelSwapper; import com.simibubi.create.foundation.utility.ghost.GhostBlocks; import com.simibubi.create.foundation.utility.outliner.Outliner; -import net.minecraft.block.Block; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BlockModelShapes; -import net.minecraft.client.renderer.model.IBakedModel; -import net.minecraft.client.renderer.model.ModelResourceLocation; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.client.settings.GraphicsFanciness; -import net.minecraft.inventory.container.PlayerContainer; -import net.minecraft.item.Item; import net.minecraft.resources.IReloadableResourceManager; import net.minecraft.resources.IResourceManager; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ChatType; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.StringTextComponent; @@ -53,187 +38,82 @@ 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; -import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.eventbus.api.IEventBus; 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 SuperByteBufferCache BUFFER_CACHE = new SuperByteBufferCache(); + public static final Outliner OUTLINER = new Outliner(); + public static final GhostBlocks GHOST_BLOCKS = new GhostBlocks(); + public static final Screen EMPTY_SCREEN = new Screen(new StringTextComponent("")) {}; + public static final ModelSwapper MODEL_SWAPPER = new ModelSwapper(); + public static final CasingConnectivity CASING_CONNECTIVITY = new CasingConnectivity(); - private static CustomBlockModels customBlockModels; - private static CustomItemModels customItemModels; - private static CustomRenderedItems customRenderedItems; - private static AllColorHandlers colorHandlers; - private static CasingConnectivity casingConnectivity; + 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 void addClientListeners(IEventBus modEventBus) { + public static final ZapperRenderHandler ZAPPER_RENDER_HANDLER = new ZapperRenderHandler(); + public static final PotatoCannonRenderHandler POTATO_CANNON_RENDER_HANDLER = new PotatoCannonRenderHandler(); + public static final SoulPulseEffectHandler SOUL_PULSE_EFFECT_HANDLER = new SoulPulseEffectHandler(); + + public static final ClientResourceReloadListener RESOURCE_RELOAD_LISTENER = new ClientResourceReloadListener(); + + public static void onCtorClient(IEventBus modEventBus, IEventBus forgeEventBus) { modEventBus.addListener(CreateClient::clientInit); - modEventBus.addListener(CreateClient::onModelBake); - modEventBus.addListener(CreateClient::onModelRegistry); - modEventBus.addListener(CreateClient::onTextureStitch); - modEventBus.addListener(AllParticleTypes::registerFactories); modEventBus.addListener(ClientEvents::loadCompleted); + modEventBus.addListener(SpriteShifter::onTextureStitchPre); + modEventBus.addListener(SpriteShifter::onTextureStitchPost); + modEventBus.addListener(AllParticleTypes::registerFactories); + modEventBus.addListener(CreateContexts::flwInit); + modEventBus.addListener(AllMaterialSpecs::flwInit); + modEventBus.addListener(ContraptionRenderDispatcher::gatherContext); - Backend.init(); - OptifineHandler.init(); + MODEL_SWAPPER.registerListeners(modEventBus); + + ZAPPER_RENDER_HANDLER.registerListeners(forgeEventBus); + POTATO_CANNON_RENDER_HANDLER.registerListeners(forgeEventBus); + + Minecraft mc = Minecraft.getInstance(); + + // null during datagen + if (mc == null) return; + + IResourceManager resourceManager = mc.getResourceManager(); + if (resourceManager instanceof IReloadableResourceManager) + ((IReloadableResourceManager) resourceManager).registerReloadListener(RESOURCE_RELOAD_LISTENER); } - 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(); + public static void clientInit(final FMLClientSetupEvent event) { + BUFFER_CACHE.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); + BUFFER_CACHE.registerCompartment(SBBContraptionManager.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.init(); + AllStitchedTextures.init(); + PonderIndex.register(); PonderIndex.registerTags(); UIRenderHelper.init(); - UIRenderHelper.enableStencil(); - IResourceManager resourceManager = Minecraft.getInstance() - .getResourceManager(); - if (resourceManager instanceof IReloadableResourceManager) - ((IReloadableResourceManager) resourceManager).addReloadListener(new ResourceReloadHandler()); - - AllBlockPartials.clientInit(); - event.enqueueWork(() -> { - CopperBacktankArmorLayer.register(); + registerLayerRenderers(Minecraft.getInstance() + .getEntityRenderDispatcher()); }); } - public static void onTextureStitch(TextureStitchEvent.Pre event) { - if (!event.getMap() - .getId() - .equals(PlayerContainer.BLOCK_ATLAS_TEXTURE)) - return; - SpriteShifter.getAllTargetSprites() - .forEach(event::addSprite); - } - - public static void onModelBake(ModelBakeEvent event) { - Map modelRegistry = event.getModelRegistry(); - PartialModel.onModelBake(event); - - getCustomBlockModels() - .foreach((block, modelFunc) -> swapModels(modelRegistry, getAllBlockStateModelLocations(block), modelFunc)); - getCustomItemModels() - .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"); - } - - protected static List getAllBlockStateModelLocations(Block block) { - List models = new ArrayList<>(); - block.getStateContainer() - .getValidStates() - .forEach(state -> { - models.add(getBlockModelLocation(block, BlockModelShapes.getPropertyMapString(state.getValues()))); - }); - return models; - } - - protected static ModelResourceLocation getBlockModelLocation(Block block, String suffix) { - return new ModelResourceLocation(block.getRegistryName(), suffix); - } - - protected static void swapModels(Map modelRegistry, - List locations, Function factory) { - locations.forEach(location -> { - swapModels(modelRegistry, location, factory); - }); - } - - protected static void swapModels(Map modelRegistry, - ModelResourceLocation location, Function factory) { - modelRegistry.put(location, factory.apply(modelRegistry.get(location))); - } - - public static CustomItemModels getCustomItemModels() { - if (customItemModels == null) - customItemModels = new CustomItemModels(); - return customItemModels; - } - - public static CustomRenderedItems getCustomRenderedItems() { - if (customRenderedItems == null) - customRenderedItems = new CustomRenderedItems(); - return customRenderedItems; - } - - public static CustomBlockModels getCustomBlockModels() { - if (customBlockModels == null) - customBlockModels = new CustomBlockModels(); - return customBlockModels; - } - - public static AllColorHandlers getColorHandler() { - if (colorHandlers == null) - colorHandlers = new AllColorHandlers(); - return colorHandlers; - } - - public static CasingConnectivity getCasingConnectivity() { - if (casingConnectivity == null) - casingConnectivity = new CasingConnectivity(); - return casingConnectivity; + protected static void registerLayerRenderers(EntityRendererManager renderManager) { + CopperBacktankArmorLayer.registerOnAll(renderManager); } public static void invalidateRenderers() { - invalidateRenderers(null); - } + BUFFER_CACHE.invalidate(); - public static void invalidateRenderers(@Nullable IWorld world) { - bufferCache.invalidate(); - - if (world != null) { - kineticRenderer.get(world) - .invalidate(); - } else { - kineticRenderer.forEach(InstancedTileRenderer::invalidate); - } - - ContraptionRenderDispatcher.invalidateAll(); + ContraptionRenderDispatcher.reset(); } public static void checkGraphicsFanciness() { @@ -241,21 +121,22 @@ public class CreateClient { if (mc.player == null) return; - if (mc.gameSettings.graphicsMode != GraphicsFanciness.FABULOUS) + if (mc.options.graphicsMode != GraphicsFanciness.FABULOUS) return; if (AllConfigs.CLIENT.ignoreFabulousWarning.get()) return; - IFormattableTextComponent text = TextComponentUtils.bracketed(new StringTextComponent("WARN")) - .formatted(TextFormatting.GOLD) + IFormattableTextComponent text = TextComponentUtils.wrapInSquareBrackets(new StringTextComponent("WARN")) + .withStyle(TextFormatting.GOLD) .append(new StringTextComponent( " Some of Create's visual features will not be available while Fabulous graphics are enabled!")) - .styled(style -> style + .withStyle(style -> style .withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/create dismissFabulousWarning")) .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new StringTextComponent("Click here to disable this warning")))); - mc.ingameGUI.addChatMessage(ChatType.CHAT, text, mc.player.getUniqueID()); + mc.gui.handleChat(ChatType.CHAT, text, mc.player.getUUID()); } + } diff --git a/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java b/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java new file mode 100644 index 000000000..61b11e4fa --- /dev/null +++ b/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java @@ -0,0 +1,52 @@ +package com.simibubi.create.api.behaviour; + +import java.util.HashMap; +import java.util.function.Consumer; + +import com.simibubi.create.Create; +import com.simibubi.create.compat.tconstruct.SpoutCasting; +import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; + +public abstract class BlockSpoutingBehaviour { + + private static final HashMap BLOCK_SPOUTING_BEHAVIOURS = new HashMap<>(); + + public static void addCustomSpoutInteraction(ResourceLocation resourceLocation, + BlockSpoutingBehaviour movementBehaviour) { + BLOCK_SPOUTING_BEHAVIOURS.put(resourceLocation, movementBehaviour); + } + + public static void forEach(Consumer accept) { + BLOCK_SPOUTING_BEHAVIOURS.values() + .forEach(accept); + } + + /** + * While idle, Spouts will call this every tick with simulate == true
+ * When fillBlock returns > 0, the Spout will start its animation cycle
+ *
+ * During this animation cycle, fillBlock is called once again with simulate == false but only on the relevant SpoutingBehaviour
+ * When fillBlock returns > 0 once again, the Spout will drain its content by the returned amount of units
+ * Perform any other side-effects in this method
+ * This method is called server-side only (except in ponder)
+ * + * @param world + * @param pos of the affected block + * @param spout + * @param availableFluid do not modify, return the amount to be subtracted instead + * @param simulate whether the spout is testing or actually performing this behaviour + * @return amount filled into the block, 0 to idle/cancel + */ + public abstract int fillBlock(World world, BlockPos pos, SpoutTileEntity spout, FluidStack availableFluid, + boolean simulate); + + public static void register() { + addCustomSpoutInteraction(Create.asResource("ticon_casting"), new SpoutCasting()); + } + +} diff --git a/src/main/java/com/simibubi/create/api/event/TileEntityBehaviourEvent.java b/src/main/java/com/simibubi/create/api/event/TileEntityBehaviourEvent.java new file mode 100644 index 000000000..03e6e4dc9 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/event/TileEntityBehaviourEvent.java @@ -0,0 +1,56 @@ +package com.simibubi.create.api.event; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; + +import net.minecraft.block.BlockState; +import net.minecraftforge.eventbus.api.GenericEvent; + +/** + * Event that is fired just before a SmartTileEntity is being deserealized
+ * Also if a new one is placed
+ * Use it to attach a new {@link TileEntityBehaviour} or replace existing ones (with caution)
+ *
+ * Actual setup of the behaviours internal workings and data should be done in TileEntityBehaviour#read() and TileEntityBehaviour#initialize() respectively.
+ *
+ * Because of the earlyness of this event, the added behaviours will have access to the initial nbt read (unless the TE was placed, not loaded), thereby allowing tiles to store and retrieve data for injected behaviours + */ +public class TileEntityBehaviourEvent extends GenericEvent { + + private BlockState state; + private T smartTileEntity; + private Map, TileEntityBehaviour> behaviours; + + public TileEntityBehaviourEvent(BlockState state, T tileEntity, + Map, TileEntityBehaviour> behaviours) { + this.state = state; + smartTileEntity = tileEntity; + this.behaviours = behaviours; + } + + @Override + public Type getGenericType() { + return smartTileEntity.getClass(); + } + + public void attach(TileEntityBehaviour behaviour) { + behaviours.put(behaviour.getType(), behaviour); + } + + public TileEntityBehaviour remove(BehaviourType type) { + return behaviours.remove(type); + } + + public T getTileEntity() { + return smartTileEntity; + } + + public BlockState getBlockState() { + return state; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/Mods.java b/src/main/java/com/simibubi/create/compat/Mods.java new file mode 100644 index 000000000..b32960505 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/Mods.java @@ -0,0 +1,41 @@ +package com.simibubi.create.compat; + +import java.util.Optional; +import java.util.function.Supplier; + +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraftforge.fml.ModList; + +/** + * For compatibility with and without another mod present, we have to define load conditions of the specific code + */ +public enum Mods { + DYNAMICTREES, + TCONSTRUCT; + + /** + * @return a boolean of whether the mod is loaded or not based on mod id + */ + public boolean isLoaded() { + return ModList.get().isLoaded(asId()); + } + + /** + * @return the mod id + */ + public String asId() { + return Lang.asId(name()); + } + + /** + * Simple hook to run code if a mod is installed + * @param toRun will be run only if the mod is loaded + * @return Optional.empty() if the mod is not loaded, otherwise an Optional of the return value of the given supplier + */ + public Optional runIfInstalled(Supplier> toRun) { + if (isLoaded()) + return Optional.of(toRun.get().get()); + return Optional.empty(); + } +} diff --git a/src/main/java/com/simibubi/create/compat/dynamictrees/DynamicTree.java b/src/main/java/com/simibubi/create/compat/dynamictrees/DynamicTree.java new file mode 100644 index 000000000..2238c7d76 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/dynamictrees/DynamicTree.java @@ -0,0 +1,63 @@ +package com.simibubi.create.compat.dynamictrees; + +import java.util.function.BiConsumer; + +import javax.annotation.Nullable; + +import com.ferreusveritas.dynamictrees.api.TreeHelper; +import com.ferreusveritas.dynamictrees.blocks.branches.BranchBlock; +import com.ferreusveritas.dynamictrees.blocks.branches.TrunkShellBlock; +import com.ferreusveritas.dynamictrees.util.BranchDestructionData; +import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class DynamicTree extends AbstractBlockBreakQueue { + private BlockPos startCutPos; + + public DynamicTree(BlockPos startCutPos) { + this.startCutPos = startCutPos; + } + + @Override + public void destroyBlocks(World world, ItemStack toDamage, @Nullable PlayerEntity playerEntity, BiConsumer drop) { + BranchBlock start = TreeHelper.getBranch(world.getBlockState(startCutPos)); + if (start == null) //if start is null, it was not a branch + start = setBranchToShellMuse(world, world.getBlockState(startCutPos)); //we check for a trunk shell instead + + if (start == null) //if it is null again, it was neither a branch nor a trunk shell and thus we return + return; + + // Play and render block break sound and particles + world.levelEvent(null, 2001, startCutPos, Block.getId(world.getBlockState(startCutPos))); + // Actually breaks the tree + + BranchDestructionData data = start.destroyBranchFromNode(world, startCutPos, Direction.DOWN, false, playerEntity); + + // Feed all the tree drops to drop bi-consumer + data.leavesDrops.forEach(stackPos -> drop.accept(stackPos.pos.offset(startCutPos), stackPos.stack)); + start.getLogDrops(world, startCutPos, data.species, data.woodVolume).forEach(stack -> drop.accept(startCutPos, stack)); + } + + private BranchBlock setBranchToShellMuse(World world, BlockState state){ + Block block = state.getBlock(); + if (block instanceof TrunkShellBlock){ + TrunkShellBlock.ShellMuse muse = ((TrunkShellBlock)block).getMuse(world, startCutPos); + if (muse != null){ + startCutPos = muse.pos; //the cut pos is moved to the center of the trunk + return TreeHelper.getBranch(muse.state); + } + } + return null; + } + + public static boolean isDynamicBranch(Block block) { + return TreeHelper.isBranch(block) || block instanceof TrunkShellBlock; + } +} 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/ConversionRecipe.java b/src/main/java/com/simibubi/create/compat/jei/ConversionRecipe.java index c6d46653b..a59c356e1 100644 --- a/src/main/java/com/simibubi/create/compat/jei/ConversionRecipe.java +++ b/src/main/java/com/simibubi/create/compat/jei/ConversionRecipe.java @@ -25,7 +25,7 @@ public class ConversionRecipe extends ProcessingRecipe { public static ConversionRecipe create(ItemStack from, ItemStack to) { ResourceLocation recipeId = Create.asResource("conversion_" + counter++); return new ProcessingRecipeBuilder<>(ConversionRecipe::new, recipeId) - .withItemIngredients(Ingredient.fromStacks(from)) + .withItemIngredients(Ingredient.of(from)) .withSingleItemOutput(to) .build(); } 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..39d2c68f7 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; @@ -33,13 +33,17 @@ import com.simibubi.create.compat.jei.category.PolishingCategory; import com.simibubi.create.compat.jei.category.PressingCategory; import com.simibubi.create.compat.jei.category.ProcessingViaFanCategory; import com.simibubi.create.compat.jei.category.SawingCategory; +import com.simibubi.create.compat.jei.category.SequencedAssemblyCategory; import com.simibubi.create.compat.jei.category.SpoutCategory; import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipeManager; import com.simibubi.create.content.contraptions.processing.BasinRecipe; +import com.simibubi.create.content.curiosities.toolbox.ToolboxScreen; +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; @@ -48,13 +52,16 @@ import com.simibubi.create.content.schematics.block.SchematicannonScreen; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.CRecipes; import com.simibubi.create.foundation.config.ConfigBase.ConfigBool; +import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; 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; @@ -72,17 +79,11 @@ import net.minecraftforge.fml.ModList; @SuppressWarnings("unused") public class CreateJEI implements IModPlugin { - private static final ResourceLocation ID = new ResourceLocation(Create.ID, "jei_plugin"); - - @Override - @Nonnull - public ResourceLocation getPluginUid() { - return ID; - } + private static final ResourceLocation ID = Create.asResource("jei_plugin"); 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) @@ -106,7 +107,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(), @@ -115,9 +118,13 @@ public class CreateJEI implements IModPlugin { .catalyst(AllBlocks.BASIN::get) .build(), + seqAssembly = register("sequenced_assembly", SequencedAssemblyCategory::new) + .recipes(AllRecipeTypes.SEQUENCED_ASSEMBLY::getType) + .build(), + autoShapeless = register("automatic_shapeless", MixingCategory::autoShapeless) - .recipes(r -> r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS && r.getIngredients() - .size() > 1 && !MechanicalPressTileEntity.canCompress(r.getIngredients()), + .recipes(r -> r.getSerializer() == IRecipeSerializer.SHAPELESS_RECIPE && r.getIngredients() + .size() > 1 && !MechanicalPressTileEntity.canCompress(r), BasinRecipe::convertShapeless) .catalyst(AllBlocks.MECHANICAL_MIXER::get) .catalyst(AllBlocks.BASIN::get) @@ -142,7 +149,7 @@ public class CreateJEI implements IModPlugin { woodCutting = register("wood_cutting", () -> new BlockCuttingCategory(Items.OAK_STAIRS)) .recipeList(() -> CondensedBlockCuttingRecipe - .condenseRecipes(findRecipesByType(SawTileEntity.woodcuttingRecipeType.getValue()))) + .condenseRecipes(findRecipesByType(SawTileEntity.woodcuttingRecipeType.get()))) .catalyst(AllBlocks.MECHANICAL_SAW::get) .enableWhenBool(c -> c.allowWoodcuttingOnSaw.get() && ModList.get() .isLoaded("druidcraft")) @@ -154,7 +161,7 @@ public class CreateJEI implements IModPlugin { .build(), autoSquare = register("automatic_packing", PackingCategory::autoSquare) - .recipes(r -> (r instanceof ICraftingRecipe) && MechanicalPressTileEntity.canCompress(r.getIngredients()), + .recipes(r -> (r instanceof ICraftingRecipe) && MechanicalPressTileEntity.canCompress(r), BasinRecipe::convertShapeless) .catalyst(AllBlocks.MECHANICAL_PRESS::get) .catalyst(AllBlocks.BASIN::get) @@ -165,9 +172,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.getType()))) .recipes(AllRecipeTypes.DEPLOYING) .catalyst(AllBlocks.DEPLOYER::get) .catalyst(AllBlocks.DEPOT::get) @@ -190,10 +198,10 @@ public class CreateJEI implements IModPlugin { .build(), autoShaped = register("automatic_shaped", MechanicalCraftingCategory::new) - .recipes(r -> r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS && r.getIngredients() + .recipes(r -> r.getSerializer() == IRecipeSerializer.SHAPELESS_RECIPE && r.getIngredients() .size() == 1) .recipes( - r -> (r.getType() == IRecipeType.CRAFTING && r.getType() != AllRecipeTypes.MECHANICAL_CRAFTING.type) + r -> (r.getType() == IRecipeType.CRAFTING && r.getType() != AllRecipeTypes.MECHANICAL_CRAFTING.getType()) && (r instanceof ShapedRecipe)) .catalyst(AllBlocks.MECHANICAL_CRAFTER::get) .enableWhen(c -> c.allowRegularCraftingInCrafter) @@ -202,160 +210,203 @@ public class CreateJEI implements IModPlugin { mechanicalCrafting = register("mechanical_crafting", MechanicalCraftingCategory::new).recipes(AllRecipeTypes.MECHANICAL_CRAFTING) .catalyst(AllBlocks.MECHANICAL_CRAFTER::get) - .build() - - ; + .build(); private > CategoryBuilder register(String name, Supplier> supplier) { return new CategoryBuilder(name, supplier); } + @Override + @Nonnull + public ResourceLocation getPluginUid() { + return ID; + } + + @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.addGuiContainerHandler(ToolboxScreen.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(IRecipeTypeInfo 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() + toAdd = toAdd.stream() .map(converter) .collect(Collectors.toList()); - return list.get(); + 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) { - return Minecraft.getInstance().world.getRecipeManager() + public static List> findRecipes(Predicate> predicate) { + return Minecraft.getInstance().level.getRecipeManager() .getRecipes() .stream() .filter(predicate) .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) + .getItems(); + 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/DoubleItemIcon.java b/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java index 9abd1c945..84ae49721 100644 --- a/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java +++ b/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java @@ -39,26 +39,26 @@ public class DoubleItemIcon implements IDrawable { secondaryStack = secondarySupplier.get(); } - RenderHelper.enable(); + RenderHelper.turnBackOn(); RenderSystem.color4f(1, 1, 1, 1); RenderSystem.enableDepthTest(); - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 0); - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(1, 1, 0); GuiGameElement.of(primaryStack) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(10, 10, 100); matrixStack.scale(.5f, .5f, .5f); GuiGameElement.of(secondaryStack) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); - matrixStack.pop(); + matrixStack.popPose(); RenderSystem.enableBlend(); } 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 51% 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..5732d4bff 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)); + for (int i = 36; i < gui.getMenu().slots.size(); i++) { + 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,19 +50,19 @@ 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; - Slot slot = gui.getContainer().inventorySlots.get(slotIndex + 36); - this.area = new Rectangle2d(gui.getGuiLeft() + slot.xPos, gui.getGuiTop() + slot.yPos, 16, 16); + Slot slot = gui.getMenu().slots.get(slotIndex + 36); + this.area = new Rectangle2d(gui.getGuiLeft() + slot.x, gui.getGuiTop() + slot.y, 16, 16); } @Override @@ -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.getMenu().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/ScreenResourceWrapper.java b/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java index 67e7ce970..a4f2989c5 100644 --- a/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java +++ b/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java @@ -27,7 +27,7 @@ public class ScreenResourceWrapper implements IDrawable { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { resource.bind(); - AbstractGui.drawTexture(matrixStack, xOffset, yOffset, 0, resource.startX, resource.startY, resource.width, + AbstractGui.blit(matrixStack, xOffset, yOffset, 0, resource.startX, resource.startY, resource.width, resource.height, 256, 256); } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java index 32526f37f..ddbec7c2c 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java @@ -6,7 +6,6 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.mutable.MutableInt; -import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; @@ -51,9 +50,9 @@ public class BasinCategory extends CreateRecipeCategory { HeatCondition requiredHeat = recipe.getRequiredHeat(); if (!requiredHeat.testBlazeBurner(HeatLevel.NONE)) - itemIngredients.add(Ingredient.fromItems(AllBlocks.BLAZE_BURNER.get())); + itemIngredients.add(Ingredient.of(AllBlocks.BLAZE_BURNER.get())); if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED)) - itemIngredients.add(Ingredient.fromItems(AllItems.BLAZE_CAKE.get())); + itemIngredients.add(Ingredient.of(AllItems.BLAZE_CAKE.get())); ingredients.setInputIngredients(itemIngredients); ingredients.setInputLists(VanillaTypes.FLUID, recipe.getFluidIngredients() @@ -62,7 +61,7 @@ public class BasinCategory extends CreateRecipeCategory { .collect(Collectors.toList())); if (!recipe.getRollableResults() .isEmpty()) - ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput()); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); if (!recipe.getFluidResults() .isEmpty()) ingredients.setOutputs(VanillaTypes.FLUID, recipe.getFluidResults()); @@ -73,17 +72,10 @@ public class BasinCategory extends CreateRecipeCategory { IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks(); - ItemStack itemOutput = recipe.getRollableResultsAsItemStacks() - .isEmpty() ? ItemStack.EMPTY - : recipe.getRollableResultsAsItemStacks() - .get(0); - FluidStack fluidOutput = recipe.getFluidResults() - .isEmpty() ? FluidStack.EMPTY - : recipe.getFluidResults() - .get(0); - NonNullList fluidIngredients = recipe.getFluidIngredients(); List> ingredients = ItemHelper.condenseIngredients(recipe.getIngredients()); + List itemOutputs = recipe.getRollableResultsAsItemStacks(); + NonNullList fluidOutputs = recipe.getFluidResults(); int size = ingredients.size() + fluidIngredients.size(); int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0; @@ -97,7 +89,7 @@ public class BasinCategory extends CreateRecipeCategory { Ingredient ingredient = pair.getFirst(); MutableInt amount = pair.getSecond(); - for (ItemStack itemStack : ingredient.getMatchingStacks()) { + for (ItemStack itemStack : ingredient.getItems()) { ItemStack stack = itemStack.copy(); stack.setCount(amount.getValue()); stacks.add(stack); @@ -115,28 +107,41 @@ public class BasinCategory extends CreateRecipeCategory { fluidStacks.set(j, withImprovedVisibility(stacks)); } - if (!itemOutput.isEmpty()) { - itemStacks.init(i, false, 141, 50 + yOffset); - itemStacks.set(i, recipe.getRecipeOutput() - .getStack()); - yOffset -= 19; + int outSize = fluidOutputs.size() + recipe.getRollableResults() + .size(); + int outputIndex = 0; + + if (!itemOutputs.isEmpty()) + addStochasticTooltip(itemStacks, recipe.getRollableResults(), i); + + for (; outputIndex < outSize; outputIndex++) { + int xPosition = 141 - (outSize % 2 != 0 && outputIndex == outSize - 1 ? 0 : outputIndex % 2 == 0 ? 10 : -9); + int yPosition = -19 * (outputIndex / 2) + 50 + yOffset; + + if (itemOutputs.size() > outputIndex) { + itemStacks.init(i, false, xPosition, yPosition + yOffset); + itemStacks.set(i, itemOutputs.get(outputIndex)); + i++; + } else { + fluidStacks.init(j, false, xPosition + 1, yPosition + 1 + yOffset); + fluidStacks.set(j, withImprovedVisibility(fluidOutputs.get(outputIndex - itemOutputs.size()))); + j++; + } + } - if (!fluidOutput.isEmpty()) { - fluidStacks.init(j, false, 142, 51 + yOffset); - fluidStacks.set(j, withImprovedVisibility(fluidOutput)); - } - - addFluidTooltip(fluidStacks, fluidIngredients, ImmutableList.of(fluidOutput)); + addFluidTooltip(fluidStacks, fluidIngredients, fluidOutputs); HeatCondition requiredHeat = recipe.getRequiredHeat(); if (!requiredHeat.testBlazeBurner(HeatLevel.NONE)) { - itemStacks.init(++i, true, 133, 80); + itemStacks.init(i, true, 133, 80); itemStacks.set(i, AllBlocks.BLAZE_BURNER.asStack()); + i++; } if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED)) { - itemStacks.init(++i, true, 152, 80); + itemStacks.init(i, true, 152, 80); itemStacks.set(i, AllItems.BLAZE_CAKE.asStack()); + i++; } } @@ -146,6 +151,8 @@ public class BasinCategory extends CreateRecipeCategory { int size = actualIngredients.size() + recipe.getFluidIngredients() .size(); + int outSize = recipe.getFluidResults().size() + recipe.getRollableResults().size(); + int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0; HeatCondition requiredHeat = recipe.getRequiredHeat(); int yOffset = 0; @@ -154,8 +161,13 @@ public class BasinCategory extends CreateRecipeCategory { AllGuiTextures.JEI_SLOT.draw(matrixStack, 16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19 + yOffset); boolean noHeat = requiredHeat == HeatCondition.NONE; - AllGuiTextures.JEI_SLOT.draw(matrixStack, 141, 50 + yOffset); - AllGuiTextures.JEI_DOWN_ARROW.draw(matrixStack, 136, 32 + yOffset); + + int vRows = (1 + outSize) / 2; + for (int i = 0; i < outSize; i++) + AllGuiTextures.JEI_SLOT.draw(matrixStack, + 141 - (outSize % 2 != 0 && i == outSize - 1 ? 0 : i % 2 == 0 ? 10 : -9), -19 * (i / 2) + 50 + yOffset); + if (vRows <= 2) + AllGuiTextures.JEI_DOWN_ARROW.draw(matrixStack, 136, -19 * (vRows - 1) + 32 + yOffset); AllGuiTextures shadow = noHeat ? AllGuiTextures.JEI_SHADOW : AllGuiTextures.JEI_LIGHT; shadow.draw(matrixStack, 81, 58 + (noHeat ? 10 : 30)); @@ -165,7 +177,7 @@ public class BasinCategory extends CreateRecipeCategory { AllGuiTextures heatBar = noHeat ? AllGuiTextures.JEI_NO_HEAT_BAR : AllGuiTextures.JEI_HEAT_BAR; heatBar.draw(matrixStack, 4, 80); - Minecraft.getInstance().fontRenderer.draw(matrixStack, Lang.translate(requiredHeat.getTranslationKey()), 9, + Minecraft.getInstance().font.draw(matrixStack, Lang.translate(requiredHeat.getTranslationKey()), 9, 86, requiredHeat.getColor()); } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java index f1e1817f9..95dd72956 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java @@ -45,7 +45,7 @@ public class BlockCuttingCategory extends CreateRecipeCategory> results = recipe.getCondensedOutputs(); for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { @@ -67,6 +67,7 @@ public class BlockCuttingCategory extends 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; @@ -45,15 +45,10 @@ public abstract class CreateRecipeCategory> implements IRec } public void setCategoryId(String name) { - this.uid = new ResourceLocation(Create.ID, name); + this.uid = Create.asResource(name); this.name = name; } - @Override - public IDrawable getIcon() { - return icon; - } - @Override public ResourceLocation getUid() { return uid; @@ -70,7 +65,12 @@ public abstract class CreateRecipeCategory> implements IRec return background; } - protected static AllGuiTextures getRenderedSlot(IRecipe recipe, int index) { + @Override + public IDrawable getIcon() { + return icon; + } + + public static AllGuiTextures getRenderedSlot(IRecipe recipe, int index) { AllGuiTextures jeiSlot = AllGuiTextures.JEI_SLOT; if (!(recipe instanceof ProcessingRecipe)) return jeiSlot; @@ -85,51 +85,66 @@ public abstract class CreateRecipeCategory> implements IRec return AllGuiTextures.JEI_CHANCE_SLOT; } - protected static IDrawable emptyBackground(int width, int height) { + public static IDrawable emptyBackground(int width, int height) { return new EmptyBackground(width, height); } - protected static IDrawable doubleItemIcon(IItemProvider item1, IItemProvider item2) { + public static IDrawable doubleItemIcon(IItemProvider item1, IItemProvider item2) { return new DoubleItemIcon(() -> new ItemStack(item1), () -> new ItemStack(item2)); } - protected static IDrawable itemIcon(IItemProvider item) { + public static IDrawable itemIcon(IItemProvider item) { return new DoubleItemIcon(() -> new ItemStack(item), () -> ItemStack.EMPTY); } - protected static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List results) { + public static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List results) { + addStochasticTooltip(itemStacks, results, 1); + } + + public static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List results, int startIndex) { itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { if (input) return; - ProcessingOutput output = results.get(slotIndex - 1); + if (slotIndex < startIndex) + return; + ProcessingOutput output = results.get(slotIndex - startIndex); float chance = output.getChance(); if (chance != 1) - tooltip.add(1, Lang.translate("recipe.processing.chance", chance < 0.01 ? "<1" : (int) (chance * 100)).formatted(TextFormatting.GOLD)); + tooltip.add(1, Lang.translate("recipe.processing.chance", chance < 0.01 ? "<1" : (int) (chance * 100)) + .withStyle(TextFormatting.GOLD)); }); } - public List withImprovedVisibility(List stacks) { + public static List withImprovedVisibility(List stacks) { return stacks.stream() - .map(this::withImprovedVisibility) + .map(CreateRecipeCategory::withImprovedVisibility) .collect(Collectors.toList()); } - public FluidStack withImprovedVisibility(FluidStack stack) { + public static FluidStack withImprovedVisibility(FluidStack stack) { FluidStack display = stack.copy(); int displayedAmount = (int) (stack.getAmount() * .75f) + 250; display.setAmount(displayedAmount); return display; } - protected static void addFluidTooltip(IGuiFluidStackGroup fluidStacks, List inputs, + public static void addFluidTooltip(IGuiFluidStackGroup fluidStacks, List inputs, List outputs) { + addFluidTooltip(fluidStacks, inputs, outputs, -1); + } + + public static void addFluidTooltip(IGuiFluidStackGroup fluidStacks, List inputs, + List outputs, int index) { List amounts = new ArrayList<>(); inputs.forEach(f -> amounts.add(f.getRequiredAmount())); outputs.forEach(f -> amounts.add(f.getAmount())); fluidStacks.addTooltipCallback((slotIndex, input, fluid, tooltip) -> { + if (index != -1 && slotIndex != index) + return; + if (fluid.getFluid() - .isEquivalentTo(AllFluids.POTION.get())) { + .isSame(AllFluids.POTION.get())) { ITextComponent name = fluid.getDisplayName(); if (tooltip.isEmpty()) tooltip.add(0, name); @@ -142,12 +157,13 @@ public abstract class CreateRecipeCategory> implements IRec .collect(Collectors.toList())); } - int amount = amounts.get(slotIndex); - ITextComponent text = (Lang.translate("generic.unit.millibuckets", amount)).formatted(TextFormatting.GOLD); + int amount = amounts.get(index != -1 ? 0 : slotIndex); + ITextComponent text = (Lang.translate("generic.unit.millibuckets", amount)).withStyle(TextFormatting.GOLD); if (tooltip.isEmpty()) tooltip.add(0, text); else { - List siblings = tooltip.get(0).getSiblings(); + List siblings = tooltip.get(0) + .getSiblings(); siblings.add(new StringTextComponent(" ")); siblings.add(text); } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java index 6d8fab965..794b43cfd 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java @@ -41,7 +41,7 @@ public class CrushingCategory extends CreateRecipeCategory results = recipe.getRollableResults(); int size = results.size(); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java index 28b14c1cc..4e88e2ca2 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java @@ -9,11 +9,13 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer; import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.utility.Lang; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.ingredients.IIngredients; +import net.minecraft.util.text.TextFormatting; public class DeployingCategory extends CreateRecipeCategory { @@ -39,20 +41,33 @@ public class DeployingCategory extends CreateRecipeCategory { + if (!input) + return; + if (slotIndex != 1) + return; + tooltip.add(1, Lang.translate("recipe.deploying.not_consumed") + .withStyle(TextFormatting.GOLD)); + }); + } + + addStochasticTooltip(itemStacks, recipe.getRollableResults(), 2); } @Override diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanBlastingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanBlastingCategory.java index f127d75c3..74ddd52f5 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/FanBlastingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanBlastingCategory.java @@ -21,14 +21,14 @@ public class FanBlastingCategory extends ProcessingViaFanCategory @Override public void renderAttachedBlock(MatrixStack matrixStack) { - - GuiGameElement.of(Blocks.FIRE.getDefaultState()) + GuiGameElement.of(Blocks.FIRE.defaultBlockState()) .scale(24) .atLocal(0, 0, 2) .render(matrixStack); - } -} \ No newline at end of file + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java index 8af3d75af..939071a61 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java @@ -40,7 +40,7 @@ public class FanWashingCategory extends ProcessingViaFanCategory results = recipe.getRollableResults(); boolean single = results.size() == 1; @@ -49,7 +49,7 @@ public class FanWashingCategory extends ProcessingViaFanCategory 9 ? 8 : 0); - getRenderedSlot(recipe, i).draw(matrixStack, 121 + xOffset, 47 + yOffset); + getRenderedSlot(recipe, i).draw(matrixStack, 126 + xOffset, 47 + yOffset); } } @Override protected void translateFan(MatrixStack ms) { - ms.translate(43, 33, 0); + ms.translate(56 + 4, 33, 0); } @Override public void renderAttachedBlock(MatrixStack matrixStack) { - matrixStack.push(); + matrixStack.pushPose(); GuiGameElement.of(Fluids.WATER) .scale(24) .atLocal(0, 0, 2) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java index ba8f9042f..1bdfc8037 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java @@ -49,7 +49,7 @@ public class ItemDrainCategory extends CreateRecipeCategory { .forEach(stack -> { if (stack.getItem() instanceof PotionItem) { FluidStack fluidFromPotionItem = PotionFluidHandler.getFluidFromPotionItem(stack); - Ingredient potion = Ingredient.fromStacks(stack); + Ingredient potion = Ingredient.of(stack); recipes.add(new ProcessingRecipeBuilder<>(EmptyingRecipe::new, Create.asResource("potions")) .withItemIngredients(potion) .withFluidOutputs(fluidFromPotionItem) @@ -70,8 +70,10 @@ public class ItemDrainCategory extends CreateRecipeCategory { ItemStack result = handler.getContainer(); if (extracted.isEmpty()) return; + if (result.isEmpty()) + return; - Ingredient ingredient = Ingredient.fromStacks(stack); + Ingredient ingredient = Ingredient.of(stack); ResourceLocation itemName = stack.getItem() .getRegistryName(); ResourceLocation fluidName = extracted.getFluid() @@ -99,7 +101,7 @@ public class ItemDrainCategory extends CreateRecipeCategory { if (!recipe.getRollableResults() .isEmpty()) - ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput()); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); if (!recipe.getFluidResults() .isEmpty()) ingredients.setOutputs(VanillaTypes.FLUID, recipe.getFluidResults()); @@ -112,14 +114,14 @@ public class ItemDrainCategory extends CreateRecipeCategory { FluidStack fluidOutput = recipe.getResultingFluid(); List matchingIngredients = Arrays.asList(recipe.getIngredients() .get(0) - .getMatchingStacks()); + .getItems()); fluidStacks.init(0, true, 132, 8); fluidStacks.set(0, withImprovedVisibility(fluidOutput)); itemStacks.init(0, true, 26, 7); itemStacks.set(0, matchingIngredients); itemStacks.init(1, false, 131, 26); - itemStacks.set(1, recipe.getRecipeOutput()); + itemStacks.set(1, recipe.getResultItem()); addFluidTooltip(fluidStacks, Collections.emptyList(), ImmutableList.of(fluidOutput)); } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java index 86febc77d..545184839 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java @@ -41,7 +41,7 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory recipeIngredients = recipe.getIngredients(); itemStacks.init(0, false, 133, 80); - itemStacks.set(0, recipe.getRecipeOutput() + itemStacks.set(0, recipe.getResultItem() .getStack()); int x = getXPadding(recipe); @@ -66,7 +66,7 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory list = new ArrayList<>(); TranslationTextComponent crash = new TranslationTextComponent("jei.tooltip.error.crash"); - list.add(crash.formatted(TextFormatting.RED)); + list.add(crash.withStyle(TextFormatting.RED)); return list; } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java index ddd53ff55..fda2f0e9b 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java @@ -41,7 +41,7 @@ public class MillingCategory extends CreateRecipeCategory results = recipe.getRollableResults(); boolean single = results.size() == 1; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MysteriousItemConversionCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MysteriousItemConversionCategory.java index 621bc3594..86332537c 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MysteriousItemConversionCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MysteriousItemConversionCategory.java @@ -23,9 +23,10 @@ public class MysteriousItemConversionCategory extends CreateRecipeCategory results = recipe.getRollableResults(); itemStacks.init(0, true, 26, 16); - itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); + itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getItems())); itemStacks.init(1, false, 131, 16); itemStacks.set(1, results.get(0).getStack()); } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java index 2dcdce197..dac7c0e38 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java @@ -4,8 +4,10 @@ import java.util.Arrays; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; +import com.simibubi.create.compat.jei.category.animations.AnimatedBlazeBurner; import com.simibubi.create.compat.jei.category.animations.AnimatedPress; import com.simibubi.create.content.contraptions.processing.BasinRecipe; +import com.simibubi.create.content.contraptions.processing.HeatCondition; import com.simibubi.create.foundation.gui.AllGuiTextures; import mezz.jei.api.gui.IRecipeLayout; @@ -19,6 +21,7 @@ import net.minecraft.util.NonNullList; public class PackingCategory extends BasinCategory { private AnimatedPress press = new AnimatedPress(true); + private final AnimatedBlazeBurner heater = new AnimatedBlazeBurner(); private PackingType type; enum PackingType { @@ -55,12 +58,12 @@ public class PackingCategory extends BasinCategory { while (i < size) { Ingredient ingredient = ingredients2.get(i); itemStacks.init(i, true, (rows == 2 ? 26 : 17) + (i % rows) * 19, 50 - (i / rows) * 19); - itemStacks.set(i, Arrays.asList(ingredient.getMatchingStacks())); + itemStacks.set(i, Arrays.asList(ingredient.getItems())); i++; } itemStacks.init(i, false, 141, 50); - itemStacks.set(i, recipe.getRecipeOutput()); + itemStacks.set(i, recipe.getResultItem()); } @Override @@ -80,7 +83,11 @@ public class PackingCategory extends BasinCategory { AllGuiTextures.JEI_SHADOW.draw(matrixStack, 81, 68); } - press.draw(matrixStack, getBackground().getWidth() / 2 + 6, 40); + HeatCondition requiredHeat = recipe.getRequiredHeat(); + if (requiredHeat != HeatCondition.NONE) + heater.withHeat(requiredHeat.visualizeAsBlazeBurner()) + .draw(matrixStack, getBackground().getWidth() / 2 + 3, 55); + press.draw(matrixStack, getBackground().getWidth() / 2 + 3, 34); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java index 99a5cbaf0..e3e2a461d 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java @@ -47,7 +47,7 @@ public class PolishingCategory extends CreateRecipeCategory ingredients = recipe.getIngredients(); ItemStack[] matchingStacks = ingredients.get(0) - .getMatchingStacks(); + .getItems(); if (matchingStacks.length == 0) return; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java index fbd9d0656..ac32b8c5c 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java @@ -41,7 +41,7 @@ public class PressingCategory extends CreateRecipeCategory { itemStacks.init(0, true, 26, 50); itemStacks.set(0, Arrays.asList(recipe.getIngredients() .get(0) - .getMatchingStacks())); + .getItems())); List results = recipe.getRollableResults(); for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { 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..4d0467a57 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 @@ -10,7 +10,6 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.utility.Lang; import mezz.jei.api.constants.VanillaTypes; @@ -21,7 +20,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 { @@ -36,12 +34,12 @@ public abstract class ProcessingViaFanCategory> extends Cre @Override public void setIngredients(T recipe, IIngredients ingredients) { ingredients.setInputIngredients(recipe.getIngredients()); - ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput()); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); } public static Supplier getFan(String name) { return () -> AllBlocks.ENCASED_FAN.asStack() - .setDisplayName(Lang.translate("recipe." + name + ".fan").formatted(TextFormatting.RESET)); + .setHoverName(Lang.translate("recipe." + name + ".fan").withStyle(style -> style.withItalic(false))); } @Override @@ -50,10 +48,10 @@ public abstract class ProcessingViaFanCategory> extends Cre itemStacks.init(0, true, 20, 47); itemStacks.set(0, Arrays.asList(recipe.getIngredients() .get(0) - .getMatchingStacks())); + .getItems())); itemStacks.init(1, false, 139, 47); - itemStacks.set(1, recipe.getRecipeOutput()); + itemStacks.set(1, recipe.getResultItem()); } protected void renderWidgets(MatrixStack matrixStack, T recipe, double mouseX, double mouseY) { @@ -69,25 +67,26 @@ public abstract class ProcessingViaFanCategory> extends Cre if (matrixStack == null) return; renderWidgets(matrixStack, recipe, mouseX, mouseY); - matrixStack.push(); + + matrixStack.pushPose(); translateFan(matrixStack); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-12.5f)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(22.5f)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(-12.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f)); int scale = 24; - GuiGameElement.of(AllBlockPartials.ENCASED_FAN_INNER) + AnimatedKinetics.defaultBlockElement(AllBlockPartials.ENCASED_FAN_INNER) .rotateBlock(180, 0, AnimatedKinetics.getCurrentAngle() * 16) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlocks.ENCASED_FAN.getDefaultState()) + AnimatedKinetics.defaultBlockElement(AllBlocks.ENCASED_FAN.getDefaultState()) .rotateBlock(0, 180, 0) .atLocal(0, 0, 0) .scale(scale) .render(matrixStack); renderAttachedBlock(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } protected void translateFan(MatrixStack matrixStack) { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java index 7e249d103..83a6275e4 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java @@ -39,7 +39,9 @@ public class SawingCategory extends CreateRecipeCategory { public void setRecipe(IRecipeLayout recipeLayout, CuttingRecipe recipe, IIngredients ingredients) { IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); itemStacks.init(0, true, 43, 4); - itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); + itemStacks.set(0, Arrays.asList(recipe.getIngredients() + .get(0) + .getItems())); List results = recipe.getRollableResults(); for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { @@ -47,7 +49,8 @@ public class SawingCategory extends CreateRecipeCategory { int yOffset = (outputIndex / 2) * -19; itemStacks.init(outputIndex + 1, false, 117 + xOffset, 47 + yOffset); - itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); + itemStacks.set(outputIndex + 1, results.get(outputIndex) + .getStack()); } addStochasticTooltip(itemStacks, results); @@ -56,13 +59,15 @@ public class SawingCategory extends CreateRecipeCategory { @Override public void draw(CuttingRecipe recipe, MatrixStack matrixStack, double mouseX, double mouseY) { AllGuiTextures.JEI_SLOT.draw(matrixStack, 43, 4); - int size = recipe.getRollableResults().size(); + int size = recipe.getRollableResults() + .size(); for (int i = 0; i < size; i++) { int xOffset = i % 2 == 0 ? 0 : 19; int yOffset = (i / 2) * -19; getRenderedSlot(recipe, i).draw(matrixStack, 117 + xOffset, 47 + yOffset); } AllGuiTextures.JEI_DOWN_ARROW.draw(matrixStack, 70, 6); + AllGuiTextures.JEI_SHADOW.draw(matrixStack, 72 - 17, 42 + 13); saw.draw(matrixStack, 72, 42); } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java new file mode 100644 index 000000000..74a81570f --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java @@ -0,0 +1,252 @@ +package com.simibubi.create.compat.jei.category; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllItems; +import com.simibubi.create.compat.jei.EmptyBackground; +import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedRecipe; +import com.simibubi.create.foundation.fluid.FluidIngredient; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.utility.Lang; + +import mezz.jei.api.constants.VanillaTypes; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.TranslationTextComponent; + +public class SequencedAssemblyCategory extends CreateRecipeCategory { + + Map subCategories = new HashMap<>(); + + public SequencedAssemblyCategory() { + super(itemIcon(AllItems.PRECISION_MECHANISM.get()), new EmptyBackground(180, 115)); + } + + @Override + public Class getRecipeClass() { + return SequencedAssemblyRecipe.class; + } + + @Override + public void setIngredients(SequencedAssemblyRecipe recipe, IIngredients ingredients) { + List assemblyIngredients = getAllItemIngredients(recipe); + List assemblyFluidIngredients = getAllFluidIngredients(recipe); + ingredients.setInputIngredients(assemblyIngredients); + if (!assemblyFluidIngredients.isEmpty()) + ingredients.setInputLists(VanillaTypes.FLUID, assemblyFluidIngredients.stream() + .map(FluidIngredient::getMatchingFluidStacks) + .collect(Collectors.toList())); + ingredients.setOutputs(VanillaTypes.ITEM, + ImmutableList.of(recipe.getResultItem(), recipe.getTransitionalItem())); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, SequencedAssemblyRecipe recipe, IIngredients ingredients) { + IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); + IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks(); + int xOffset = recipe.getOutputChance() == 1 ? 0 : -7; + + itemStacks.init(0, true, 26 + xOffset, 90); + itemStacks.set(0, Arrays.asList(recipe.getIngredient() + .getItems())); + + ItemStack result = recipe.getResultItem(); + itemStacks.init(1, false, 131 + xOffset, 90); + itemStacks.set(1, result); + + int width = 0; + int margin = 3; + for (SequencedRecipe sequencedRecipe : recipe.getSequence()) + width += getSubCategory(sequencedRecipe).getWidth() + margin; + width -= margin; + int x = width / -2 + getBackground().getWidth() / 2; + int index = 2; + int fluidIndex = 0; + for (SequencedRecipe sequencedRecipe : recipe.getSequence()) { + SequencedAssemblySubCategory subCategory = getSubCategory(sequencedRecipe); + index += subCategory.addItemIngredients(sequencedRecipe, itemStacks, x, index); + fluidIndex += subCategory.addFluidIngredients(sequencedRecipe, fluidStacks, x, fluidIndex); + x += subCategory.getWidth() + margin; + } + + // In case machines should be displayed as ingredients + +// List> inputs = ingredients.getInputs(VanillaTypes.ITEM); +// int catalystX = -2; +// int catalystY = 14; +// for (; index < inputs.size(); index++) { +// itemStacks.init(index, true, catalystX, catalystY); +// itemStacks.set(index, inputs.get(index)); +// catalystY += 19; +// } + + itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { + if (slotIndex != 1) + return; + float chance = recipe.getOutputChance(); + if (chance != 1) + tooltip.add(1, Lang.translate("recipe.processing.chance", chance < 0.01 ? "<1" : (int) (chance * 100)) + .withStyle(TextFormatting.GOLD)); + }); + } + + private SequencedAssemblySubCategory getSubCategory(SequencedRecipe sequencedRecipe) { + return subCategories.computeIfAbsent(sequencedRecipe.getRecipe() + .getSerializer() + .getRegistryName(), + rl -> sequencedRecipe.getAsAssemblyRecipe() + .getJEISubCategory() + .get() + .get()); + + } + + final String[] romans = { "I", "II", "III", "IV", "V", "VI", "-" }; + + @Override + public void draw(SequencedAssemblyRecipe recipe, MatrixStack matrixStack, double mouseX, double mouseY) { + FontRenderer font = Minecraft.getInstance().font; + + matrixStack.pushPose(); + matrixStack.translate(0, 15, 0); + boolean singleOutput = recipe.getOutputChance() == 1; + int xOffset = singleOutput ? 0 : -7; + AllGuiTextures.JEI_SLOT.draw(matrixStack, 26 + xOffset, 75); + (singleOutput ? AllGuiTextures.JEI_SLOT : AllGuiTextures.JEI_CHANCE_SLOT).draw(matrixStack, 131 + xOffset, 75); + AllGuiTextures.JEI_LONG_ARROW.draw(matrixStack, 52 + xOffset, 79); + if (!singleOutput) { + AllGuiTextures.JEI_CHANCE_SLOT.draw(matrixStack, 150 + xOffset, 75); + ITextComponent component = new StringTextComponent("?").withStyle(TextFormatting.BOLD); + font.drawShadow(matrixStack, component, font.width(component) / -2 + 8 + 150 + xOffset, 2 + 78, + 0xefefef); + } + + if (recipe.getLoops() > 1) { + matrixStack.pushPose(); + matrixStack.translate(15, 9, 0); + RenderSystem.color4f(.65f, .65f, .65f, 1); + AllIcons.I_REFRESH.draw(matrixStack, 50 + xOffset, 75); + RenderSystem.color4f(1, 1, 1, 1); + ITextComponent repeat = new StringTextComponent("x" + recipe.getLoops()); + font.draw(matrixStack, repeat, 66 + xOffset, 80, 0x888888); + matrixStack.popPose(); + } + + matrixStack.popPose(); + + int width = 0; + int margin = 3; + for (SequencedRecipe sequencedRecipe : recipe.getSequence()) + width += getSubCategory(sequencedRecipe).getWidth() + margin; + width -= margin; + matrixStack.translate(width / -2 + getBackground().getWidth() / 2, 0, 0); + + matrixStack.pushPose(); + List> sequence = recipe.getSequence(); + for (int i = 0; i < sequence.size(); i++) { + SequencedRecipe sequencedRecipe = sequence.get(i); + SequencedAssemblySubCategory subCategory = getSubCategory(sequencedRecipe); + int subWidth = subCategory.getWidth(); + StringTextComponent component = new StringTextComponent("" + romans[Math.min(i, 6)]); + font.draw(matrixStack, component, font.width(component) / -2 + subWidth / 2, 2, 0x888888); + subCategory.draw(sequencedRecipe, matrixStack, mouseX, mouseY, i); + matrixStack.translate(subWidth + margin, 0, 0); + } + matrixStack.popPose(); + } + + @Override + public List getTooltipStrings(SequencedAssemblyRecipe recipe, double mouseX, double mouseY) { + List tooltip = new ArrayList(); + + TranslationTextComponent junk = Lang.translate("recipe.assembly.junk"); + + boolean singleOutput = recipe.getOutputChance() == 1; + boolean willRepeat = recipe.getLoops() > 1; + + int xOffset = -7; + int minX = 150 + xOffset; + int maxX = minX + 18; + int minY = 90; + int maxY = minY + 18; + if (!singleOutput && mouseX >= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY) { + float chance = recipe.getOutputChance(); + tooltip.add(junk); + tooltip.add(Lang.translate("recipe.processing.chance", chance < 0.01 ? "<1" : 100 - (int) (chance * 100)) + .withStyle(TextFormatting.GOLD)); + return tooltip; + } + + minX = 55 + xOffset; + maxX = minX + 65; + minY = 92; + maxY = minY + 24; + if (willRepeat && mouseX >= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY) { + tooltip.add(Lang.translate("recipe.assembly.repeat", recipe.getLoops())); + return tooltip; + } + + if (mouseY > 5 && mouseY < 84) { + int width = 0; + int margin = 3; + for (SequencedRecipe sequencedRecipe : recipe.getSequence()) + width += getSubCategory(sequencedRecipe).getWidth() + margin; + width -= margin; + xOffset = width / 2 + getBackground().getWidth() / -2; + + double relativeX = mouseX + xOffset; + List> sequence = recipe.getSequence(); + for (int i = 0; i < sequence.size(); i++) { + SequencedRecipe sequencedRecipe = sequence.get(i); + SequencedAssemblySubCategory subCategory = getSubCategory(sequencedRecipe); + if (relativeX >= 0 && relativeX < subCategory.getWidth()) { + tooltip.add(Lang.translate("recipe.assembly.step", i + 1)); + tooltip.add(sequencedRecipe.getAsAssemblyRecipe() + .getDescriptionForAssembly() + .plainCopy() + .withStyle(TextFormatting.DARK_GREEN)); + return tooltip; + } + relativeX -= subCategory.getWidth() + margin; + } + } + + return tooltip; + } + + private List getAllFluidIngredients(SequencedAssemblyRecipe recipe) { + List assemblyFluidIngredients = new ArrayList<>(); + recipe.addAdditionalFluidIngredients(assemblyFluidIngredients); + return assemblyFluidIngredients; + } + + private List getAllItemIngredients(SequencedAssemblyRecipe recipe) { + List assemblyIngredients = new ArrayList<>(); + assemblyIngredients.add(recipe.getIngredient()); + assemblyIngredients.add(Ingredient.of(recipe.getTransitionalItem())); + recipe.addAdditionalIngredientsAndMachines(assemblyIngredients); + return assemblyIngredients; + } + +} 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..dd9f16238 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; @@ -51,7 +52,7 @@ public class SpoutCategory extends CreateRecipeCategory { .forEach(stack -> { if (stack.getItem() instanceof PotionItem) { FluidStack fluidFromPotionItem = PotionFluidHandler.getFluidFromPotionItem(stack); - Ingredient bottle = Ingredient.fromItems(Items.GLASS_BOTTLE); + Ingredient bottle = Ingredient.of(Items.GLASS_BOTTLE); recipes.add(new ProcessingRecipeBuilder<>(FillingRecipe::new, Create.asResource("potions")) .withItemIngredients(bottle) .withFluidIngredients(FluidIngredient.fromFluidStack(fluidFromPotionItem)) @@ -71,16 +72,18 @@ 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); ItemStack container = fhi.getContainer(); - if (container.isItemEqual(copy)) + if (container.sameItem(copy)) return; if (container.isEmpty()) return; - Ingredient bucket = Ingredient.fromStacks(stack); + Ingredient bucket = Ingredient.of(stack); ResourceLocation itemName = stack.getItem() .getRegistryName(); ResourceLocation fluidName = fluidCopy.getFluid() @@ -114,7 +117,7 @@ public class SpoutCategory extends CreateRecipeCategory { if (!recipe.getRollableResults() .isEmpty()) - ingredients.setOutput(VanillaTypes.ITEM, recipe.getRecipeOutput()); + ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); if (!recipe.getFluidResults() .isEmpty()) ingredients.setOutputs(VanillaTypes.FLUID, recipe.getFluidResults()); @@ -127,14 +130,14 @@ public class SpoutCategory extends CreateRecipeCategory { FluidIngredient fluidIngredient = recipe.getRequiredFluid(); List matchingIngredients = Arrays.asList(recipe.getIngredients() .get(0) - .getMatchingStacks()); + .getItems()); fluidStacks.init(0, true, 27, 32); fluidStacks.set(0, withImprovedVisibility(fluidIngredient.getMatchingFluidStacks())); itemStacks.init(0, true, 26, 50); itemStacks.set(0, matchingIngredients); itemStacks.init(1, false, 131, 50); - itemStacks.set(1, recipe.getRecipeOutput()); + itemStacks.set(1, recipe.getResultItem()); addFluidTooltip(fluidStacks, ImmutableList.of(fluidIngredient), Collections.emptyList()); } 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..84302d924 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,16 +1,16 @@ 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 com.simibubi.create.foundation.utility.AnimationTickHolder; -import mezz.jei.api.gui.drawable.IDrawable; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3f; -public class AnimatedBlazeBurner implements IDrawable { +public class AnimatedBlazeBurner extends AnimatedKinetics { private HeatLevel heatLevel; @@ -20,34 +20,26 @@ public class AnimatedBlazeBurner implements IDrawable { } public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 200); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-15.5f)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(22.5f)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(-15.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f)); int scale = 23; - GuiGameElement.of(AllBlocks.BLAZE_BURNER.getDefaultState()) + blockElement(AllBlocks.BLAZE_BURNER.getDefaultState()) .atLocal(0, 1.65, 0) .scale(scale) .render(matrixStack); + float offset = (MathHelper.sin(AnimationTickHolder.getRenderTime() / 16f) + 0.5f) / 16f; PartialModel blaze = AllBlockPartials.BLAZES.get(heatLevel); - GuiGameElement.of(blaze) - .atLocal(1, 1.65, 1) + blockElement(blaze) + .atLocal(1, 1.65 + offset, 1) .rotate(0, 180, 0) .scale(scale) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } - @Override - public int getWidth() { - return 50; - } - - @Override - public int getHeight() { - return 50; - } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrafter.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrafter.java index 826e1d9ec..ecee0a86f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrafter.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrafter.java @@ -1,36 +1,35 @@ package com.simibubi.create.compat.jei.category.animations; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.GuiGameElement; -import com.simibubi.create.foundation.utility.MatrixStacker; public class AnimatedCrafter extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 0); AllGuiTextures.JEI_SHADOW.draw(matrixStack, -16, 13); matrixStack.translate(3, 16, 0); - MatrixStacker.of(matrixStack) + MatrixTransformStack.of(matrixStack) .rotateX(-12.5f) .rotateY(-22.5f); int scale = 22; - GuiGameElement.of(cogwheel()) + blockElement(cogwheel()) .rotateBlock(90, 0, getCurrentAngle()) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlocks.MECHANICAL_CRAFTER.getDefaultState()) + blockElement(AllBlocks.MECHANICAL_CRAFTER.getDefaultState()) .rotateBlock(0, 180, 0) .scale(scale) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } } 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..29ef44198 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,9 +1,7 @@ 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; import net.minecraft.block.BlockState; import net.minecraft.state.properties.BlockStateProperties; @@ -12,27 +10,28 @@ import net.minecraft.util.math.vector.Vector3f; public class AnimatedCrushingWheels extends AnimatedKinetics { + private final BlockState wheel = AllBlocks.CRUSHING_WHEEL.getDefaultState() + .setValue(BlockStateProperties.AXIS, Axis.X); + @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - RenderSystem.enableDepthTest(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 100); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(-22.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(-22.5f)); int scale = 22; - - BlockState wheel = AllBlocks.CRUSHING_WHEEL.get() - .getDefaultState() - .with(BlockStateProperties.AXIS, Axis.X); - GuiGameElement.of(wheel) + blockElement(wheel) .rotateBlock(0, 90, -getCurrentAngle()) .scale(scale) .render(matrixStack); - GuiGameElement.of(wheel) + blockElement(wheel) .rotateBlock(0, 90, getCurrentAngle()) .atLocal(2, 0, 0) .scale(scale) .render(matrixStack); + + matrixStack.popPose(); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java index 862e94194..e5236ee95 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java @@ -4,58 +4,56 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock; -import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; -import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3f; public class AnimatedDeployer extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 100); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-15.5f)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(22.5f)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(-15.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f)); int scale = 20; - GuiGameElement.of(shaft(Axis.Z)) + blockElement(shaft(Axis.Z)) .rotateBlock(0, 0, getCurrentAngle()) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlocks.DEPLOYER.getDefaultState() - .with(DeployerBlock.FACING, Direction.DOWN) - .with(DeployerBlock.AXIS_ALONG_FIRST_COORDINATE, false)) + blockElement(AllBlocks.DEPLOYER.getDefaultState() + .setValue(DeployerBlock.FACING, Direction.DOWN) + .setValue(DeployerBlock.AXIS_ALONG_FIRST_COORDINATE, false)) .scale(scale) .render(matrixStack); - float cycle = AnimationTickHolder.getRenderTime() % 30; + float cycle = (AnimationTickHolder.getRenderTime() - offset * 8) % 30; float offset = cycle < 10 ? cycle / 10f : cycle < 20 ? (20 - cycle) / 10f : 0; - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(0, offset * 17, 0); - GuiGameElement.of(AllBlockPartials.DEPLOYER_POLE) + blockElement(AllBlockPartials.DEPLOYER_POLE) .rotateBlock(90, 0, 0) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlockPartials.DEPLOYER_HAND_HOLDING) + blockElement(AllBlockPartials.DEPLOYER_HAND_HOLDING) .rotateBlock(90, 0, 0) .scale(scale) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); - GuiGameElement.of(AllBlocks.DEPOT.getDefaultState()) + blockElement(AllBlocks.DEPOT.getDefaultState()) .atLocal(0, 2, 0) .scale(scale) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedItemDrain.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedItemDrain.java index 41bed07e1..3186ad0c7 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedItemDrain.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedItemDrain.java @@ -3,7 +3,6 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.gui.GuiGameElement; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer.Impl; @@ -22,25 +21,25 @@ public class AnimatedItemDrain extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 100); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-15.5f)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(22.5f)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(-15.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f)); int scale = 20; - GuiGameElement.of(AllBlocks.ITEM_DRAIN.getDefaultState()) + blockElement(AllBlocks.ITEM_DRAIN.getDefaultState()) .scale(scale) .render(matrixStack); Impl buffer = IRenderTypeBuffer.immediate(Tessellator.getInstance() - .getBuffer()); + .getBuilder()); MatrixStack ms = new MatrixStack(); ms.scale(scale, -scale, scale); float from = 2/16f; float to = 1f - from; - FluidRenderer.renderTiledFluidBB(fluid, from, from, from, to, 3/4f, to, buffer, ms, 0xf000f0, false); - buffer.draw(); + FluidRenderer.renderTiledFluidBB(fluid, from, from, from, to, 3/4f, to, buffer, ms, 0xF000F0, false); + buffer.endBatch(); - matrixStack.pop(); + matrixStack.popPose(); } } 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..069a397e2 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,11 @@ 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.gui.CustomLightingSettings; +import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.gui.ILightingSettings; import com.simibubi.create.foundation.utility.AnimationTickHolder; import mezz.jei.api.gui.drawable.IDrawable; @@ -11,19 +14,52 @@ import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction.Axis; public abstract class AnimatedKinetics implements IDrawable { + + public int offset = 0; + + public static final ILightingSettings DEFAULT_LIGHTING = CustomLightingSettings.builder() + .firstLightRotation(12.5f, 45.0f) + .secondLightRotation(-20.0f, 50.0f) + .build(); + + /** + * Only use this method outside of subclasses. + * Use {@link #blockElement(BlockState)} if calling from inside a subclass. + */ + public static GuiGameElement.GuiRenderBuilder defaultBlockElement(BlockState state) { + return GuiGameElement.of(state) + .lighting(DEFAULT_LIGHTING); + } + + /** + * Only use this method outside of subclasses. + * Use {@link #blockElement(PartialModel)} if calling from inside a subclass. + */ + public static GuiGameElement.GuiRenderBuilder defaultBlockElement(PartialModel partial) { + return GuiGameElement.of(partial) + .lighting(DEFAULT_LIGHTING); + } public static float getCurrentAngle() { - return ((AnimationTickHolder.getRenderTime()) * 4f) % 360; + return (AnimationTickHolder.getRenderTime() * 4f) % 360; } protected BlockState shaft(Axis axis) { - return AllBlocks.SHAFT.getDefaultState().with(BlockStateProperties.AXIS, axis); + return AllBlocks.SHAFT.getDefaultState().setValue(BlockStateProperties.AXIS, axis); } protected PartialModel cogwheel() { return AllBlockPartials.SHAFTLESS_COGWHEEL; } + protected GuiGameElement.GuiRenderBuilder blockElement(BlockState state) { + return defaultBlockElement(state); + } + + protected GuiGameElement.GuiRenderBuilder blockElement(PartialModel partial) { + return defaultBlockElement(partial); + } + @Override public int getWidth() { return 50; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java index 8e98eb372..4c9b87063 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java @@ -4,29 +4,28 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.GuiGameElement; public class AnimatedMillstone extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 0); AllGuiTextures.JEI_SHADOW.draw(matrixStack, -16, 13); matrixStack.translate(-2, 18, 0); int scale = 22; - GuiGameElement.of(AllBlockPartials.MILLSTONE_COG) + blockElement(AllBlockPartials.MILLSTONE_COG) .rotateBlock(22.5, getCurrentAngle() * 2, 0) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlocks.MILLSTONE.getDefaultState()) + blockElement(AllBlocks.MILLSTONE.getDefaultState()) .rotateBlock(22.5, 22.5, 0) .scale(scale) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java index 5359d7b76..1b95917a9 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java @@ -3,7 +3,6 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.math.MathHelper; @@ -13,42 +12,42 @@ public class AnimatedMixer extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 200); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-15.5f)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(22.5f)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(-15.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f)); int scale = 23; - GuiGameElement.of(cogwheel()) + blockElement(cogwheel()) .rotateBlock(0, getCurrentAngle() * 2, 0) .atLocal(0, 0, 0) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlocks.MECHANICAL_MIXER.getDefaultState()) + blockElement(AllBlocks.MECHANICAL_MIXER.getDefaultState()) .atLocal(0, 0, 0) .scale(scale) .render(matrixStack); float animation = ((MathHelper.sin(AnimationTickHolder.getRenderTime() / 32f) + 1) / 5) + .5f; - GuiGameElement.of(AllBlockPartials.MECHANICAL_MIXER_POLE) + blockElement(AllBlockPartials.MECHANICAL_MIXER_POLE) .atLocal(0, animation, 0) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlockPartials.MECHANICAL_MIXER_HEAD) + blockElement(AllBlockPartials.MECHANICAL_MIXER_HEAD) .rotateBlock(0, getCurrentAngle() * 4, 0) .atLocal(0, animation, 0) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlocks.BASIN.getDefaultState()) + blockElement(AllBlocks.BASIN.getDefaultState()) .atLocal(0, 1.65, 0) .scale(scale) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java index a7e1d262a..a812afaa8 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java @@ -3,7 +3,6 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.Direction.Axis; @@ -19,37 +18,37 @@ public class AnimatedPress extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); - matrixStack.translate(xOffset, yOffset, 100); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-15.5f)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(22.5f)); - int scale = basin ? 20 : 24; + matrixStack.pushPose(); + matrixStack.translate(xOffset, yOffset, 200); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(-15.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f)); + int scale = basin ? 23 : 24; - GuiGameElement.of(shaft(Axis.Z)) + blockElement(shaft(Axis.Z)) .rotateBlock(0, 0, getCurrentAngle()) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlocks.MECHANICAL_PRESS.getDefaultState()) + blockElement(AllBlocks.MECHANICAL_PRESS.getDefaultState()) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlockPartials.MECHANICAL_PRESS_HEAD) + blockElement(AllBlockPartials.MECHANICAL_PRESS_HEAD) .atLocal(0, -getAnimatedHeadOffset(), 0) .scale(scale) .render(matrixStack); if (basin) - GuiGameElement.of(AllBlocks.BASIN.getDefaultState()) + blockElement(AllBlocks.BASIN.getDefaultState()) .atLocal(0, 1.65, 0) .scale(scale) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } private float getAnimatedHeadOffset() { - float cycle = (AnimationTickHolder.getRenderTime()) % 30; + float cycle = (AnimationTickHolder.getRenderTime() - offset * 8) % 30; if (cycle < 10) { float progress = cycle / 10; return -(progress * progress * progress); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java index a13365b2e..de5e9dd97 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java @@ -4,8 +4,6 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.saw.SawBlock; -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.GuiGameElement; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -15,33 +13,31 @@ public class AnimatedSaw extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 0); - AllGuiTextures.JEI_SHADOW.draw(matrixStack, -16, 13); - matrixStack.translate(0, 0, 200); - matrixStack.translate(29, 17, 0); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-22.5f)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(90 - 225f)); + matrixStack.translate(2, 22, 0); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(-15.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f + 90)); int scale = 25; - GuiGameElement.of(shaft(Axis.X)) + blockElement(shaft(Axis.X)) .rotateBlock(-getCurrentAngle(), 0, 0) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlocks.MECHANICAL_SAW.getDefaultState() - .with(SawBlock.FACING, Direction.UP)) + blockElement(AllBlocks.MECHANICAL_SAW.getDefaultState() + .setValue(SawBlock.FACING, Direction.UP)) .rotateBlock(0, 0, 0) .scale(scale) .render(matrixStack); - GuiGameElement.of(AllBlockPartials.SAW_BLADE_VERTICAL_ACTIVE) + blockElement(AllBlockPartials.SAW_BLADE_VERTICAL_ACTIVE) .rotateBlock(0, -90, -90) .scale(scale) .render(matrixStack); - matrixStack.pop(); + matrixStack.popPose(); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java index 40f23c032..0e09a4c51 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java @@ -6,7 +6,6 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -27,60 +26,60 @@ public class AnimatedSpout extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(xOffset, yOffset, 100); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-15.5f)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(22.5f)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees(-15.5f)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(22.5f)); int scale = 20; - GuiGameElement.of(AllBlocks.SPOUT.getDefaultState()) + blockElement(AllBlocks.SPOUT.getDefaultState()) .scale(scale) .render(matrixStack); - float cycle = AnimationTickHolder.getRenderTime() % 30; + float cycle = (AnimationTickHolder.getRenderTime() - offset * 8) % 30; float squeeze = cycle < 20 ? MathHelper.sin((float) (cycle / 20f * Math.PI)) : 0; squeeze *= 20; - matrixStack.push(); + matrixStack.pushPose(); - GuiGameElement.of(AllBlockPartials.SPOUT_TOP) + blockElement(AllBlockPartials.SPOUT_TOP) .scale(scale) .render(matrixStack); matrixStack.translate(0, -3 * squeeze / 32f, 0); - GuiGameElement.of(AllBlockPartials.SPOUT_MIDDLE) + blockElement(AllBlockPartials.SPOUT_MIDDLE) .scale(scale) .render(matrixStack); matrixStack.translate(0, -3 * squeeze / 32f, 0); - GuiGameElement.of(AllBlockPartials.SPOUT_BOTTOM) + blockElement(AllBlockPartials.SPOUT_BOTTOM) .scale(scale) .render(matrixStack); matrixStack.translate(0, -3 * squeeze / 32f, 0); - matrixStack.pop(); + matrixStack.popPose(); - GuiGameElement.of(AllBlocks.DEPOT.getDefaultState()) + blockElement(AllBlocks.DEPOT.getDefaultState()) .atLocal(0, 2, 0) .scale(scale) .render(matrixStack); Impl buffer = IRenderTypeBuffer.immediate(Tessellator.getInstance() - .getBuffer()); - matrixStack.push(); + .getBuilder()); + matrixStack.pushPose(); matrixStack.scale(16, -16, 16); float from = 2/16f; float to = 1f - from; - FluidRenderer.renderTiledFluidBB(fluids.get(0), from, from, from, to, to, to, buffer, matrixStack, 0xf000f0, false); - matrixStack.pop(); + FluidRenderer.renderTiledFluidBB(fluids.get(0), from, from, from, to, to, to, buffer, matrixStack, 0xF000F0, false); + matrixStack.popPose(); float width = 1 / 128f * squeeze; matrixStack.translate(scale / 2f, scale * 1.5f, scale / 2f); matrixStack.scale(16, -16, 16); matrixStack.translate(-width / 2, 0, -width / 2); - FluidRenderer.renderTiledFluidBB(fluids.get(0), 0, -0.001f, 0, width, 2.001f, width, buffer, matrixStack, 0xf000f0, + FluidRenderer.renderTiledFluidBB(fluids.get(0), 0, -0.001f, 0, width, 2.001f, width, buffer, matrixStack, 0xF000F0, false); - buffer.draw(); + buffer.endBatch(); - matrixStack.pop(); + matrixStack.popPose(); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java new file mode 100644 index 000000000..bf4345225 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java @@ -0,0 +1,171 @@ +package com.simibubi.create.compat.jei.category.sequencedAssembly; + +import java.util.Arrays; +import java.util.Collections; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.compat.jei.category.CreateRecipeCategory; +import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer; +import com.simibubi.create.compat.jei.category.animations.AnimatedPress; +import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; +import com.simibubi.create.compat.jei.category.animations.AnimatedSpout; +import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; +import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedRecipe; +import com.simibubi.create.foundation.fluid.FluidIngredient; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.utility.Lang; + +import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; +import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; +import net.minecraft.util.text.TextFormatting; + +public abstract class SequencedAssemblySubCategory { + + private int width; + + public SequencedAssemblySubCategory(int width) { + this.width = width; + } + + public int getWidth() { + return width; + } + + public int addItemIngredients(SequencedRecipe recipe, IGuiItemStackGroup itemStacks, int x, int index) { + return 0; + } + + public int addFluidIngredients(SequencedRecipe recipe, IGuiFluidStackGroup fluidStacks, int x, int index) { + return 0; + } + + public abstract void draw(SequencedRecipe recipe, MatrixStack ms, double mouseX, double mouseY, int index); + + public static class AssemblyPressing extends SequencedAssemblySubCategory { + + AnimatedPress press; + + public AssemblyPressing() { + super(25); + press = new AnimatedPress(false); + } + + @Override + public void draw(SequencedRecipe recipe, MatrixStack ms, double mouseX, double mouseY, int index) { + press.offset = index; + ms.pushPose(); + ms.translate(-5, 50, 0); + ms.scale(.6f, .6f, .6f); + press.draw(ms, getWidth() / 2, 0); + ms.popPose(); + } + + } + + public static class AssemblySpouting extends SequencedAssemblySubCategory { + + AnimatedSpout spout; + + public AssemblySpouting() { + super(25); + spout = new AnimatedSpout(); + } + + @Override + public int addFluidIngredients(SequencedRecipe recipe, IGuiFluidStackGroup fluidStacks, int x, int index) { + FluidIngredient fluidIngredient = recipe.getRecipe() + .getFluidIngredients() + .get(0); + fluidStacks.init(index, true, x + 4, 15); + fluidStacks.set(index, + CreateRecipeCategory.withImprovedVisibility(fluidIngredient.getMatchingFluidStacks())); + CreateRecipeCategory.addFluidTooltip(fluidStacks, ImmutableList.of(fluidIngredient), + Collections.emptyList(), index); + return 1; + } + + @Override + public void draw(SequencedRecipe recipe, MatrixStack ms, double mouseX, double mouseY, int index) { + spout.offset = index; + AllGuiTextures.JEI_SLOT.draw(ms, 3, 14); + ms.pushPose(); + ms.translate(-7, 50, 0); + ms.scale(.75f, .75f, .75f); + spout.withFluids(recipe.getRecipe() + .getFluidIngredients() + .get(0) + .getMatchingFluidStacks()) + .draw(ms, getWidth() / 2, 0); + ms.popPose(); + } + + } + + public static class AssemblyDeploying extends SequencedAssemblySubCategory { + + AnimatedDeployer deployer; + + public AssemblyDeploying() { + super(25); + deployer = new AnimatedDeployer(); + } + + @Override + public int addItemIngredients(SequencedRecipe recipe, IGuiItemStackGroup itemStacks, int x, int index) { + itemStacks.init(index, true, x + 3, 14); + itemStacks.set(index, Arrays.asList(recipe.getRecipe() + .getIngredients() + .get(1) + .getItems())); + + IAssemblyRecipe contained = recipe.getAsAssemblyRecipe(); + if (contained instanceof DeployerApplicationRecipe && ((DeployerApplicationRecipe) contained).shouldKeepHeldItem()) { + itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { + if (!input) + return; + if (slotIndex != index) + return; + tooltip.add(1, Lang.translate("recipe.deploying.not_consumed") + .withStyle(TextFormatting.GOLD)); + }); + } + + return 1; + } + + @Override + public void draw(SequencedRecipe recipe, MatrixStack ms, double mouseX, double mouseY, int index) { + deployer.offset = index; + ms.pushPose(); + ms.translate(-7, 50, 0); + ms.scale(.75f, .75f, .75f); + deployer.draw(ms, getWidth() / 2, 0); + ms.popPose(); + AllGuiTextures.JEI_SLOT.draw(ms, 3, 14); + } + + } + + public static class AssemblyCutting extends SequencedAssemblySubCategory { + + AnimatedSaw saw; + + public AssemblyCutting() { + super(25); + saw = new AnimatedSaw(); + } + + @Override + public void draw(SequencedRecipe recipe, MatrixStack ms, double mouseX, double mouseY, int index) { + ms.pushPose(); + ms.translate(0, 51.5f, 0); + ms.scale(.6f, .6f, .6f); + saw.draw(ms, getWidth() / 2, 30); + ms.popPose(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java b/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java new file mode 100644 index 000000000..88f47a402 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java @@ -0,0 +1,72 @@ +package com.simibubi.create.compat.tconstruct; + +import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity; +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.fluid.FluidHelper; + +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.World; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + +public class SpoutCasting extends BlockSpoutingBehaviour { + + static Boolean TICON_PRESENT = null; + + ResourceLocation TABLE = new ResourceLocation("tconstruct", "table"); + ResourceLocation BASIN = new ResourceLocation("tconstruct", "basin"); + + @Override + public int fillBlock(World level, BlockPos pos, SpoutTileEntity spout, FluidStack availableFluid, + boolean simulate) { + if (!enabled()) + return 0; + + TileEntity te = level.getBlockEntity(pos); + if (te == null) + return 0; + + IFluidHandler handler = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, Direction.UP) + .orElse(null); + if (handler == null) + return 0; + if (handler.getTanks() != 1) + return 0; + + ResourceLocation registryName = te.getType() + .getRegistryName(); + if (!registryName.equals(TABLE) && !registryName.equals(BASIN)) + return 0; + if (!handler.isFluidValid(0, availableFluid)) + return 0; + + FluidStack containedFluid = handler.getFluidInTank(0); + if (!(containedFluid.isEmpty() || containedFluid.isFluidEqual(availableFluid))) + return 0; + + // Do not fill if it would only partially fill the table (unless > 1000mb) + int amount = availableFluid.getAmount(); + if (amount < 1000 + && handler.fill(FluidHelper.copyStackWithAmount(availableFluid, amount + 1), FluidAction.SIMULATE) > amount) + return 0; + + // Return amount filled into the table/basin + return handler.fill(availableFluid, simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE); + } + + private boolean enabled() { + if (TICON_PRESENT == null) + TICON_PRESENT = Mods.TCONSTRUCT.isLoaded(); + if (!TICON_PRESENT) + return false; + return AllConfigs.SERVER.recipes.allowCastingBySpout.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/CreateItemGroup.java b/src/main/java/com/simibubi/create/content/CreateItemGroup.java index e773d83b5..b36ce6945 100644 --- a/src/main/java/com/simibubi/create/content/CreateItemGroup.java +++ b/src/main/java/com/simibubi/create/content/CreateItemGroup.java @@ -19,7 +19,7 @@ public class CreateItemGroup extends CreateItemGroupBase { } @Override - public ItemStack createIcon() { + public ItemStack makeIcon() { return AllBlocks.COGWHEEL.asStack(); } 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..32ca513d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java +++ b/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java @@ -5,7 +5,7 @@ import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -28,45 +28,45 @@ 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; - World world = Minecraft.getInstance().world; - BlockPos toOutline = te.hasSource() ? te.source : te.getPos(); + World world = Minecraft.getInstance().level; + BlockPos toOutline = te.hasSource() ? te.source : te.getBlockPos(); BlockState state = te.getBlockState(); VoxelShape shape = world.getBlockState(toOutline) - .getRenderShape(world, toOutline); + .getBlockSupportShape(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.bounds() + .move(toOutline)) + .lineWidth(1 / 16f) + .colored(te.hasSource() ? Color.generateFromLong(te.network).getRGB() : 0xffcc00); if (state.getBlock() instanceof IRotate) { Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); - Vector3d vec = Vector3d.of(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis) - .getDirectionVec()); - Vector3d center = VecHelper.getCenterOf(te.getPos()); - CreateClient.outliner.showLine("rotationAxis", center.add(vec), center.subtract(vec)) - .lineWidth(1 / 16f); + Vector3d vec = Vector3d.atLowerCornerOf(Direction.get(AxisDirection.POSITIVE, axis) + .getNormal()); + Vector3d center = VecHelper.getCenterOf(te.getBlockPos()); + CreateClient.OUTLINER.showLine("rotationAxis", center.add(vec), center.subtract(vec)) + .lineWidth(1 / 16f); } } public static boolean isActive() { - return Minecraft.getInstance().gameSettings.showDebugInfo && AllConfigs.CLIENT.rainbowDebug.get(); + return Minecraft.getInstance().options.renderDebug && AllConfigs.CLIENT.rainbowDebug.get(); } public static KineticTileEntity getSelectedTE() { - RayTraceResult obj = Minecraft.getInstance().objectMouseOver; - ClientWorld world = Minecraft.getInstance().world; + RayTraceResult obj = Minecraft.getInstance().hitResult; + ClientWorld world = Minecraft.getInstance().level; if (obj == null) return null; if (world == null) @@ -75,7 +75,7 @@ public class KineticDebugger { return null; BlockRayTraceResult ray = (BlockRayTraceResult) obj; - TileEntity te = world.getTileEntity(ray.getPos()); + TileEntity te = world.getBlockEntity(ray.getBlockPos()); if (!(te instanceof KineticTileEntity)) return null; diff --git a/src/main/java/com/simibubi/create/content/contraptions/KineticNetwork.java b/src/main/java/com/simibubi/create/content/contraptions/KineticNetwork.java index bbbe8e585..af9076cb6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/KineticNetwork.java +++ b/src/main/java/com/simibubi/create/content/contraptions/KineticNetwork.java @@ -89,7 +89,7 @@ public class KineticNetwork { te.updateFromNetwork(0, 0, 0); if (members.isEmpty()) { - TorquePropagator.networks.get(te.getWorld()) + TorquePropagator.networks.get(te.getLevel()) .remove(this.id); return; } @@ -109,9 +109,9 @@ public class KineticNetwork { boolean wasOverStressed = te.isOverStressed(); te.updateFromNetwork(currentCapacity, currentStress, getSize()); if (!wasOverStressed && te.isOverStressed() && te.getTheoreticalSpeed() != 0) { - AllTriggers.triggerForNearbyPlayers(AllTriggers.OVERSTRESSED, te.getWorld(), te.getPos(), 4); + AllTriggers.triggerForNearbyPlayers(AllTriggers.OVERSTRESSED, te.getLevel(), te.getBlockPos(), 4); if (containsFlywheel) - AllTriggers.triggerForNearbyPlayers(AllTriggers.OVERSTRESS_FLYWHEEL, te.getWorld(), te.getPos(), 4); + AllTriggers.triggerForNearbyPlayers(AllTriggers.OVERSTRESS_FLYWHEEL, te.getLevel(), te.getBlockPos(), 4); } } @@ -147,8 +147,8 @@ public class KineticNetwork { for (Iterator iterator = sources.keySet() .iterator(); iterator.hasNext();) { KineticTileEntity te = iterator.next(); - if (te.getWorld() - .getTileEntity(te.getPos()) != te) { + if (te.getLevel() + .getBlockEntity(te.getBlockPos()) != te) { iterator.remove(); continue; } @@ -164,8 +164,8 @@ public class KineticNetwork { for (Iterator iterator = members.keySet() .iterator(); iterator.hasNext();) { KineticTileEntity te = iterator.next(); - if (te.getWorld() - .getTileEntity(te.getPos()) != te) { + if (te.getLevel() + .getBlockEntity(te.getBlockPos()) != te) { iterator.remove(); continue; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/RotationPropagator.java b/src/main/java/com/simibubi/create/content/contraptions/RotationPropagator.java index faa8c2046..c12e8a081 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/RotationPropagator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/RotationPropagator.java @@ -51,20 +51,20 @@ public class RotationPropagator { final IRotate definitionFrom = (IRotate) fromBlock; final IRotate definitionTo = (IRotate) toBlock; - final BlockPos diff = to.getPos() - .subtract(from.getPos()); - final Direction direction = Direction.getFacingFromVector(diff.getX(), diff.getY(), diff.getZ()); - final World world = from.getWorld(); + final BlockPos diff = to.getBlockPos() + .subtract(from.getBlockPos()); + final Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); + final World world = from.getLevel(); boolean alignedAxes = true; for (Axis axis : Axis.values()) if (axis != direction.getAxis()) - if (axis.getCoordinate(diff.getX(), diff.getY(), diff.getZ()) != 0) + if (axis.choose(diff.getX(), diff.getY(), diff.getZ()) != 0) alignedAxes = false; boolean connectedByAxis = - alignedAxes && definitionFrom.hasShaftTowards(world, from.getPos(), stateFrom, direction) - && definitionTo.hasShaftTowards(world, to.getPos(), stateTo, direction.getOpposite()); + alignedAxes && definitionFrom.hasShaftTowards(world, from.getBlockPos(), stateFrom, direction) + && definitionTo.hasShaftTowards(world, to.getBlockPos(), stateTo, direction.getOpposite()); boolean connectedByGears = ICogWheel.isSmallCog(stateFrom) && ICogWheel.isSmallCog(stateTo); @@ -89,10 +89,10 @@ public class RotationPropagator { // Large Gear <-> Large Gear if (isLargeToLargeGear(stateFrom, stateTo, diff)) { - Axis sourceAxis = stateFrom.get(AXIS); - Axis targetAxis = stateTo.get(AXIS); - int sourceAxisDiff = sourceAxis.getCoordinate(diff.getX(), diff.getY(), diff.getZ()); - int targetAxisDiff = targetAxis.getCoordinate(diff.getX(), diff.getY(), diff.getZ()); + Axis sourceAxis = stateFrom.getValue(AXIS); + Axis targetAxis = stateTo.getValue(AXIS); + int sourceAxisDiff = sourceAxis.choose(diff.getX(), diff.getY(), diff.getZ()); + int targetAxisDiff = targetAxis.choose(diff.getX(), diff.getY(), diff.getZ()); return sourceAxisDiff > 0 ^ targetAxisDiff > 0 ? -1 : 1; } @@ -107,7 +107,7 @@ public class RotationPropagator { // Gear <-> Gear if (connectedByGears) { - if (diff.manhattanDistance(BlockPos.ZERO) != 1) + if (diff.distManhattan(BlockPos.ZERO) != 1) return 0; if (ICogWheel.isLargeCog(stateTo)) return 0; @@ -125,11 +125,11 @@ public class RotationPropagator { final BlockState stateTo = to.getBlockState(); // Rotation Speed Controller <-> Large Gear - if (isLargeCogToSpeedController(stateFrom, stateTo, to.getPos() - .subtract(from.getPos()))) + if (isLargeCogToSpeedController(stateFrom, stateTo, to.getBlockPos() + .subtract(from.getBlockPos()))) return SpeedControllerTileEntity.getConveyedSpeed(from, to, true); - if (isLargeCogToSpeedController(stateTo, stateFrom, from.getPos() - .subtract(to.getPos()))) + if (isLargeCogToSpeedController(stateTo, stateFrom, from.getBlockPos() + .subtract(to.getBlockPos()))) return SpeedControllerTileEntity.getConveyedSpeed(to, from, false); float rotationSpeedModifier = getRotationSpeedModifier(from, to); @@ -139,12 +139,12 @@ public class RotationPropagator { private static boolean isLargeToLargeGear(BlockState from, BlockState to, BlockPos diff) { if (!ICogWheel.isLargeCog(from) || !ICogWheel.isLargeCog(to)) return false; - Axis fromAxis = from.get(AXIS); - Axis toAxis = to.get(AXIS); + Axis fromAxis = from.getValue(AXIS); + Axis toAxis = to.getValue(AXIS); if (fromAxis == toAxis) return false; for (Axis axis : Axis.values()) { - int axisDiff = axis.getCoordinate(diff.getX(), diff.getY(), diff.getZ()); + int axisDiff = axis.choose(diff.getX(), diff.getY(), diff.getZ()); if (axis == fromAxis || axis == toAxis) { if (axisDiff == 0) return false; @@ -171,15 +171,15 @@ public class RotationPropagator { } private static boolean isLargeToSmallCog(BlockState from, BlockState to, IRotate defTo, BlockPos diff) { - Axis axisFrom = from.get(AXIS); + Axis axisFrom = from.getValue(AXIS); if (axisFrom != defTo.getRotationAxis(to)) return false; - if (axisFrom.getCoordinate(diff.getX(), diff.getY(), diff.getZ()) != 0) + if (axisFrom.choose(diff.getX(), diff.getY(), diff.getZ()) != 0) return false; for (Axis axis : Axis.values()) { if (axis == axisFrom) continue; - if (Math.abs(axis.getCoordinate(diff.getX(), diff.getY(), diff.getZ())) != 1) + if (Math.abs(axis.choose(diff.getX(), diff.getY(), diff.getZ())) != 1) return false; } return true; @@ -188,12 +188,12 @@ public class RotationPropagator { private static boolean isLargeCogToSpeedController(BlockState from, BlockState to, BlockPos diff) { if (!ICogWheel.isLargeCog(from) || !AllBlocks.ROTATION_SPEED_CONTROLLER.has(to)) return false; - if (!diff.equals(BlockPos.ZERO.down())) + if (!diff.equals(BlockPos.ZERO.below())) return false; - Axis axis = from.get(CogWheelBlock.AXIS); + Axis axis = from.getValue(CogWheelBlock.AXIS); if (axis.isVertical()) return false; - if (to.get(SpeedControllerBlock.HORIZONTAL_AXIS) == axis) + if (to.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) == axis) return false; return true; } @@ -205,9 +205,9 @@ public class RotationPropagator { * @param pos */ public static void handleAdded(World worldIn, BlockPos pos, KineticTileEntity addedTE) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; - if (!worldIn.isBlockPresent(pos)) + if (!worldIn.isLoaded(pos)) return; propagateNewSource(addedTE); } @@ -218,8 +218,8 @@ public class RotationPropagator { * @param currentTE */ private static void propagateNewSource(KineticTileEntity currentTE) { - BlockPos pos = currentTE.getPos(); - World world = currentTE.getWorld(); + BlockPos pos = currentTE.getBlockPos(); + World world = currentTE.getLevel(); for (KineticTileEntity neighbourTE : getConnectedNeighbours(currentTE)) { float speedOfCurrent = currentTE.getTheoreticalSpeed(); @@ -251,7 +251,7 @@ public class RotationPropagator { // Neighbour faster, overpower the incoming tree if (Math.abs(oppositeSpeed) > Math.abs(speedOfCurrent)) { float prevSpeed = currentTE.getSpeed(); - currentTE.setSource(neighbourTE.getPos()); + currentTE.setSource(neighbourTE.getBlockPos()); currentTE.setSpeed(getConveyedSpeed(neighbourTE, currentTE)); currentTE.onSpeedChanged(prevSpeed); currentTE.sendData(); @@ -271,11 +271,11 @@ public class RotationPropagator { continue; } - if (currentTE.hasSource() && currentTE.source.equals(neighbourTE.getPos())) + if (currentTE.hasSource() && currentTE.source.equals(neighbourTE.getBlockPos())) currentTE.removeSource(); float prevSpeed = neighbourTE.getSpeed(); - neighbourTE.setSource(currentTE.getPos()); + neighbourTE.setSource(currentTE.getBlockPos()); neighbourTE.setSpeed(getConveyedSpeed(currentTE, neighbourTE)); neighbourTE.onSpeedChanged(prevSpeed); neighbourTE.sendData(); @@ -289,7 +289,7 @@ public class RotationPropagator { float prevSpeed = neighbourTE.getSpeed(); neighbourTE.setSpeed(newSpeed); - neighbourTE.setSource(currentTE.getPos()); + neighbourTE.setSource(currentTE.getBlockPos()); neighbourTE.onSpeedChanged(prevSpeed); neighbourTE.sendData(); propagateNewSource(neighbourTE); @@ -305,7 +305,7 @@ public class RotationPropagator { * @param removedTE */ public static void handleRemoved(World worldIn, BlockPos pos, KineticTileEntity removedTE) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; if (removedTE == null) return; @@ -316,7 +316,7 @@ public class RotationPropagator { BlockState neighbourState = worldIn.getBlockState(neighbourPos); if (!(neighbourState.getBlock() instanceof IRotate)) continue; - TileEntity tileEntity = worldIn.getTileEntity(neighbourPos); + TileEntity tileEntity = worldIn.getBlockEntity(neighbourPos); if (!(tileEntity instanceof KineticTileEntity)) continue; @@ -336,16 +336,16 @@ public class RotationPropagator { * @param updateTE */ private static void propagateMissingSource(KineticTileEntity updateTE) { - final World world = updateTE.getWorld(); + final World world = updateTE.getLevel(); List potentialNewSources = new LinkedList<>(); List frontier = new LinkedList<>(); - frontier.add(updateTE.getPos()); + frontier.add(updateTE.getBlockPos()); BlockPos missingSource = updateTE.hasSource() ? updateTE.source : null; while (!frontier.isEmpty()) { final BlockPos pos = frontier.remove(0); - TileEntity tileEntity = world.getTileEntity(pos); + TileEntity tileEntity = world.getBlockEntity(pos); if (!(tileEntity instanceof KineticTileEntity)) continue; final KineticTileEntity currentTE = (KineticTileEntity) tileEntity; @@ -354,7 +354,7 @@ public class RotationPropagator { currentTE.sendData(); for (KineticTileEntity neighbourTE : getConnectedNeighbours(currentTE)) { - if (neighbourTE.getPos() + if (neighbourTE.getBlockPos() .equals(missingSource)) continue; if (!neighbourTE.hasSource()) @@ -368,7 +368,7 @@ public class RotationPropagator { if (neighbourTE.isSource()) potentialNewSources.add(neighbourTE); - frontier.add(neighbourTE.getPos()); + frontier.add(neighbourTE.getBlockPos()); } } @@ -381,14 +381,14 @@ public class RotationPropagator { } private static KineticTileEntity findConnectedNeighbour(KineticTileEntity currentTE, BlockPos neighbourPos) { - BlockState neighbourState = currentTE.getWorld() + BlockState neighbourState = currentTE.getLevel() .getBlockState(neighbourPos); if (!(neighbourState.getBlock() instanceof IRotate)) return null; if (!neighbourState.hasTileEntity()) return null; - TileEntity neighbourTE = currentTE.getWorld() - .getTileEntity(neighbourPos); + TileEntity neighbourTE = currentTE.getLevel() + .getBlockEntity(neighbourPos); if (!(neighbourTE instanceof KineticTileEntity)) return null; KineticTileEntity neighbourKTE = (KineticTileEntity) neighbourTE; @@ -403,8 +403,8 @@ public class RotationPropagator { public static boolean isConnected(KineticTileEntity from, KineticTileEntity to) { final BlockState stateFrom = from.getBlockState(); final BlockState stateTo = to.getBlockState(); - return isLargeCogToSpeedController(stateFrom, stateTo, to.getPos() - .subtract(from.getPos())) || getRotationSpeedModifier(from, to) != 0 + return isLargeCogToSpeedController(stateFrom, stateTo, to.getBlockPos() + .subtract(from.getBlockPos())) || getRotationSpeedModifier(from, to) != 0 || from.isCustomConnection(to, stateFrom, stateTo); } @@ -423,13 +423,13 @@ public class RotationPropagator { private static List getPotentialNeighbourLocations(KineticTileEntity te) { List neighbours = new LinkedList<>(); - if (!te.getWorld() - .isAreaLoaded(te.getPos(), 1)) + if (!te.getLevel() + .isAreaLoaded(te.getBlockPos(), 1)) return neighbours; for (Direction facing : Iterate.directions) - neighbours.add(te.getPos() - .offset(facing)); + neighbours.add(te.getBlockPos() + .relative(facing)); BlockState blockState = te.getBlockState(); if (!(blockState.getBlock() instanceof IRotate)) 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..72b8fd57c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java @@ -15,18 +15,18 @@ 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) { Long id = te.network; KineticNetwork network; - Map map = networks.get(te.getWorld()); + Map map = networks.get(te.getLevel()); if (id == null) return null; 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..3133c09ab 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,17 +1,17 @@ package com.simibubi.create.content.contraptions.base; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.jozufozu.flywheel.backend.material.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); } @Override protected Direction getShaftDirection() { - return tile.getBlockState().get(BlockStateProperties.FACING).getOpposite(); + return tile.getBlockState().getValue(BlockStateProperties.FACING).getOpposite(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/CasingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/CasingBlock.java index 75fb9c3d3..e3e1e4a0a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/CasingBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/CasingBlock.java @@ -29,7 +29,7 @@ public class CasingBlock extends Block implements IWrenchable { @Override public boolean canHarvestBlock(BlockState state, IBlockReader world, BlockPos pos, PlayerEntity player) { - for (ToolType toolType : player.getHeldItemMainhand().getToolTypes()) { + for (ToolType toolType : player.getMainHandItem().getToolTypes()) { if (isToolEffective(state, toolType)) return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/CutoutRotatingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/CutoutRotatingInstance.java new file mode 100644 index 000000000..65b164208 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/CutoutRotatingInstance.java @@ -0,0 +1,16 @@ +package com.simibubi.create.content.contraptions.base; + +import com.jozufozu.flywheel.backend.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.simibubi.create.foundation.render.AllMaterialSpecs; + +public class CutoutRotatingInstance extends SingleRotatingInstance { + public CutoutRotatingInstance(MaterialManager modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + protected InstanceMaterial getRotatingMaterial() { + return materialManager.defaultCutout() + .material(AllMaterialSpecs.ROTATING); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalAxisKineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalAxisKineticBlock.java index e3e4bc013..b51c78b95 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalAxisKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalAxisKineticBlock.java @@ -24,30 +24,30 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(AXIS_ALONG_FIRST_COORDINATE); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } protected Direction getFacingForPlacement(BlockItemUseContext context) { Direction facing = context.getNearestLookingDirection() .getOpposite(); if (context.getPlayer() != null && context.getPlayer() - .isSneaking()) + .isShiftKeyDown()) facing = facing.getOpposite(); return facing; } protected boolean getAxisAlignmentForPlacement(BlockItemUseContext context) { - return context.getPlacementHorizontalFacing() + return context.getHorizontalDirection() .getAxis() == Axis.X; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { Direction facing = getFacingForPlacement(context); - BlockPos pos = context.getPos(); - World world = context.getWorld(); + BlockPos pos = context.getClickedPos(); + World world = context.getLevel(); boolean alongFirst = false; Axis faceAxis = facing.getAxis(); @@ -70,7 +70,7 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc for (Direction side : Iterate.horizontalDirections) { if (!prefersConnectionTo(world, pos, side, true) - && !prefersConnectionTo(world, pos, side.rotateY(), false)) + && !prefersConnectionTo(world, pos, side.getClockWise(), false)) continue; if (prefferedSide != null && prefferedSide.getAxis() != side.getAxis()) { prefferedSide = null; @@ -83,15 +83,15 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc alongFirst = prefferedSide.getAxis() == Axis.X; } - return this.getDefaultState() - .with(FACING, facing) - .with(AXIS_ALONG_FIRST_COORDINATE, alongFirst); + return this.defaultBlockState() + .setValue(FACING, facing) + .setValue(AXIS_ALONG_FIRST_COORDINATE, alongFirst); } protected boolean prefersConnectionTo(IWorldReader reader, BlockPos pos, Direction facing, boolean shaftAxis) { if (!shaftAxis) return false; - BlockPos neighbourPos = pos.offset(facing); + BlockPos neighbourPos = pos.relative(facing); BlockState blockState = reader.getBlockState(neighbourPos); Block block = blockState.getBlock(); return block instanceof IRotate @@ -100,9 +100,9 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc @Override public Axis getRotationAxis(BlockState state) { - Axis pistonAxis = state.get(FACING) + Axis pistonAxis = state.getValue(FACING) .getAxis(); - boolean alongFirst = state.get(AXIS_ALONG_FIRST_COORDINATE); + boolean alongFirst = state.getValue(AXIS_ALONG_FIRST_COORDINATE); if (pistonAxis == Axis.X) return alongFirst ? Axis.Y : Axis.Z; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalKineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalKineticBlock.java index d6b43ef65..a95b29bda 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalKineticBlock.java @@ -21,20 +21,20 @@ public abstract class DirectionalKineticBlock extends KineticBlock { } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(FACING); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } public Direction getPreferredFacing(BlockItemUseContext context) { Direction prefferedSide = null; for (Direction side : Iterate.directions) { - BlockState blockState = context.getWorld() - .getBlockState(context.getPos() - .offset(side)); + BlockState blockState = context.getLevel() + .getBlockState(context.getClickedPos() + .relative(side)); if (blockState.getBlock() instanceof IRotate) { - if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getWorld(), context.getPos() - .offset(side), blockState, side.getOpposite())) + if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getLevel(), context.getClickedPos() + .relative(side), blockState, side.getOpposite())) if (prefferedSide != null && prefferedSide.getAxis() != side.getAxis()) { prefferedSide = null; break; @@ -50,22 +50,22 @@ public abstract class DirectionalKineticBlock extends KineticBlock { public BlockState getStateForPlacement(BlockItemUseContext context) { Direction preferred = getPreferredFacing(context); if (preferred == null || (context.getPlayer() != null && context.getPlayer() - .isSneaking())) { + .isShiftKeyDown())) { Direction nearestLookingDirection = context.getNearestLookingDirection(); - return getDefaultState().with(FACING, context.getPlayer() != null && context.getPlayer() - .isSneaking() ? nearestLookingDirection : nearestLookingDirection.getOpposite()); + return defaultBlockState().setValue(FACING, context.getPlayer() != null && context.getPlayer() + .isShiftKeyDown() ? nearestLookingDirection : nearestLookingDirection.getOpposite()); } - return getDefaultState().with(FACING, preferred.getOpposite()); + return defaultBlockState().setValue(FACING, preferred.getOpposite()); } @Override public BlockState rotate(BlockState state, Rotation rot) { - return state.with(FACING, rot.rotate(state.get(FACING))); + return state.setValue(FACING, rot.rotate(state.getValue(FACING))); } @Override public BlockState mirror(BlockState state, Mirror mirrorIn) { - return state.rotate(mirrorIn.toRotation(state.get(FACING))); + return state.rotate(mirrorIn.getRotation(state.getValue(FACING))); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/GeneratingKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/GeneratingKineticTileEntity.java index 916b8fe27..b96f34fff 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/GeneratingKineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/GeneratingKineticTileEntity.java @@ -36,7 +36,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity { @Override public void setSource(BlockPos source) { super.setSource(source); - TileEntity tileEntity = world.getTileEntity(source); + TileEntity tileEntity = level.getBlockEntity(source); if (!(tileEntity instanceof KineticTileEntity)) return; KineticTileEntity sourceTe = (KineticTileEntity) tileEntity; @@ -59,8 +59,8 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity { float stressBase = calculateAddedStressCapacity(); if (stressBase != 0 && IRotate.StressImpact.isEnabled()) { - tooltip.add(componentSpacing.copy().append(Lang.translate("gui.goggles.generator_stats"))); - tooltip.add(componentSpacing.copy().append(Lang.translate("tooltip.capacityProvided").formatted(TextFormatting.GRAY))); + tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.goggles.generator_stats"))); + tooltip.add(componentSpacing.plainCopy().append(Lang.translate("tooltip.capacityProvided").withStyle(TextFormatting.GRAY))); float speed = getTheoreticalSpeed(); if (speed != getGeneratedSpeed() && speed != 0) @@ -70,12 +70,12 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity { float stressTotal = stressBase * speed; tooltip.add( - componentSpacing.copy() + componentSpacing.plainCopy() .append(new StringTextComponent(" " + IHaveGoggleInformation.format(stressTotal)) .append(Lang.translate("generic.unit.stress")) - .formatted(TextFormatting.AQUA)) + .withStyle(TextFormatting.AQUA)) .append(" ") - .append(Lang.translate("gui.goggles.at_current_speed").formatted(TextFormatting.DARK_GRAY))); + .append(Lang.translate("gui.goggles.at_current_speed").withStyle(TextFormatting.DARK_GRAY))); added = true; } @@ -87,7 +87,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity { float speed = getGeneratedSpeed(); float prevSpeed = this.speed; - if (world.isRemote) + if (level.isClientSide) return; if (prevSpeed != speed) { @@ -141,7 +141,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity { // Staying below Overpowered speed if (Math.abs(prevSpeed) >= Math.abs(speed)) { if (Math.signum(prevSpeed) != Math.signum(speed)) - world.destroyBlock(pos, true); + level.destroyBlock(worldPosition, true); return; } @@ -161,6 +161,6 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity { } public Long createNetworkId() { - return pos.toLong(); + return worldPosition.asLong(); } } 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..c5fa91df2 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,24 +1,24 @@ package com.simibubi.create.content.contraptions.base; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.material.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); } protected Direction getShaftDirection() { - return blockState.get(BlockStateProperties.FACING); + return blockState.getValue(BlockStateProperties.FACING); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalAxisKineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalAxisKineticBlock.java index 659d87bc6..1aceb4799 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalAxisKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalAxisKineticBlock.java @@ -25,25 +25,25 @@ public abstract class HorizontalAxisKineticBlock extends KineticBlock { } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(HORIZONTAL_AXIS); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { Axis preferredAxis = getPreferredHorizontalAxis(context); if (preferredAxis != null) - return this.getDefaultState().with(HORIZONTAL_AXIS, preferredAxis); - return this.getDefaultState().with(HORIZONTAL_AXIS, context.getPlacementHorizontalFacing().rotateY().getAxis()); + return this.defaultBlockState().setValue(HORIZONTAL_AXIS, preferredAxis); + return this.defaultBlockState().setValue(HORIZONTAL_AXIS, context.getHorizontalDirection().getClockWise().getAxis()); } public static Axis getPreferredHorizontalAxis(BlockItemUseContext context) { Direction prefferedSide = null; for (Direction side : Iterate.horizontalDirections) { - BlockState blockState = context.getWorld().getBlockState(context.getPos().offset(side)); + BlockState blockState = context.getLevel().getBlockState(context.getClickedPos().relative(side)); if (blockState.getBlock() instanceof IRotate) { - if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getWorld(), context.getPos().offset(side), + if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getLevel(), context.getClickedPos().relative(side), blockState, side.getOpposite())) if (prefferedSide != null && prefferedSide.getAxis() != side.getAxis()) { prefferedSide = null; @@ -58,19 +58,19 @@ public abstract class HorizontalAxisKineticBlock extends KineticBlock { @Override public Axis getRotationAxis(BlockState state) { - return state.get(HORIZONTAL_AXIS); + return state.getValue(HORIZONTAL_AXIS); } @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.get(HORIZONTAL_AXIS); + return face.getAxis() == state.getValue(HORIZONTAL_AXIS); } @Override public BlockState rotate(BlockState state, Rotation rot) { - Axis axis = state.get(HORIZONTAL_AXIS); - return state.with(HORIZONTAL_AXIS, - rot.rotate(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis)).getAxis()); + Axis axis = state.getValue(HORIZONTAL_AXIS); + return state.setValue(HORIZONTAL_AXIS, + rot.rotate(Direction.get(AxisDirection.POSITIVE, axis)).getAxis()); } @Override 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..2ccdd215a 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,18 +1,18 @@ package com.simibubi.create.content.contraptions.base; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.jozufozu.flywheel.backend.material.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); } @Override protected Direction getShaftDirection() { - return blockState.get(BlockStateProperties.HORIZONTAL_FACING).getOpposite(); + return blockState.getValue(BlockStateProperties.HORIZONTAL_FACING).getOpposite(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalKineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalKineticBlock.java index e763f9f03..fb844a7f9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalKineticBlock.java @@ -21,27 +21,27 @@ public abstract class HorizontalKineticBlock extends KineticBlock { } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(HORIZONTAL_FACING); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - return this.getDefaultState() - .with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing() + return this.defaultBlockState() + .setValue(HORIZONTAL_FACING, context.getHorizontalDirection() .getOpposite()); } public Direction getPreferredHorizontalFacing(BlockItemUseContext context) { Direction prefferedSide = null; for (Direction side : Iterate.horizontalDirections) { - BlockState blockState = context.getWorld() - .getBlockState(context.getPos() - .offset(side)); + BlockState blockState = context.getLevel() + .getBlockState(context.getClickedPos() + .relative(side)); if (blockState.getBlock() instanceof IRotate) { - if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getWorld(), context.getPos() - .offset(side), blockState, side.getOpposite())) + if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getLevel(), context.getClickedPos() + .relative(side), blockState, side.getOpposite())) if (prefferedSide != null && prefferedSide.getAxis() != side.getAxis()) { prefferedSide = null; break; @@ -55,12 +55,12 @@ public abstract class HorizontalKineticBlock extends KineticBlock { @Override public BlockState rotate(BlockState state, Rotation rot) { - return state.with(HORIZONTAL_FACING, rot.rotate(state.get(HORIZONTAL_FACING))); + return state.setValue(HORIZONTAL_FACING, rot.rotate(state.getValue(HORIZONTAL_FACING))); } @Override public BlockState mirror(BlockState state, Mirror mirrorIn) { - return state.rotate(mirrorIn.toRotation(state.get(HORIZONTAL_FACING))); + return state.rotate(mirrorIn.getRotation(state.getValue(HORIZONTAL_FACING))); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/IRotate.java b/src/main/java/com/simibubi/create/content/contraptions/base/IRotate.java index 958290270..2f2540eb7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/IRotate.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/IRotate.java @@ -72,9 +72,9 @@ public interface IRotate extends IWrenchable { level.append(" (" + IHaveGoggleInformation.format(Math.abs(speed))).append(Lang.translate("generic.unit.rpm")).append(") "); if (overstressed) - level.formatted(TextFormatting.DARK_GRAY, TextFormatting.STRIKETHROUGH); + level.withStyle(TextFormatting.DARK_GRAY, TextFormatting.STRIKETHROUGH); else - level.formatted(speedLevel.getTextColor()); + level.withStyle(speedLevel.getTextColor()); return level; } @@ -115,7 +115,7 @@ public interface IRotate extends IWrenchable { level.append(String.format(" (%s%%) ", (int) (stressPercent * 100))); - return level.formatted(color); + return level.withStyle(color); } } 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/KineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java index 864737fae..c2dc5f863 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java @@ -31,7 +31,7 @@ public abstract class KineticBlock extends Block implements IRotate { @Override public boolean canHarvestBlock(BlockState state, IBlockReader world, BlockPos pos, PlayerEntity player) { - for (ToolType toolType : player.getHeldItemMainhand() + for (ToolType toolType : player.getMainHandItem() .getToolTypes()) { if (isToolEffective(state, toolType)) return true; @@ -45,13 +45,13 @@ public abstract class KineticBlock extends Block implements IRotate { } @Override - public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + public void onPlace(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { // onBlockAdded is useless for init, as sometimes the TE gets re-instantiated // however, if a block change occurs that does not change kinetic connections, // we can prevent a major re-propagation here - TileEntity tileEntity = worldIn.getTileEntity(pos); + TileEntity tileEntity = worldIn.getBlockEntity(pos); if (tileEntity instanceof KineticTileEntity) { KineticTileEntity kineticTileEntity = (KineticTileEntity) tileEntity; kineticTileEntity.preventSpeedUpdate = 0; @@ -78,6 +78,8 @@ public abstract class KineticBlock extends Block implements IRotate { } protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) { + if (oldState.getBlock() != newState.getBlock()) + return false; return getRotationAxis(newState) == getRotationAxis(oldState); } @@ -85,11 +87,11 @@ public abstract class KineticBlock extends Block implements IRotate { public abstract TileEntity createTileEntity(BlockState state, IBlockReader world); @Override - public void updateDiagonalNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags, int count) { - if (worldIn.isRemote()) + public void updateIndirectNeighbourShapes(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags, int count) { + if (worldIn.isClientSide()) return; - TileEntity tileEntity = worldIn.getTileEntity(pos); + TileEntity tileEntity = worldIn.getBlockEntity(pos); if (!(tileEntity instanceof KineticTileEntity)) return; KineticTileEntity kte = (KineticTileEntity) tileEntity; @@ -106,11 +108,11 @@ public abstract class KineticBlock extends Block implements IRotate { } @Override - public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { - if (worldIn.isRemote) + public void setPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + if (worldIn.isClientSide) return; - TileEntity tileEntity = worldIn.getTileEntity(pos); + TileEntity tileEntity = worldIn.getBlockEntity(pos); if (!(tileEntity instanceof KineticTileEntity)) return; 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..0b5b15595 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,10 +1,9 @@ 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.simibubi.create.foundation.utility.ColorHelper; +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.Color; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3f; @@ -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); } @@ -25,7 +24,7 @@ public class KineticData extends BasicData { } public KineticData setPosition(Vector3f pos) { - return setPosition(pos.getX(), pos.getY(), pos.getZ()); + return setPosition(pos.x(), pos.y(), pos.z()); } public KineticData setPosition(float x, float y, float z) { @@ -45,56 +44,39 @@ public class KineticData extends BasicData { } public KineticData setColor(KineticTileEntity te) { - if (te.hasSource()) { - setColor(te.network); + if (te.hasNetwork()) { + setColor(Color.generateFromLong(te.network)); }else { - setColor(0xFF, 0xFF, 0x00); - } - return this; - } - - public KineticData setColor(Long l) { - if (l != null) - return setColor(l.longValue()); - else { setColor(0xFF, 0xFF, 0xFF); - return this; } + return this; } - private KineticData setColor(long l) { - int color = ColorHelper.colorFromLong(l); - byte r = (byte) ((color >> 16) & 0xFF); - byte g = (byte) ((color >> 8) & 0xFF); - byte b = (byte) (color & 0xFF); - setColor(r, g, b); - - return this; + public KineticData setColor(Color c) { + setColor(c.getRed(), c.getGreen(), c.getBlue()); + return this; } 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/KineticEffectHandler.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticEffectHandler.java index 9e9d70c0b..6709d540e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticEffectHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticEffectHandler.java @@ -29,9 +29,9 @@ public class KineticEffectHandler { } public void tick() { - World world = kte.getWorld(); + World world = kte.getLevel(); - if (world.isRemote) { + if (world.isClientSide) { if (overStressedTime > 0) if (--overStressedTime == 0) if (kte.isOverStressed()) { @@ -59,15 +59,15 @@ public class KineticEffectHandler { } public void spawnEffect(IParticleData particle, float maxMotion, int amount) { - World world = kte.getWorld(); + World world = kte.getLevel(); if (world == null) return; - if (!world.isRemote) + if (!world.isClientSide) return; - Random r = world.rand; + Random r = world.random; for (int i = 0; i < amount; i++) { Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, r, maxMotion); - Vector3d position = VecHelper.getCenterOf(kte.getPos()); + Vector3d position = VecHelper.getCenterOf(kte.getBlockPos()); world.addParticle(particle, position.x, position.y, position.z, motion.x, motion.y, motion.z); } } @@ -87,8 +87,8 @@ public class KineticEffectHandler { float radius2 = kb.getParticleTargetRadius(); Axis axis = kb.getRotationAxis(state); - BlockPos pos = kte.getPos(); - World world = kte.getWorld(); + BlockPos pos = kte.getBlockPos(); + World world = kte.getLevel(); if (axis == null) return; if (world == null) @@ -105,7 +105,7 @@ public class KineticEffectHandler { AllTriggers.triggerForNearbyPlayers(AllTriggers.ROTATION, world, pos, 5); RotationIndicatorParticleData particleData = new RotationIndicatorParticleData(color, particleSpeed, radius1, radius2, 10, axisChar); - ((ServerWorld) world).spawnParticle(particleData, vec.x, vec.y, vec.z, 20, 0, 0, 0, 1); + ((ServerWorld) world).sendParticles(particleData, vec.x, vec.y, vec.z, 20, 0, 0, 0, 1); } } 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..930e89411 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; @@ -16,11 +18,11 @@ import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation; import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock; +import com.simibubi.create.foundation.block.BlockStressValues; 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; @@ -77,7 +79,7 @@ public abstract class KineticTileEntity extends SmartTileEntity @Override public void initialize() { - if (hasNetwork() && !world.isRemote) { + if (hasNetwork() && !level.isClientSide) { KineticNetwork network = getOrCreateNetwork(); if (!network.initialized) network.initFromTE(capacity, stress, networkSize); @@ -89,13 +91,13 @@ public abstract class KineticTileEntity extends SmartTileEntity @Override public void tick() { - if (!world.isRemote && needsSpeedUpdate()) + if (!level.isClientSide && needsSpeedUpdate()) attachKinetics(); super.tick(); effects.tick(); - if (world.isRemote) { + if (level.isClientSide) { cachedBoundingBox = null; // cache the bounding box for every frame between ticks DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio()); return; @@ -123,10 +125,10 @@ public abstract class KineticTileEntity extends SmartTileEntity return; } - if (!world.isBlockPresent(source)) + if (!level.isLoaded(source)) return; - TileEntity tileEntity = world.getTileEntity(source); + TileEntity tileEntity = level.getBlockEntity(source); KineticTileEntity sourceTe = tileEntity instanceof KineticTileEntity ? (KineticTileEntity) tileEntity : null; if (sourceTe == null || sourceTe.speed == 0) { @@ -159,22 +161,22 @@ public abstract class KineticTileEntity extends SmartTileEntity } } - public float calculateAddedStressCapacity() { - float capacity = (float) AllConfigs.SERVER.kinetics.stressValues.getCapacityOf(getStressConfigKey()); - this.lastCapacityProvided = capacity; - return capacity; - } - protected Block getStressConfigKey() { return getBlockState().getBlock(); } public float calculateStressApplied() { - float impact = (float) AllConfigs.SERVER.kinetics.stressValues.getImpactOf(getStressConfigKey()); + float impact = (float) BlockStressValues.getImpact(getStressConfigKey()); this.lastStressApplied = impact; return impact; } + public float calculateAddedStressCapacity() { + float capacity = (float) BlockStressValues.getCapacity(getStressConfigKey()); + this.lastCapacityProvided = capacity; + return capacity; + } + public void onSpeedChanged(float previousSpeed) { boolean fromOrToZero = (previousSpeed == 0) != (getSpeed() == 0); boolean directionSwap = !fromOrToZero && Math.signum(previousSpeed) != Math.signum(getSpeed()); @@ -183,13 +185,13 @@ public abstract class KineticTileEntity extends SmartTileEntity } @Override - public void remove() { - if (!world.isRemote) { + public void setRemoved() { + if (!level.isClientSide) { if (hasNetwork()) getOrCreateNetwork().remove(this); detachKinetics(); } - super.remove(); + super.setRemoved(); } @Override @@ -257,7 +259,7 @@ public abstract class KineticTileEntity extends SmartTileEntity effects.triggerOverStressedEffect(); if (clientPacket) - FastRenderDispatcher.enqueueUpdate(this); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } public float getGeneratedSpeed() { @@ -288,10 +290,10 @@ public abstract class KineticTileEntity extends SmartTileEntity public void setSource(BlockPos source) { this.source = source; - if (world == null || world.isRemote) + if (level == null || level.isClientSide) return; - TileEntity tileEntity = world.getTileEntity(source); + TileEntity tileEntity = level.getBlockEntity(source); if (!(tileEntity instanceof KineticTileEntity)) { removeSource(); return; @@ -329,7 +331,7 @@ public abstract class KineticTileEntity extends SmartTileEntity } public KineticNetwork getOrCreateNetwork() { - return Create.torquePropagator.getOrCreateNetworkFor(this); + return Create.TORQUE_PROPAGATOR.getOrCreateNetworkFor(this); } public boolean hasNetwork() { @@ -338,11 +340,11 @@ public abstract class KineticTileEntity extends SmartTileEntity public void attachKinetics() { updateSpeed = false; - RotationPropagator.handleAdded(world, pos, this); + RotationPropagator.handleAdded(level, worldPosition, this); } public void detachKinetics() { - RotationPropagator.handleRemoved(world, pos, this); + RotationPropagator.handleRemoved(level, worldPosition, this); } public boolean isSpeedRequirementFulfilled() { @@ -361,17 +363,17 @@ public abstract class KineticTileEntity extends SmartTileEntity } public static void switchToBlockState(World world, BlockPos pos, BlockState state) { - if (world.isRemote) + if (world.isClientSide) return; - TileEntity tileEntityIn = world.getTileEntity(pos); + TileEntity tileEntityIn = world.getBlockEntity(pos); BlockState currentState = world.getBlockState(pos); boolean isKinetic = tileEntityIn instanceof KineticTileEntity; if (currentState == state) return; if (tileEntityIn == null || !isKinetic) { - world.setBlockState(pos, state, 3); + world.setBlock(pos, state, 3); return; } @@ -385,7 +387,7 @@ public abstract class KineticTileEntity extends SmartTileEntity tileEntity.removeSource(); } - world.setBlockState(pos, state, 3); + world.setBlock(pos, state, 3); } @Override @@ -396,27 +398,27 @@ public abstract class KineticTileEntity extends SmartTileEntity boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0; if (overStressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) { - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.stressometer.overstressed") - .formatted(GOLD))); + .withStyle(GOLD))); ITextComponent hint = Lang.translate("gui.contraptions.network_overstressed"); List cutString = TooltipHelper.cutTextComponent(hint, GRAY, TextFormatting.WHITE); for (int i = 0; i < cutString.size(); i++) - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(cutString.get(i))); return true; } if (notFastEnough) { - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("tooltip.speedRequirement") - .formatted(GOLD))); + .withStyle(GOLD))); ITextComponent hint = - Lang.translate("gui.contraptions.not_fast_enough", I18n.format(getBlockState().getBlock() - .getTranslationKey())); + Lang.translate("gui.contraptions.not_fast_enough", I18n.get(getBlockState().getBlock() + .getDescriptionId())); List cutString = TooltipHelper.cutTextComponent(hint, GRAY, TextFormatting.WHITE); for (int i = 0; i < cutString.size(); i++) - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(cutString.get(i))); return true; } @@ -430,21 +432,21 @@ public abstract class KineticTileEntity extends SmartTileEntity float stressAtBase = calculateStressApplied(); if (calculateStressApplied() != 0 && StressImpact.isEnabled()) { - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.goggles.kinetic_stats"))); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("tooltip.stressImpact") - .formatted(TextFormatting.GRAY))); + .withStyle(TextFormatting.GRAY))); float stressTotal = stressAtBase * Math.abs(getTheoreticalSpeed()); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(new StringTextComponent(" " + IHaveGoggleInformation.format(stressTotal)) .append(Lang.translate("generic.unit.stress")) .append(" ") - .formatted(TextFormatting.AQUA)) + .withStyle(TextFormatting.AQUA)) .append(Lang.translate("gui.goggles.at_current_speed") - .formatted(TextFormatting.DARK_GRAY))); + .withStyle(TextFormatting.DARK_GRAY))); added = true; } @@ -476,6 +478,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; } @@ -517,13 +527,13 @@ public abstract class KineticTileEntity extends SmartTileEntity return neighbours; Axis axis = block.getRotationAxis(state); - BlockPos.getAllInBox(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) + BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) .forEach(offset -> { - if (axis.getCoordinate(offset.getX(), offset.getY(), offset.getZ()) != 0) + if (axis.choose(offset.getX(), offset.getY(), offset.getZ()) != 0) return; - if (offset.distanceSq(0, 0, 0, false) != BlockPos.ZERO.distanceSq(1, 1, 0, false)) + if (offset.distSqr(0, 0, 0, false) != BlockPos.ZERO.distSqr(1, 1, 0, false)) return; - neighbours.add(pos.add(offset)); + neighbours.add(worldPosition.offset(offset)); }); return neighbours; } @@ -551,9 +561,8 @@ public abstract class KineticTileEntity extends SmartTileEntity @Override public void requestModelDataUpdate() { super.requestModelDataUpdate(); - if (!this.removed) { - FastRenderDispatcher.enqueueUpdate(this); - } + if (!this.remove) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } protected AxisAlignedBB cachedBoundingBox; @@ -575,18 +584,19 @@ 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, worldPosition, pitch); Block block = getBlockState().getBlock(); if (ICogWheel.isSmallCog(block) || ICogWheel.isLargeCog(block) || block instanceof GearboxBlock) - SoundScapes.playCogwheelAmbience(pos, pitch); + SoundScapes.play(AmbienceGroup.COG, worldPosition, pitch); } protected boolean isNoisy() { return true; } + } 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..5961777ca 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,10 +9,9 @@ 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; +import com.simibubi.create.foundation.utility.Color; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -26,7 +26,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -@EventBusSubscriber(value = Dist.CLIENT) +@EventBusSubscriber(Dist.CLIENT) public class KineticTileEntityRenderer extends SafeTileEntityRenderer { public static final Compartment KINETIC_TILE = new Compartment<>(); @@ -39,16 +39,16 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer 0) - buffer.color(ColorHelper.mixColors(white, 0xFF0000, overStressedEffect)); + buffer.color(Color.WHITE.mixWith(Color.RED, overStressedEffect)); else - buffer.color(ColorHelper.mixColors(white, 0x00FFBB, -overStressedEffect)); + buffer.color(Color.WHITE.mixWith(Color.SPRING_GREEN, -overStressedEffect)); else - buffer.color(white); + buffer.color(Color.WHITE); } return buffer; @@ -107,7 +106,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,12 +84,13 @@ public abstract class KineticTileInstance extends T return shaft(getRotationAxis()); } - protected final RenderMaterial> getRotatingMaterial() { - return renderer.getMaterial(KineticRenderMaterials.ROTATING); - } + protected InstanceMaterial getRotatingMaterial() { + return materialManager.defaultSolid() + .material(AllMaterialSpecs.ROTATING); + } public static BlockState shaft(Direction.Axis axis) { return AllBlocks.SHAFT.getDefaultState() - .with(ShaftBlock.AXIS, axis); + .setValue(ShaftBlock.AXIS, axis); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java index 75c45893c..16dbd32a3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java @@ -18,8 +18,8 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock { public RotatedPillarKineticBlock(Properties properties) { super(properties); - this.setDefaultState(this.getDefaultState() - .with(AXIS, Direction.Axis.Y)); + this.registerDefaultState(this.defaultBlockState() + .setValue(AXIS, Direction.Axis.Y)); } @Override @@ -27,11 +27,11 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock { switch (rot) { case COUNTERCLOCKWISE_90: case CLOCKWISE_90: - switch (state.get(AXIS)) { + switch (state.getValue(AXIS)) { case X: - return state.with(AXIS, Direction.Axis.Z); + return state.setValue(AXIS, Direction.Axis.Z); case Z: - return state.with(AXIS, Direction.Axis.X); + return state.setValue(AXIS, Direction.Axis.X); default: return state; } @@ -43,12 +43,12 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock { public static Axis getPreferredAxis(BlockItemUseContext context) { Axis prefferedAxis = null; for (Direction side : Iterate.directions) { - BlockState blockState = context.getWorld() - .getBlockState(context.getPos() - .offset(side)); + BlockState blockState = context.getLevel() + .getBlockState(context.getClickedPos() + .relative(side)); if (blockState.getBlock() instanceof IRotate) { - if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getWorld(), context.getPos() - .offset(side), blockState, side.getOpposite())) + if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getLevel(), context.getClickedPos() + .relative(side), blockState, side.getOpposite())) if (prefferedAxis != null && prefferedAxis != side.getAxis()) { prefferedAxis = null; break; @@ -61,7 +61,7 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock { } @Override - protected void fillStateContainer(StateContainer.Builder builder) { + protected void createBlockStateDefinition(StateContainer.Builder builder) { builder.add(AXIS); } @@ -69,12 +69,12 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock { public BlockState getStateForPlacement(BlockItemUseContext context) { Axis preferredAxis = getPreferredAxis(context); if (preferredAxis != null && (context.getPlayer() == null || !context.getPlayer() - .isSneaking())) - return this.getDefaultState() - .with(AXIS, preferredAxis); - return this.getDefaultState() - .with(AXIS, preferredAxis != null && context.getPlayer() - .isSneaking() ? context.getFace() + .isShiftKeyDown())) + return this.defaultBlockState() + .setValue(AXIS, preferredAxis); + return this.defaultBlockState() + .setValue(AXIS, preferredAxis != null && context.getPlayer() + .isShiftKeyDown() ? context.getClickedFace() .getAxis() : context.getNearestLookingDirection() .getAxis()); 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..b155b5fba 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,33 +11,33 @@ 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); - setRotationAxis(orientation.getUnitVector()); + Direction orientation = Direction.get(Direction.AxisDirection.POSITIVE, axis); + setRotationAxis(orientation.step()); return this; } public RotatingData setRotationAxis(Vector3f axis) { - setRotationAxis(axis.getX(), axis.getY(), axis.getZ()); + setRotationAxis(axis.x(), axis.y(), axis.z()); 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..e7b747d02 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,20 @@ package com.simibubi.create.content.contraptions.base; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.material.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.defaultSolid() + .material(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..90a5efdb6 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.material.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/AssemblyOperatorBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorBlockItem.java new file mode 100644 index 000000000..b39595fb7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorBlockItem.java @@ -0,0 +1,54 @@ +package com.simibubi.create.content.contraptions.components; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; +import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItem; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.vector.Vector3d; + +public class AssemblyOperatorBlockItem extends BlockItem { + + public AssemblyOperatorBlockItem(Block block, Properties builder) { + super(block, builder); + } + + @Override + public ActionResultType place(BlockItemUseContext context) { + BlockPos placedOnPos = context.getClickedPos() + .relative(context.getClickedFace() + .getOpposite()); + BlockState placedOnState = context.getLevel() + .getBlockState(placedOnPos); + if (operatesOn(placedOnState) && context.getClickedFace() == Direction.UP) { + if (context.getLevel() + .getBlockState(placedOnPos.above(2)) + .getMaterial() + .isReplaceable()) + context = adjustContext(context, placedOnPos); + else + return ActionResultType.FAIL; + } + + return super.place(context); + } + + protected BlockItemUseContext adjustContext(BlockItemUseContext context, BlockPos placedOnPos) { + BlockPos up = placedOnPos.above(2); + return new AssemblyOperatorUseContext(context.getLevel(), context.getPlayer(), context.getHand(), context.getItemInHand(), new BlockRayTraceResult(new Vector3d((double)up.getX() + 0.5D + (double) Direction.UP.getStepX() * 0.5D, (double)up.getY() + 0.5D + (double) Direction.UP.getStepY() * 0.5D, (double)up.getZ() + 0.5D + (double) Direction.UP.getStepZ() * 0.5D), Direction.UP, up, false)); + } + + protected boolean operatesOn(BlockState placedOnState) { + if (AllBlocks.BELT.has(placedOnState)) + return placedOnState.getValue(BeltBlock.SLOPE) == BeltSlope.HORIZONTAL; + return AllBlocks.BASIN.has(placedOnState) || AllBlocks.DEPOT.has(placedOnState) || AllBlocks.WEIGHTED_EJECTOR.has(placedOnState); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorUseContext.java b/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorUseContext.java new file mode 100644 index 000000000..80fde6127 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorUseContext.java @@ -0,0 +1,16 @@ +package com.simibubi.create.content.contraptions.components; + +import javax.annotation.Nullable; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.world.World; + +public class AssemblyOperatorUseContext extends BlockItemUseContext { + public AssemblyOperatorUseContext(World p_i50056_1_, @Nullable PlayerEntity p_i50056_2_, Hand p_i50056_3_, ItemStack p_i50056_4_, BlockRayTraceResult p_i50056_5_) { + super(p_i50056_1_, p_i50056_2_, p_i50056_3_, p_i50056_4_, p_i50056_5_); + } +} 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..cc3e6535c 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) { @@ -67,7 +66,7 @@ public class ActorData extends InstanceData { } public ActorData setRotationAxis(Vector3f axis) { - setRotationAxis(axis.getX(), axis.getY(), axis.getZ()); + setRotationAxis(axis.x(), axis.y(), axis.z()); return this; } @@ -80,7 +79,7 @@ public class ActorData extends InstanceData { } public ActorData setRotationCenter(Vector3f axis) { - setRotationCenter(axis.getX(), axis.getY(), axis.getZ()); + setRotationCenter(axis.x(), axis.y(), axis.z()); return this; } @@ -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.i(); + this.qY = q.j(); + this.qZ = q.k(); + this.qW = q.r(); + 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/AttachedActorBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/AttachedActorBlock.java index c9ea4bac8..827540eac 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/AttachedActorBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/AttachedActorBlock.java @@ -37,41 +37,41 @@ public abstract class AttachedActorBlock extends HorizontalBlock implements IWre @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - Direction direction = state.get(HORIZONTAL_FACING); + Direction direction = state.getValue(FACING); return AllShapes.HARVESTER_BASE.get(direction); } @Override - protected void fillStateContainer(Builder builder) { - builder.add(HORIZONTAL_FACING); - super.fillStateContainer(builder); + protected void createBlockStateDefinition(Builder builder) { + builder.add(FACING); + super.createBlockStateDefinition(builder); } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - Direction direction = state.get(HORIZONTAL_FACING); - BlockPos offset = pos.offset(direction.getOpposite()); + public boolean canSurvive(BlockState state, IWorldReader worldIn, BlockPos pos) { + Direction direction = state.getValue(FACING); + BlockPos offset = pos.relative(direction.getOpposite()); return BlockHelper.hasBlockSolidSide(worldIn.getBlockState(offset), worldIn, offset, direction); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { Direction facing; - if (context.getFace().getAxis().isVertical()) - facing = context.getPlacementHorizontalFacing().getOpposite(); + if (context.getClickedFace().getAxis().isVertical()) + facing = context.getHorizontalDirection().getOpposite(); else { BlockState blockState = - context.getWorld().getBlockState(context.getPos().offset(context.getFace().getOpposite())); + context.getLevel().getBlockState(context.getClickedPos().relative(context.getClickedFace().getOpposite())); if (blockState.getBlock() instanceof AttachedActorBlock) - facing = blockState.get(HORIZONTAL_FACING); + facing = blockState.getValue(FACING); else - facing = context.getFace(); + facing = context.getClickedFace(); } - return getDefaultState().with(HORIZONTAL_FACING, facing); + return defaultBlockState().setValue(FACING, facing); } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java index 58417de15..b635039d8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java @@ -2,13 +2,17 @@ package com.simibubi.create.content.contraptions.components.actors; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.curiosities.bell.AbstractBellBlock; +import net.minecraft.block.Block; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.World; public class BellMovementBehaviour extends MovementBehaviour { + @Override public boolean renderAsNormalTileEntity() { return true; @@ -16,17 +20,29 @@ public class BellMovementBehaviour extends MovementBehaviour { @Override public void onSpeedChanged(MovementContext context, Vector3d oldMotion, Vector3d motion) { - double dotProduct = oldMotion.dotProduct(motion); + double dotProduct = oldMotion.dot(motion); if (dotProduct <= 0 && (context.relativeMotion.length() != 0) || context.firstMovement) - context.world.playSound(null, new BlockPos(context.position), SoundEvents.BLOCK_BELL_USE, - SoundCategory.BLOCKS, 2.0F, 1.0F); + playSound(context); } @Override public void stopMoving(MovementContext context) { if (context.position != null) - context.world.playSound(null, new BlockPos(context.position), SoundEvents.BLOCK_BELL_USE, SoundCategory.BLOCKS, - 2.0F, 1.0F); + playSound(context); + } + + public static void playSound(MovementContext context) { + World world = context.world; + BlockPos pos = new BlockPos(context.position); + Block block = context.state.getBlock(); + + if (block instanceof AbstractBellBlock) { + ((AbstractBellBlock) block).playSound(world, pos); + } else { + // Vanilla bell sound + world.playSound(null, pos, SoundEvents.BELL_BLOCK, + SoundCategory.BLOCKS, 2f, 1f); + } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java index a74d1a200..a9b11e083 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java @@ -77,17 +77,17 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { } @Override - public void remove() { - if (!world.isRemote && destroyProgress != 0) - world.sendBlockBreakProgress(breakerId, breakingPos, -1); - super.remove(); + public void setRemoved() { + if (!level.isClientSide && destroyProgress != 0) + level.destroyBlockProgress(breakerId, breakingPos, -1); + super.setRemoved(); } @Override public void tick() { super.tick(); - if (world.isRemote) + if (level.isClientSide) return; if (!shouldRun()) return; @@ -101,31 +101,31 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { if (ticksUntilNextProgress-- > 0) return; - BlockState stateToBreak = world.getBlockState(breakingPos); - float blockHardness = stateToBreak.getBlockHardness(world, breakingPos); + BlockState stateToBreak = level.getBlockState(breakingPos); + float blockHardness = stateToBreak.getDestroySpeed(level, breakingPos); if (!canBreak(stateToBreak, blockHardness)) { if (destroyProgress != 0) { destroyProgress = 0; - world.sendBlockBreakProgress(breakerId, breakingPos, -1); + level.destroyBlockProgress(breakerId, breakingPos, -1); } return; } float breakSpeed = getBreakSpeed(); destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); - world.playSound(null, pos, stateToBreak.getSoundType().getHitSound(), SoundCategory.NEUTRAL, .25f, 1); + level.playSound(null, worldPosition, stateToBreak.getSoundType().getHitSound(), SoundCategory.NEUTRAL, .25f, 1); if (destroyProgress >= 10) { onBlockBroken(stateToBreak); destroyProgress = 0; ticksUntilNextProgress = -1; - world.sendBlockBreakProgress(breakerId, breakingPos, -1); + level.destroyBlockProgress(breakerId, breakingPos, -1); return; } ticksUntilNextProgress = (int) (blockHardness / breakSpeed); - world.sendBlockBreakProgress(breakerId, breakingPos, (int) destroyProgress); + level.destroyBlockProgress(breakerId, breakingPos, (int) destroyProgress); } public boolean canBreak(BlockState stateToBreak, float blockHardness) { @@ -138,23 +138,23 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { } public void onBlockBroken(BlockState stateToBreak) { - FluidState FluidState = world.getFluidState(breakingPos); - world.playEvent(2001, breakingPos, Block.getStateId(stateToBreak)); - TileEntity tileentity = stateToBreak.hasTileEntity() ? world.getTileEntity(breakingPos) : null; - Vector3d vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(breakingPos), world.rand, .125f); + FluidState FluidState = level.getFluidState(breakingPos); + level.levelEvent(2001, breakingPos, Block.getId(stateToBreak)); + TileEntity tileentity = stateToBreak.hasTileEntity() ? level.getBlockEntity(breakingPos) : null; + Vector3d vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(breakingPos), level.random, .125f); - Block.getDrops(stateToBreak, (ServerWorld) world, breakingPos, tileentity).forEach((stack) -> { - if (!stack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS) - && !world.restoringBlockSnapshots) { - ItemEntity itementity = new ItemEntity(world, vec.x, vec.y, vec.z, stack); - itementity.setDefaultPickupDelay(); - itementity.setMotion(Vector3d.ZERO); - world.addEntity(itementity); + Block.getDrops(stateToBreak, (ServerWorld) level, breakingPos, tileentity).forEach((stack) -> { + if (!stack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) + && !level.restoringBlockSnapshots) { + ItemEntity itementity = new ItemEntity(level, vec.x, vec.y, vec.z, stack); + itementity.setDefaultPickUpDelay(); + itementity.setDeltaMovement(Vector3d.ZERO); + level.addFreshEntity(itementity); } }); - if (world instanceof ServerWorld) - stateToBreak.spawnAdditionalDrops((ServerWorld) world, breakingPos, ItemStack.EMPTY); - world.setBlockState(breakingPos, FluidState.getBlockState(), 3); + if (level instanceof ServerWorld) + stateToBreak.spawnAfterBreak((ServerWorld) level, breakingPos, ItemStack.EMPTY); + level.setBlock(breakingPos, FluidState.createLegacyBlock(), 3); } protected float getBreakSpeed() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java index 14c090563..b23ce8153 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java @@ -25,7 +25,7 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { @Override public void startMoving(MovementContext context) { - if (context.world.isRemote) + if (context.world.isClientSide) return; context.data.putInt("BreakerId", -BlockBreakingKineticTileEntity.NEXT_BREAKER_ID.incrementAndGet()); } @@ -35,9 +35,9 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { World world = context.world; BlockState stateVisited = world.getBlockState(pos); - if (!stateVisited.isNormalCube(world, pos)) + if (!stateVisited.isRedstoneConductor(world, pos)) damageEntities(context, pos, world); - if (world.isRemote) + if (world.isClientSide) return; if (!canBreak(world, pos, stateVisited)) return; @@ -50,29 +50,29 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { DamageSource damageSource = getDamageSource(); if (damageSource == null && !throwsEntities()) return; - Entities: for (Entity entity : world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos))) { + Entities: for (Entity entity : world.getEntitiesOfClass(Entity.class, new AxisAlignedBB(pos))) { if (entity instanceof ItemEntity) continue; if (entity instanceof AbstractContraptionEntity) continue; if (entity instanceof AbstractMinecartEntity) - for (Entity passenger : entity.getRecursivePassengers()) + for (Entity passenger : entity.getIndirectPassengers()) if (passenger instanceof AbstractContraptionEntity && ((AbstractContraptionEntity) passenger).getContraption() == context.contraption) continue Entities; - if (damageSource != null && !world.isRemote) { + if (damageSource != null && !world.isClientSide) { float damage = (float) MathHelper.clamp(6 * Math.pow(context.relativeMotion.length(), 0.4) + 1, 2, 10); - entity.attackEntityFrom(damageSource, damage); + entity.hurt(damageSource, damage); } - if (throwsEntities() && (world.isRemote == (entity instanceof PlayerEntity))) { + if (throwsEntities() && (world.isClientSide == (entity instanceof PlayerEntity))) { Vector3d motionBoost = context.motion.add(0, context.motion.length() / 4f, 0); int maxBoost = 4; if (motionBoost.length() > maxBoost) { motionBoost = motionBoost.subtract(motionBoost.normalize().scale(motionBoost.length() - maxBoost)); } - entity.setMotion(entity.getMotion().add(motionBoost)); - entity.velocityChanged = true; + entity.setDeltaMovement(entity.getDeltaMovement().add(motionBoost)); + entity.hurtMarked = true; } } } @@ -88,7 +88,7 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { @Override public void stopMoving(MovementContext context) { CompoundNBT data = context.data; - if (context.world.isRemote) + if (context.world.isClientSide) return; if (!data.contains("BreakingPos")) return; @@ -102,7 +102,7 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { data.remove("BreakingPos"); context.stall = false; - world.sendBlockBreakProgress(id, breakingPos, -1); + world.destroyBlockProgress(id, breakingPos, -1); } @Override @@ -129,7 +129,7 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { public void tickBreaker(MovementContext context) { CompoundNBT data = context.data; - if (context.world.isRemote) + if (context.world.isClientSide) return; if (!data.contains("BreakingPos")) return; @@ -149,7 +149,7 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { int destroyProgress = data.getInt("Progress"); int id = data.getInt("BreakerId"); BlockState stateToBreak = world.getBlockState(breakingPos); - float blockHardness = stateToBreak.getBlockHardness(world, breakingPos); + float blockHardness = stateToBreak.getDestroySpeed(world, breakingPos); if (!canBreak(world, breakingPos, stateToBreak)) { if (destroyProgress != 0) { @@ -157,7 +157,7 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { data.remove("Progress"); data.remove("TicksUntilNextProgress"); data.remove("BreakingPos"); - world.sendBlockBreakProgress(id, breakingPos, -1); + world.destroyBlockProgress(id, breakingPos, -1); } context.stall = false; return; @@ -166,20 +166,21 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { float breakSpeed = MathHelper.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f); destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); world.playSound(null, breakingPos, stateToBreak.getSoundType().getHitSound(), SoundCategory.NEUTRAL, .25f, 1); - + if (destroyProgress >= 10) { - world.sendBlockBreakProgress(id, breakingPos, -1); - + world.destroyBlockProgress(id, breakingPos, -1); + // break falling blocks from top to bottom BlockPos ogPos = breakingPos; - BlockState stateAbove = world.getBlockState(breakingPos.up()); + BlockState stateAbove = world.getBlockState(breakingPos.above()); while (stateAbove.getBlock() instanceof FallingBlock) { - breakingPos = breakingPos.up(); - stateAbove = world.getBlockState(breakingPos.up()); + breakingPos = breakingPos.above(); + stateAbove = world.getBlockState(breakingPos.above()); } stateToBreak = world.getBlockState(breakingPos); - + context.stall = false; + if (shouldDestroyStartBlock(stateToBreak)) BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack)); onBlockBroken(context, ogPos, stateToBreak); ticksUntilNextProgress = -1; @@ -190,13 +191,17 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour { } ticksUntilNextProgress = (int) (blockHardness / breakSpeed); - world.sendBlockBreakProgress(id, breakingPos, (int) destroyProgress); + world.destroyBlockProgress(id, breakingPos, (int) destroyProgress); data.putInt("TicksUntilNextProgress", ticksUntilNextProgress); data.putInt("Progress", destroyProgress); } + protected boolean shouldDestroyStartBlock(BlockState stateToBreak) { + return true; + } + public boolean canBreak(World world, BlockPos breakingPos, BlockState state) { - float blockHardness = state.getBlockHardness(world, breakingPos); + float blockHardness = state.getDestroySpeed(world, breakingPos); return BlockBreakingKineticTileEntity.isBreakable(state, blockHardness); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java index e27cffee5..39ac14bce 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java @@ -16,20 +16,20 @@ public class CampfireMovementBehaviour extends MovementBehaviour { @Override public void tick(MovementContext context) { - if (context.world == null || !context.world.isRemote || context.position == null - || !context.state.get(CampfireBlock.LIT)) + if (context.world == null || !context.world.isClientSide || context.position == null + || !context.state.getValue(CampfireBlock.LIT)) return; // Mostly copied from CampfireBlock and CampfireTileEntity - Random random = context.world.rand; + Random random = context.world.random; if (random.nextFloat() < 0.11F) { for (int i = 0; i < random.nextInt(2) + 2; ++i) { - context.world.addOptionalParticle( - context.state.get(CampfireBlock.SIGNAL_FIRE) ? ParticleTypes.CAMPFIRE_SIGNAL_SMOKE + context.world.addAlwaysVisibleParticle( + context.state.getValue(CampfireBlock.SIGNAL_FIRE) ? ParticleTypes.CAMPFIRE_SIGNAL_SMOKE : ParticleTypes.CAMPFIRE_COSY_SMOKE, - true, context.position.getX() + random.nextDouble() / (random.nextBoolean() ? 3D : -3D), - context.position.getY() + random.nextDouble() + random.nextDouble(), - context.position.getZ() + random.nextDouble() / (random.nextBoolean() ? 3D : -3D), 0.0D, 0.07D, + true, context.position.x() + random.nextDouble() / (random.nextBoolean() ? 3D : -3D), + context.position.y() + random.nextDouble() + random.nextDouble(), + context.position.z() + random.nextDouble() / (random.nextBoolean() ? 3D : -3D), 0.0D, 0.07D, 0.0D); } } 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..c142cd2cf 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.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.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,16 +17,17 @@ 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.defaultSolid() + .material(AllMaterialSpecs.ACTORS); BlockState state = context.state; - facing = state.get(DrillBlock.FACING); + facing = state.getValue(DrillBlock.FACING); Direction.Axis axis = facing.getAxis(); float eulerX = AngleHelper.verticalAngle(facing); @@ -34,9 +36,9 @@ public class DrillActorInstance extends ActorInstance { if (axis == Direction.Axis.Y) eulerY = 0; else - eulerY = facing.getHorizontalAngle() + ((axis == Direction.Axis.X) ? 180 : 0); + eulerY = facing.toYRot() + ((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/DrillBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillBlock.java index b7c9d029a..0e0a95fba 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillBlock.java @@ -30,7 +30,7 @@ import net.minecraft.world.World; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class DrillBlock extends DirectionalKineticBlock implements ITE { - public static DamageSource damageSourceDrill = new DamageSource("create.mechanical_drill").setDamageBypassesArmor(); + public static DamageSource damageSourceDrill = new DamageSource("create.mechanical_drill").bypassArmor(); public DrillBlock(Properties properties) { super(properties); @@ -42,15 +42,15 @@ public class DrillBlock extends DirectionalKineticBlock implements ITE { if (te.getSpeed() == 0) return; - entityIn.attackEntityFrom(damageSourceDrill, (float) getDamage(te.getSpeed())); + entityIn.hurt(damageSourceDrill, (float) getDamage(te.getSpeed())); }); } @@ -61,7 +61,7 @@ public class DrillBlock extends DirectionalKineticBlock implements ITE 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); + Direction facing = referenceState.getValue(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..8942b48c5 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.material.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; @@ -22,22 +23,22 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { @Override public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.get(DrillBlock.FACING) + return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(DrillBlock.FACING) .getOpposite()); } @Override public Vector3d getActiveAreaOffset(MovementContext context) { - return Vector3d.of(context.state.get(DrillBlock.FACING) - .getDirectionVec()).scale(.65f); + return Vector3d.atLowerCornerOf(context.state.getValue(DrillBlock.FACING) + .getNormal()).scale(.65f); } @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..7270d25ec 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 @@ -1,16 +1,19 @@ package com.simibubi.create.content.contraptions.components.actors; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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.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,12 +32,11 @@ 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); + Direction facing = state.getValue(DrillBlock.FACING); float speed = (float) (context.contraption.stalled || !VecHelper.isVecPointingTowards(context.relativeMotion, 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.getModel(); + m.pushPose(); + MatrixTransformStack.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.getWorld(), + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid())); + + m.popPose(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillTileEntity.java index 065d18491..6c124890e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillTileEntity.java @@ -11,7 +11,7 @@ public class DrillTileEntity extends BlockBreakingKineticTileEntity { @Override protected BlockPos getBreakingPos() { - return getPos().offset(getBlockState().get(DrillBlock.FACING)); + return getBlockPos().relative(getBlockState().getValue(DrillBlock.FACING)); } } 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..936a88bb5 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,19 @@ package com.simibubi.create.content.contraptions.components.actors; import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING; +import com.jozufozu.flywheel.backend.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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,18 +34,19 @@ 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.defaultCutout() + .material(Materials.TRANSFORMED); BlockState state = context.state; - facing = state.get(HORIZONTAL_FACING); + facing = state.getValue(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); + horizontalAngle = facing.toYRot() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0); harvester.setBlockLight(localBlockLight()); } @@ -74,7 +76,7 @@ public class HarvesterActorInstance extends ActorInstance { @Override public void beginFrame() { MatrixStack ms = new MatrixStack(); - MatrixStacker msr = MatrixStacker.of(ms); + MatrixTransformStack msr = MatrixTransformStack.of(ms); msr.translate(context.localPos) .centre() 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..e7f604707 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 @@ -1,32 +1,37 @@ package com.simibubi.create.content.contraptions.components.actors; -import static net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING; +import static net.minecraft.block.HorizontalBlock.FACING; 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.material.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.config.AllConfigs; 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.AbstractPlantBlock; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.CocoaBlock; import net.minecraft.block.CropsBlock; -import net.minecraft.block.KelpBlock; -import net.minecraft.block.KelpTopBlock; import net.minecraft.block.SugarCaneBlock; +import net.minecraft.block.SweetBerryBushBlock; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.state.IntegerProperty; import net.minecraft.state.Property; import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tags.BlockTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; @@ -36,7 +41,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { @Override public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.get(HORIZONTAL_FACING) + return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(FACING) .getOpposite()); } @@ -47,21 +52,23 @@ 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 public Vector3d getActiveAreaOffset(MovementContext context) { - return Vector3d.of(context.state.get(HORIZONTAL_FACING) - .getDirectionVec()) + return Vector3d.atLowerCornerOf(context.state.getValue(FACING) + .getNormal()) .scale(.45); } @@ -71,7 +78,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { BlockState stateVisited = world.getBlockState(pos); boolean notCropButCuttable = false; - if (world.isRemote) + if (world.isClientSide) return; if (!isValidCrop(world, pos, stateVisited)) { @@ -81,37 +88,55 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { return; } + ItemStack item = ItemStack.EMPTY; + float effectChance = 1; + + if (stateVisited.getBlock() + .is(BlockTags.LEAVES)) { + item = new ItemStack(Items.SHEARS); + effectChance = .45f; + } + MutableBoolean seedSubtracted = new MutableBoolean(notCropButCuttable); BlockState state = stateVisited; - BlockHelper.destroyBlock(world, pos, 1, stack -> { - if (!seedSubtracted.getValue() && stack.isItemEqual(new ItemStack(state.getBlock()))) { + BlockHelper.destroyBlockAs(world, pos, null, item, effectChance, stack -> { + if (AllConfigs.SERVER.kinetics.harvesterReplants.get() && !seedSubtracted.getValue() + && stack.sameItem(new ItemStack(state.getBlock()))) { stack.shrink(1); seedSubtracted.setTrue(); } dropItem(context, stack); }); - world.setBlockState(pos, cutCrop(world, pos, stateVisited)); + world.setBlockAndUpdate(pos, cutCrop(world, pos, stateVisited)); } private boolean isValidCrop(World world, BlockPos pos, BlockState state) { + boolean harvestPartial = AllConfigs.SERVER.kinetics.harvestPartiallyGrown.get(); + boolean replant = AllConfigs.SERVER.kinetics.harvesterReplants.get(); + if (state.getBlock() instanceof CropsBlock) { CropsBlock crop = (CropsBlock) state.getBlock(); - if (!crop.isMaxAge(state)) - return false; - return true; + if (harvestPartial) + return state.getValue(crop.getAgeProperty()) != 0 || !replant; + return crop.isMaxAge(state); } + if (state.getCollisionShape(world, pos) .isEmpty() || state.getBlock() instanceof CocoaBlock) { for (Property property : state.getProperties()) { if (!(property instanceof IntegerProperty)) continue; + IntegerProperty ageProperty = (IntegerProperty) property; if (!property.getName() - .equals(BlockStateProperties.AGE_0_1.getName())) + .equals(BlockStateProperties.AGE_1.getName())) continue; - if (((IntegerProperty) property).getAllowedValues() - .size() - 1 != state.get((IntegerProperty) property) - .intValue()) + int age = state.getValue(ageProperty) + .intValue(); + if (state.getBlock() instanceof SweetBerryBushBlock && age <= 1 && replant) + continue; + if (age == 0 && replant || !harvestPartial && (ageProperty.getPossibleValues() + .size() - 1 != age)) continue; return true; } @@ -125,19 +150,20 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { return false; if (state.getBlock() instanceof SugarCaneBlock) return true; + if (state.getBlock() + .is(BlockTags.LEAVES)) + return true; if (state.getCollisionShape(world, pos) .isEmpty() || state.getBlock() instanceof CocoaBlock) { - if (state.getBlock() instanceof KelpBlock) - return true; - if (state.getBlock() instanceof KelpTopBlock) + if (state.getBlock() instanceof AbstractPlantBlock) return true; for (Property property : state.getProperties()) { if (!(property instanceof IntegerProperty)) continue; if (!property.getName() - .equals(BlockStateProperties.AGE_0_1.getName())) + .equals(BlockStateProperties.AGE_1.getName())) continue; return false; } @@ -150,34 +176,46 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { } private BlockState cutCrop(World world, BlockPos pos, BlockState state) { - if (state.getBlock() instanceof CropsBlock) { - CropsBlock crop = (CropsBlock) state.getBlock(); - return crop.withAge(0); - } - if (state.getBlock() == Blocks.SUGAR_CANE || state.getBlock() == Blocks.KELP) { + if (!AllConfigs.SERVER.kinetics.harvesterReplants.get()) { if (state.getFluidState() .isEmpty()) - return Blocks.AIR.getDefaultState(); + return Blocks.AIR.defaultBlockState(); return state.getFluidState() - .getBlockState(); + .createLegacyBlock(); + } + + Block block = state.getBlock(); + if (block instanceof CropsBlock) { + CropsBlock crop = (CropsBlock) block; + return crop.getStateForAge(0); + } + if (block == Blocks.SWEET_BERRY_BUSH) { + return state.setValue(BlockStateProperties.AGE_3, Integer.valueOf(1)); + } + if (block == Blocks.SUGAR_CANE || block instanceof AbstractPlantBlock) { + if (state.getFluidState() + .isEmpty()) + return Blocks.AIR.defaultBlockState(); + return state.getFluidState() + .createLegacyBlock(); } 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_1.getName())) continue; - return state.with((IntegerProperty) property, Integer.valueOf(0)); + return state.setValue((IntegerProperty) property, Integer.valueOf(0)); } } if (state.getFluidState() .isEmpty()) - return Blocks.AIR.getDefaultState(); + return Blocks.AIR.defaultBlockState(); return state.getFluidState() - .getBlockState(); + .createLegacyBlock(); } } 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..0aac5f333 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; @@ -33,16 +35,16 @@ public class HarvesterRenderer extends SafeTileEntityRenderer type) { super(type); } - // For simulations such as Ponder - float manuallyAnimatedSpeed; + @Override + @OnlyIn(Dist.CLIENT) + public AxisAlignedBB getRenderBoundingBox() { + return RENDER_BOX.move(worldPosition); + } + + public float getAnimatedSpeed() { + return manuallyAnimatedSpeed; + } public void setAnimatedSpeed(float speed) { manuallyAnimatedSpeed = speed; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java index 98e628ab0..8c5603afb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.contraptions.components.actors; -import static net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING; +import static net.minecraft.block.HorizontalBlock.FACING; import com.simibubi.create.content.contraptions.components.actors.PloughBlock.PloughFakePlayer; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; @@ -8,6 +8,7 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.block.BubbleColumnBlock; import net.minecraft.block.FarmlandBlock; import net.minecraft.block.FlowingFluidBlock; import net.minecraft.item.ItemStack; @@ -30,7 +31,7 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour { @Override public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.get(HORIZONTAL_FACING) + return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(FACING) .getOpposite()); } @@ -38,10 +39,10 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour { public void visitNewPosition(MovementContext context, BlockPos pos) { super.visitNewPosition(context, pos); World world = context.world; - if (world.isRemote) + if (world.isClientSide) return; - BlockPos below = pos.down(); - if (!world.isBlockPresent(below)) + BlockPos below = pos.below(); + if (!world.isLoaded(below)) return; Vector3d vec = VecHelper.getCenterOf(pos); @@ -51,18 +52,18 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour { return; BlockRayTraceResult ray = world - .rayTraceBlocks(new RayTraceContext(vec, vec.add(0, -1, 0), BlockMode.OUTLINE, FluidMode.NONE, player)); + .clip(new RayTraceContext(vec, vec.add(0, -1, 0), BlockMode.OUTLINE, FluidMode.NONE, player)); if (ray.getType() != Type.BLOCK) return; ItemUseContext ctx = new ItemUseContext(player, Hand.MAIN_HAND, ray); - new ItemStack(Items.DIAMOND_HOE).onItemUse(ctx); + new ItemStack(Items.DIAMOND_HOE).useOn(ctx); } @Override public Vector3d getActiveAreaOffset(MovementContext context) { - return Vector3d.of(context.state.get(HORIZONTAL_FACING) - .getDirectionVec()).scale(.45); + return Vector3d.atLowerCornerOf(context.state.getValue(FACING) + .getNormal()).scale(.45); } @Override @@ -72,10 +73,15 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour { @Override public boolean canBreak(World world, BlockPos breakingPos, BlockState state) { + if (world.getBlockState(breakingPos.below()) + .getBlock() instanceof FarmlandBlock) + return false; + if (state.getBlock() instanceof FlowingFluidBlock) + return false; + if (state.getBlock() instanceof BubbleColumnBlock) + return false; return state.getCollisionShape(world, breakingPos) - .isEmpty() && !(state.getBlock() instanceof FlowingFluidBlock) - && !(world.getBlockState(breakingPos.down()) - .getBlock() instanceof FarmlandBlock); + .isEmpty(); } @Override @@ -85,7 +91,7 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour { if (brokenState.getBlock() == Blocks.SNOW && context.world instanceof ServerWorld) { ServerWorld world = (ServerWorld) context.world; brokenState.getDrops(new LootContext.Builder(world).withParameter(LootParameters.BLOCK_STATE, brokenState) - .withParameter(LootParameters.ORIGIN, Vector3d.ofCenter(pos)) + .withParameter(LootParameters.ORIGIN, Vector3d.atCenterOf(pos)) .withParameter(LootParameters.THIS_ENTITY, getPlayer(context)) .withParameter(LootParameters.TOOL, new ItemStack(Items.IRON_SHOVEL))) .forEach(s -> dropItem(context, s)); @@ -102,7 +108,7 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour { private PloughFakePlayer getPlayer(MovementContext context) { if (!(context.temporaryData instanceof PloughFakePlayer) && context.world != null) { PloughFakePlayer player = new PloughFakePlayer((ServerWorld) context.world); - player.setHeldItem(Hand.MAIN_HAND, new ItemStack(Items.DIAMOND_HOE)); + player.setItemInHand(Hand.MAIN_HAND, new ItemStack(Items.DIAMOND_HOE)); context.temporaryData = player; } return (PloughFakePlayer) context.temporaryData; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableFluidInterfaceTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableFluidInterfaceTileEntity.java index 4c27df6f1..1559bd22d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableFluidInterfaceTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableFluidInterfaceTileEntity.java @@ -51,7 +51,7 @@ public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTi return super.getCapability(cap, side); } - class InterfaceFluidHandler implements IFluidHandler { + public class InterfaceFluidHandler implements IFluidHandler { private IFluidHandler wrapped; @@ -85,7 +85,7 @@ public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTi return 0; int fill = wrapped.fill(resource, action); if (fill > 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/PortableStorageInterfaceBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java index 7afae49c4..147ae09bf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java @@ -5,7 +5,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; @@ -20,7 +20,7 @@ import net.minecraft.world.World; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -public class PortableStorageInterfaceBlock extends ProperDirectionalBlock +public class PortableStorageInterfaceBlock extends WrenchableDirectionalBlock implements ITE { boolean fluids; @@ -57,22 +57,22 @@ public class PortableStorageInterfaceBlock extends ProperDirectionalBlock @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - return getDefaultState().with(FACING, context.getNearestLookingDirection() + return defaultBlockState().setValue(FACING, context.getNearestLookingDirection() .getOpposite()); } @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.PORTABLE_STORAGE_INTERFACE.get(state.get(FACING)); + return AllShapes.PORTABLE_STORAGE_INTERFACE.get(state.getValue(FACING)); } @Override - public boolean hasComparatorInputOverride(BlockState state) { + public boolean hasAnalogOutputSignal(BlockState state) { return true; } @Override - public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) { + public int getAnalogOutputSignal(BlockState blockState, World worldIn, BlockPos pos) { return getTileEntityOptional(worldIn, pos).map(te -> te.isConnected() ? 15 : 0) .orElse(0); } 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..c0d2a2a19 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; @@ -25,15 +26,15 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { @Override public Vector3d getActiveAreaOffset(MovementContext context) { - return Vector3d.of(context.state.get(PortableStorageInterfaceBlock.FACING) - .getDirectionVec()).scale(1.85f); + return Vector3d.atLowerCornerOf(context.state.getValue(PortableStorageInterfaceBlock.FACING) + .getNormal()).scale(1.85f); } @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 @@ -54,13 +55,13 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { if (psi == null) return false; - if ((psi.isTransferring() || psi.isPowered()) && !context.world.isRemote) + if ((psi.isTransferring() || psi.isPowered()) && !context.world.isClientSide) return false; - context.data.put(_workingPos_, NBTUtil.writeBlockPos(psi.getPos())); - if (!context.world.isRemote) { - Vector3d diff = VecHelper.getCenterOf(psi.getPos()) + context.data.put(_workingPos_, NBTUtil.writeBlockPos(psi.getBlockPos())); + if (!context.world.isClientSide) { + Vector3d diff = VecHelper.getCenterOf(psi.getBlockPos()) .subtract(context.position); - diff = VecHelper.project(diff, Vector3d.of(currentFacing.getDirectionVec())); + diff = VecHelper.project(diff, Vector3d.atLowerCornerOf(currentFacing.getNormal())); float distance = (float) (diff.length() + 1.85f - 1); psi.startTransferringTo(context.contraption, distance); } else { @@ -71,7 +72,7 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { @Override public void tick(MovementContext context) { - if (context.world.isRemote) { + if (context.world.isClientSide) { boolean stalled = context.contraption.stalled; if (stalled && !context.data.contains(_workingPos_)) { BlockPos pos = new BlockPos(context.position); @@ -116,7 +117,7 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { Direction facing) { for (int i = 0; i < 2; i++) { PortableStorageInterfaceTileEntity interfaceAt = - getStationaryInterfaceAt(world, pos.offset(facing, i), state, facing); + getStationaryInterfaceAt(world, pos.relative(facing, i), state, facing); if (interfaceAt == null) continue; return interfaceAt; @@ -126,23 +127,23 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { private PortableStorageInterfaceTileEntity getStationaryInterfaceAt(World world, BlockPos pos, BlockState state, Direction facing) { - TileEntity te = world.getTileEntity(pos); + TileEntity te = world.getBlockEntity(pos); if (!(te instanceof PortableStorageInterfaceTileEntity)) return null; BlockState blockState = world.getBlockState(pos); if (blockState.getBlock() != state.getBlock()) return null; - if (blockState.get(PortableStorageInterfaceBlock.FACING) != facing.getOpposite()) + if (blockState.getValue(PortableStorageInterfaceBlock.FACING) != facing.getOpposite()) return null; return (PortableStorageInterfaceTileEntity) te; } private Optional getCurrentFacingIfValid(MovementContext context) { - Vector3d directionVec = Vector3d.of(context.state.get(PortableStorageInterfaceBlock.FACING) - .getDirectionVec()); + Vector3d directionVec = Vector3d.atLowerCornerOf(context.state.getValue(PortableStorageInterfaceBlock.FACING) + .getNormal()); directionVec = context.rotation.apply(directionVec); - Direction facingFromVector = Direction.getFacingFromVector(directionVec.x, directionVec.y, directionVec.z); - if (directionVec.distanceTo(Vector3d.of(facingFromVector.getDirectionVec())) > 1 / 2f) + Direction facingFromVector = Direction.getNearest(directionVec.x, directionVec.y, directionVec.z); + if (directionVec.distanceTo(Vector3d.atLowerCornerOf(facingFromVector.getNormal())) > 1 / 2f) return Optional.empty(); return Optional.of(facingFromVector); } 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..6bdabeae9 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; @@ -36,16 +37,16 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer sbb.light(light) - .renderInto(ms, vb), ms); + IVertexBuilder vb = buffer.getBuffer(RenderType.solid()); + 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()); + IVertexBuilder vb = buffer.getBuffer(RenderType.solid()); float renderPartialTicks = AnimationTickHolder.getPartialTicks(); float progress = 0; @@ -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.getModel(), sbb -> sbb.light(matrices.getWorld(), + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), 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.getValue(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) { @@ -101,7 +94,7 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer dynamicTree = TreeCutter.findDynamicTree(brokenState.getBlock(), pos); + if (dynamicTree.isPresent()) { + dynamicTree.get().destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos)); + return; + } + TreeCutter.findTree(context.world, pos).destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos)); } @@ -69,15 +80,20 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { Vector3d dropPos = VecHelper.getCenterOf(pos); float distance = (float) dropPos.distanceTo(context.position); ItemEntity entity = new ItemEntity(world, dropPos.x, dropPos.y, dropPos.z, remainder); - entity.setMotion(context.relativeMotion.scale(distance / 20f)); - world.addEntity(entity); + entity.setDeltaMovement(context.relativeMotion.scale(distance / 20f)); + world.addFreshEntity(entity); } @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 + protected boolean shouldDestroyStartBlock(BlockState stateToBreak) { + return !TreeCutter.canDynamicTreeCutFrom(stateToBreak.getBlock()); } @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..87ef62be5 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 @@ -45,28 +45,28 @@ public class SeatBlock extends Block { } @Override - public void fillItemGroup(ItemGroup group, NonNullList p_149666_2_) { - if (group != ItemGroup.SEARCH && !inCreativeTab) + public void fillItemCategory(ItemGroup group, NonNullList p_149666_2_) { + if (group != ItemGroup.TAB_SEARCH && !inCreativeTab) return; - super.fillItemGroup(group, p_149666_2_); + super.fillItemCategory(group, p_149666_2_); } @Override - public void onFallenUpon(World p_180658_1_, BlockPos p_180658_2_, Entity p_180658_3_, float p_180658_4_) { - super.onFallenUpon(p_180658_1_, p_180658_2_, p_180658_3_, p_180658_4_ * 0.5F); + public void fallOn(World p_180658_1_, BlockPos p_180658_2_, Entity p_180658_3_, float p_180658_4_) { + super.fallOn(p_180658_1_, p_180658_2_, p_180658_3_, p_180658_4_ * 0.5F); } @Override - public void onLanded(IBlockReader reader, Entity entity) { - BlockPos pos = entity.getBlockPos(); - if (entity instanceof PlayerEntity || !(entity instanceof LivingEntity) || !canBePickedUp(entity) || isSeatOccupied(entity.world, pos)) { - Blocks.PINK_BED.onLanded(reader, entity); + public void updateEntityAfterFallOn(IBlockReader reader, Entity entity) { + BlockPos pos = entity.blockPosition(); + if (entity instanceof PlayerEntity || !(entity instanceof LivingEntity) || !canBePickedUp(entity) || isSeatOccupied(entity.level, pos)) { + Blocks.PINK_BED.updateEntityAfterFallOn(reader, entity); return; } if (reader.getBlockState(pos) .getBlock() != this) return; - sitDown(entity.world, pos, entity); + sitDown(entity.level, pos, entity); } @Override @@ -88,46 +88,46 @@ public class SeatBlock extends Block { } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult p_225533_6_) { - if (player.isSneaking()) + if (player.isShiftKeyDown()) return ActionResultType.PASS; - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getItemInHand(hand); for (DyeColor color : DyeColor.values()) { if (!heldItem.getItem() - .isIn(DyeHelper.getTagOfDye(color))) + .is(DyeHelper.getTagOfDye(color))) continue; - if (world.isRemote) + if (world.isClientSide) return ActionResultType.SUCCESS; - BlockState newState = AllBlocks.SEATS[color.ordinal()].getDefaultState(); + BlockState newState = AllBlocks.SEATS.get(color).getDefaultState(); if (newState != state) - world.setBlockState(pos, newState); + world.setBlockAndUpdate(pos, newState); return ActionResultType.SUCCESS; } - List seats = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos)); + List seats = world.getEntitiesOfClass(SeatEntity.class, new AxisAlignedBB(pos)); if (!seats.isEmpty()) { SeatEntity seatEntity = seats.get(0); List passengers = seatEntity.getPassengers(); if (!passengers.isEmpty() && passengers.get(0) instanceof PlayerEntity) return ActionResultType.PASS; - if (!world.isRemote) { - seatEntity.removePassengers(); + if (!world.isClientSide) { + seatEntity.ejectPassengers(); player.startRiding(seatEntity); } return ActionResultType.SUCCESS; } - if (world.isRemote) + if (world.isClientSide) return ActionResultType.SUCCESS; sitDown(world, pos, player); return ActionResultType.SUCCESS; } public static boolean isSeatOccupied(World world, BlockPos pos) { - return !world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos)) + return !world.getEntitiesOfClass(SeatEntity.class, new AxisAlignedBB(pos)) .isEmpty(); } @@ -136,17 +136,17 @@ public class SeatBlock extends Block { } public static void sitDown(World world, BlockPos pos, Entity entity) { - if (world.isRemote) + if (world.isClientSide) return; SeatEntity seat = new SeatEntity(world, pos); - seat.setPos(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f); - world.addEntity(seat); + seat.setPosRaw(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f); + world.addFreshEntity(seat); entity.startRiding(seat, true); } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } - + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatEntity.java index b5dea8fcd..9777aedd8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatEntity.java @@ -27,13 +27,13 @@ public class SeatEntity extends Entity implements IEntityAdditionalSpawnData { public SeatEntity(World world, BlockPos pos) { this(AllEntityTypes.SEAT.get(), world); - noClip = true; + noPhysics = true; } public static EntityType.Builder build(EntityType.Builder builder) { @SuppressWarnings("unchecked") EntityType.Builder entityBuilder = (EntityType.Builder) builder; - return entityBuilder.size(0.25f, 0.35f); + return entityBuilder.sized(0.25f, 0.35f); } @Override @@ -42,29 +42,29 @@ public class SeatEntity extends Entity implements IEntityAdditionalSpawnData { } @Override - public void setPos(double x, double y, double z) { - super.setPos(x, y, z); + public void setPosRaw(double x, double y, double z) { + super.setPosRaw(x, y, z); AxisAlignedBB bb = getBoundingBox(); Vector3d diff = new Vector3d(x, y, z).subtract(bb.getCenter()); - setBoundingBox(bb.offset(diff)); + setBoundingBox(bb.move(diff)); } @Override - public void setMotion(Vector3d p_213317_1_) {} + public void setDeltaMovement(Vector3d p_213317_1_) {} @Override public void tick() { - if (world.isRemote) + if (level.isClientSide) return; - boolean blockPresent = world.getBlockState(getBlockPos()) + boolean blockPresent = level.getBlockState(blockPosition()) .getBlock() instanceof SeatBlock; - if (isBeingRidden() && blockPresent) + if (isVehicle() && blockPresent) return; this.remove(); } @Override - protected boolean canBeRidden(Entity entity) { + protected boolean canRide(Entity entity) { // Fake Players (tested with deployers) have a BUNCH of weird issues, don't let them ride seats return !(entity instanceof FakePlayer); } @@ -72,21 +72,21 @@ public class SeatEntity extends Entity implements IEntityAdditionalSpawnData { @Override protected void removePassenger(Entity entity) { super.removePassenger(entity); - Vector3d pos = entity.getPositionVec(); - entity.setPosition(pos.x, pos.y + 0.85f, pos.z); + Vector3d pos = entity.position(); + entity.setPos(pos.x, pos.y + 0.85f, pos.z); } @Override - protected void registerData() {} + protected void defineSynchedData() {} @Override - protected void readAdditional(CompoundNBT p_70037_1_) {} + protected void readAdditionalSaveData(CompoundNBT p_70037_1_) {} @Override - protected void writeAdditional(CompoundNBT p_213281_1_) {} + protected void addAdditionalSaveData(CompoundNBT p_213281_1_) {} @Override - public IPacket createSpawnPacket() { + public IPacket getAddEntityPacket() { return NetworkHooks.getEntitySpawningPacket(this); } @@ -102,7 +102,7 @@ public class SeatEntity extends Entity implements IEntityAdditionalSpawnData { } @Override - public ResourceLocation getEntityTexture(SeatEntity p_110775_1_) { + public ResourceLocation getTextureLocation(SeatEntity p_110775_1_) { return null; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java index e2143baf2..84776eb68 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java @@ -40,8 +40,8 @@ public class SeatMovementBehaviour extends MovementBehaviour { Map seatMapping = context.contraption.getSeatMapping(); BlockState blockState = context.world.getBlockState(pos); - boolean slab = blockState.getBlock() instanceof SlabBlock && blockState.get(SlabBlock.TYPE) == SlabType.BOTTOM; - boolean solid = blockState.isSolid() || slab; + boolean slab = blockState.getBlock() instanceof SlabBlock && blockState.getValue(SlabBlock.TYPE) == SlabType.BOTTOM; + boolean solid = blockState.canOcclude() || slab; // Occupied if (seatMapping.containsValue(index)) { @@ -53,7 +53,7 @@ public class SeatMovementBehaviour extends MovementBehaviour { continue; for (Entity entity : contraptionEntity.getPassengers()) { if (!entry.getKey() - .equals(entity.getUniqueID())) + .equals(entity.getUUID())) continue; toDismount = entity; } @@ -62,7 +62,7 @@ public class SeatMovementBehaviour extends MovementBehaviour { toDismount.stopRiding(); Vector3d position = VecHelper.getCenterOf(pos) .add(0, slab ? .5f : 1f, 0); - toDismount.setPositionAndUpdate(position.x, position.y, position.z); + toDismount.teleportTo(position.x, position.y, position.z); toDismount.getPersistentData() .remove("ContraptionDismountLocation"); } @@ -72,8 +72,8 @@ public class SeatMovementBehaviour extends MovementBehaviour { if (solid) return; - List nearbyEntities = context.world.getEntitiesWithinAABB(Entity.class, - new AxisAlignedBB(pos).shrink(1 / 16f), SeatBlock::canBePickedUp); + List nearbyEntities = context.world.getEntitiesOfClass(Entity.class, + new AxisAlignedBB(pos).deflate(1 / 16f), SeatBlock::canBePickedUp); if (!nearbyEntities.isEmpty()) contraptionEntity.addSittingPassenger(nearbyEntities.get(0), index); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/ContraptionBlockSource.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/ContraptionBlockSource.java index 57bfc9449..d7660c434 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/ContraptionBlockSource.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/ContraptionBlockSource.java @@ -31,42 +31,42 @@ public class ContraptionBlockSource implements IBlockSource { } @Override - public double getX() { + public double x() { return (double)this.pos.getX() + 0.5D; } @Override - public double getY() { + public double y() { return (double)this.pos.getY() + 0.5D; } @Override - public double getZ() { + public double z() { return (double)this.pos.getZ() + 0.5D; } @Override - public BlockPos getBlockPos() { + public BlockPos getPos() { return pos; } @Override public BlockState getBlockState() { - if(context.state.contains(BlockStateProperties.FACING) && overrideFacing != null) - return context.state.with(BlockStateProperties.FACING, overrideFacing); + if(context.state.hasProperty(BlockStateProperties.FACING) && overrideFacing != null) + return context.state.setValue(BlockStateProperties.FACING, overrideFacing); return context.state; } @Override @Nullable - public T getBlockTileEntity() { + public T getEntity() { return null; } @Override @Nullable - public ServerWorld getWorld() { + public ServerWorld getLevel() { MinecraftServer server = context.world.getServer(); - return server != null ? server.getWorld(context.world.getRegistryKey()) : null; + return server != null ? server.getLevel(context.world.dimension()) : null; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java index 39837a67f..a423fb7e7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java @@ -7,7 +7,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import mcp.MethodsReturnNonnullByDefault; -import net.minecraft.block.Block; +import net.minecraft.block.AbstractBlock; import net.minecraft.block.Blocks; import net.minecraft.block.DispenserBlock; import net.minecraft.dispenser.DefaultDispenseItemBehavior; @@ -42,7 +42,7 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour { DispenseItemLocation location = getDispenseLocation(context); if (location.isEmpty()) { - context.world.playEvent(1001, pos, 0); + context.world.levelEvent(1001, pos, 0); } else { ItemStack itemstack = getItemStackAt(location, context); // Special dispense item behaviour for moving contraptions @@ -59,7 +59,7 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour { return; } - IDispenseItemBehavior idispenseitembehavior = BEHAVIOUR_LOOKUP.getBehavior(itemstack); + IDispenseItemBehavior idispenseitembehavior = BEHAVIOUR_LOOKUP.getDispenseMethod(itemstack); if (idispenseitembehavior instanceof ProjectileDispenseBehavior) { // Projectile behaviours can be converted most of the time IMovedDispenseItemBehaviour iMovedDispenseItemBehaviour = MovedProjectileDispenserBehaviour.of((ProjectileDispenseBehavior) idispenseitembehavior); setItemStackAt(location, iMovedDispenseItemBehaviour.dispense(itemstack, context, pos), context); @@ -67,10 +67,10 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour { return; } - Vector3d facingVec = Vector3d.of(context.state.get(DispenserBlock.FACING).getDirectionVec()); + Vector3d facingVec = Vector3d.atLowerCornerOf(context.state.getValue(DispenserBlock.FACING).getNormal()); facingVec = context.rotation.apply(facingVec); facingVec.normalize(); - Direction clostestFacing = Direction.getFacingFromVector(facingVec.x, facingVec.y, facingVec.z); + Direction clostestFacing = Direction.getNearest(facingVec.x, facingVec.y, facingVec.z); ContraptionBlockSource blockSource = new ContraptionBlockSource(context, pos, clostestFacing); if (idispenseitembehavior.getClass() != DefaultDispenseItemBehavior.class) { // There is a dispense item behaviour registered for the vanilla dispenser @@ -89,11 +89,11 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour { @MethodsReturnNonnullByDefault private static class DispenserLookup extends DispenserBlock { protected DispenserLookup() { - super(Block.Properties.from(Blocks.DISPENSER)); + super(AbstractBlock.Properties.copy(Blocks.DISPENSER)); } - public IDispenseItemBehavior getBehavior(ItemStack itemStack) { - return super.getBehavior(itemStack); + public IDispenseItemBehavior getDispenseMethod(ItemStack itemStack) { + return super.getDispenseMethod(itemStack); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DropperMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DropperMovementBehaviour.java index 27aa13c60..e9771be43 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DropperMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DropperMovementBehaviour.java @@ -21,7 +21,7 @@ public class DropperMovementBehaviour extends MovementBehaviour { protected void activate(MovementContext context, BlockPos pos) { DispenseItemLocation location = getDispenseLocation(context); if (location.isEmpty()) { - context.world.playEvent(1001, pos, 0); + context.world.levelEvent(1001, pos, 0); } else { setItemStackAt(location, defaultBehaviour.dispense(getItemStackAt(location, context), context, pos), context); } @@ -29,7 +29,7 @@ public class DropperMovementBehaviour extends MovementBehaviour { @Override public void visitNewPosition(MovementContext context, BlockPos pos) { - if (context.world.isRemote) + if (context.world.isClientSide) return; collectItems(context); activate(context, pos); @@ -37,7 +37,7 @@ public class DropperMovementBehaviour extends MovementBehaviour { private void collectItems(MovementContext context) { getStacks(context).stream().filter(itemStack -> !itemStack.isEmpty() && itemStack.getItem() != Items.AIR && itemStack.getMaxStackSize() > itemStack.getCount()).forEach(itemStack -> itemStack.grow( - ItemHelper.extract(context.contraption.inventory, itemStack::isItemEqual, ItemHelper.ExtractionCountMode.UPTO, itemStack.getMaxStackSize() - itemStack.getCount(), false).getCount())); + ItemHelper.extract(context.contraption.inventory, itemStack::sameItem, ItemHelper.ExtractionCountMode.UPTO, itemStack.getMaxStackSize() - itemStack.getCount(), false).getCount())); } private void updateTemporaryData(MovementContext context) { @@ -62,7 +62,7 @@ public class DropperMovementBehaviour extends MovementBehaviour { if (testStack == null || testStack.isEmpty()) continue; if (testStack.getMaxStackSize() == 1) { - location = new DispenseItemLocation(false, ItemHelper.findFirstMatchingSlotIndex(context.contraption.inventory, testStack::isItemEqual)); + location = new DispenseItemLocation(false, ItemHelper.findFirstMatchingSlotIndex(context.contraption.inventory, testStack::sameItem)); if (!getItemStackAt(location, context).isEmpty()) useable.add(location); } else if (testStack.getCount() >= 2) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java index c70c6b899..bfb7e7e9f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java @@ -47,17 +47,17 @@ public interface IMovedDispenseItemBehaviour { if (context.world instanceof ServerWorld) { EntityType entityType = ((SpawnEggItem) itemStack.getItem()).getType(itemStack.getTag()); Entity spawnedEntity = entityType.spawn((ServerWorld) context.world, itemStack, null, - pos.add(facing.x + .7, facing.y + .7, facing.z + .7), SpawnReason.DISPENSER, facing.y < .5, + pos.offset(facing.x + .7, facing.y + .7, facing.z + .7), SpawnReason.DISPENSER, facing.y < .5, false); if (spawnedEntity != null) - spawnedEntity.setMotion(context.motion.scale(2)); + spawnedEntity.setDeltaMovement(context.motion.scale(2)); } itemStack.shrink(1); return itemStack; } }; - for (SpawnEggItem spawneggitem : SpawnEggItem.getEggs()) + for (SpawnEggItem spawneggitem : SpawnEggItem.eggs()) DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(spawneggitem, spawnEggDispenseBehaviour); } @@ -92,10 +92,10 @@ public interface IMovedDispenseItemBehaviour { double y = pos.getY() + facing.y * .7 + .5; double z = pos.getZ() + facing.z * .7 + .5; TNTEntity tntentity = new TNTEntity(context.world, x, y, z, null); - tntentity.addVelocity(context.motion.x, context.motion.y, context.motion.z); - context.world.addEntity(tntentity); + tntentity.push(context.motion.x, context.motion.y, context.motion.z); + context.world.addFreshEntity(tntentity); context.world.playSound(null, tntentity.getX(), tntentity.getY(), tntentity.getZ(), - SoundEvents.ENTITY_TNT_PRIMED, SoundCategory.BLOCKS, 1.0F, 1.0F); + SoundEvents.TNT_PRIMED, SoundCategory.BLOCKS, 1.0F, 1.0F); itemStack.shrink(1); return itemStack; } @@ -112,14 +112,14 @@ public interface IMovedDispenseItemBehaviour { FireworkRocketEntity fireworkrocketentity = new FireworkRocketEntity(context.world, itemStack, x, y, z, true); fireworkrocketentity.shoot(facing.x, facing.y, facing.z, 0.5F, 1.0F); - context.world.addEntity(fireworkrocketentity); + context.world.addFreshEntity(fireworkrocketentity); itemStack.shrink(1); return itemStack; } @Override protected void playDispenseSound(IWorld world, BlockPos pos) { - world.playEvent(1004, pos, 0); + world.levelEvent(1004, pos, 0); } }); @@ -127,22 +127,22 @@ public interface IMovedDispenseItemBehaviour { new MovedDefaultDispenseItemBehaviour() { @Override protected void playDispenseSound(IWorld world, BlockPos pos) { - world.playEvent(1018, pos, 0); + world.levelEvent(1018, pos, 0); } @Override protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vector3d facing) { - Random random = context.world.rand; + Random random = context.world.random; double x = pos.getX() + facing.x * .7 + .5; double y = pos.getY() + facing.y * .7 + .5; double z = pos.getZ() + facing.z * .7 + .5; - context.world.addEntity(Util.make( + context.world.addFreshEntity(Util.make( new SmallFireballEntity(context.world, x, y, z, random.nextGaussian() * 0.05D + facing.x + context.motion.x, random.nextGaussian() * 0.05D + facing.y + context.motion.y, random.nextGaussian() * 0.05D + facing.z + context.motion.z), - (p_229425_1_) -> p_229425_1_.setStack(itemStack))); + (p_229425_1_) -> p_229425_1_.setItem(itemStack))); itemStack.shrink(1); return itemStack; } @@ -154,21 +154,21 @@ public interface IMovedDispenseItemBehaviour { protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vector3d facing) { this.successful = false; - BlockPos interactAt = pos.offset(getClosestFacingDirection(facing)); + BlockPos interactAt = pos.relative(getClosestFacingDirection(facing)); BlockState state = context.world.getBlockState(interactAt); Block block = state.getBlock(); - if (block.isIn(BlockTags.BEEHIVES) && state.get(BeehiveBlock.HONEY_LEVEL) >= 5) { - ((BeehiveBlock) block).takeHoney(context.world, state, interactAt, null, + if (block.is(BlockTags.BEEHIVES) && state.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { + ((BeehiveBlock) block).releaseBeesAndResetHoneyLevel(context.world, state, interactAt, null, BeehiveTileEntity.State.BEE_RELEASED); this.successful = true; return placeItemInInventory(itemStack, new ItemStack(Items.HONEY_BOTTLE), context, pos, facing); } else if (context.world.getFluidState(interactAt) - .isTagged(FluidTags.WATER)) { + .is(FluidTags.WATER)) { this.successful = true; return placeItemInInventory(itemStack, - PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.WATER), context, pos, + PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER), context, pos, facing); } else { return super.dispenseStack(itemStack, context, pos, facing); @@ -181,13 +181,13 @@ public interface IMovedDispenseItemBehaviour { @Override protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vector3d facing) { - BlockPos interactAt = pos.offset(getClosestFacingDirection(facing)); + BlockPos interactAt = pos.relative(getClosestFacingDirection(facing)); BlockState state = context.world.getBlockState(interactAt); Block block = state.getBlock(); if (block instanceof IBucketPickupHandler) { - Fluid fluid = ((IBucketPickupHandler) block).pickupFluid(context.world, interactAt, state); + Fluid fluid = ((IBucketPickupHandler) block).takeLiquid(context.world, interactAt, state); if (fluid instanceof FlowingFluid) - return placeItemInInventory(itemStack, new ItemStack(fluid.getFilledBucket()), context, pos, + return placeItemInInventory(itemStack, new ItemStack(fluid.getBucket()), context, pos, facing); } return super.dispenseStack(itemStack, context, pos, facing); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedDefaultDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedDefaultDispenseItemBehaviour.java index 88aea0fed..d12d2d31a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedDefaultDispenseItemBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedDefaultDispenseItemBehaviour.java @@ -21,32 +21,32 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha double d0 = p_82486_4_.getX() + facing.x + .5; double d1 = p_82486_4_.getY() + facing.y + .5; double d2 = p_82486_4_.getZ() + facing.z + .5; - if (Direction.getFacingFromVector(facing.x, facing.y, facing.z).getAxis() == Direction.Axis.Y) { + if (Direction.getNearest(facing.x, facing.y, facing.z).getAxis() == Direction.Axis.Y) { d1 = d1 - 0.125D; } else { d1 = d1 - 0.15625D; } ItemEntity itementity = new ItemEntity(p_82486_0_, d0, d1, d2, p_82486_1_); - double d3 = p_82486_0_.rand.nextDouble() * 0.1D + 0.2D; - itementity.setMotion(p_82486_0_.rand.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.getX() * d3 + context.motion.x, p_82486_0_.rand.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.getY() * d3 + context.motion.y, p_82486_0_.rand.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.getZ() * d3 + context.motion.z); - p_82486_0_.addEntity(itementity); + double d3 = p_82486_0_.random.nextDouble() * 0.1D + 0.2D; + itementity.setDeltaMovement(p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.x() * d3 + context.motion.x, p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.y() * d3 + context.motion.y, p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.z() * d3 + context.motion.z); + p_82486_0_.addFreshEntity(itementity); } @Override public ItemStack dispense(ItemStack itemStack, MovementContext context, BlockPos pos) { - Vector3d facingVec = Vector3d.of(context.state.get(DispenserBlock.FACING).getDirectionVec()); + Vector3d facingVec = Vector3d.atLowerCornerOf(context.state.getValue(DispenserBlock.FACING).getNormal()); facingVec = context.rotation.apply(facingVec); facingVec.normalize(); Direction closestToFacing = getClosestFacingDirection(facingVec); - IInventory iinventory = HopperTileEntity.getInventoryAtPosition(context.world, pos.offset(closestToFacing)); + IInventory iinventory = HopperTileEntity.getContainerAt(context.world, pos.relative(closestToFacing)); if (iinventory == null) { this.playDispenseSound(context.world, pos); this.spawnDispenseParticles(context.world, pos, closestToFacing); return this.dispenseStack(itemStack, context, pos, facingVec); } else { - if (HopperTileEntity.putStackInInventoryAllSlots(null, iinventory, itemStack.copy().split(1), closestToFacing.getOpposite()).isEmpty()) + if (HopperTileEntity.addItem(null, iinventory, itemStack.copy().split(1), closestToFacing.getOpposite()).isEmpty()) itemStack.shrink(1); return itemStack; } @@ -65,7 +65,7 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha * Play the dispense sound from the specified block. */ protected void playDispenseSound(IWorld world, BlockPos pos) { - world.playEvent(1000, pos, 0); + world.levelEvent(1000, pos, 0); } /** @@ -76,11 +76,11 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha } protected void spawnDispenseParticles(IWorld world, BlockPos pos, Direction direction) { - world.playEvent(2000, pos, direction.getIndex()); + world.levelEvent(2000, pos, direction.get3DDataValue()); } protected Direction getClosestFacingDirection(Vector3d exactFacing) { - return Direction.getFacingFromVector(exactFacing.x, exactFacing.y, exactFacing.z); + return Direction.getNearest(exactFacing.x, exactFacing.y, exactFacing.z); } protected ItemStack placeItemInInventory(ItemStack consumedFrom, ItemStack output, MovementContext context, BlockPos pos, Vector3d facing) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedOptionalDispenseBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedOptionalDispenseBehaviour.java index d3eb7e88e..9b8ecef5e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedOptionalDispenseBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedOptionalDispenseBehaviour.java @@ -8,6 +8,6 @@ public class MovedOptionalDispenseBehaviour extends MovedDefaultDispenseItemBeha @Override protected void playDispenseSound(IWorld world, BlockPos pos) { - world.playEvent(this.successful ? 1000 : 1001, pos, 0); + world.levelEvent(this.successful ? 1000 : 1001, pos, 0); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java index bd39d404f..313253630 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java @@ -28,14 +28,14 @@ public abstract class MovedProjectileDispenserBehaviour extends MovedDefaultDisp return itemStack; Vector3d effectiveMovementVec = facing.scale(getProjectileVelocity()).add(context.motion); ProjectileEntity.shoot(effectiveMovementVec.x, effectiveMovementVec.y, effectiveMovementVec.z, (float) effectiveMovementVec.length(), this.getProjectileInaccuracy()); - context.world.addEntity(ProjectileEntity); + context.world.addFreshEntity(ProjectileEntity); itemStack.shrink(1); return itemStack; } @Override protected void playDispenseSound(IWorld world, BlockPos pos) { - world.playEvent(1002, pos, 0); + world.levelEvent(1002, pos, 0); } @Nullable @@ -81,19 +81,19 @@ public abstract class MovedProjectileDispenserBehaviour extends MovedDefaultDisp } private static Method getProjectileEntityLookup() { - Method getProjectileEntity = ObfuscationReflectionHelper.findMethod(ProjectileDispenseBehavior.class, "func_82499_a", World.class, IPosition.class, ItemStack.class); + Method getProjectileEntity = ObfuscationReflectionHelper.findMethod(ProjectileDispenseBehavior.class, "func_82499_a", World.class, IPosition.class, ItemStack.class); // getProjectile getProjectileEntity.setAccessible(true); return getProjectileEntity; } private static Method getProjectileInaccuracyLookup() { - Method getProjectileInaccuracy = ObfuscationReflectionHelper.findMethod(ProjectileDispenseBehavior.class, "func_82498_a"); + Method getProjectileInaccuracy = ObfuscationReflectionHelper.findMethod(ProjectileDispenseBehavior.class, "func_82498_a"); // getUncertainty getProjectileInaccuracy.setAccessible(true); return getProjectileInaccuracy; } private static Method getProjectileVelocityLookup() { - Method getProjectileVelocity = ObfuscationReflectionHelper.findMethod(ProjectileDispenseBehavior.class, "func_82500_b"); + Method getProjectileVelocity = ObfuscationReflectionHelper.findMethod(ProjectileDispenseBehavior.class, "func_82500_b"); // getPower getProjectileVelocity.setAccessible(true); return getProjectileVelocity; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java index 5da3e0b13..a751cc024 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java @@ -14,17 +14,17 @@ public class SimplePos implements IPosition { } @Override - public double getX() { + public double x() { return x; } @Override - public double getY() { + public double y() { return y; } @Override - public double getZ() { + public double z() { return z; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockBlock.java index 3b179fc49..9782accaf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockBlock.java @@ -49,22 +49,22 @@ public class CuckooClockBlock extends HorizontalKineticBlock { } @Override - public void fillItemGroup(ItemGroup group, NonNullList items) { + public void fillItemCategory(ItemGroup group, NonNullList items) { if (!mysterious) - super.fillItemGroup(group, items); + super.fillItemCategory(group, items); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { Direction preferred = getPreferredHorizontalFacing(context); if (preferred != null) - return getDefaultState().with(HORIZONTAL_FACING, preferred.getOpposite()); - return this.getDefaultState().with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing().getOpposite()); + return defaultBlockState().setValue(HORIZONTAL_FACING, preferred.getOpposite()); + return this.defaultBlockState().setValue(HORIZONTAL_FACING, context.getHorizontalDirection().getOpposite()); } @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face == state.get(HORIZONTAL_FACING).getOpposite(); + return face == state.getValue(HORIZONTAL_FACING).getOpposite(); } public static boolean containsSurprise(BlockState state) { @@ -74,11 +74,11 @@ public class CuckooClockBlock extends HorizontalKineticBlock { @Override public Axis getRotationAxis(BlockState state) { - return state.get(HORIZONTAL_FACING).getAxis(); + return state.getValue(HORIZONTAL_FACING).getAxis(); } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(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..935baf026 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,13 +9,11 @@ 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; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction; import net.minecraft.util.math.MathHelper; @@ -34,19 +33,18 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer { CuckooClockTileEntity clock = (CuckooClockTileEntity) te; BlockState blockState = te.getBlockState(); - int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, te.getPos()); - Direction direction = blockState.get(CuckooClockBlock.HORIZONTAL_FACING); + Direction direction = blockState.getValue(CuckooClockBlock.HORIZONTAL_FACING); - IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); + IVertexBuilder vb = buffer.getBuffer(RenderType.solid()); // Render Hands SuperByteBuffer hourHand = PartialBufferer.get(AllBlockPartials.CUCKOO_HOUR_HAND, blockState); SuperByteBuffer minuteHand = PartialBufferer.get(AllBlockPartials.CUCKOO_MINUTE_HAND, blockState); float hourAngle = clock.hourHand.get(partialTicks); float minuteAngle = clock.minuteHand.get(partialTicks); - rotateHand(hourHand, hourAngle, direction).light(packedLightmapCoords) + rotateHand(hourHand, hourAngle, direction).light(light) .renderInto(ms, vb); - rotateHand(minuteHand, minuteAngle, direction).light(packedLightmapCoords) + rotateHand(minuteHand, minuteAngle, direction).light(light) .renderInto(ms, vb); // Doors @@ -72,9 +70,9 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer { } } - rotateDoor(leftDoor, angle, true, direction).light(packedLightmapCoords) + rotateDoor(leftDoor, angle, true, direction).light(light) .renderInto(ms, vb); - rotateDoor(rightDoor, angle, false, direction).light(packedLightmapCoords) + rotateDoor(rightDoor, angle, false, direction).light(light) .renderInto(ms, vb); // Figure @@ -83,9 +81,9 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer { PartialModel partialModel = (clock.animationType == Animation.PIG ? AllBlockPartials.CUCKOO_PIG : AllBlockPartials.CUCKOO_CREEPER); SuperByteBuffer figure = PartialBufferer.get(partialModel, blockState); - figure.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(direction.rotateYCCW()))); + figure.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(direction.getCounterClockWise()))); figure.translate(offset, 0, 0); - figure.light(packedLightmapCoords) + figure.light(light) .renderInto(ms, vb); } @@ -98,7 +96,7 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer { private SuperByteBuffer transform(PartialModel partial, KineticTileEntity te) { return PartialBufferer.getFacing(partial, te.getBlockState(), te.getBlockState() - .get(CuckooClockBlock.HORIZONTAL_FACING) + .getValue(CuckooClockBlock.HORIZONTAL_FACING) .getOpposite()); } @@ -106,7 +104,7 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer { float pivotX = 2 / 16f; float pivotY = 6 / 16f; float pivotZ = 8 / 16f; - buffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.rotateYCCW()))); + buffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getCounterClockWise()))); buffer.translate(pivotX, pivotY, pivotZ); buffer.rotate(Direction.EAST, angle); buffer.translate(-pivotX, -pivotY, -pivotZ); @@ -117,7 +115,7 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer { float pivotX = 2 / 16f; float pivotY = 0; float pivotZ = (left ? 6 : 10) / 16f; - buffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.rotateYCCW()))); + buffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getCounterClockWise()))); buffer.translate(pivotX, pivotY, pivotZ); buffer.rotate(Direction.UP, AngleHelper.rad(angle) * (left ? -1 : 1)); buffer.translate(-pivotX, -pivotY, -pivotZ); 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..a38d44ee1 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,11 +66,25 @@ public class CuckooClockTileEntity extends KineticTileEntity { if (getSpeed() == 0) return; - int dayTime = (int) (world.getDayTime() % 24000); + + boolean isNatural = level.dimensionType().natural(); + int dayTime = (int) ((level.getDayTime() * (isNatural ? 1 : 24)) % 24000); int hours = (dayTime / 1000 + 6) % 24; int minutes = (dayTime % 1000) * 60 / 1000; - if (!world.isRemote) { + if (!isNatural) { + if (level.isClientSide) { + moveHands(hours, minutes); + + if (AnimationTickHolder.getTicks() % 6 == 0) + playSound(SoundEvents.NOTE_BLOCK_HAT, 1 / 16f, 2f); + else if (AnimationTickHolder.getTicks() % 3 == 0) + playSound(SoundEvents.NOTE_BLOCK_HAT, 1 / 16f, 1.5f); + } + return; + } + + if (!level.isClientSide) { if (animationType == Animation.NONE) { if (hours == 12 && minutes < 5) startAnimation(Animation.PIG); @@ -83,23 +97,23 @@ public class CuckooClockTileEntity extends KineticTileEntity { animationType = Animation.NONE; if (animationType == Animation.SURPRISE && animationProgress.value == 50) { - Vector3d center = VecHelper.getCenterOf(pos); - world.destroyBlock(pos, false); - world.createExplosion(null, CUCKOO_SURPRISE, null, center.x, center.y, center.z, 3, false, + Vector3d center = VecHelper.getCenterOf(worldPosition); + level.destroyBlock(worldPosition, false); + level.explode(null, CUCKOO_SURPRISE, null, center.x, center.y, center.z, 3, false, Explosion.Mode.BREAK); } } } - if (world.isRemote) { + if (level.isClientSide) { moveHands(hours, minutes); if (animationType == Animation.NONE) { if (AnimationTickHolder.getTicks() % 32 == 0) - playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 2f); + playSound(SoundEvents.NOTE_BLOCK_HAT, 1 / 16f, 2f); else if (AnimationTickHolder.getTicks() % 16 == 0) - playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 1.5f); + playSound(SoundEvents.NOTE_BLOCK_HAT, 1 / 16f, 1.5f); } else { boolean isSurprise = animationType == Animation.SURPRISE; @@ -111,29 +125,29 @@ public class CuckooClockTileEntity extends KineticTileEntity { // sounds if (value == 1) - playSound(SoundEvents.BLOCK_NOTE_BLOCK_CHIME, 2, .5f); + playSound(SoundEvents.NOTE_BLOCK_CHIME, 2, .5f); if (value == 21) - playSound(SoundEvents.BLOCK_NOTE_BLOCK_CHIME, 2, 0.793701f); + playSound(SoundEvents.NOTE_BLOCK_CHIME, 2, 0.793701f); if (value > 30 && isSurprise) { - Vector3d pos = VecHelper.offsetRandomly(VecHelper.getCenterOf(this.pos), world.rand, .5f); - world.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y, pos.z, 0, 0, 0); + Vector3d pos = VecHelper.offsetRandomly(VecHelper.getCenterOf(this.worldPosition), level.random, .5f); + level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y, pos.z, 0, 0, 0); } if (value == 40 && isSurprise) - playSound(SoundEvents.ENTITY_TNT_PRIMED, 1f, 1f); + playSound(SoundEvents.TNT_PRIMED, 1f, 1f); int step = isSurprise ? 3 : 15; for (int phase = 30; phase <= 60; phase += step) { if (value == phase - step / 3) - playSound(SoundEvents.BLOCK_CHEST_OPEN, 1 / 16f, 2f); + playSound(SoundEvents.CHEST_OPEN, 1 / 16f, 2f); if (value == phase) { if (animationType == Animation.PIG) - playSound(SoundEvents.ENTITY_PIG_AMBIENT, 1 / 4f, 1f); + playSound(SoundEvents.PIG_AMBIENT, 1 / 4f, 1f); else - playSound(SoundEvents.ENTITY_CREEPER_HURT, 1 / 4f, 3f); + playSound(SoundEvents.CREEPER_HURT, 1 / 4f, 3f); } if (value == phase + step / 3) - playSound(SoundEvents.BLOCK_CHEST_CLOSE, 1 / 16f, 2f); + playSound(SoundEvents.CHEST_CLOSE, 1 / 16f, 2f); } @@ -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); - + AllTriggers.triggerForNearbyPlayers(AllTriggers.CUCKOO, level, worldPosition, 10); + sendData(); } @@ -169,12 +183,12 @@ public class CuckooClockTileEntity extends KineticTileEntity { } private void playSound(SoundEvent sound, float volume, float pitch) { - Vector3d vec = VecHelper.getCenterOf(pos); - world.playSound(vec.x, vec.y, vec.z, sound, SoundCategory.BLOCKS, volume, pitch, false); + Vector3d vec = VecHelper.getCenterOf(worldPosition); + level.playLocalSound(vec.x, vec.y, vec.z, sound, SoundCategory.BLOCKS, volume, pitch, false); } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java index db6b86bfd..2c4c78fa2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -22,6 +23,8 @@ import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants.NBT; @@ -34,17 +37,17 @@ public class ConnectedInputHandler { public static boolean shouldConnect(World world, BlockPos pos, Direction face, Direction direction) { BlockState refState = world.getBlockState(pos); - if (!refState.contains(HORIZONTAL_FACING)) + if (!refState.hasProperty(HORIZONTAL_FACING)) return false; - Direction refDirection = refState.get(HORIZONTAL_FACING); + Direction refDirection = refState.getValue(HORIZONTAL_FACING); if (direction.getAxis() == refDirection.getAxis()) return false; if (face == refDirection) return false; - BlockState neighbour = world.getBlockState(pos.offset(direction)); + BlockState neighbour = world.getBlockState(pos.relative(direction)); if (!AllBlocks.MECHANICAL_CRAFTER.has(neighbour)) return false; - if (refDirection != neighbour.get(HORIZONTAL_FACING)) + if (refDirection != neighbour.getValue(HORIZONTAL_FACING)) return false; return true; } @@ -56,16 +59,16 @@ public class ConnectedInputHandler { if (crafter1 == null || crafter2 == null) return; - BlockPos controllerPos1 = crafter1.getPos() - .add(crafter1.input.data.get(0)); - BlockPos controllerPos2 = crafter2.getPos() - .add(crafter2.input.data.get(0)); + BlockPos controllerPos1 = crafter1.getBlockPos() + .offset(crafter1.input.data.get(0)); + BlockPos controllerPos2 = crafter2.getBlockPos() + .offset(crafter2.input.data.get(0)); if (controllerPos1.equals(controllerPos2)) { MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1); Set positions = controller.input.data.stream() - .map(controllerPos1::add) + .map(controllerPos1::offset) .collect(Collectors.toSet()); List frontier = new LinkedList<>(); List splitGroup = new ArrayList<>(); @@ -76,7 +79,7 @@ public class ConnectedInputHandler { while (!frontier.isEmpty()) { BlockPos current = frontier.remove(0); for (Direction direction : Iterate.directions) { - BlockPos next = current.offset(direction); + BlockPos next = current.relative(direction); if (!positions.remove(next)) continue; splitGroup.add(next); @@ -87,9 +90,9 @@ public class ConnectedInputHandler { initAndAddAll(world, crafter1, positions); initAndAddAll(world, crafter2, splitGroup); - crafter1.markDirty(); + crafter1.setChanged(); crafter1.connectivityChanged(); - crafter2.markDirty(); + crafter2.setChanged(); crafter2.connectivityChanged(); return; } @@ -103,11 +106,11 @@ public class ConnectedInputHandler { connectControllers(world, crafter1, crafter2); - world.setBlockState(crafter1.getPos(), crafter1.getBlockState(), 3); + world.setBlock(crafter1.getBlockPos(), crafter1.getBlockState(), 3); - crafter1.markDirty(); + crafter1.setChanged(); crafter1.connectivityChanged(); - crafter2.markDirty(); + crafter2.setChanged(); crafter2.connectivityChanged(); } @@ -115,8 +118,8 @@ public class ConnectedInputHandler { crafter.input = new ConnectedInput(); positions.forEach(splitPos -> { modifyAndUpdate(world, splitPos, input -> { - input.attachTo(crafter.getPos(), splitPos); - crafter.input.data.add(splitPos.subtract(crafter.getPos())); + input.attachTo(crafter.getBlockPos(), splitPos); + crafter.input.data.add(splitPos.subtract(crafter.getBlockPos())); }); }); } @@ -125,8 +128,8 @@ public class ConnectedInputHandler { MechanicalCrafterTileEntity crafter2) { crafter1.input.data.forEach(offset -> { - BlockPos connectedPos = crafter1.getPos() - .add(offset); + BlockPos connectedPos = crafter1.getBlockPos() + .offset(offset); modifyAndUpdate(world, connectedPos, input -> { }); }); @@ -134,26 +137,26 @@ public class ConnectedInputHandler { crafter2.input.data.forEach(offset -> { if (offset.equals(BlockPos.ZERO)) return; - BlockPos connectedPos = crafter2.getPos() - .add(offset); + BlockPos connectedPos = crafter2.getBlockPos() + .offset(offset); modifyAndUpdate(world, connectedPos, input -> { - input.attachTo(crafter1.getPos(), connectedPos); + input.attachTo(crafter1.getBlockPos(), connectedPos); crafter1.input.data.add(BlockPos.ZERO.subtract(input.data.get(0))); }); }); - crafter2.input.attachTo(crafter1.getPos(), crafter2.getPos()); + crafter2.input.attachTo(crafter1.getBlockPos(), crafter2.getBlockPos()); crafter1.input.data.add(BlockPos.ZERO.subtract(crafter2.input.data.get(0))); } private static void modifyAndUpdate(World world, BlockPos pos, Consumer callback) { - TileEntity te = world.getTileEntity(pos); + TileEntity te = world.getBlockEntity(pos); if (!(te instanceof MechanicalCrafterTileEntity)) return; MechanicalCrafterTileEntity crafter = (MechanicalCrafterTileEntity) te; callback.accept(crafter.input); - crafter.markDirty(); + crafter.setChanged(); crafter.connectivityChanged(); } @@ -174,15 +177,32 @@ public class ConnectedInputHandler { public IItemHandler getItemHandler(World world, BlockPos pos) { if (!isController) { - BlockPos controllerPos = pos.add(data.get(0)); + BlockPos controllerPos = pos.offset(data.get(0)); ConnectedInput input = CrafterHelper.getInput(world, controllerPos); if (input == this || input == null || !input.isController) return new ItemStackHandler(); return input.getItemHandler(world, controllerPos); } + Direction facing = Direction.SOUTH; + BlockState blockState = world.getBlockState(pos); + if (blockState.hasProperty(MechanicalCrafterBlock.HORIZONTAL_FACING)) + facing = blockState.getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); + AxisDirection axisDirection = facing.getAxisDirection(); + Axis compareAxis = facing.getClockWise() + .getAxis(); + + Comparator invOrdering = (p1, p2) -> { + int compareY = -Integer.compare(p1.getY(), p2.getY()); + int modifier = axisDirection.getStep() * (compareAxis == Axis.Z ? -1 : 1); + int c1 = compareAxis.choose(p1.getX(), p1.getY(), p1.getZ()); + int c2 = compareAxis.choose(p2.getX(), p2.getY(), p2.getZ()); + return compareY != 0 ? compareY : modifier * Integer.compare(c1, c2); + }; + List list = data.stream() - .map(l -> CrafterHelper.getCrafter(world, pos.add(l))) + .sorted(invOrdering) + .map(l -> CrafterHelper.getCrafter(world, pos.offset(l))) .filter(Objects::nonNull) .map(crafter -> crafter.getInventory()) .collect(Collectors.toList()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterCTBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterCTBehaviour.java index f4cf702e7..3649a3ab4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterCTBehaviour.java @@ -21,7 +21,7 @@ public class CrafterCTBehaviour extends ConnectedTextureBehaviour { Direction face) { if (state.getBlock() != other.getBlock()) return false; - if (state.get(HORIZONTAL_FACING) != other.get(HORIZONTAL_FACING)) + if (state.getValue(HORIZONTAL_FACING) != other.getValue(HORIZONTAL_FACING)) return false; ConnectedInput input1 = CrafterHelper.getInput(reader, pos); @@ -32,8 +32,8 @@ public class CrafterCTBehaviour extends ConnectedTextureBehaviour { if (input1.data.isEmpty() || input2.data.isEmpty()) return false; try { - if (pos.add(input1.data.get(0)) - .equals(otherPos.add(input2.data.get(0)))) + if (pos.offset(input1.data.get(0)) + .equals(otherPos.offset(input2.data.get(0)))) return true; } catch (IndexOutOfBoundsException e) { // race condition. data somehow becomes empty between the last 2 if statements @@ -47,7 +47,7 @@ public class CrafterCTBehaviour extends ConnectedTextureBehaviour { if (!direction.getAxis() .isVertical()) return false; - Direction facing = state.get(HORIZONTAL_FACING); + Direction facing = state.getValue(HORIZONTAL_FACING); if (facing.getAxis() == direction.getAxis()) return false; @@ -59,7 +59,7 @@ public class CrafterCTBehaviour extends ConnectedTextureBehaviour { @Override public CTSpriteShiftEntry get(BlockState state, Direction direction) { - Direction facing = state.get(HORIZONTAL_FACING); + Direction facing = state.getValue(HORIZONTAL_FACING); boolean isFront = facing.getAxis() == direction.getAxis(); boolean isVertical = direction.getAxis() .isVertical(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterHelper.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterHelper.java index ed41f7c3a..b954fe412 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterHelper.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterHelper.java @@ -7,7 +7,7 @@ import net.minecraft.world.IBlockDisplayReader; public class CrafterHelper { public static MechanicalCrafterTileEntity getCrafter(IBlockDisplayReader reader, BlockPos pos) { - TileEntity te = reader.getTileEntity(pos); + TileEntity te = reader.getBlockEntity(pos); if (!(te instanceof MechanicalCrafterTileEntity)) return null; return (MechanicalCrafterTileEntity) te; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterBlock.java index 05c41789d..d732ea2e2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterBlock.java @@ -47,12 +47,12 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT public MechanicalCrafterBlock(Properties properties) { super(properties); - setDefaultState(getDefaultState().with(POINTING, Pointing.UP)); + registerDefaultState(defaultBlockState().setValue(POINTING, Pointing.UP)); } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(POINTING)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POINTING)); } @Override @@ -62,35 +62,35 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT @Override public Axis getRotationAxis(BlockState state) { - return state.get(HORIZONTAL_FACING) + return state.getValue(HORIZONTAL_FACING) .getAxis(); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - Direction face = context.getFace(); - BlockPos placedOnPos = context.getPos() - .offset(face.getOpposite()); - BlockState blockState = context.getWorld() + Direction face = context.getClickedFace(); + BlockPos placedOnPos = context.getClickedPos() + .relative(face.getOpposite()); + BlockState blockState = context.getLevel() .getBlockState(placedOnPos); if ((blockState.getBlock() != this) || (context.getPlayer() != null && context.getPlayer() - .isSneaking())) { + .isShiftKeyDown())) { BlockState stateForPlacement = super.getStateForPlacement(context); - Direction direction = stateForPlacement.get(HORIZONTAL_FACING); + Direction direction = stateForPlacement.getValue(HORIZONTAL_FACING); if (direction != face) - stateForPlacement = stateForPlacement.with(POINTING, pointingFromFacing(face, direction)); + stateForPlacement = stateForPlacement.setValue(POINTING, pointingFromFacing(face, direction)); return stateForPlacement; } - Direction otherFacing = blockState.get(HORIZONTAL_FACING); + Direction otherFacing = blockState.getValue(HORIZONTAL_FACING); Pointing pointing = pointingFromFacing(face, otherFacing); - return getDefaultState().with(HORIZONTAL_FACING, otherFacing) - .with(POINTING, pointing); + return defaultBlockState().setValue(HORIZONTAL_FACING, otherFacing) + .setValue(POINTING, pointing); } @Override - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { if (state.getBlock() == newState.getBlock()) { if (getTargetDirection(state) != getTargetDirection(newState)) { MechanicalCrafterTileEntity crafter = CrafterHelper.getCrafter(worldIn, pos); @@ -103,29 +103,29 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT MechanicalCrafterTileEntity crafter = CrafterHelper.getCrafter(worldIn, pos); if (crafter != null) { if (crafter.covered) - Block.spawnAsEntity(worldIn, pos, AllItems.CRAFTER_SLOT_COVER.asStack()); + Block.popResource(worldIn, pos, AllItems.CRAFTER_SLOT_COVER.asStack()); crafter.ejectWholeGrid(); } for (Direction direction : Iterate.directions) { - if (direction.getAxis() == state.get(HORIZONTAL_FACING) + if (direction.getAxis() == state.getValue(HORIZONTAL_FACING) .getAxis()) continue; - BlockPos otherPos = pos.offset(direction); + BlockPos otherPos = pos.relative(direction); ConnectedInput thisInput = CrafterHelper.getInput(worldIn, pos); ConnectedInput otherInput = CrafterHelper.getInput(worldIn, otherPos); if (thisInput == null || otherInput == null) continue; - if (!pos.add(thisInput.data.get(0)) - .equals(otherPos.add(otherInput.data.get(0)))) + if (!pos.offset(thisInput.data.get(0)) + .equals(otherPos.offset(otherInput.data.get(0)))) continue; ConnectedInputHandler.toggleConnection(worldIn, pos, otherPos); } - worldIn.removeTileEntity(pos); + worldIn.removeBlockEntity(pos); } } @@ -146,9 +146,9 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { - if (context.getFace() == state.get(HORIZONTAL_FACING)) { - if (!context.getWorld().isRemote) - KineticTileEntity.switchToBlockState(context.getWorld(), context.getPos(), state.cycle(POINTING)); + if (context.getClickedFace() == state.getValue(HORIZONTAL_FACING)) { + if (!context.getLevel().isClientSide) + KineticTileEntity.switchToBlockState(context.getLevel(), context.getClickedPos(), state.cycle(POINTING)); return ActionResultType.SUCCESS; } @@ -156,12 +156,12 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT } @Override - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - ItemStack heldItem = player.getHeldItem(handIn); + ItemStack heldItem = player.getItemInHand(handIn); boolean isHand = heldItem.isEmpty() && handIn == Hand.MAIN_HAND; - TileEntity te = worldIn.getTileEntity(pos); + TileEntity te = worldIn.getBlockEntity(pos); if (!(te instanceof MechanicalCrafterTileEntity)) return ActionResultType.PASS; MechanicalCrafterTileEntity crafter = (MechanicalCrafterTileEntity) te; @@ -170,7 +170,7 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT if (AllBlocks.MECHANICAL_ARM.isIn(heldItem)) return ActionResultType.PASS; - if (hit.getFace() == state.get(HORIZONTAL_FACING)) { + if (hit.getDirection() == state.getValue(HORIZONTAL_FACING)) { if (crafter.phase != Phase.IDLE && !wrenched) { crafter.ejectWholeGrid(); @@ -178,7 +178,7 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT } if (crafter.phase == Phase.IDLE && !isHand && !wrenched) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return ActionResultType.SUCCESS; if (AllItems.CRAFTER_SLOT_COVER.isIn(heldItem)) { @@ -187,7 +187,7 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT if (!crafter.inventory.isEmpty()) return ActionResultType.PASS; crafter.covered = true; - crafter.markDirty(); + crafter.setChanged(); crafter.sendData(); if (!player.isCreative()) heldItem.shrink(1); @@ -201,17 +201,17 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT ItemStack remainder = ItemHandlerHelper.insertItem(capability.orElse(new ItemStackHandler()), heldItem.copy(), false); if (remainder.getCount() != heldItem.getCount()) - player.setHeldItem(handIn, remainder); + player.setItemInHand(handIn, remainder); return ActionResultType.SUCCESS; } - ItemStack inSlot = crafter.getInventory().getStackInSlot(0); + ItemStack inSlot = crafter.getInventory().getItem(0); if (inSlot.isEmpty()) { if (crafter.covered && !wrenched) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return ActionResultType.SUCCESS; crafter.covered = false; - crafter.markDirty(); + crafter.setChanged(); crafter.sendData(); if (!player.isCreative()) player.inventory.placeItemBackInInventory(worldIn, AllItems.CRAFTER_SLOT_COVER.asStack()); @@ -221,7 +221,7 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT } if (!isHand && !ItemHandlerHelper.canItemStacksStack(heldItem, inSlot)) return ActionResultType.PASS; - if (worldIn.isRemote) + if (worldIn.isClientSide) return ActionResultType.SUCCESS; player.inventory.placeItemBackInInventory(worldIn, inSlot); crafter.getInventory().setStackInSlot(0, ItemStack.EMPTY); @@ -252,25 +252,25 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock implements IT public static Direction getTargetDirection(BlockState state) { if (!AllBlocks.MECHANICAL_CRAFTER.has(state)) return Direction.UP; - Direction facing = state.get(HORIZONTAL_FACING); - Pointing point = state.get(POINTING); + Direction facing = state.getValue(HORIZONTAL_FACING); + Pointing point = state.getValue(POINTING); Vector3d targetVec = new Vector3d(0, 1, 0); targetVec = VecHelper.rotate(targetVec, -point.getXRotation(), Axis.Z); targetVec = VecHelper.rotate(targetVec, AngleHelper.horizontalAngle(facing), Axis.Y); - return Direction.getFacingFromVector(targetVec.x, targetVec.y, targetVec.z); + return Direction.getNearest(targetVec.x, targetVec.y, targetVec.z); } public static boolean isValidTarget(World world, BlockPos targetPos, BlockState crafterState) { BlockState targetState = world.getBlockState(targetPos); - if (!world.isBlockPresent(targetPos)) + if (!world.isLoaded(targetPos)) return false; if (!AllBlocks.MECHANICAL_CRAFTER.has(targetState)) return false; - if (crafterState.get(HORIZONTAL_FACING) != targetState.get(HORIZONTAL_FACING)) + if (crafterState.getValue(HORIZONTAL_FACING) != targetState.getValue(HORIZONTAL_FACING)) return false; - if (Math.abs(crafterState.get(POINTING) + if (Math.abs(crafterState.getValue(POINTING) .getXRotation() - - targetState.get(POINTING) + - targetState.getValue(POINTING) .getXRotation()) == 180) return false; 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..cfacf3990 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,39 +2,42 @@ 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.material.MaterialManager; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.jozufozu.flywheel.util.transform.TransformStack; 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() { - Direction facing = blockState.get(MechanicalCrafterBlock.HORIZONTAL_FACING); + protected Instancer getModel() { + Direction facing = blockState.getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); - Supplier ms = () -> { - MatrixStack stack = new MatrixStack(); - MatrixStacker stacker = MatrixStacker.of(stack).centre(); - - if (facing.getAxis() == Direction.Axis.X) - stacker.rotateZ(90); - else if (facing.getAxis() == Direction.Axis.Z) - stacker.rotateX(90); - - stacker.unCentre(); - return stack; - }; - return getRotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, blockState, facing, ms); + return getRotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, blockState, facing, rotateToFace(facing)); } + + private Supplier rotateToFace(Direction facing) { + return () -> { + MatrixStack stack = new MatrixStack(); + TransformStack stacker = MatrixTransformStack.of(stack) + .centre(); + + if (facing.getAxis() == Direction.Axis.X) stacker.rotateZ(90); + else if (facing.getAxis() == Direction.Axis.Z) stacker.rotateX(90); + + stacker.unCentre(); + return stack; + }; + } } 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..67e38873d 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,9 @@ 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.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -11,18 +14,15 @@ 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; -import com.simibubi.create.foundation.utility.MatrixStacker; +import com.simibubi.create.foundation.utility.Pointing; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.item.ItemStack; @@ -41,25 +41,27 @@ public class MechanicalCrafterRenderer extends SafeTileEntityRenderer { - if (getStackInSlot(slot).isEmpty()) + if (getItem(slot).isEmpty()) return; if (te.phase == Phase.IDLE) te.checkCompletedRecipe(false); @@ -72,8 +72,8 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { return stack; ItemStack insertItem = super.insertItem(slot, stack, simulate); if (insertItem.getCount() != stack.getCount() && !simulate) - te.getWorld() - .playSound(null, te.getPos(), SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, + te.getLevel() + .playSound(null, te.getBlockPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .5f); return insertItem; } @@ -83,7 +83,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { protected Inventory inventory; protected GroupedItems groupedItems = new GroupedItems(); protected ConnectedInput input = new ConnectedInput(); - protected LazyOptional invSupplier = LazyOptional.of(() -> input.getItemHandler(world, pos)); + protected LazyOptional invSupplier = LazyOptional.of(() -> input.getItemHandler(level, worldPosition)); protected boolean reRender; protected Phase phase; protected int countDown; @@ -176,25 +176,25 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { if (!clientPacket) return; if (compound.contains("Redraw")) - world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 16); + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); if (phaseBefore != phase && phase == Phase.CRAFTING) groupedItemsBeforeCraft = before; if (phaseBefore == Phase.EXPORTING && phase == Phase.WAITING) { - Direction facing = getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING); - Vector3d vec = Vector3d.of(facing.getDirectionVec()) + Direction facing = getBlockState().getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); + Vector3d vec = Vector3d.atLowerCornerOf(facing.getNormal()) .scale(.75) - .add(VecHelper.getCenterOf(pos)); + .add(VecHelper.getCenterOf(worldPosition)); Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(getBlockState()); - vec = vec.add(Vector3d.of(targetDirection.getDirectionVec()) + vec = vec.add(Vector3d.atLowerCornerOf(targetDirection.getNormal()) .scale(1)); - world.addParticle(ParticleTypes.CRIT, vec.x, vec.y, vec.z, 0, 0, 0); + level.addParticle(ParticleTypes.CRIT, vec.x, vec.y, vec.z, 0, 0, 0); } } @Override - public void remove() { + public void setRemoved() { invSupplier.invalidate(); - super.remove(); + super.setRemoved(); } public int getCountDownSpeed() { @@ -210,11 +210,11 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { if (phase == Phase.ACCEPTING) return; - boolean onClient = world.isRemote; + boolean onClient = level.isClientSide; boolean runLogic = !onClient || isVirtual(); - if (wasPoweredBefore != world.isBlockPowered(pos)) { - wasPoweredBefore = world.isBlockPowered(pos); + if (wasPoweredBefore != level.hasNeighborSignal(worldPosition)) { + wasPoweredBefore = level.hasNeighborSignal(worldPosition); if (wasPoweredBefore) { if (!runLogic) return; @@ -236,7 +236,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { } ItemStack result = - isVirtual() ? scriptedResult : RecipeGridHandler.tryToApplyRecipe(world, groupedItems); + isVirtual() ? scriptedResult : RecipeGridHandler.tryToApplyRecipe(level, groupedItems); if (result != null) { List containers = new ArrayList<>(); @@ -282,12 +282,12 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { return; } - Pointing pointing = getBlockState().get(MechanicalCrafterBlock.POINTING); + Pointing pointing = getBlockState().getValue(MechanicalCrafterBlock.POINTING); groupedItems.mergeOnto(targetingCrafter.groupedItems, pointing); groupedItems = new GroupedItems(); - + float pitch = targetingCrafter.groupedItems.grid.size() * 1/16f + .5f; - AllSoundEvents.CRAFTER_CLICK.playOnServer(world, pos, 1, pitch); + AllSoundEvents.CRAFTER_CLICK.playOnServer(level, worldPosition, 1, pitch); phase = Phase.WAITING; countDown = 0; @@ -301,18 +301,18 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { if (phase == Phase.CRAFTING) { if (onClient) { - Direction facing = getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING); + Direction facing = getBlockState().getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); float progress = countDown / 2000f; - Vector3d facingVec = Vector3d.of(facing.getDirectionVec()); + Vector3d facingVec = Vector3d.atLowerCornerOf(facing.getNormal()); Vector3d vec = facingVec.scale(.65) - .add(VecHelper.getCenterOf(pos)); - Vector3d offset = VecHelper.offsetRandomly(Vector3d.ZERO, world.rand, .125f) - .mul(VecHelper.axisAlingedPlaneOf(facingVec)) + .add(VecHelper.getCenterOf(worldPosition)); + Vector3d offset = VecHelper.offsetRandomly(Vector3d.ZERO, level.random, .125f) + .multiply(VecHelper.axisAlingedPlaneOf(facingVec)) .normalize() .scale(progress * .5f) .add(vec); if (progress > .5f) - world.addParticle(ParticleTypes.CRIT, offset.x, offset.y, offset.z, 0, 0, 0); + level.addParticle(ParticleTypes.CRIT, offset.x, offset.y, offset.z, 0, 0, 0); if (!groupedItemsBeforeCraft.grid.isEmpty() && progress < .5f) { if (groupedItems.grid.containsKey(Pair.of(0, 0))) { @@ -320,13 +320,13 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { groupedItemsBeforeCraft = new GroupedItems(); for (int i = 0; i < 10; i++) { - Vector3d randVec = VecHelper.offsetRandomly(Vector3d.ZERO, world.rand, .125f) - .mul(VecHelper.axisAlingedPlaneOf(facingVec)) + Vector3d randVec = VecHelper.offsetRandomly(Vector3d.ZERO, level.random, .125f) + .multiply(VecHelper.axisAlingedPlaneOf(facingVec)) .normalize() .scale(.25f); Vector3d offset2 = randVec.add(vec); randVec = randVec.scale(.35f); - world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), offset2.x, offset2.y, + level.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), offset2.x, offset2.y, offset2.z, randVec.x, randVec.y, randVec.z); } } @@ -335,12 +335,12 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { int prev = countDown; countDown -= getCountDownSpeed(); - + if (countDown < 1000 && prev >= 1000) { - AllSoundEvents.CRAFTER_CLICK.playOnServer(world, pos, 1, 2); - AllSoundEvents.CRAFTER_CRAFT.playOnServer(world, pos); + AllSoundEvents.CRAFTER_CLICK.playOnServer(level, worldPosition, 1, 2); + AllSoundEvents.CRAFTER_CRAFT.playOnServer(level, worldPosition); } - + if (countDown < 0) { countDown = 0; if (!runLogic) @@ -363,8 +363,8 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { } protected DirectBeltInputBehaviour getTargetingBelt() { - BlockPos targetPos = pos.offset(getTargetDirection()); - return TileEntityBehaviour.get(world, targetPos, DirectBeltInputBehaviour.TYPE); + BlockPos targetPos = worldPosition.relative(getTargetDirection()); + return TileEntityBehaviour.get(level, targetPos, DirectBeltInputBehaviour.TYPE); } public void tryInsert() { @@ -380,7 +380,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { for (Entry, ItemStack> entry : groupedItems.grid.entrySet()) { Pair pair = entry.getKey(); ItemStack stack = entry.getValue(); - BlockFace face = getTargetFace(world, pos, getBlockState()); + BlockFace face = getTargetFace(level, worldPosition, getBlockState()); ItemStack remainder = behaviour == null ? inserting.insert(stack.copy()) : behaviour.handleInsertion(stack, face.getFace(), false); @@ -411,15 +411,15 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { public void eject() { BlockState blockState = getBlockState(); boolean present = AllBlocks.MECHANICAL_CRAFTER.has(blockState); - Vector3d vec = present ? Vector3d.of(blockState.get(HORIZONTAL_FACING) - .getDirectionVec()) + Vector3d vec = present ? Vector3d.atLowerCornerOf(blockState.getValue(HORIZONTAL_FACING) + .getNormal()) .scale(.75f) : Vector3d.ZERO; - Vector3d ejectPos = VecHelper.getCenterOf(pos) + Vector3d ejectPos = VecHelper.getCenterOf(worldPosition) .add(vec); groupedItems.grid.forEach((pair, stack) -> dropItem(ejectPos, stack)); - if (!inventory.getStackInSlot(0) + if (!inventory.getItem(0) .isEmpty()) - dropItem(ejectPos, inventory.getStackInSlot(0)); + dropItem(ejectPos, inventory.getItem(0)); phase = Phase.IDLE; groupedItems = new GroupedItems(); inventory.setStackInSlot(0, ItemStack.EMPTY); @@ -427,15 +427,15 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { } public void dropItem(Vector3d ejectPos, ItemStack stack) { - ItemEntity itemEntity = new ItemEntity(world, ejectPos.x, ejectPos.y, ejectPos.z, stack); - itemEntity.setDefaultPickupDelay(); - world.addEntity(itemEntity); + ItemEntity itemEntity = new ItemEntity(level, ejectPos.x, ejectPos.y, ejectPos.z, stack); + itemEntity.setDefaultPickUpDelay(); + level.addFreshEntity(itemEntity); } @Override public void lazyTick() { super.lazyTick(); - if (world.isRemote && !isVirtual()) + if (level.isClientSide && !isVirtual()) return; if (phase == Phase.IDLE && craftingItemPresent()) checkCompletedRecipe(false); @@ -444,19 +444,19 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { } public boolean craftingItemPresent() { - return !inventory.getStackInSlot(0) + return !inventory.getItem(0) .isEmpty(); } public boolean craftingItemOrCoverPresent() { - return !inventory.getStackInSlot(0) + return !inventory.getItem(0) .isEmpty() || covered; } protected void checkCompletedRecipe(boolean poweredStart) { if (getSpeed() == 0) return; - if (world.isRemote && !isVirtual()) + if (level.isClientSide && !isVirtual()) return; List chain = RecipeGridHandler.getAllCraftersOfChainIf(this, poweredStart ? MechanicalCrafterTileEntity::craftingItemPresent @@ -469,7 +469,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { protected void begin() { phase = Phase.ACCEPTING; - groupedItems = new GroupedItems(inventory.getStackInSlot(0)); + groupedItems = new GroupedItems(inventory.getItem(0)); inventory.setStackInSlot(0, ItemStack.EMPTY); if (RecipeGridHandler.getPrecedingCrafters(this) .isEmpty()) { @@ -505,7 +505,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { reRender = true; sendData(); invSupplier.invalidate(); - invSupplier = LazyOptional.of(() -> input.getItemHandler(world, pos)); + invSupplier = LazyOptional.of(() -> input.getItemHandler(level, worldPosition)); } public Inventory getInventory() { @@ -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/MechanicalCraftingInventory.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingInventory.java index 600cb4996..21cf5d725 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingInventory.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingInventory.java @@ -12,7 +12,7 @@ import net.minecraft.item.ItemStack; public class MechanicalCraftingInventory extends CraftingInventory { private static Container dummyContainer = new Container(null, -1) { - public boolean canInteractWith(PlayerEntity playerIn) { + public boolean stillValid(PlayerEntity playerIn) { return false; } }; @@ -22,7 +22,7 @@ public class MechanicalCraftingInventory extends CraftingInventory { for (int y = 0; y < items.height; y++) { for (int x = 0; x < items.width; x++) { ItemStack stack = items.grid.get(Pair.of(x + items.minX, y + items.minY)); - setInventorySlotContents(x + (items.height - y - 1) * items.width, + setItem(x + (items.height - y - 1) * items.width, stack == null ? ItemStack.EMPTY : stack.copy()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingRecipe.java index a44acfa42..4eef6c570 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingRecipe.java @@ -10,52 +10,99 @@ import net.minecraft.item.crafting.IRecipeType; import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.ShapedRecipe; import net.minecraft.network.PacketBuffer; +import net.minecraft.util.JSONUtils; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; public class MechanicalCraftingRecipe extends ShapedRecipe { + private boolean acceptMirrored; + public MechanicalCraftingRecipe(ResourceLocation idIn, String groupIn, int recipeWidthIn, int recipeHeightIn, - NonNullList recipeItemsIn, ItemStack recipeOutputIn) { + NonNullList recipeItemsIn, ItemStack recipeOutputIn, boolean acceptMirrored) { super(idIn, groupIn, recipeWidthIn, recipeHeightIn, recipeItemsIn, recipeOutputIn); + this.acceptMirrored = acceptMirrored; } - private static MechanicalCraftingRecipe fromShaped(ShapedRecipe recipe) { + private static MechanicalCraftingRecipe fromShaped(ShapedRecipe recipe, boolean acceptMirrored) { return new MechanicalCraftingRecipe(recipe.getId(), recipe.getGroup(), recipe.getWidth(), recipe.getHeight(), - recipe.getIngredients(), recipe.getRecipeOutput()); + recipe.getIngredients(), recipe.getResultItem(), acceptMirrored); } @Override public boolean matches(CraftingInventory inv, World worldIn) { - return inv instanceof MechanicalCraftingInventory && super.matches(inv, worldIn); + if (!(inv instanceof MechanicalCraftingInventory)) + return false; + if (acceptsMirrored()) + return super.matches(inv, worldIn); + + // From ShapedRecipe except the symmetry + for (int i = 0; i <= inv.getWidth() - this.getWidth(); ++i) + for (int j = 0; j <= inv.getHeight() - this.getHeight(); ++j) + if (this.matchesSpecific(inv, i, j)) + return true; + return false; + } + + // From ShapedRecipe + private boolean matchesSpecific(CraftingInventory inv, int p_77573_2_, int p_77573_3_) { + NonNullList ingredients = getIngredients(); + int width = getWidth(); + int height = getHeight(); + for (int i = 0; i < inv.getWidth(); ++i) { + for (int j = 0; j < inv.getHeight(); ++j) { + int k = i - p_77573_2_; + int l = j - p_77573_3_; + Ingredient ingredient = Ingredient.EMPTY; + if (k >= 0 && l >= 0 && k < width && l < height) + ingredient = ingredients.get(k + l * width); + if (!ingredient.test(inv.getItem(i + j * inv.getWidth()))) + return false; + } + } + return true; } @Override public IRecipeType getType() { - return AllRecipeTypes.MECHANICAL_CRAFTING.type; + return AllRecipeTypes.MECHANICAL_CRAFTING.getType(); } - + @Override - public boolean isDynamic() { + public boolean isSpecial() { return true; } - + @Override public IRecipeSerializer getSerializer() { - return AllRecipeTypes.MECHANICAL_CRAFTING.serializer; + return AllRecipeTypes.MECHANICAL_CRAFTING.getSerializer(); + } + + public boolean acceptsMirrored() { + return acceptMirrored; } public static class Serializer extends ShapedRecipe.Serializer { @Override - public ShapedRecipe read(ResourceLocation recipeId, JsonObject json) { - return fromShaped(super.read(recipeId, json)); + public ShapedRecipe fromJson(ResourceLocation recipeId, JsonObject json) { + return fromShaped(super.fromJson(recipeId, json), JSONUtils.getAsBoolean(json, "acceptMirrored", true)); } - + @Override - public ShapedRecipe read(ResourceLocation recipeId, PacketBuffer buffer) { - return fromShaped(super.read(recipeId, buffer)); + public ShapedRecipe fromNetwork(ResourceLocation recipeId, PacketBuffer buffer) { + return fromShaped(super.fromNetwork(recipeId, buffer), buffer.readBoolean() && buffer.readBoolean()); + } + + @Override + public void toNetwork(PacketBuffer p_199427_1_, ShapedRecipe p_199427_2_) { + super.toNetwork(p_199427_1_, p_199427_2_); + if (p_199427_2_ instanceof MechanicalCraftingRecipe) { + p_199427_1_.writeBoolean(true); + p_199427_1_.writeBoolean(((MechanicalCraftingRecipe) p_199427_2_).acceptsMirrored()); + } else + p_199427_1_.writeBoolean(false); } } 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..12a0ee73a 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,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Predicate; +import java.util.stream.IntStream; import org.apache.commons.lang3.tuple.Pair; @@ -22,6 +23,8 @@ import com.simibubi.create.foundation.utility.Pointing; import net.minecraft.block.BlockState; import net.minecraft.inventory.CraftingInventory; import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.FireworkRocketRecipe; +import net.minecraft.item.crafting.ICraftingRecipe; import net.minecraft.item.crafting.IRecipeType; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; @@ -63,8 +66,8 @@ public class RecipeGridHandler { empty = true; else allEmpty = false; - if (poweredStart && current.getWorld() - .isBlockPowered(current.getPos())) + if (poweredStart && current.getLevel() + .hasNeighborSignal(current.getBlockPos())) powered = true; crafters.add(current); @@ -86,29 +89,29 @@ public class RecipeGridHandler { if (!isCrafter(state)) return null; - BlockPos targetPos = crafter.getPos() - .offset(MechanicalCrafterBlock.getTargetDirection(state)); - MechanicalCrafterTileEntity targetTE = CrafterHelper.getCrafter(crafter.getWorld(), targetPos); + BlockPos targetPos = crafter.getBlockPos() + .relative(MechanicalCrafterBlock.getTargetDirection(state)); + MechanicalCrafterTileEntity targetTE = CrafterHelper.getCrafter(crafter.getLevel(), targetPos); if (targetTE == null) return null; BlockState targetState = targetTE.getBlockState(); if (!isCrafter(targetState)) return null; - if (state.get(HORIZONTAL_FACING) != targetState.get(HORIZONTAL_FACING)) + if (state.getValue(HORIZONTAL_FACING) != targetState.getValue(HORIZONTAL_FACING)) return null; return targetTE; } public static List getPrecedingCrafters(MechanicalCrafterTileEntity crafter) { - BlockPos pos = crafter.getPos(); - World world = crafter.getWorld(); + BlockPos pos = crafter.getBlockPos(); + World world = crafter.getLevel(); List crafters = new ArrayList<>(); BlockState blockState = crafter.getBlockState(); if (!isCrafter(blockState)) return crafters; - Direction blockFacing = blockState.get(HORIZONTAL_FACING); + Direction blockFacing = blockState.getValue(HORIZONTAL_FACING); Direction blockPointing = MechanicalCrafterBlock.getTargetDirection(blockState); for (Direction facing : Iterate.directions) { if (blockFacing.getAxis() == facing.getAxis()) @@ -116,13 +119,13 @@ public class RecipeGridHandler { if (blockPointing == facing) continue; - BlockPos neighbourPos = pos.offset(facing); + BlockPos neighbourPos = pos.relative(facing); BlockState neighbourState = world.getBlockState(neighbourPos); if (!isCrafter(neighbourState)) continue; if (MechanicalCrafterBlock.getTargetDirection(neighbourState) != facing.getOpposite()) continue; - if (blockFacing != neighbourState.get(HORIZONTAL_FACING)) + if (blockFacing != neighbourState.getValue(HORIZONTAL_FACING)) continue; MechanicalCrafterTileEntity te = CrafterHelper.getCrafter(world, neighbourPos); if (te == null) @@ -144,16 +147,28 @@ public class RecipeGridHandler { ItemStack result = null; if (AllConfigs.SERVER.recipes.allowRegularCraftingInCrafter.get()) result = world.getRecipeManager() - .getRecipe(IRecipeType.CRAFTING, craftinginventory, world) - .map(r -> r.getCraftingResult(craftinginventory)) + .getRecipeFor(IRecipeType.CRAFTING, craftinginventory, world) + .filter(r -> isRecipeAllowed(r, craftinginventory)) + .map(r -> r.assemble(craftinginventory)) .orElse(null); if (result == null) result = AllRecipeTypes.MECHANICAL_CRAFTING.find(craftinginventory, world) - .map(r -> r.getCraftingResult(craftinginventory)) + .map(r -> r.assemble(craftinginventory)) .orElse(null); 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.getContainerSize()) + .map(i -> inventory.getItem(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; @@ -192,7 +207,7 @@ public class RecipeGridHandler { CompoundNBT entry = (CompoundNBT) inbt; int x = entry.getInt("x"); int y = entry.getInt("y"); - ItemStack stack = ItemStack.read(entry.getCompound("item")); + ItemStack stack = ItemStack.of(entry.getCompound("item")); items.grid.put(Pair.of(x, y), stack); }); return items; 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..916e384b0 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; @@ -37,7 +37,7 @@ public class HandCrankBlock extends DirectionalKineticBlock implements ITE te.turn(player.isSneaking())); - player.addExhaustion(getRotationSpeed() * AllConfigs.SERVER.kinetics.crankHungerMultiplier.getF()); + withTileEntityDo(worldIn, pos, te -> te.turn(player.isShiftKeyDown())); + player.causeFoodExhaustion(getRotationSpeed() * AllConfigs.SERVER.kinetics.crankHungerMultiplier.getF()); return ActionResultType.SUCCESS; } @@ -67,16 +67,16 @@ public class HandCrankBlock extends DirectionalKineticBlock implements ITE modelManager, HandCrankTileEntity tile) { + public HandCrankInstance(MaterialManager modelManager, HandCrankTileEntity tile) { super(modelManager, tile); this.tile = tile; @@ -31,9 +31,9 @@ public class HandCrankInstance extends SingleRotatingInstance implements IDynami if (renderedHandle == null) return; - facing = blockState.get(BlockStateProperties.FACING); + facing = blockState.getValue(BlockStateProperties.FACING); Direction opposite = facing.getOpposite(); - InstancedModel model = getTransformMaterial().getModel(renderedHandle, blockState, opposite); + Instancer model = getTransformMaterial().getModel(renderedHandle, blockState, opposite); crank = model.createInstance(); rotateCrank(); @@ -51,10 +51,10 @@ public class HandCrankInstance extends SingleRotatingInstance implements IDynami float angle = (tile.independentAngle + AnimationTickHolder.getPartialTicks() * tile.chasingVelocity) / 360; MatrixStack ms = new MatrixStack(); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .translate(getInstancePosition()) .centre() - .rotate(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis), angle) + .rotate(Direction.get(Direction.AxisDirection.POSITIVE, axis), angle) .unCentre(); crank.setTransform(ms); 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..f4a6c7871 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.getLevel())) return; BlockState state = te.getBlockState(); Block block = state.getBlock(); @@ -38,12 +38,12 @@ public class HandCrankRenderer extends KineticTileEntityRenderer { if (renderedHandle == null) return; - Direction facing = state.get(FACING); + Direction facing = state.getValue(FACING); SuperByteBuffer handle = PartialBufferer.getFacing(renderedHandle, state, facing.getOpposite()); HandCrankTileEntity crank = (HandCrankTileEntity) te; kineticRotationTransform(handle, te, facing.getAxis(), (crank.independentAngle + partialTicks * crank.chasingVelocity) / 360, light); - handle.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + handle.renderInto(ms, buffer.getBuffer(RenderType.solid())); } } 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..c7ad300fd 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 @@ -9,6 +9,8 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntityType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; public class HandCrankTileEntity extends GeneratingKineticTileEntity { @@ -29,7 +31,7 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity { inUse = 10; this.backwards = back; - if (update && !world.isRemote) + if (update && !level.isClientSide) updateGeneratedRotation(); } @@ -40,7 +42,7 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity { return 0; HandCrankBlock crank = (HandCrankBlock) block; int speed = (inUse == 0 ? 0 : backwards ? -1 : 1) * crank.getRotationSpeed(); - return convertToDirection(speed, getBlockState().get(HandCrankBlock.FACING)); + return convertToDirection(speed, getBlockState().getValue(HandCrankBlock.FACING)); } @Override @@ -66,7 +68,7 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity { if (inUse > 0) { inUse--; - if (inUse == 0 && !world.isRemote) + if (inUse == 0 && !level.isClientSide) updateGeneratedRotation(); } } @@ -77,17 +79,18 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } @Override + @OnlyIn(Dist.CLIENT) public void tickAudio() { super.tickAudio(); if (inUse > 0 && AnimationTickHolder.getTicks() % 10 == 0) { if (!AllBlocks.HAND_CRANK.has(getBlockState())) return; - AllSoundEvents.CRANKING.playAt(world, pos, (inUse) / 2.5f, .65f + (10 - inUse) / 10f, true); + AllSoundEvents.CRANKING.playAt(level, worldPosition, (inUse) / 2.5f, .65f + (10 - inUse) / 10f, 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..7d0b97fe8 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; @@ -38,32 +38,32 @@ public class ValveHandleBlock extends HandCrankBlock { } @Override - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - ItemStack heldItem = player.getHeldItem(handIn); + ItemStack heldItem = player.getItemInHand(handIn); for (DyeColor color : DyeColor.values()) { if (!heldItem.getItem() - .isIn(DyeHelper.getTagOfDye(color))) + .is(DyeHelper.getTagOfDye(color))) continue; - if (worldIn.isRemote) + if (worldIn.isClientSide) 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() + .setValue(FACING, state.getValue(FACING)); if (newState != state) - worldIn.setBlockState(pos, newState); + worldIn.setBlockAndUpdate(pos, newState); return ActionResultType.SUCCESS; } - return super.onUse(state, worldIn, pos, player, handIn, hit); + return super.use(state, worldIn, pos, player, handIn, hit); } @Override - public void fillItemGroup(ItemGroup group, NonNullList p_149666_2_) { - if (group != ItemGroup.SEARCH && !inCreativeTab) + public void fillItemCategory(ItemGroup group, NonNullList p_149666_2_) { + if (group != ItemGroup.TAB_SEARCH && !inCreativeTab) return; - super.fillItemGroup(group, p_149666_2_); + super.fillItemCategory(group, p_149666_2_); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/AbstractCrushingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/AbstractCrushingRecipe.java index 350a5269a..ec8c290d4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/AbstractCrushingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/AbstractCrushingRecipe.java @@ -1,14 +1,14 @@ package com.simibubi.create.content.contraptions.components.crusher; -import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import net.minecraftforge.items.wrapper.RecipeWrapper; public abstract class AbstractCrushingRecipe extends ProcessingRecipe { - public AbstractCrushingRecipe(AllRecipeTypes recipeType, ProcessingRecipeParams params) { + public AbstractCrushingRecipe(IRecipeTypeInfo recipeType, ProcessingRecipeParams params) { super(recipeType, params); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingRecipe.java index d03b8e07e..e4bfa6be3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingRecipe.java @@ -20,9 +20,9 @@ public class CrushingRecipe extends AbstractCrushingRecipe { if (inv.isEmpty()) return false; return ingredients.get(0) - .test(inv.getStackInSlot(0)); + .test(inv.getItem(0)); } - + @Override protected int getMaxOutputCount() { return 7; 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..c0afc346b 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 @@ -38,11 +38,11 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE @Override public Axis getRotationAxis(BlockState state) { - return state.get(AXIS); + return state.getValue(AXIS); } @Override - public BlockRenderType getRenderType(BlockState state) { + public BlockRenderType getRenderShape(BlockState state) { return BlockRenderType.ENTITYBLOCK_ANIMATED; } @@ -53,35 +53,35 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE } @Override - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { for (Direction d : Iterate.directions) { - if (d.getAxis() == state.get(AXIS)) + if (d.getAxis() == state.getValue(AXIS)) continue; - if (AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(worldIn.getBlockState(pos.offset(d)))) - worldIn.setBlockState(pos.offset(d), Blocks.AIR.getDefaultState()); + if (AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(worldIn.getBlockState(pos.relative(d)))) + worldIn.setBlockAndUpdate(pos.relative(d), Blocks.AIR.defaultBlockState()); } if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) { - worldIn.removeTileEntity(pos); + worldIn.removeBlockEntity(pos); } } public void updateControllers(BlockState state, World world, BlockPos pos, Direction side) { - if (side.getAxis() == state.get(AXIS)) + if (side.getAxis() == state.getValue(AXIS)) return; if (world == null) return; - BlockPos controllerPos = pos.offset(side); - BlockPos otherWheelPos = pos.offset(side, 2); + BlockPos controllerPos = pos.relative(side); + BlockPos otherWheelPos = pos.relative(side, 2); boolean controllerExists = AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(world.getBlockState(controllerPos)); boolean controllerIsValid = controllerExists && world.getBlockState(controllerPos) - .get(VALID); + .getValue(VALID); Direction controllerOldDirection = controllerExists ? world.getBlockState(controllerPos) - .get(FACING) + .getValue(FACING) : null; boolean controllerShouldExist = false; @@ -92,39 +92,34 @@ 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.getValue(AXIS); + Axis sideAxis = side.getAxis(); + int controllerADO = Math.round(Math.signum(te.getSpeed())) * side.getAxisDirection().getStep(); + Vector3d controllerDirVec = new Vector3d(wheelAxis == Axis.X ? 1 : 0 + , wheelAxis == Axis.Y ? 1 : 0 + , wheelAxis == Axis.Z ? 1 : 0) + .cross(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.getNearest(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.getValue(AXIS) != state.getValue(AXIS)) + controllerShouldExist = false; } if (!controllerShouldExist) { if (controllerExists) - world.setBlockState(controllerPos, Blocks.AIR.getDefaultState()); + world.setBlockAndUpdate(controllerPos, Blocks.AIR.defaultBlockState()); return; } @@ -133,13 +128,13 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE .getMaterial() .isReplaceable()) return; - world.setBlockState(controllerPos, AllBlocks.CRUSHING_WHEEL_CONTROLLER.getDefaultState() - .with(VALID, controllerShouldBeValid) - .with(FACING, controllerNewDirection)); + world.setBlockAndUpdate(controllerPos, AllBlocks.CRUSHING_WHEEL_CONTROLLER.getDefaultState() + .setValue(VALID, controllerShouldBeValid) + .setValue(FACING, controllerNewDirection)); } else if (controllerIsValid != controllerShouldBeValid || controllerOldDirection != controllerNewDirection) { - world.setBlockState(controllerPos, world.getBlockState(controllerPos) - .with(VALID, controllerShouldBeValid) - .with(FACING, controllerNewDirection)); + world.setBlockAndUpdate(controllerPos, world.getBlockState(controllerPos) + .setValue(VALID, controllerShouldBeValid) + .setValue(FACING, controllerNewDirection)); } ((CrushingWheelControllerBlock) AllBlocks.CRUSHING_WHEEL_CONTROLLER.get()) @@ -148,41 +143,39 @@ 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; + public void entityInside(BlockState state, World worldIn, BlockPos pos, Entity entityIn) { + 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.getValue(AXIS) == Axis.X) { + z = speed / 20f; + x += (pos.getX() + .5f - entityIn.getX()) * .1f; } + if (state.getValue(AXIS) == Axis.Z) { + x = speed / -20f; + z += (pos.getZ() + .5f - entityIn.getZ()) * .1f; + } + entityIn.setDeltaMovement(entityIn.getDeltaMovement() + .add(x, 0, z)); } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { + public boolean canSurvive(BlockState state, IWorldReader worldIn, BlockPos pos) { for (Direction direction : Iterate.directions) { - BlockPos neighbourPos = pos.offset(direction); + BlockPos neighbourPos = pos.relative(direction); BlockState neighbourState = worldIn.getBlockState(neighbourPos); - Axis stateAxis = state.get(AXIS); + Axis stateAxis = state.getValue(AXIS); if (AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(neighbourState) && direction.getAxis() != stateAxis) return false; if (!AllBlocks.CRUSHING_WHEEL.has(neighbourState)) continue; - if (neighbourState.get(AXIS) != stateAxis || stateAxis != direction.getAxis()) + if (neighbourState.getValue(AXIS) != stateAxis || stateAxis != direction.getAxis()) return false; } @@ -191,7 +184,7 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.get(AXIS); + return face.getAxis() == state.getValue(AXIS); } @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..b136458b1 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 @@ -52,7 +52,7 @@ public class CrushingWheelControllerBlock extends DirectionalBlock } @Override - public boolean isReplaceable(BlockState state, BlockItemUseContext useContext) { + public boolean canBeReplaced(BlockState state, BlockItemUseContext useContext) { return false; } @@ -67,17 +67,17 @@ public class CrushingWheelControllerBlock extends DirectionalBlock } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(VALID); builder.add(FACING); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } - public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) { - if (!state.get(VALID)) + public void entityInside(BlockState state, World worldIn, BlockPos pos, Entity entityIn) { + if (!state.getValue(VALID)) return; - Direction facing = state.get(FACING); + Direction facing = state.getValue(FACING); Axis axis = facing.getAxis(); checkEntityForProcessing(worldIn, pos, entityIn); @@ -85,45 +85,45 @@ public class CrushingWheelControllerBlock extends DirectionalBlock withTileEntityDo(worldIn, pos, te -> { if (te.processingEntity == entityIn) - entityIn.setMotionMultiplier(state, new Vector3d(axis == Axis.X ? (double) 0.05F : 0.25D + entityIn.makeStuckInBlock(state, new Vector3d(axis == Axis.X ? (double) 0.05F : 0.25D , axis == Axis.Y ? (double) 0.05F : 0.25D , axis == Axis.Z ? (double) 0.05F : 0.25D)); }); } - 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.level.getDifficulty() == Difficulty.PEACEFUL) + return; - te.startCrushing(entityIn); - } catch (TileEntityException e) {} + te.startCrushing(entityIn); } @Override - public void onLanded(IBlockReader worldIn, Entity entityIn) { - super.onLanded(worldIn, entityIn); + public void updateEntityAfterFallOn(IBlockReader worldIn, Entity entityIn) { + super.updateEntityAfterFallOn(worldIn, entityIn); //Moved to onEntityCollision to allow for omnidirectional input } @Override public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) { - if (!stateIn.get(VALID)) + if (!stateIn.getValue(VALID)) return; if (rand.nextInt(1) != 0) return; @@ -134,7 +134,7 @@ public class CrushingWheelControllerBlock extends DirectionalBlock } @Override - public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, + public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) { updateSpeed(stateIn, worldIn, currentPos); return stateIn; @@ -142,7 +142,7 @@ public class CrushingWheelControllerBlock extends DirectionalBlock public void updateSpeed(BlockState state, IWorld world, BlockPos pos) { withTileEntityDo(world, pos, te -> { - if (!state.get(VALID)) { + if (!state.getValue(VALID)) { if (te.crushingspeed != 0) { te.crushingspeed = 0; te.sendData(); @@ -151,13 +151,15 @@ public class CrushingWheelControllerBlock extends DirectionalBlock } for (Direction d : Iterate.directions) { - BlockState neighbour = world.getBlockState(pos.offset(d)); + BlockState neighbour = world.getBlockState(pos.relative(d)); if (!AllBlocks.CRUSHING_WHEEL.has(neighbour)) continue; - if (neighbour.get(BlockStateProperties.AXIS) == d.getAxis()) + if (neighbour.getValue(BlockStateProperties.AXIS) == d.getAxis()) continue; - KineticTileEntity wheelTe = (KineticTileEntity) world.getTileEntity(pos.offset(d)); - te.crushingspeed = Math.abs(wheelTe.getSpeed() / 50f); + TileEntity adjTe = world.getBlockEntity(pos.relative(d)); + if (!(adjTe instanceof KineticTileEntity)) + continue; + te.crushingspeed = Math.abs(((KineticTileEntity) adjTe).getSpeed() / 50f); te.sendData(); break; } @@ -167,44 +169,44 @@ public class CrushingWheelControllerBlock extends DirectionalBlock @Override public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - if (!state.get(VALID)) - return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING)); + VoxelShape standardShape = AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.getValue(FACING)); + + if (!state.getValue(VALID)) + 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.getValue(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 - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { if (!state.hasTileEntity() || state.getBlock() == newState.getBlock()) return; withTileEntityDo(worldIn, pos, te -> ItemHelper.dropContents(worldIn, pos, te.inventory)); - worldIn.removeTileEntity(pos); + worldIn.removeBlockEntity(pos); } @Override public Class getTileEntityClass() { return CrushingWheelControllerTileEntity.class; } - + @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java index e8562843c..5928a5838 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java @@ -13,6 +13,8 @@ import com.simibubi.create.content.contraptions.processing.ProcessingInventory; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; 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.sound.SoundScapes.AmbienceGroup; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; @@ -38,8 +40,11 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; +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.fml.DistExecutor; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.wrapper.RecipeWrapper; @@ -77,7 +82,7 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { BlockState blockState = getBlockState(); if (blockState == null) return false; - Direction direction = blockState.get(CrushingWheelControllerBlock.FACING); + Direction direction = blockState.getValue(CrushingWheelControllerBlock.FACING); return direction == Direction.DOWN || direction == side; } @@ -86,48 +91,52 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { super.tick(); if (searchForEntity) { searchForEntity = false; - List search = world.getEntitiesInAABBexcluding(null, new AxisAlignedBB(getPos()), - e -> entityUUID.equals(e.getUniqueID())); + List search = level.getEntities((Entity) null, new AxisAlignedBB(getBlockPos()), + e -> entityUUID.equals(e.getUUID())); if (search.isEmpty()) clear(); else processingEntity = search.get(0); } - - if (!isOccupied()) return; if (crushingspeed == 0) return; + if (level.isClientSide) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio()); + float speed = crushingspeed * 4; - Vector3d centerPos = VecHelper.getCenterOf(pos); - Direction facing = getBlockState().get(FACING); - int offset = facing.getAxisDirection().getOffset(); - Vector3d outSpeed = new Vector3d((facing.getAxis() == Axis.X ? 0.25D : 0.0D) * offset - , offset == 1 ? (facing.getAxis() == Axis.Y ? 0.5D : 0.0D) : 0.0D //Increased upwards speed so upwards crushing wheels shoot out the item properly. - , (facing.getAxis() == Axis.Z ? 0.25D : 0.0D) * offset); //No downwards speed, so downwards crushing wheels drop the items as before. - Vector3d outPos = centerPos.add((facing.getAxis() == Axis.X ? .55f * offset : 0f) - , (facing.getAxis() == Axis.Y ? .55f * offset : 0f) - , (facing.getAxis() == Axis.Z ? .55f * offset : 0f)); + Vector3d centerPos = VecHelper.getCenterOf(worldPosition); + Direction facing = getBlockState().getValue(FACING); + int offset = facing.getAxisDirection() + .getStep(); + Vector3d outSpeed = new Vector3d((facing.getAxis() == Axis.X ? 0.25D : 0.0D) * offset, + offset == 1 ? (facing.getAxis() == Axis.Y ? 0.5D : 0.0D) : 0.0D // Increased upwards speed so upwards + // crushing wheels shoot out the item + // properly. + , (facing.getAxis() == Axis.Z ? 0.25D : 0.0D) * offset); // No downwards speed, so downwards crushing wheels + // drop the items as before. + Vector3d outPos = centerPos.add((facing.getAxis() == Axis.X ? .55f * offset : 0f), + (facing.getAxis() == Axis.Y ? .55f * offset : 0f), (facing.getAxis() == Axis.Z ? .55f * offset : 0f)); if (!hasEntity()) { float processingSpeed = - MathHelper.clamp((speed) / (!inventory.appliedRecipe ? MathHelper.log2(inventory.getStackInSlot(0) - .getCount()) : 1), .25f, 20); + MathHelper.clamp((speed) / (!inventory.appliedRecipe ? MathHelper.log2(inventory.getStackInSlot(0) + .getCount()) : 1), .25f, 20); inventory.remainingTime -= processingSpeed; spawnParticles(inventory.getStackInSlot(0)); - if (world.isRemote) + if (level.isClientSide) return; if (inventory.remainingTime < 20 && !inventory.appliedRecipe) { applyRecipe(); inventory.appliedRecipe = true; - world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16); + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); return; } @@ -136,12 +145,13 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { } inventory.remainingTime = 0; - //Output Items - if (facing.getAxis().isHorizontal() || facing == Direction.DOWN) { - BlockPos nextPos = pos.add(facing.getAxis() == Axis.X ? 1f * offset : 0f - , (-1f) - , facing.getAxis() == Axis.Z ? 1f * offset : 0f); - DirectBeltInputBehaviour behaviour = TileEntityBehaviour.get(world, nextPos, DirectBeltInputBehaviour.TYPE); + // Output Items + if (facing.getAxis() + .isHorizontal() || facing == Direction.DOWN) { + BlockPos nextPos = worldPosition.offset(facing.getAxis() == Axis.X ? 1f * offset : 0f, (-1f), + facing.getAxis() == Axis.Z ? 1f * offset : 0f); + DirectBeltInputBehaviour behaviour = + TileEntityBehaviour.get(level, nextPos, DirectBeltInputBehaviour.TYPE); if (behaviour != null) { boolean changed = false; if (!behaviour.canInsertFromSide(facing)) @@ -157,97 +167,112 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { changed = true; } if (changed) { - markDirty(); + setChanged(); sendData(); } return; } } - //Eject Items + // Eject Items for (int slot = 0; slot < inventory.getSlots(); slot++) { ItemStack stack = inventory.getStackInSlot(slot); if (stack.isEmpty()) continue; - ItemEntity entityIn = new ItemEntity(world, outPos.x, outPos.y, outPos.z, stack); - entityIn.setMotion(outSpeed); + ItemEntity entityIn = new ItemEntity(level, outPos.x, outPos.y, outPos.z, stack); + entityIn.setDeltaMovement(outSpeed); entityIn.getPersistentData() - .put("BypassCrushingWheel", NBTUtil.writeBlockPos(pos)); - world.addEntity(entityIn); + .put("BypassCrushingWheel", NBTUtil.writeBlockPos(worldPosition)); + level.addFreshEntity(entityIn); } inventory.clear(); - world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16); - + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); return; } if (!processingEntity.isAlive() || !processingEntity.getBoundingBox() - .intersects(new AxisAlignedBB(pos).grow(.5f))) { + .intersects(new AxisAlignedBB(worldPosition).inflate(.5f))) { clear(); return; } - double xMotion = ((pos.getX() + .5f) - processingEntity.getX()) / 2f; - double zMotion = ((pos.getZ() + .5f) - processingEntity.getZ()) / 2f; - if (processingEntity.isSneaking()) + double xMotion = ((worldPosition.getX() + .5f) - processingEntity.getX()) / 2f; + double zMotion = ((worldPosition.getZ() + .5f) - processingEntity.getZ()) / 2f; + if (processingEntity.isShiftKeyDown()) xMotion = zMotion = 0; double movement = Math.max(-speed / 4f, -.5f) * -offset; - processingEntity.setMotion(new Vector3d(facing.getAxis() == Axis.X ? movement : xMotion - , facing.getAxis() == Axis.Y ? movement : 0f //Do not move entities upwards or downwards for horizontal crushers, - , facing.getAxis() == Axis.Z ? movement : zMotion)); //Or they'll only get their feet crushed. + processingEntity.setDeltaMovement( + new Vector3d(facing.getAxis() == Axis.X ? movement : xMotion, facing.getAxis() == Axis.Y ? movement : 0f // Do + // not + // move + // entities + // upwards + // or + // downwards + // for + // horizontal + // crushers, + , facing.getAxis() == Axis.Z ? movement : zMotion)); // Or they'll only get their feet crushed. - if (world.isRemote) + if (level.isClientSide) return; if (!(processingEntity instanceof ItemEntity)) { - Vector3d entityOutPos = outPos.add(facing.getAxis() == Axis.X ? .5f * offset : 0f - , facing.getAxis() == Axis.Y ? .5f * offset : 0f - , facing.getAxis() == Axis.Z ? .5f * offset : 0f); + Vector3d entityOutPos = outPos.add(facing.getAxis() == Axis.X ? .5f * offset : 0f, + facing.getAxis() == Axis.Y ? .5f * offset : 0f, facing.getAxis() == Axis.Z ? .5f * offset : 0f); int crusherDamage = AllConfigs.SERVER.kinetics.crushingDamage.get(); if (processingEntity instanceof LivingEntity) { - if ((((LivingEntity) processingEntity).getHealth() - crusherDamage <= 0) //Takes LivingEntity instances as exception, so it can move them before it would kill them. - && (((LivingEntity) processingEntity).hurtTime <= 0)) { //This way it can actually output the items to the right spot. - processingEntity.setPosition(entityOutPos.x - , entityOutPos.y - , entityOutPos.z); + if ((((LivingEntity) processingEntity).getHealth() - crusherDamage <= 0) // Takes LivingEntity instances + // as exception, so it can + // move them before it would + // kill them. + && (((LivingEntity) processingEntity).hurtTime <= 0)) { // This way it can actually output the items + // to the right spot. + processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z); } } - processingEntity.attackEntityFrom(CrushingWheelTileEntity.damageSource, - crusherDamage); + processingEntity.hurt(CrushingWheelTileEntity.damageSource, crusherDamage); if (!processingEntity.isAlive()) { - processingEntity.setPosition(entityOutPos.x - , entityOutPos.y - , entityOutPos.z); + processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z); } return; } ItemEntity itemEntity = (ItemEntity) processingEntity; - itemEntity.setPickupDelay(20); + itemEntity.setPickUpDelay(20); if (facing.getAxis() == Axis.Y) { - if (processingEntity.getY() * -offset < (centerPos.y - .25f) * -offset) { + if (processingEntity.getY() * -offset < (centerPos.y - .25f) * -offset) { intakeItem(itemEntity); } } else if (facing.getAxis() == Axis.Z) { - if (processingEntity.getZ() * -offset < (centerPos.z - .25f) * -offset) { + if (processingEntity.getZ() * -offset < (centerPos.z - .25f) * -offset) { intakeItem(itemEntity); } } else { - if (processingEntity.getX() * -offset < (centerPos.x - .25f) * -offset) { + if (processingEntity.getX() * -offset < (centerPos.x - .25f) * -offset) { intakeItem(itemEntity); } } } + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + float pitch = MathHelper.clamp((crushingspeed / 256f) + .45f, .85f, 1f); + if (entityUUID == null && inventory.getStackInSlot(0) + .isEmpty()) + return; + SoundScapes.play(AmbienceGroup.CRUSHING, worldPosition, pitch); + } + private void intakeItem(ItemEntity itemEntity) { inventory.clear(); inventory.setStackInSlot(0, itemEntity.getItem() - .copy()); + .copy()); itemInserted(inventory.getStackInSlot(0)); itemEntity.remove(); - world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16); + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); } protected void spawnParticles(ItemStack stack) { @@ -257,14 +282,14 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { IParticleData particleData = null; if (stack.getItem() instanceof BlockItem) particleData = new BlockParticleData(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() - .getDefaultState()); + .defaultBlockState()); else particleData = new ItemParticleData(ParticleTypes.ITEM, stack); - Random r = world.rand; + Random r = level.random; for (int i = 0; i < 4; i++) - world.addParticle(particleData, pos.getX() + r.nextFloat(), pos.getY() + r.nextFloat(), - pos.getZ() + r.nextFloat(), 0, 0, 0); + level.addParticle(particleData, worldPosition.getX() + r.nextFloat(), worldPosition.getY() + r.nextFloat(), + worldPosition.getZ() + r.nextFloat(), 0, 0, 0); } private void applyRecipe() { @@ -273,11 +298,11 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { List list = new ArrayList<>(); if (recipe.isPresent()) { int rolls = inventory.getStackInSlot(0) - .getCount(); + .getCount(); inventory.clear(); for (int roll = 0; roll < rolls; roll++) { List rolledResults = recipe.get() - .rollResults(); + .rollResults(); for (int i = 0; i < rolledResults.size(); i++) { ItemStack stack = rolledResults.get(i); ItemHelper.addToList(stack, list); @@ -292,16 +317,16 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { } public Optional> findRecipe() { - Optional> crushingRecipe = AllRecipeTypes.CRUSHING.find(wrapper, world); + Optional> crushingRecipe = AllRecipeTypes.CRUSHING.find(wrapper, level); if (!crushingRecipe.isPresent()) - crushingRecipe = AllRecipeTypes.MILLING.find(wrapper, world); + crushingRecipe = AllRecipeTypes.MILLING.find(wrapper, level); return crushingRecipe; } @Override public void write(CompoundNBT compound, boolean clientPacket) { if (hasEntity()) - compound.put("Entity", NBTUtil.fromUuid(entityUUID)); + compound.put("Entity", NBTUtil.createUUID(entityUUID)); compound.put("Inventory", inventory.serializeNBT()); compound.putFloat("Speed", crushingspeed); super.write(compound, clientPacket); @@ -311,7 +336,7 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { super.fromTag(state, compound, clientPacket); if (compound.contains("Entity") && !isOccupied()) { - entityUUID = NBTUtil.readUniqueId(NBTHelper.getINBT(compound, "Entity")); + entityUUID = NBTUtil.loadUUID(NBTHelper.getINBT(compound, "Entity")); this.searchForEntity = true; } crushingspeed = compound.getFloat("Speed"); @@ -320,13 +345,13 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { public void startCrushing(Entity entity) { processingEntity = entity; - entityUUID = entity.getUniqueID(); + entityUUID = entity.getUUID(); } private void itemInserted(ItemStack stack) { Optional> recipe = findRecipe(); inventory.remainingTime = recipe.isPresent() ? recipe.get() - .getProcessingDuration() : 100; + .getProcessingDuration() : 100; inventory.appliedRecipe = false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java index ea210238d..fa0fa32af 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java @@ -17,8 +17,8 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber public class CrushingWheelTileEntity extends KineticTileEntity { - public static DamageSource damageSource = new DamageSource("create.crush").setDamageBypassesArmor() - .setDifficultyScaled(); + public static DamageSource damageSource = new DamageSource("create.crush").bypassArmor() + .setScalesWithDifficulty(); public CrushingWheelTileEntity(TileEntityType type) { super(type); @@ -33,13 +33,13 @@ public class CrushingWheelTileEntity extends KineticTileEntity { public void fixControllers() { for (Direction d : Iterate.directions) - ((CrushingWheelBlock) getBlockState().getBlock()).updateControllers(getBlockState(), getWorld(), getPos(), + ((CrushingWheelBlock) getBlockState().getBlock()).updateControllers(getBlockState(), getLevel(), getBlockPos(), d); } @Override public AxisAlignedBB makeRenderBoundingBox() { - return new AxisAlignedBB(pos).grow(1); + return new AxisAlignedBB(worldPosition).inflate(1); } @Override @@ -61,7 +61,7 @@ public class CrushingWheelTileEntity extends KineticTileEntity { return; Vector3d outSpeed = Vector3d.ZERO; for (ItemEntity outputItem : event.getDrops()) { - outputItem.setMotion(outSpeed); + outputItem.setDeltaMovement(outSpeed); } } 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..697089b22 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; @@ -38,13 +38,18 @@ public class BeltDeployerCallbacks { if (deployerTileEntity.mode == Mode.PUNCH) return ProcessingResult.PASS; BlockState blockState = deployerTileEntity.getBlockState(); - if (!blockState.contains(FACING) || blockState.get(FACING) != Direction.DOWN) + if (!blockState.hasProperty(FACING) || blockState.getValue(FACING) != Direction.DOWN) return ProcessingResult.PASS; if (deployerTileEntity.state != State.WAITING) return ProcessingResult.HOLD; if (deployerTileEntity.redstoneLocked) return ProcessingResult.PASS; + DeployerFakePlayer player = deployerTileEntity.getPlayer(); + ItemStack held = player == null ? ItemStack.EMPTY : player.getMainHandItem(); + + if (held.isEmpty()) + return ProcessingResult.HOLD; if (deployerTileEntity.getRecipe(s.stack) == null) return ProcessingResult.PASS; @@ -58,8 +63,14 @@ public class BeltDeployerCallbacks { if (deployerTileEntity.getSpeed() == 0) return ProcessingResult.PASS; BlockState blockState = deployerTileEntity.getBlockState(); - if (!blockState.contains(FACING) || blockState.get(FACING) != Direction.DOWN) + if (!blockState.hasProperty(FACING) || blockState.getValue(FACING) != Direction.DOWN) return ProcessingResult.PASS; + + DeployerFakePlayer player = deployerTileEntity.getPlayer(); + ItemStack held = player == null ? ItemStack.EMPTY : player.getMainHandItem(); + if (held.isEmpty()) + return ProcessingResult.HOLD; + IRecipe recipe = deployerTileEntity.getRecipe(s.stack); if (recipe == null) return ProcessingResult.PASS; @@ -68,10 +79,10 @@ public class BeltDeployerCallbacks { activate(s, i, deployerTileEntity, recipe); return ProcessingResult.HOLD; } - + if (deployerTileEntity.state == State.WAITING) { if (deployerTileEntity.redstoneLocked) - return ProcessingResult.PASS; + return ProcessingResult.PASS; deployerTileEntity.start(); } @@ -89,9 +100,13 @@ 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; }) + .map(t -> { + t.locked = false; + return t; + }) .collect(Collectors.toList()); TransportedItemStack left = transported.copy(); @@ -103,17 +118,24 @@ public class BeltDeployerCallbacks { else handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left)); - ItemStack heldItem = deployerTileEntity.player.getHeldItemMainhand(); - if (heldItem.isDamageable()) - heldItem.damageItem(1, deployerTileEntity.player, s -> s.sendBreakAnimation(Hand.MAIN_HAND)); - else - heldItem.shrink(1); + ItemStack heldItem = deployerTileEntity.player.getMainHandItem(); + boolean unbreakable = heldItem.hasTag() && heldItem.getTag() + .getBoolean("Unbreakable"); + boolean keepHeld = + recipe instanceof DeployerApplicationRecipe && ((DeployerApplicationRecipe) recipe).shouldKeepHeldItem(); - BlockPos pos = deployerTileEntity.getPos(); - World world = deployerTileEntity.getWorld(); + if (!unbreakable && !keepHeld) { + if (heldItem.isDamageableItem()) + heldItem.hurtAndBreak(1, deployerTileEntity.player, s -> s.broadcastBreakEvent(Hand.MAIN_HAND)); + else + heldItem.shrink(1); + } + + BlockPos pos = deployerTileEntity.getBlockPos(); + World world = deployerTileEntity.getLevel(); if (heldItem.isEmpty()) - world.playSound(null, pos, SoundEvents.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, .25f, 1); - world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .25f, .75f); + world.playSound(null, pos, SoundEvents.ITEM_BREAK, SoundCategory.BLOCKS, .25f, 1); + world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundCategory.BLOCKS, .25f, .75f); if (recipe instanceof SandPaperPolishingRecipe) AllSoundEvents.AUTO_POLISH.playOnServer(world, pos, .25f, 1f); 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..21768e690 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,25 @@ 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.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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,19 +42,20 @@ 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.defaultSolid() + .material(Materials.TRANSFORMED); BlockState state = context.state; DeployerTileEntity.Mode mode = NBTHelper.readEnum(context.tileData, "Mode", DeployerTileEntity.Mode.class); PartialModel handPose = DeployerRenderer.getHandPose(mode); stationaryTimer = context.data.contains("StationaryTimer"); - facing = state.get(FACING); + facing = state.getValue(FACING); - boolean rotatePole = state.get(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; + boolean rotatePole = state.getValue(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; yRot = AngleHelper.horizontalAngle(facing); zRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; zRotPole = rotatePole ? 90 : 0; @@ -63,9 +64,10 @@ 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.defaultSolid() + .material(AllMaterialSpecs.ROTATING) + .getModel(KineticTileInstance.shaft(axis)) + .createInstance(); int blockLight = localBlockLight(); @@ -90,10 +92,10 @@ public class DeployerActorInstance extends ActorInstance { factor = .5f - MathHelper.clamp(MathHelper.lerp(AnimationTickHolder.getPartialTicks(), distance, nextDistance), 0, 1); } - Vector3d offset = Vector3d.of(facing.getDirectionVec()).scale(factor); + Vector3d offset = Vector3d.atLowerCornerOf(facing.getNormal()).scale(factor); MatrixStack ms = new MatrixStack(); - MatrixStacker msr = MatrixStacker.of(ms); + MatrixTransformStack msr = MatrixTransformStack.of(ms); msr.translate(context.localPos) .translate(offset); @@ -101,7 +103,7 @@ public class DeployerActorInstance extends ActorInstance { transformModel(msr, pole, hand, yRot, zRot, zRotPole); } - static void transformModel(MatrixStacker msr, ModelData pole, ModelData hand, float yRot, float zRot, float zRotPole) { + static void transformModel(MatrixTransformStack msr, ModelData pole, ModelData hand, float yRot, float zRot, float zRotPole) { msr.centre(); msr.rotate(Direction.SOUTH, (float) ((zRot) / 180 * Math.PI)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerApplicationRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerApplicationRecipe.java index 1e4b1e449..aabfa2846 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerApplicationRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerApplicationRecipe.java @@ -1,32 +1,51 @@ package com.simibubi.create.content.contraptions.components.deployer; import java.util.List; +import java.util.Set; +import java.util.function.Supplier; import java.util.stream.Collectors; -import com.simibubi.create.AllItems; +import com.google.gson.JsonObject; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.Create; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; +import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.foundation.utility.Lang; +import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.Ingredient; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.JSONUtils; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +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.items.wrapper.RecipeWrapper; -public class DeployerApplicationRecipe extends ProcessingRecipe { +public class DeployerApplicationRecipe extends ProcessingRecipe implements IAssemblyRecipe { + + private boolean keepHeldItem; public DeployerApplicationRecipe(ProcessingRecipeParams params) { super(AllRecipeTypes.DEPLOYING, params); + keepHeldItem = false; } @Override public boolean matches(RecipeWrapper inv, World p_77569_2_) { return ingredients.get(0) - .test(inv.getStackInSlot(0)) + .test(inv.getItem(0)) && ingredients.get(1) - .test(inv.getStackInSlot(1)); + .test(inv.getItem(1)); } @Override @@ -39,28 +58,84 @@ public class DeployerApplicationRecipe extends ProcessingRecipe { return 2; } + public boolean shouldKeepHeldItem() { + return keepHeldItem; + } + public Ingredient getRequiredHeldItem() { if (ingredients.isEmpty()) throw new IllegalStateException("Deploying Recipe: " + id.toString() + " has no tool!"); - return ingredients.get(0); + return ingredients.get(1); } public Ingredient getProcessedItem() { if (ingredients.size() < 2) throw new IllegalStateException("Deploying Recipe: " + id.toString() + " has no ingredient!"); - return ingredients.get(1); + return ingredients.get(0); } public static List convert(List> sandpaperRecipes) { return sandpaperRecipes.stream() - .map(r -> new ProcessingRecipeBuilder<>(DeployerApplicationRecipe::new, Create.asResource(r.getId() - .getPath() + "_using_deployer")) - .require(Ingredient.fromItems(AllItems.SAND_PAPER.get(), AllItems.RED_SAND_PAPER.get())) - .require(r.getIngredients() + .map(r -> new ProcessingRecipeBuilder<>(DeployerApplicationRecipe::new, new ResourceLocation(r.getId() + .getNamespace(), + r.getId() + .getPath() + "_using_deployer")).require(r.getIngredients() .get(0)) - .output(r.getRecipeOutput()) - .build()) + .require(AllItemTags.SANDPAPER.tag) + .output(r.getResultItem()) + .build()) .collect(Collectors.toList()); } + @Override + public void addAssemblyIngredients(List list) { + list.add(ingredients.get(1)); + } + + @Override + public void readAdditional(JsonObject json) { + super.readAdditional(json); + keepHeldItem = JSONUtils.getAsBoolean(json, "keepHeldItem", false); + } + + @Override + public void writeAdditional(JsonObject json) { + super.writeAdditional(json); + if (keepHeldItem) + json.addProperty("keepHeldItem", keepHeldItem); + } + + @Override + public void readAdditional(PacketBuffer buffer) { + super.readAdditional(buffer); + keepHeldItem = buffer.readBoolean(); + } + + @Override + public void writeAdditional(PacketBuffer buffer) { + super.writeAdditional(buffer); + buffer.writeBoolean(keepHeldItem); + } + + @Override + @OnlyIn(Dist.CLIENT) + public ITextComponent getDescriptionForAssembly() { + ItemStack[] matchingStacks = ingredients.get(1) + .getItems(); + if (matchingStacks.length == 0) + return new StringTextComponent("Invalid"); + return Lang.translate("recipe.assembly.deploying_item", + new TranslationTextComponent(matchingStacks[0].getDescriptionId()).getString()); + } + + @Override + public void addRequiredMachines(Set list) { + list.add(AllBlocks.DEPLOYER.get()); + } + + @Override + public Supplier> getJEISubCategory() { + return () -> SequencedAssemblySubCategory.AssemblyDeploying::new; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java index 43d4d656b..d6bc343a6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java @@ -6,6 +6,7 @@ import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.contraptions.components.AssemblyOperatorUseContext; import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; @@ -15,11 +16,13 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.material.PushReaction; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; import net.minecraft.pathfinding.PathType; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; @@ -42,63 +45,63 @@ public class DeployerBlock extends DirectionalAxisKineticBlock implements ITE { if (te.player != null && !isMoving) { - te.player.inventory.dropAllItems(); - te.overflowItems.forEach(itemstack -> te.player.dropItem(itemstack, true, false)); + te.player.inventory.dropAll(); + te.overflowItems.forEach(itemstack -> te.player.drop(itemstack, true, false)); te.player.remove(); te.player = null; } }); TileEntityBehaviour.destroy(worldIn, pos, FilteringBehaviour.TYPE); - worldIn.removeTileEntity(pos); + worldIn.removeBlockEntity(pos); } } @Override - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - ItemStack heldByPlayer = player.getHeldItem(handIn) + ItemStack heldByPlayer = player.getItemInHand(handIn) .copy(); if (AllItems.WRENCH.isIn(heldByPlayer)) return ActionResultType.PASS; - if (hit.getFace() != state.get(FACING)) + if (hit.getDirection() != state.getValue(FACING)) return ActionResultType.PASS; - if (worldIn.isRemote) + if (worldIn.isClientSide) return ActionResultType.SUCCESS; withTileEntityDo(worldIn, pos, te -> { - ItemStack heldByDeployer = te.player.getHeldItemMainhand() + ItemStack heldByDeployer = te.player.getMainHandItem() .copy(); if (heldByDeployer.isEmpty() && heldByPlayer.isEmpty()) return; - player.setHeldItem(handIn, heldByDeployer); - te.player.setHeldItem(Hand.MAIN_HAND, heldByPlayer); + player.setItemInHand(handIn, heldByDeployer); + te.player.setItemInHand(Hand.MAIN_HAND, heldByPlayer); te.sendData(); }); @@ -109,22 +112,27 @@ public class DeployerBlock extends DirectionalAxisKineticBlock implements ITE getTileEntityClass() { return DeployerTileEntity.class; } - + @Override - public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { - super.onBlockAdded(state, world, pos, oldState, isMoving); + public void onPlace(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, world, pos, oldState, isMoving); withTileEntityDo(world, pos, DeployerTileEntity::redstoneUpdate); } - + @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, boolean p_220069_6_) { withTileEntityDo(world, pos, DeployerTileEntity::redstoneUpdate); } - + @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } + @Override + protected Direction getFacingForPlacement(BlockItemUseContext context) { + if (context instanceof AssemblyOperatorUseContext) return Direction.DOWN; + else return super.getFacingForPlacement(context); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java index 76163d2ee..a2bc9d666 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java @@ -57,7 +57,7 @@ public class DeployerFakePlayer extends FakePlayer { } @Override - public OptionalInt openContainer(INamedContainerProvider container) { + public OptionalInt openMenu(INamedContainerProvider container) { return OptionalInt.empty(); } @@ -73,12 +73,12 @@ public class DeployerFakePlayer extends FakePlayer { } @Override - public Vector3d getPositionVec() { + public Vector3d position() { return new Vector3d(getX(), getY(), getZ()); } @Override - public float getCooldownPeriod() { + public float getCurrentItemAttackStrengthDelay() { return 1 / 64f; } @@ -88,7 +88,7 @@ public class DeployerFakePlayer extends FakePlayer { } @Override - public ItemStack onFoodEaten(World world, ItemStack stack) { + public ItemStack eat(World world, ItemStack stack) { stack.shrink(1); return stack; } @@ -104,11 +104,11 @@ public class DeployerFakePlayer extends FakePlayer { if (!(event.getSource() instanceof EntityDamageSource)) return; EntityDamageSource source = (EntityDamageSource) event.getSource(); - Entity trueSource = source.getTrueSource(); + Entity trueSource = source.getEntity(); if (trueSource != null && trueSource instanceof DeployerFakePlayer) { DeployerFakePlayer fakePlayer = (DeployerFakePlayer) trueSource; event.getDrops() - .forEach(stack -> fakePlayer.inventory.placeItemBackInInventory(trueSource.world, stack.getItem())); + .forEach(stack -> fakePlayer.inventory.placeItemBackInInventory(trueSource.level, stack.getItem())); event.setCanceled(true); } } @@ -118,8 +118,8 @@ public class DeployerFakePlayer extends FakePlayer { @Override public void remove(boolean keepData) { - if (blockBreakingProgress != null && !world.isRemote) - world.sendBlockBreakProgress(getEntityId(), blockBreakingProgress.getKey(), -1); + if (blockBreakingProgress != null && !level.isClientSide) + level.destroyBlockProgress(getId(), blockBreakingProgress.getKey(), -1); super.remove(keepData); } @@ -142,11 +142,11 @@ public class DeployerFakePlayer extends FakePlayer { switch (setting) { case ALL: - mob.setAttackTarget(null); + mob.setTarget(null); break; case CREEPERS: if (mob instanceof CreeperEntity) - mob.setAttackTarget(null); + mob.setTarget(null); break; case NONE: default: @@ -159,10 +159,10 @@ public class DeployerFakePlayer extends FakePlayer { } @Override - public void sendPacket(IPacket packetIn) {} + public void send(IPacket packetIn) {} @Override - public void sendPacket(IPacket packetIn, + public void send(IPacket packetIn, GenericFutureListener> futureListeners) {} } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java index b5c071b12..b65aaff17 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.contraptions.components.deployer; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -15,7 +15,7 @@ public class DeployerFilterSlot extends ValueBoxTransform { @Override protected Vector3d getLocalOffset(BlockState state) { - Direction facing = state.get(DeployerBlock.FACING); + Direction facing = state.getValue(DeployerBlock.FACING); Vector3d vec = VecHelper.voxelSpace(8f, 13.5f, 11.5f); float yRot = AngleHelper.horizontalAngle(facing); @@ -28,10 +28,10 @@ public class DeployerFilterSlot extends ValueBoxTransform { @Override protected void rotate(BlockState state, MatrixStack ms) { - Direction facing = state.get(DeployerBlock.FACING); + Direction facing = state.getValue(DeployerBlock.FACING); float xRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0; float yRot = AngleHelper.horizontalAngle(facing) + 180; - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .rotateY(yRot) .rotateX(xRot); } 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..60809d55c 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,6 +5,7 @@ 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; @@ -13,6 +14,8 @@ import org.apache.commons.lang3.tuple.Pair; import com.google.common.collect.Multimap; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlockItem; import com.simibubi.create.content.curiosities.tools.SandPaperItem; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; @@ -24,12 +27,14 @@ import net.minecraft.block.BeehiveBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.block.DoublePlantBlock; import net.minecraft.block.material.Material; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.attributes.Attribute; import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.item.ItemEntity; +import net.minecraft.entity.merchant.villager.AbstractVillagerEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.fluid.Fluid; @@ -44,6 +49,7 @@ import net.minecraft.item.ItemUseContext; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.server.management.PlayerInteractionManager; +import net.minecraft.state.properties.DoubleBlockHalf; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResultType; @@ -74,26 +80,26 @@ public class DeployerHandler { boolean rayMode = false; private ItemUseWorld(World world, Direction face, BlockPos pos) { - super(world, world.getChunkProvider()); + super(world, world.getChunkSource()); this.face = face; this.pos = pos; } @Override - public BlockRayTraceResult rayTraceBlocks(RayTraceContext context) { + public BlockRayTraceResult clip(RayTraceContext context) { rayMode = true; - BlockRayTraceResult rayTraceBlocks = super.rayTraceBlocks(context); + BlockRayTraceResult rayTraceBlocks = super.clip(context); rayMode = false; return rayTraceBlocks; } @Override public BlockState getBlockState(BlockPos position) { - if (rayMode && (pos.offset(face.getOpposite(), 3) + if (rayMode && (pos.relative(face.getOpposite(), 3) .equals(position) - || pos.offset(face.getOpposite(), 1) + || pos.relative(face.getOpposite(), 1) .equals(position))) - return Blocks.BEDROCK.getDefaultState(); + return Blocks.BEDROCK.defaultBlockState(); return world.getBlockState(position); } } @@ -108,7 +114,7 @@ public class DeployerHandler { BucketItem bucketItem = (BucketItem) held.getItem(); Fluid fluid = bucketItem.getFluid(); if (fluid != Fluids.EMPTY && world.getFluidState(targetPos) - .getFluid() == fluid) + .getType() == fluid) return false; } @@ -121,13 +127,13 @@ public class DeployerHandler { static void activate(DeployerFakePlayer player, Vector3d vec, BlockPos clickedPos, Vector3d extensionVector, Mode mode) { - Multimap attributeModifiers = player.getHeldItemMainhand() + Multimap attributeModifiers = player.getMainHandItem() .getAttributeModifiers(EquipmentSlotType.MAINHAND); player.getAttributes() - .addTemporaryModifiers(attributeModifiers); + .addTransientAttributeModifiers(attributeModifiers); activateInner(player, vec, clickedPos, extensionVector, mode); player.getAttributes() - .addTemporaryModifiers(attributeModifiers); + .addTransientAttributeModifiers(attributeModifiers); } private static void activateInner(DeployerFakePlayer player, Vector3d vec, BlockPos clickedPos, @@ -135,17 +141,19 @@ public class DeployerHandler { Vector3d rayOrigin = vec.add(extensionVector.scale(3 / 2f + 1 / 64f)); Vector3d rayTarget = vec.add(extensionVector.scale(5 / 2f - 1 / 64f)); - player.setPosition(rayOrigin.x, rayOrigin.y, rayOrigin.z); + player.setPos(rayOrigin.x, rayOrigin.y, rayOrigin.z); BlockPos pos = new BlockPos(vec); - ItemStack stack = player.getHeldItemMainhand(); + ItemStack stack = player.getMainHandItem(); Item item = stack.getItem(); // Check for entities - final ServerWorld world = player.getServerWorld(); - List entities = world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(clickedPos)); + final ServerWorld world = player.getLevel(); + List entities = world.getEntitiesOfClass(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())); + Entity entity = entities.get(world.random.nextInt(entities.size())); List capturedDrops = new ArrayList<>(); boolean success = false; entity.captureDrops(capturedDrops); @@ -158,18 +166,24 @@ public class DeployerHandler { return; } if (cancelResult == null) { - if (entity.processInitialInteract(player, hand) - .isAccepted()) + if (entity.interact(player, hand) + .consumesAction()){ + if (entity instanceof AbstractVillagerEntity) { + AbstractVillagerEntity villager = ((AbstractVillagerEntity) entity); + if (villager.getTradingPlayer() instanceof DeployerFakePlayer) + villager.setTradingPlayer(null); + } success = true; - else if (entity instanceof LivingEntity && stack.useOnEntity(player, (LivingEntity) entity, hand) - .isAccepted()) + } + else if (entity instanceof LivingEntity && stack.interactLivingEntity(player, (LivingEntity) entity, hand) + .consumesAction()) success = true; } - if (!success && stack.isFood() && entity instanceof PlayerEntity) { + if (!success && stack.isEdible() && entity instanceof PlayerEntity) { PlayerEntity playerEntity = (PlayerEntity) entity; - if (playerEntity.canEat(item.getFood() - .canEatWhenFull())) { - playerEntity.onFoodEaten(world, stack); + if (playerEntity.canEat(item.getFoodProperties() + .canAlwaysEat())) { + playerEntity.eat(world, stack); player.spawnedItemEffects = stack.copy(); success = true; } @@ -178,8 +192,8 @@ public class DeployerHandler { // Punch entity if (mode == Mode.PUNCH) { - player.resetCooldown(); - player.attackTargetEntityWithCurrentItem(entity); + player.resetAttackStrengthTicker(); + player.attack(entity); success = true; } @@ -192,18 +206,18 @@ public class DeployerHandler { // Shoot ray RayTraceContext rayTraceContext = new RayTraceContext(rayOrigin, rayTarget, BlockMode.OUTLINE, FluidMode.NONE, player); - BlockRayTraceResult result = world.rayTraceBlocks(rayTraceContext); - if (result.getPos() != clickedPos) - result = new BlockRayTraceResult(result.getHitVec(), result.getFace(), clickedPos, result.isInside()); + BlockRayTraceResult result = world.clip(rayTraceContext); + if (result.getBlockPos() != clickedPos) + result = new BlockRayTraceResult(result.getLocation(), result.getDirection(), clickedPos, result.isInside()); BlockState clickedState = world.getBlockState(clickedPos); - Direction face = result.getFace(); + Direction face = result.getDirection(); if (face == null) - face = Direction.getFacingFromVector(extensionVector.x, extensionVector.y, extensionVector.z) + face = Direction.getNearest(extensionVector.x, extensionVector.y, extensionVector.z) .getOpposite(); // Left click if (mode == Mode.PUNCH) { - if (!world.isBlockModifiable(player, clickedPos)) + if (!world.mayInteract(player, clickedPos)) return; if (clickedState.getShape(world, clickedPos) .isEmpty()) { @@ -216,11 +230,11 @@ public class DeployerHandler { if (BlockHelper.extinguishFire(world, player, clickedPos, face)) // FIXME: is there an equivalent in world, as there was in 1.15? return; if (event.getUseBlock() != DENY) - clickedState.onBlockClicked(world, clickedPos, player); + clickedState.attack(world, clickedPos, player); if (stack.isEmpty()) return; - float progress = clickedState.getPlayerRelativeBlockHardness(player, world, clickedPos) * 16; + float progress = clickedState.getDestroyProgress(player, world, clickedPos) * 16; float before = 0; Pair blockBreakingProgress = player.blockBreakingProgress; if (blockBreakingProgress != null) @@ -230,8 +244,8 @@ public class DeployerHandler { .getHitSound(), SoundCategory.NEUTRAL, .25f, 1); if (progress >= 1) { - tryHarvestBlock(player.interactionManager, clickedPos); - world.sendBlockBreakProgress(player.getEntityId(), clickedPos, -1); + tryHarvestBlock(player.gameMode, clickedPos); + world.destroyBlockProgress(player.getId(), clickedPos, -1); player.blockBreakingProgress = null; return; } @@ -241,7 +255,7 @@ public class DeployerHandler { } if ((int) (before * 10) != (int) (progress * 10)) - world.sendBlockBreakProgress(player.getEntityId(), clickedPos, (int) (progress * 10)); + world.destroyBlockProgress(player.getId(), clickedPos, (int) (progress * 10)); player.blockBreakingProgress = Pair.of(clickedPos, progress); return; } @@ -264,37 +278,39 @@ public class DeployerHandler { return; } - boolean holdingSomething = !player.getHeldItemMainhand() + boolean holdingSomething = !player.getMainHandItem() .isEmpty(); boolean flag1 = - !(player.isSneaking() && holdingSomething) || (stack.doesSneakBypassUse(world, clickedPos, player)); + !(player.isShiftKeyDown() && holdingSomething) || (stack.doesSneakBypassUse(world, clickedPos, player)); // Use on block if (useBlock != DENY && flag1 - && safeOnUse(clickedState, world, clickedPos, player, hand, result) == ActionResultType.SUCCESS) + && safeOnUse(clickedState, world, clickedPos, player, hand, result).consumesAction()) 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.canBeReplaced(new BlockItemUseContext(itemusecontext))) return; // Reposition fire placement for convenience if (item == Items.FLINT_AND_STEEL) { - Direction newFace = result.getFace(); - BlockPos newPos = result.getPos(); - if (!AbstractFireBlock.method_30032(world, clickedPos, newFace)) + Direction newFace = result.getDirection(); + BlockPos newPos = result.getBlockPos(); + if (!AbstractFireBlock.canBePlacedAt(world, clickedPos, newFace)) newFace = Direction.UP; if (clickedState.getMaterial() == Material.AIR) - newPos = newPos.offset(face.getOpposite()); - result = new BlockRayTraceResult(result.getHitVec(), newFace, newPos, result.isInside()); + newPos = newPos.relative(face.getOpposite()); + result = new BlockRayTraceResult(result.getLocation(), newFace, newPos, result.isInside()); itemusecontext = new ItemUseContext(player, hand, result); } // 'Inert' item use behaviour & block placement - ActionResultType onItemUse = stack.onItemUse(itemusecontext); - if (onItemUse == ActionResultType.SUCCESS) + ActionResultType onItemUse = stack.useOn(itemusecontext); + if (onItemUse.consumesAction()) return; if (item == Items.ENDER_PEARL) return; @@ -304,62 +320,76 @@ public class DeployerHandler { if (item instanceof BucketItem || item instanceof SandPaperItem) itemUseWorld = new ItemUseWorld(world, face, pos); - ActionResult onItemRightClick = item.onItemRightClick(itemUseWorld, player, hand); - ItemStack resultStack = onItemRightClick.getResult(); + ActionResult onItemRightClick = item.use(itemUseWorld, player, hand); + ItemStack resultStack = onItemRightClick.getObject(); if (resultStack != stack || resultStack.getCount() != stack.getCount() || resultStack.getUseDuration() > 0 - || resultStack.getDamage() != stack.getDamage()) { - player.setHeldItem(hand, onItemRightClick.getResult()); + || resultStack.getDamageValue() != stack.getDamageValue()) { + player.setItemInHand(hand, onItemRightClick.getObject()); } CompoundNBT tag = stack.getTag(); if (tag != null && stack.getItem() instanceof SandPaperItem && tag.contains("Polishing")) { - player.spawnedItemEffects = ItemStack.read(tag.getCompound("Polishing")); + player.spawnedItemEffects = ItemStack.of(tag.getCompound("Polishing")); AllSoundEvents.AUTO_POLISH.playOnServer(world, pos, .25f, 1f); } - if (!player.getActiveItemStack() + if (!player.getUseItem() .isEmpty()) - player.setHeldItem(hand, stack.onItemUseFinish(world, player)); + player.setItemInHand(hand, stack.finishUsingItem(world, player)); - player.resetActiveHand(); + player.stopUsingItem(); } public static boolean tryHarvestBlock(PlayerInteractionManager interactionManager, BlockPos pos) { // <> PlayerInteractionManager#tryHarvestBlock - ServerWorld world = interactionManager.world; + ServerWorld world = interactionManager.level; ServerPlayerEntity player = interactionManager.player; BlockState blockstate = world.getBlockState(pos); - GameType gameType = interactionManager.getGameType(); + GameType gameType = interactionManager.getGameModeForPlayer(); if (net.minecraftforge.common.ForgeHooks.onBlockBreakEvent(world, gameType, player, pos) == -1) return false; - TileEntity tileentity = world.getTileEntity(pos); - if (player.getHeldItemMainhand() + TileEntity tileentity = world.getBlockEntity(pos); + if (player.getMainHandItem() .onBlockStartBreak(pos, player)) return false; - if (player.isBlockBreakingRestricted(world, pos, gameType)) + if (player.blockActionRestricted(world, pos, gameType)) return false; - ItemStack prevHeldItem = player.getHeldItemMainhand(); + ItemStack prevHeldItem = player.getMainHandItem(); ItemStack heldItem = prevHeldItem.copy(); boolean canHarvest = blockstate.canHarvestBlock(world, pos, player); - prevHeldItem.onBlockDestroyed(world, blockstate, pos, player); + prevHeldItem.mineBlock(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.above(); + BlockState stateUp = world.getBlockState(posUp); + if (blockstate.getBlock() instanceof DoublePlantBlock + && blockstate.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER + && stateUp.getBlock() == blockstate.getBlock() + && stateUp.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER + ) { + // hack to prevent DoublePlantBlock from dropping a duplicate item + world.setBlock(pos, Blocks.AIR.defaultBlockState(), 35); + world.setBlock(posUp, Blocks.AIR.defaultBlockState(), 35); + } else { + if (!blockstate.removedByPlayer(world, pos, player, canHarvest, world.getFluidState(pos))) + return true; + } blockstate.getBlock() - .onPlayerDestroy(world, pos, blockstate); + .destroy(world, pos, blockstate); if (!canHarvest) return true; Block.getDrops(blockstate, world, pos, tileentity, player, prevHeldItem) .forEach(item -> player.inventory.placeItemBackInInventory(world, item)); - blockstate.spawnAdditionalDrops(world, pos, prevHeldItem); + blockstate.spawnAfterBreak(world, pos, prevHeldItem); return true; } @@ -367,7 +397,7 @@ public class DeployerHandler { Hand hand, BlockRayTraceResult ray) { if (state.getBlock() instanceof BeehiveBlock) return safeOnBeehiveUse(state, world, pos, player, hand); - return state.onUse(world, player, hand, ray); + return state.use(world, player, hand, ray); } protected static ActionResultType safeOnBeehiveUse(BlockState state, World world, BlockPos pos, PlayerEntity player, @@ -375,28 +405,28 @@ public class DeployerHandler { // <> BeehiveBlock#onUse BeehiveBlock block = (BeehiveBlock) state.getBlock(); - ItemStack prevHeldItem = player.getHeldItem(hand); - int honeyLevel = state.get(BeehiveBlock.HONEY_LEVEL); + ItemStack prevHeldItem = player.getItemInHand(hand); + int honeyLevel = state.getValue(BeehiveBlock.HONEY_LEVEL); boolean success = false; if (honeyLevel < 5) return ActionResultType.PASS; if (prevHeldItem.getItem() == Items.SHEARS) { - world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_BEEHIVE_SHEAR, + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundCategory.NEUTRAL, 1.0F, 1.0F); // <> BeehiveBlock#dropHoneycomb player.inventory.placeItemBackInInventory(world, new ItemStack(Items.HONEYCOMB, 3)); - prevHeldItem.damageItem(1, player, s -> s.sendBreakAnimation(hand)); + prevHeldItem.hurtAndBreak(1, player, s -> s.broadcastBreakEvent(hand)); success = true; } if (prevHeldItem.getItem() == Items.GLASS_BOTTLE) { prevHeldItem.shrink(1); - world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.ITEM_BOTTLE_FILL, + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundCategory.NEUTRAL, 1.0F, 1.0F); ItemStack honeyBottle = new ItemStack(Items.HONEY_BOTTLE); if (prevHeldItem.isEmpty()) - player.setHeldItem(hand, honeyBottle); + player.setItemInHand(hand, honeyBottle); else player.inventory.placeItemBackInInventory(world, honeyBottle); success = true; @@ -405,7 +435,7 @@ public class DeployerHandler { if (!success) return ActionResultType.PASS; - block.takeHoney(world, state, pos); + block.resetHoneyLevel(world, state, pos); return ActionResultType.SUCCESS; } 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..d2c7b1c2d 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.material.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,13 +36,13 @@ 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; - facing = blockState.get(FACING); + facing = blockState.getValue(FACING); - boolean rotatePole = blockState.get(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; + boolean rotatePole = blockState.getValue(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; yRot = AngleHelper.horizontalAngle(facing); zRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; @@ -68,7 +68,7 @@ public class DeployerInstance extends ShaftInstance implements IDynamicInstance, float newProgress = getProgress(AnimationTickHolder.getPartialTicks()); - if (!newHand && MathHelper.epsilonEquals(newProgress, progress)) return; + if (!newHand && MathHelper.equal(newProgress, progress)) return; progress = newProgress; newHand = false; @@ -118,7 +118,7 @@ public class DeployerInstance extends ShaftInstance implements IDynamicInstance, float handLength = currentHand == AllBlockPartials.DEPLOYER_HAND_POINTING ? 0 : currentHand == AllBlockPartials.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; float distance = Math.min(MathHelper.clamp(progress, 0, 1) * (tile.reach + handLength), 21 / 16f); - Vector3i facingVec = facing.getDirectionVec(); + Vector3i facingVec = facing.getNormal(); BlockPos blockPos = getInstancePosition(); float x = blockPos.getX() + ((float) facingVec.getX()) * distance; @@ -131,12 +131,12 @@ public class DeployerInstance extends ShaftInstance implements IDynamicInstance, static void updateRotation(OrientedData pole, OrientedData hand, float yRot, float zRot, float zRotPole) { - Quaternion q = Direction.SOUTH.getUnitVector().getDegreesQuaternion(zRot); - q.multiply(Direction.UP.getUnitVector().getDegreesQuaternion(yRot)); + Quaternion q = Direction.SOUTH.step().rotationDegrees(zRot); + q.mul(Direction.UP.step().rotationDegrees(yRot)); hand.setRotation(q); - q.multiply(Direction.SOUTH.getUnitVector().getDegreesQuaternion(zRotPole)); + q.mul(Direction.SOUTH.step().rotationDegrees(zRotPole)); pole.setRotation(q); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerItemHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerItemHandler.java index 0e7ba0183..55dfa8d48 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerItemHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerItemHandler.java @@ -32,16 +32,16 @@ public class DeployerItemHandler implements IItemHandlerModifiable { public ItemStack getHeld() { if (player == null) return ItemStack.EMPTY; - return player.getHeldItemMainhand(); + return player.getMainHandItem(); } public void set(ItemStack stack) { if (player == null) return; - if (te.getWorld().isRemote) + if (te.getLevel().isClientSide) return; - player.setHeldItem(Hand.MAIN_HAND, stack); - te.markDirty(); + player.setItemInHand(Hand.MAIN_HAND, stack); + te.setChanged(); te.sendData(); } @@ -119,7 +119,7 @@ public class DeployerItemHandler implements IItemHandlerModifiable { .split(amount); ItemStack toReturn = held.split(amount); - te.markDirty(); + te.setChanged(); te.sendData(); return toReturn; } 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..8db2c3089 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.material.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; @@ -50,20 +51,20 @@ public class DeployerMovementBehaviour extends MovementBehaviour { @Override public Vector3d getActiveAreaOffset(MovementContext context) { - return Vector3d.of(context.state.get(DeployerBlock.FACING) - .getDirectionVec()) + return Vector3d.atLowerCornerOf(context.state.getValue(DeployerBlock.FACING) + .getNormal()) .scale(2); } @Override public void visitNewPosition(MovementContext context, BlockPos pos) { - if (context.world.isRemote) + if (context.world.isClientSide) return; tryGrabbingItem(context); DeployerFakePlayer player = getPlayer(context); Mode mode = getMode(context); - if (mode == Mode.USE && !DeployerHandler.shouldActivate(player.getHeldItemMainhand(), context.world, pos, null)) + if (mode == Mode.USE && !DeployerHandler.shouldActivate(player.getMainHandItem(), context.world, pos, null)) return; activate(context, pos, player, mode); @@ -78,12 +79,12 @@ public class DeployerMovementBehaviour extends MovementBehaviour { if (AllItems.SCHEMATIC.isIn(filter)) activateAsSchematicPrinter(context, pos, player, world, filter); - Vector3d facingVec = Vector3d.of(context.state.get(DeployerBlock.FACING) - .getDirectionVec()); + Vector3d facingVec = Vector3d.atLowerCornerOf(context.state.getValue(DeployerBlock.FACING) + .getNormal()); facingVec = context.rotation.apply(facingVec); Vector3d vec = context.position.subtract(facingVec.scale(2)); - player.rotationYaw = AbstractContraptionEntity.yawFromVector(facingVec); - player.rotationPitch = AbstractContraptionEntity.pitchFromVector(facingVec) - 90; + player.yRot = AbstractContraptionEntity.yawFromVector(facingVec); + player.xRot = AbstractContraptionEntity.pitchFromVector(facingVec) - 90; DeployerHandler.activate(player, vec, pos, facingVec, mode); } @@ -104,43 +105,43 @@ public class DeployerMovementBehaviour extends MovementBehaviour { if (schematicWorld == null) return; if (!schematicWorld.getBounds() - .isVecInside(pos.subtract(schematicWorld.anchor))) + .isInside(pos.subtract(schematicWorld.anchor))) return; BlockState blockState = schematicWorld.getBlockState(pos); - ItemRequirement requirement = ItemRequirement.of(blockState); + ItemRequirement requirement = ItemRequirement.of(blockState, schematicWorld.getBlockEntity(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; if (AllBlockTags.SAFE_NBT.matches(blockState)) { - TileEntity tile = schematicWorld.getTileEntity(pos); + TileEntity tile = schematicWorld.getBlockEntity(pos); if (tile != null) { - data = tile.write(new CompoundNBT()); + data = tile.save(new CompoundNBT()); data = NBTProcessors.process(tile, data, true); } } - BlockSnapshot blocksnapshot = BlockSnapshot.create(world.getRegistryKey(), world, pos); + BlockSnapshot blocksnapshot = BlockSnapshot.create(world.dimension(), world, pos); BlockHelper.placeSchematicBlock(world, blockState, pos, firstRequired, data); if (ForgeEventFactory.onBlockPlace(player, blocksnapshot, Direction.UP)) blocksnapshot.restore(true, false); @@ -148,7 +149,7 @@ public class DeployerMovementBehaviour extends MovementBehaviour { @Override public void tick(MovementContext context) { - if (context.world.isRemote) + if (context.world.isClientSide) return; if (!context.stall) return; @@ -175,14 +176,14 @@ public class DeployerMovementBehaviour extends MovementBehaviour { @Override public void stopMoving(MovementContext context) { - if (context.world.isRemote) + if (context.world.isClientSide) return; DeployerFakePlayer player = getPlayer(context); if (player == null) return; - context.tileData.put("Inventory", player.inventory.write(new ListNBT())); + context.tileData.put("Inventory", player.inventory.save(new ListNBT())); player.remove(); } @@ -190,14 +191,14 @@ public class DeployerMovementBehaviour extends MovementBehaviour { DeployerFakePlayer player = getPlayer(context); if (player == null) return; - if (player.getHeldItemMainhand() + if (player.getMainHandItem() .isEmpty()) { ItemStack filter = getFilter(context); if (AllItems.SCHEMATIC.isIn(filter)) return; ItemStack held = ItemHelper.extract(context.contraption.inventory, stack -> FilterItem.test(context.world, stack, filter), 1, false); - player.setHeldItem(Hand.MAIN_HAND, held); + player.setItemInHand(Hand.MAIN_HAND, held); } } @@ -208,13 +209,13 @@ public class DeployerMovementBehaviour extends MovementBehaviour { PlayerInventory inv = player.inventory; ItemStack filter = getFilter(context); - for (List list : Arrays.asList(inv.armorInventory, inv.offHandInventory, inv.mainInventory)) { + for (List list : Arrays.asList(inv.armor, inv.offhand, inv.items)) { for (int i = 0; i < list.size(); ++i) { ItemStack itemstack = list.get(i); if (itemstack.isEmpty()) continue; - if (list == inv.mainInventory && i == inv.currentItem + if (list == inv.items && i == inv.selected && FilterItem.test(context.world, itemstack, filter)) continue; @@ -229,16 +230,16 @@ public class DeployerMovementBehaviour extends MovementBehaviour { DeployerFakePlayer player = getPlayer(context); if (player == null) return; - context.data.put("HeldItem", player.getHeldItemMainhand() + context.data.put("HeldItem", player.getMainHandItem() .serializeNBT()); } private DeployerFakePlayer getPlayer(MovementContext context) { if (!(context.temporaryData instanceof DeployerFakePlayer) && context.world instanceof ServerWorld) { DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerWorld) context.world); - deployerFakePlayer.inventory.read(context.tileData.getList("Inventory", NBT.TAG_COMPOUND)); + deployerFakePlayer.inventory.load(context.tileData.getList("Inventory", NBT.TAG_COMPOUND)); if (context.data.contains("HeldItem")) - deployerFakePlayer.setHeldItem(Hand.MAIN_HAND, ItemStack.read(context.data.getCompound("HeldItem"))); + deployerFakePlayer.setItemInHand(Hand.MAIN_HAND, ItemStack.of(context.data.getCompound("HeldItem"))); context.tileData.remove("Inventory"); context.temporaryData = deployerFakePlayer; } @@ -246,7 +247,7 @@ public class DeployerMovementBehaviour extends MovementBehaviour { } private ItemStack getFilter(MovementContext context) { - return ItemStack.read(context.tileData.getCompound("Filter")); + return ItemStack.of(context.tileData.getCompound("Filter")); } private Mode getMode(MovementContext context) { @@ -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/DeployerMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java new file mode 100644 index 000000000..c942df926 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.contraptions.components.deployer; + +import org.apache.commons.lang3.tuple.MutablePair; + +import com.simibubi.create.AllItems; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.feature.template.Template.BlockInfo; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.common.util.Constants; + +public class DeployerMovingInteraction extends MovingInteractionBehaviour { + + @Override + public boolean handlePlayerInteraction(PlayerEntity player, Hand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + BlockInfo info = contraptionEntity.getContraption() + .getBlocks() + .get(localPos); + if (info == null) + return false; + MovementContext ctx = null; + int index = -1; + for (MutablePair pair : contraptionEntity.getContraption() + .getActors()) { + if (info.equals(pair.left)) { + ctx = pair.right; + index = contraptionEntity.getContraption() + .getActors() + .indexOf(pair); + break; + } + } + if (ctx == null) + return false; + + ItemStack heldStack = player.getItemInHand(activeHand); + if (heldStack.getItem() + .equals(AllItems.WRENCH.get())) { + DeployerTileEntity.Mode mode = NBTHelper.readEnum(ctx.tileData, "Mode", DeployerTileEntity.Mode.class); + NBTHelper.writeEnum(ctx.tileData, "Mode", + mode == DeployerTileEntity.Mode.PUNCH ? DeployerTileEntity.Mode.USE : DeployerTileEntity.Mode.PUNCH); + + } else { + if (ctx.world.isClientSide) + return true; // we'll try again on the server side + DeployerFakePlayer fake = null; + + if (!(ctx.temporaryData instanceof DeployerFakePlayer) && ctx.world instanceof ServerWorld) { + DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerWorld) ctx.world); + deployerFakePlayer.inventory.load(ctx.tileData.getList("Inventory", Constants.NBT.TAG_COMPOUND)); + ctx.temporaryData = fake = deployerFakePlayer; + ctx.tileData.remove("Inventory"); + } else + fake = (DeployerFakePlayer) ctx.temporaryData; + + if (fake == null) + return false; + + ItemStack deployerItem = fake.getMainHandItem(); + player.setItemInHand(activeHand, deployerItem.copy()); + fake.setItemInHand(Hand.MAIN_HAND, heldStack.copy()); + ctx.tileData.put("HeldItem", heldStack.serializeNBT()); + ctx.data.put("HeldItem", heldStack.serializeNBT()); + } + if (index >= 0) + setContraptionActorData(contraptionEntity, index, info, ctx); + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRecipeSearchEvent.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRecipeSearchEvent.java new file mode 100644 index 000000000..0b204fc4f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRecipeSearchEvent.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.contraptions.components.deployer; + +import java.util.Optional; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.crafting.IRecipe; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class DeployerRecipeSearchEvent extends Event { + private final DeployerTileEntity tileEntity; + private final RecipeWrapper inventory; + @Nullable + IRecipe recipe = null; + private int maxPriority = 0; + + public DeployerRecipeSearchEvent(DeployerTileEntity tileEntity, RecipeWrapper inventory) { + this.tileEntity = tileEntity; + this.inventory = inventory; + } + + @Override + public boolean isCancelable() { + return true; + } + + public DeployerTileEntity getTileEntity() { + return tileEntity; + } + + public RecipeWrapper getInventory() { + return inventory; + } + + // lazyness to not scan for recipes that aren't selected + public boolean shouldAddRecipeWithPriority(int priority) { + return !isCanceled() && priority > maxPriority; + } + + @Nullable + public IRecipe getRecipe() { + if (isCanceled()) + return null; + return recipe; + } + + public void addRecipe(Supplier>> recipeSupplier, int priority) { + if (!shouldAddRecipeWithPriority(priority)) + return; + recipeSupplier.get().ifPresent(newRecipe -> { + this.recipe = newRecipe; + maxPriority = priority; + }); + } +} 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..03c0d1ffc 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,24 +12,23 @@ 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; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.ItemRenderer; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.item.BlockItem; @@ -35,10 +36,8 @@ 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; public class DeployerRenderer extends SafeTileEntityRenderer { @@ -52,7 +51,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.getLevel())) return; renderComponents(te, partialTicks, ms, buffer, light, overlay); } @@ -64,19 +63,19 @@ public class DeployerRenderer extends SafeTileEntityRenderer BlockState deployerState = te.getBlockState(); Vector3d offset = getHandOffset(te, partialTicks, deployerState).add(VecHelper.getCenterOf(BlockPos.ZERO)); - ms.push(); + ms.pushPose(); ms.translate(offset.x, offset.y, offset.z); - Direction facing = deployerState.get(FACING); + Direction facing = deployerState.getValue(FACING); boolean punching = te.mode == Mode.PUNCH; float yRot = AngleHelper.horizontalAngle(facing) + 180; float zRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0; boolean displayMode = facing == Direction.UP && te.getSpeed() == 0 && !punching; - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(yRot)); + ms.mulPose(Vector3f.YP.rotationDegrees(yRot)); if (!displayMode) { - ms.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(zRot)); + ms.mulPose(Vector3f.XP.rotationDegrees(zRot)); ms.translate(0, 0, -11 / 16f); } @@ -88,7 +87,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer TransformType transform = TransformType.NONE; boolean isBlockItem = (te.heldItem.getItem() instanceof BlockItem) - && itemRenderer.getItemModelWithOverrides(te.heldItem, Minecraft.getInstance().world, null) + && itemRenderer.getModel(te.heldItem, Minecraft.getInstance().level, null) .isGui3d(); if (displayMode) { @@ -96,7 +95,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer ms.translate(0, isBlockItem ? 9 / 16f : 11 / 16f, 0); ms.scale(scale, scale, scale); transform = TransformType.GROUND; - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AnimationTickHolder.getRenderTime(te.getWorld()))); + ms.mulPose(Vector3f.YP.rotationDegrees(AnimationTickHolder.getRenderTime(te.getLevel()))); } else { float scale = punching ? .75f : isBlockItem ? .75f - 1 / 64f : .5f; @@ -104,45 +103,45 @@ public class DeployerRenderer extends SafeTileEntityRenderer transform = punching ? TransformType.THIRD_PERSON_RIGHT_HAND : TransformType.FIXED; } - itemRenderer.renderItem(te.heldItem, transform, light, overlay, ms, buffer); - ms.pop(); + itemRenderer.renderStatic(te.heldItem, transform, light, overlay, ms, buffer); + ms.popPose(); } 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())) { + IVertexBuilder vb = buffer.getBuffer(RenderType.solid()); + if (!Backend.getInstance().canUseInstancing(te.getLevel())) { KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), ms, vb, light); } BlockState blockState = te.getBlockState(); - BlockPos pos = te.getPos(); Vector3d offset = getHandOffset(te, partialTicks, blockState); SuperByteBuffer pole = PartialBufferer.get(AllBlockPartials.DEPLOYER_POLE, blockState); SuperByteBuffer hand = PartialBufferer.get(te.getHandPose(), blockState); - transform(te.getWorld(), pole.translate(offset.x, offset.y, offset.z), blockState, pos, true).renderInto(ms, - vb); - transform(te.getWorld(), hand.translate(offset.x, offset.y, offset.z), blockState, pos, false).renderInto(ms, - vb); + transform(pole.translate(offset.x, offset.y, offset.z), blockState, true) + .light(light) + .renderInto(ms, vb); + transform(hand.translate(offset.x, offset.y, offset.z), blockState, false) + .light(light) + .renderInto(ms, vb); } protected Vector3d getHandOffset(DeployerTileEntity te, float partialTicks, BlockState blockState) { float distance = te.getHandOffset(partialTicks); - return Vector3d.of(blockState.get(FACING).getDirectionVec()).scale(distance); + return Vector3d.atLowerCornerOf(blockState.getValue(FACING).getNormal()).scale(distance); } protected BlockState getRenderedBlockState(KineticTileEntity te) { return KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)); } - private static SuperByteBuffer transform(World world, SuperByteBuffer buffer, BlockState deployerState, - BlockPos pos, boolean axisDirectionMatters) { - Direction facing = deployerState.get(FACING); + private static SuperByteBuffer transform(SuperByteBuffer buffer, BlockState deployerState, boolean axisDirectionMatters) { + Direction facing = deployerState.getValue(FACING); float zRotLast = - axisDirectionMatters && (deployerState.get(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Axis.Z) ? 90 + axisDirectionMatters && (deployerState.getValue(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Axis.Z) ? 90 : 0; float yRot = AngleHelper.horizontalAngle(facing); float zRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; @@ -150,24 +149,18 @@ public class DeployerRenderer extends SafeTileEntityRenderer buffer.rotateCentered(Direction.SOUTH, (float) ((zRot) / 180 * Math.PI)); buffer.rotateCentered(Direction.UP, (float) ((yRot) / 180 * Math.PI)); buffer.rotateCentered(Direction.SOUTH, (float) ((zRotLast) / 180 * Math.PI)); - buffer.light(WorldRenderer.getLightmapCoordinates(world, deployerState, pos)); return buffer; } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; - IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid()); + public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + IVertexBuilder builder = buffer.getBuffer(RenderType.solid()); BlockState blockState = context.state; - BlockPos pos = BlockPos.ZERO; Mode mode = NBTHelper.readEnum(context.tileData, "Mode", Mode.class); - World world = context.world; PartialModel handPose = getHandPose(mode); 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")) { @@ -180,17 +173,24 @@ public class DeployerRenderer extends SafeTileEntityRenderer factor = .5f - MathHelper.clamp(MathHelper.lerp(AnimationTickHolder.getPartialTicks(), distance, nextDistance), 0, 1); } - Vector3d offset = Vector3d.of(blockState.get(FACING) - .getDirectionVec()).scale(factor); + Vector3d offset = Vector3d.atLowerCornerOf(blockState.getValue(FACING) + .getNormal()).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.getModel(); + m.pushPose(); + m.translate(offset.x, offset.y, offset.z); + + pole.transform(m); + hand.transform(m); + pole = transform(pole, blockState, true); + hand = transform(hand, blockState, false); + + pole.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), builder); + hand.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), builder); + + m.popPose(); } 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..22e7c28e7 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,15 +7,16 @@ 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; import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; 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; @@ -26,6 +27,7 @@ import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.block.BlockState; import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import net.minecraft.nbt.CompoundNBT; @@ -44,6 +46,7 @@ import net.minecraft.util.math.RayTraceContext.FluidMode; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.common.util.LazyOptional; @@ -102,24 +105,24 @@ public class DeployerTileEntity extends KineticTileEntity { @Override public void initialize() { super.initialize(); - if (!world.isRemote) { - player = new DeployerFakePlayer((ServerWorld) world); + if (!level.isClientSide) { + player = new DeployerFakePlayer((ServerWorld) level); if (deferredInventoryList != null) { - player.inventory.read(deferredInventoryList); + player.inventory.load(deferredInventoryList); deferredInventoryList = null; - heldItem = player.getHeldItemMainhand(); + heldItem = player.getMainHandItem(); sendData(); } - Vector3d initialPos = VecHelper.getCenterOf(pos.offset(getBlockState().get(FACING))); - player.setPosition(initialPos.x, initialPos.y, initialPos.z); + Vector3d initialPos = VecHelper.getCenterOf(worldPosition.relative(getBlockState().getValue(FACING))); + player.setPos(initialPos.x, initialPos.y, initialPos.z); } invHandler = LazyOptional.of(this::createHandler); } protected void onExtract(ItemStack stack) { - player.setHeldItem(Hand.MAIN_HAND, stack.copy()); + player.setItemInHand(Hand.MAIN_HAND, stack.copy()); sendData(); - markDirty(); + setChanged(); } protected int getTimerSpeed() { @@ -132,9 +135,9 @@ public class DeployerTileEntity extends KineticTileEntity { if (getSpeed() == 0) return; - if (!world.isRemote && player != null && player.blockBreakingProgress != null) { - if (world.isAirBlock(player.blockBreakingProgress.getKey())) { - world.sendBlockBreakProgress(player.getEntityId(), player.blockBreakingProgress.getKey(), -1); + if (!level.isClientSide && player != null && player.blockBreakingProgress != null) { + if (level.isEmptyBlock(player.blockBreakingProgress.getKey())) { + level.destroyBlockProgress(player.getId(), player.blockBreakingProgress.getKey(), -1); player.blockBreakingProgress = null; } } @@ -142,10 +145,10 @@ public class DeployerTileEntity extends KineticTileEntity { timer -= getTimerSpeed(); return; } - if (world.isRemote) + if (level.isClientSide) return; - ItemStack stack = player.getHeldItemMainhand(); + ItemStack stack = player.getMainHandItem(); if (state == State.WAITING) { if (!overflowItems.isEmpty()) { timer = getTimerSpeed() * 10; @@ -153,15 +156,15 @@ public class DeployerTileEntity extends KineticTileEntity { } boolean changed = false; - for (int i = 0; i < player.inventory.getSizeInventory(); i++) { + for (int i = 0; i < player.inventory.getContainerSize(); i++) { if (overflowItems.size() > 10) break; - ItemStack item = player.inventory.getStackInSlot(i); + ItemStack item = player.inventory.getItem(i); if (item.isEmpty()) continue; if (item != stack || !filtering.test(item)) { overflowItems.add(item); - player.inventory.setInventorySlotContents(i, ItemStack.EMPTY); + player.inventory.setItem(i, ItemStack.EMPTY); changed = true; } } @@ -172,8 +175,8 @@ public class DeployerTileEntity extends KineticTileEntity { return; } - Direction facing = getBlockState().get(FACING); - if (mode == Mode.USE && !DeployerHandler.shouldActivate(stack, world, pos.offset(facing, 2), facing)) { + Direction facing = getBlockState().getValue(FACING); + if (mode == Mode.USE && !DeployerHandler.shouldActivate(stack, level, worldPosition.relative(facing, 2), facing)) { timer = getTimerSpeed() * 10; return; } @@ -211,14 +214,14 @@ public class DeployerTileEntity extends KineticTileEntity { protected void start() { state = State.EXPANDING; Vector3d movementVector = getMovementVector(); - Vector3d rayOrigin = VecHelper.getCenterOf(pos) + Vector3d rayOrigin = VecHelper.getCenterOf(worldPosition) .add(movementVector.scale(3 / 2f)); - Vector3d rayTarget = VecHelper.getCenterOf(pos) + Vector3d rayTarget = VecHelper.getCenterOf(worldPosition) .add(movementVector.scale(5 / 2f)); RayTraceContext rayTraceContext = new RayTraceContext(rayOrigin, rayTarget, BlockMode.OUTLINE, FluidMode.NONE, player); - BlockRayTraceResult result = world.rayTraceBlocks(rayTraceContext); - reach = (float) (.5f + Math.min(result.getHitVec() + BlockRayTraceResult result = level.clip(rayTraceContext); + reach = (float) (.5f + Math.min(result.getLocation() .subtract(rayOrigin) .length(), .75f)); timer = 1000; @@ -226,17 +229,17 @@ public class DeployerTileEntity extends KineticTileEntity { } public boolean startBoop(Direction facing) { - if (!world.isAirBlock(pos.offset(facing, 1)) || !world.isAirBlock(pos.offset(facing, 2))) + if (!level.isEmptyBlock(worldPosition.relative(facing, 1)) || !level.isEmptyBlock(worldPosition.relative(facing, 2))) return false; - BlockPos otherDeployer = pos.offset(facing, 4); - if (!world.isBlockPresent(otherDeployer)) + BlockPos otherDeployer = worldPosition.relative(facing, 4); + if (!level.isLoaded(otherDeployer)) return false; - TileEntity otherTile = world.getTileEntity(otherDeployer); + TileEntity otherTile = level.getBlockEntity(otherDeployer); if (!(otherTile instanceof DeployerTileEntity)) return false; DeployerTileEntity deployerTile = (DeployerTileEntity) otherTile; - if (world.getBlockState(otherDeployer) - .get(FACING) + if (level.getBlockState(otherDeployer) + .getValue(FACING) .getOpposite() != facing || deployerTile.mode != Mode.PUNCH) return false; @@ -249,7 +252,7 @@ public class DeployerTileEntity extends KineticTileEntity { } public void triggerBoop() { - TileEntity otherTile = world.getTileEntity(pos.offset(getBlockState().get(FACING), 4)); + TileEntity otherTile = level.getBlockEntity(worldPosition.relative(getBlockState().getValue(FACING), 4)); if (!(otherTile instanceof DeployerTileEntity)) return; @@ -268,32 +271,32 @@ public class DeployerTileEntity extends KineticTileEntity { // award nearby players List players = - world.getEntitiesWithinAABB(ServerPlayerEntity.class, new AxisAlignedBB(pos).grow(9)); + level.getEntitiesOfClass(ServerPlayerEntity.class, new AxisAlignedBB(worldPosition).inflate(9)); players.forEach(AllTriggers.DEPLOYER_BOOP::trigger); } protected void activate() { Vector3d movementVector = getMovementVector(); - Direction direction = getBlockState().get(FACING); - Vector3d center = VecHelper.getCenterOf(pos); - BlockPos clickedPos = pos.offset(direction, 2); - player.rotationYaw = direction.getHorizontalAngle(); - player.rotationPitch = direction == Direction.UP ? -90 : direction == Direction.DOWN ? 90 : 0; + Direction direction = getBlockState().getValue(FACING); + Vector3d center = VecHelper.getCenterOf(worldPosition); + BlockPos clickedPos = worldPosition.relative(direction, 2); + player.yRot = direction.toYRot(); + player.xRot = direction == Direction.UP ? -90 : direction == Direction.DOWN ? 90 : 0; if (direction == Direction.DOWN - && TileEntityBehaviour.get(world, clickedPos, TransportedItemStackHandlerBehaviour.TYPE) != null) + && TileEntityBehaviour.get(level, clickedPos, TransportedItemStackHandlerBehaviour.TYPE) != null) return; // Belt processing handled in BeltDeployerCallbacks DeployerHandler.activate(player, center, clickedPos, movementVector, mode); if (player != null) - heldItem = player.getHeldItemMainhand(); + heldItem = player.getMainHandItem(); } protected Vector3d getMovementVector() { if (!AllBlocks.DEPLOYER.has(getBlockState())) return Vector3d.ZERO; - return Vector3d.of(getBlockState().get(FACING) - .getDirectionVec()); + return Vector3d.atLowerCornerOf(getBlockState().getValue(FACING) + .getNormal()); } @Override @@ -306,16 +309,16 @@ public class DeployerTileEntity extends KineticTileEntity { deferredInventoryList = compound.getList("Inventory", NBT.TAG_COMPOUND); overflowItems = NBTHelper.readItemList(compound.getList("Overflow", NBT.TAG_COMPOUND)); if (compound.contains("HeldItem")) - heldItem = ItemStack.read(compound.getCompound("HeldItem")); + heldItem = ItemStack.of(compound.getCompound("HeldItem")); super.fromTag(blockState, compound, clientPacket); if (!clientPacket) return; reach = compound.getFloat("Reach"); if (compound.contains("Particle")) { - ItemStack particleStack = ItemStack.read(compound.getCompound("Particle")); - SandPaperItem.spawnParticles(VecHelper.getCenterOf(pos) - .add(getMovementVector().scale(reach + 1)), particleStack, this.world); + ItemStack particleStack = ItemStack.of(compound.getCompound("Particle")); + SandPaperItem.spawnParticles(VecHelper.getCenterOf(worldPosition) + .add(getMovementVector().scale(reach + 1)), particleStack, this.level); } } @@ -327,12 +330,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); + player.inventory.save(invNBT); compound.put("Inventory", invNBT); + compound.put("HeldItem", player.getMainHandItem().serializeNBT()); compound.put("Overflow", NBTHelper.writeItemList(overflowItems)); + } else if (deferredInventoryList != null) { + compound.put("Inventory", deferredInventoryList); } super.write(compound, clientPacket); @@ -342,7 +346,7 @@ public class DeployerTileEntity extends KineticTileEntity { compound.putFloat("Reach", reach); if (player == null) return; - compound.put("HeldItem", player.getHeldItemMainhand() + compound.put("HeldItem", player.getMainHandItem() .serializeNBT()); if (player.spawnedItemEffects != null) { compound.put("Particle", player.spawnedItemEffects.serializeNBT()); @@ -355,9 +359,9 @@ public class DeployerTileEntity extends KineticTileEntity { } public void redstoneUpdate() { - if (world.isRemote) + if (level.isClientSide) return; - boolean blockPowered = world.isBlockPowered(pos); + boolean blockPowered = level.hasNeighborSignal(worldPosition); if (blockPowered == redstoneLocked) return; redstoneLocked = blockPowered; @@ -371,19 +375,19 @@ public class DeployerTileEntity extends KineticTileEntity { @Override public AxisAlignedBB makeRenderBoundingBox() { - return super.makeRenderBoundingBox().grow(3); + return super.makeRenderBoundingBox().inflate(3); } @Override - public void remove() { - super.remove(); + public void setRemoved() { + super.setRemoved(); if (invHandler != null) invHandler.invalidate(); } public void changeMode() { mode = mode == Mode.PUNCH ? Mode.USE : Mode.PUNCH; - markDirty(); + setChanged(); sendData(); } @@ -407,7 +411,7 @@ public class DeployerTileEntity extends KineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } @@ -438,19 +442,37 @@ public class DeployerTileEntity extends KineticTileEntity { SandPaperInv sandpaperInv = new SandPaperInv(ItemStack.EMPTY); @Nullable - public IRecipe getRecipe(ItemStack stack) { - if (player == null) + public IRecipe getRecipe(ItemStack stack) { + // safety checks + if (player == null || level == null) return null; - ItemStack heldItemMainhand = player.getHeldItemMainhand(); + + // sandpaper = op + ItemStack heldItemMainhand = player.getMainHandItem(); if (heldItemMainhand.getItem() instanceof SandPaperItem) { - sandpaperInv.setInventorySlotContents(0, stack); - return AllRecipeTypes.SANDPAPER_POLISHING.find(sandpaperInv, world) + sandpaperInv.setItem(0, stack); + return AllRecipeTypes.SANDPAPER_POLISHING.find(sandpaperInv, level) .orElse(null); } - recipeInv.setInventorySlotContents(0, heldItemMainhand); - recipeInv.setInventorySlotContents(1, stack); - return AllRecipeTypes.DEPLOYING.find(recipeInv, world) - .orElse(null); + + // inventory + recipeInv.setItem(0, stack); + recipeInv.setItem(1, heldItemMainhand); + + // event nonsense + DeployerRecipeSearchEvent event = new DeployerRecipeSearchEvent(this, recipeInv); + + // creates deployer recipes + event.addRecipe(() -> SequencedAssemblyRecipe.getRecipe(level, event.getInventory(), + AllRecipeTypes.DEPLOYING.getType(), DeployerApplicationRecipe.class), 100); + event.addRecipe(() -> AllRecipeTypes.DEPLOYING.find(event.getInventory(), level), 50); + + // post the event, get result + MinecraftForge.EVENT_BUS.post(event); + return event.getRecipe(); } + public DeployerFakePlayer getPlayer() { + return player; + } } 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..97f522e18 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; @@ -46,10 +46,10 @@ import net.minecraftforge.fml.DistExecutor; public class AirCurrent { - private static final DamageSource damageSourceFire = new DamageSource("create.fan_fire").setDifficultyScaled() - .setFireDamage(); - private static final DamageSource damageSourceLava = new DamageSource("create.fan_lava").setDifficultyScaled() - .setFireDamage(); + private static final DamageSource damageSourceFire = new DamageSource("create.fan_fire").setScalesWithDifficulty() + .setIsFire(); + private static final DamageSource damageSourceLava = new DamageSource("create.fan_lava").setScalesWithDifficulty() + .setIsFire(); public final IAirCurrentSource source; public AxisAlignedBB bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0); @@ -73,12 +73,12 @@ public class AirCurrent { rebuild(); World world = source.getAirCurrentWorld(); Direction facing = direction; - if (world != null && world.isRemote) { + if (world != null && world.isClientSide) { float offset = pushing ? 0.5f : maxDistance + .5f; Vector3d pos = VecHelper.getCenterOf(source.getAirCurrentPos()) - .add(Vector3d.of(facing.getDirectionVec()) + .add(Vector3d.atLowerCornerOf(facing.getNormal()) .scale(offset)); - if (world.rand.nextFloat() < AllConfigs.CLIENT.fanParticleDensity.get()) + if (world.random.nextFloat() < AllConfigs.CLIENT.fanParticleDensity.get()) world.addParticle(new AirFlowParticleData(source.getAirCurrentPos()), pos.x, pos.y, pos.z, 0, 0, 0); } @@ -89,21 +89,20 @@ 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; } Vector3d center = VecHelper.getCenterOf(source.getAirCurrentPos()); - Vector3i flow = (pushing ? facing : facing.getOpposite()).getDirectionVec(); + Vector3i flow = (pushing ? facing : facing.getOpposite()).getNormal(); - float sneakModifier = entity.isSneaking() ? 4096f : 512f; + float sneakModifier = entity.isShiftKeyDown() ? 4096f : 512f; float speed = Math.abs(source.getSpeed()); - double entityDistance = entity.getPositionVec() + double entityDistance = entity.position() .distanceTo(center); float acceleration = (float) (speed / sneakModifier / (entityDistance / maxDistance)); - Vector3d previousMotion = entity.getMotion(); + Vector3d previousMotion = entity.getDeltaMovement(); float maxAcceleration = 5; double xIn = @@ -113,13 +112,13 @@ public class AirCurrent { double zIn = MathHelper.clamp(flow.getZ() * acceleration - previousMotion.z, -maxAcceleration, maxAcceleration); - entity.setMotion(previousMotion.add(new Vector3d(xIn, yIn, zIn).scale(1 / 8f))); + entity.setDeltaMovement(previousMotion.add(new Vector3d(xIn, yIn, zIn).scale(1 / 8f))); entity.fallDistance = 0; DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> enableClientPlayerSound(entity, MathHelper.clamp(speed / 128f * .4f, 0.01f, .4f))); if (entity instanceof ServerPlayerEntity) - ((ServerPlayerEntity) entity).connection.floatingTickCount = 0; + ((ServerPlayerEntity) entity).connection.aboveGroundTickCount = 0; entityDistance -= .5f; InWorldProcessing.Type processingType = getSegmentAt((float) entityDistance); @@ -132,41 +131,41 @@ public class AirCurrent { } if (entity instanceof ItemEntity) { - InWorldProcessing.spawnParticlesForProcessing(world, entity.getPositionVec(), processingType); + InWorldProcessing.spawnParticlesForProcessing(world, entity.position(), processingType); ItemEntity itemEntity = (ItemEntity) entity; - if (world.isRemote) + if (world.isClientSide) continue; if (InWorldProcessing.canProcess(itemEntity, processingType)) InWorldProcessing.applyProcessing(itemEntity, processingType); continue; } - if (world.isRemote) + if (world.isClientSide) continue; switch (processingType) { case BLASTING: - if (!entity.isFireImmune()) { - entity.setFire(10); - entity.attackEntityFrom(damageSourceLava, 4); + if (!entity.fireImmune()) { + entity.setSecondsOnFire(10); + entity.hurt(damageSourceLava, 4); } break; case SMOKING: - if (!entity.isFireImmune()) { - entity.setFire(2); - entity.attackEntityFrom(damageSourceFire, 2); + if (!entity.fireImmune()) { + entity.setSecondsOnFire(2); + entity.hurt(damageSourceFire, 2); } break; case SPLASHING: if (entity instanceof EndermanEntity || entity.getType() == EntityType.SNOW_GOLEM || entity.getType() == EntityType.BLAZE) { - entity.attackEntityFrom(DamageSource.DROWN, 2); + entity.hurt(DamageSource.DROWN, 2); } - if (!entity.isBurning()) + if (!entity.isOnFire()) break; - entity.extinguish(); - world.playSound(null, entity.getBlockPos(), SoundEvents.ENTITY_GENERIC_EXTINGUISH_FIRE, - SoundCategory.NEUTRAL, 0.7F, 1.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.4F); + entity.clearFire(); + world.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, + SoundCategory.NEUTRAL, 0.7F, 1.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.4F); break; default: break; @@ -191,7 +190,7 @@ public class AirCurrent { BlockPos start = source.getAirCurrentPos(); float max = this.maxDistance; Direction facing = direction; - Vector3d directionVec = Vector3d.of(facing.getDirectionVec()); + Vector3d directionVec = Vector3d.atLowerCornerOf(facing.getNormal()); maxDistance = getFlowLimit(world, start, max, facing); // Determine segments with transported fluids/gases @@ -206,7 +205,7 @@ public class AirCurrent { int searchStep = pushing ? 1 : -1; for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) { - BlockPos currentPos = start.offset(direction, i); + BlockPos currentPos = start.relative(direction, i); InWorldProcessing.Type newType = InWorldProcessing.Type.byBlock(world, currentPos); if (newType != Type.NONE) type = newType; @@ -229,40 +228,40 @@ public class AirCurrent { float factor = maxDistance - 1; Vector3d scale = directionVec.scale(factor); if (factor > 0) - bounds = new AxisAlignedBB(start.offset(direction)).expand(scale); + bounds = new AxisAlignedBB(start.relative(direction)).expandTowards(scale); else { - bounds = new AxisAlignedBB(start.offset(direction)).contract(scale.x, scale.y, scale.z) - .offset(scale); + bounds = new AxisAlignedBB(start.relative(direction)).contract(scale.x, scale.y, scale.z) + .move(scale); } } findAffectedHandlers(); } public static float getFlowLimit(World world, BlockPos start, float max, Direction facing) { - Vector3d directionVec = Vector3d.of(facing.getDirectionVec()); + Vector3d directionVec = Vector3d.atLowerCornerOf(facing.getNormal()); Vector3d planeVec = VecHelper.axisAlingedPlaneOf(directionVec); // 4 Rays test for holes in the shapes blocking the flow float offsetDistance = .25f; - Vector3d[] offsets = new Vector3d[] { planeVec.mul(offsetDistance, offsetDistance, offsetDistance), - planeVec.mul(-offsetDistance, -offsetDistance, offsetDistance), - planeVec.mul(offsetDistance, -offsetDistance, -offsetDistance), - planeVec.mul(-offsetDistance, offsetDistance, -offsetDistance), }; + Vector3d[] offsets = new Vector3d[] { planeVec.multiply(offsetDistance, offsetDistance, offsetDistance), + planeVec.multiply(-offsetDistance, -offsetDistance, offsetDistance), + planeVec.multiply(offsetDistance, -offsetDistance, -offsetDistance), + planeVec.multiply(-offsetDistance, offsetDistance, -offsetDistance), }; float limitedDistance = 0; // Determine the distance of the air flow Outer: for (int i = 1; i <= max; i++) { - BlockPos currentPos = start.offset(facing, i); - if (!world.isBlockPresent(currentPos)) + BlockPos currentPos = start.relative(facing, i); + if (!world.isLoaded(currentPos)) break; BlockState state = world.getBlockState(currentPos); if (shouldAlwaysPass(state)) continue; - VoxelShape voxelshape = state.getCollisionShape(world, currentPos, ISelectionContext.dummy()); + VoxelShape voxelshape = state.getCollisionShape(world, currentPos, ISelectionContext.empty()); if (voxelshape.isEmpty()) continue; - if (voxelshape == VoxelShapes.fullCube()) { + if (voxelshape == VoxelShapes.block()) { max = i - 1; break; } @@ -273,11 +272,11 @@ public class AirCurrent { .add(offset); Vector3d rayEnd = rayStart.add(directionVec.scale(1 + 1 / 32f)); BlockRayTraceResult blockraytraceresult = - world.rayTraceBlocks(rayStart, rayEnd, currentPos, voxelshape, state); + world.clipWithInteractionOverride(rayStart, rayEnd, currentPos, voxelshape, state); if (blockraytraceresult == null) continue Outer; - double distance = i - 1 + blockraytraceresult.getHitVec() + double distance = i - 1 + blockraytraceresult.getLocation() .distanceTo(rayStart); if (limitedDistance < distance) limitedDistance = (float) distance; @@ -292,7 +291,7 @@ public class AirCurrent { public void findEntities() { caughtEntities.clear(); caughtEntities = source.getAirCurrentWorld() - .getEntitiesWithinAABBExcludingEntity(null, bounds); + .getEntities(null, bounds); } public void findAffectedHandlers() { @@ -305,8 +304,8 @@ public class AirCurrent { continue; for (int offset : Iterate.zeroAndOne) { - BlockPos pos = start.offset(direction, i) - .down(offset); + BlockPos pos = start.relative(direction, i) + .below(offset); TransportedItemStackHandlerBehaviour behaviour = TileEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE); if (behaviour != null) @@ -327,7 +326,7 @@ public class AirCurrent { handler.handleProcessingOnAllItems((transported) -> { InWorldProcessing.spawnParticlesForProcessing(world, handler.getWorldPositionOf(transported), processingType); - if (world.isRemote) + if (world.isClientSide) return TransportedResult.doNothing(); return InWorldProcessing.applyProcessing(transported, world, processingType); }); @@ -361,18 +360,18 @@ public class AirCurrent { @OnlyIn(Dist.CLIENT) private static void enableClientPlayerSound(Entity e, float maxVolume) { if (e != Minecraft.getInstance() - .getRenderViewEntity()) + .getCameraEntity()) return; isClientPlayerInAirCurrent = true; - float pitch = (float) MathHelper.clamp(e.getMotion() + float pitch = (float) MathHelper.clamp(e.getDeltaMovement() .length() * .5f, .5f, 2f); - if (flyingSound == null || flyingSound.isDonePlaying()) { - flyingSound = new AirCurrentSound(SoundEvents.ITEM_ELYTRA_FLYING, pitch); + if (flyingSound == null || flyingSound.isStopped()) { + flyingSound = new AirCurrentSound(SoundEvents.ELYTRA_FLYING, pitch); Minecraft.getInstance() - .getSoundHandler() + .getSoundManager() .play(flyingSound); } flyingSound.setPitch(pitch); @@ -383,10 +382,18 @@ public class AirCurrent { public static void tickClientPlayerSounds() { if (!AirCurrent.isClientPlayerInAirCurrent && flyingSound != null) if (flyingSound.isFaded()) - flyingSound.stop(); + flyingSound.stopSound(); else flyingSound.fadeOut(); isClientPlayerInAirCurrent = false; } + public static boolean isPlayerCreativeFlying(Entity entity) { + if (entity instanceof PlayerEntity) { + PlayerEntity player = (PlayerEntity) entity; + return player.isCreative() && player.abilities.flying; + } + return false; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrentSound.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrentSound.java index 7a9c4a7db..72a39910b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrentSound.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrentSound.java @@ -12,9 +12,9 @@ public class AirCurrentSound extends TickableSound { super(p_i46532_1_, SoundCategory.BLOCKS); this.pitch = pitch; volume = 0.01f; - repeat = true; - repeatDelay = 0; - global = true; + looping = true; + delay = 0; + relative = true; } @Override @@ -23,26 +23,26 @@ public class AirCurrentSound extends TickableSound { public void setPitch(float pitch) { this.pitch = pitch; } - + public void fadeIn(float maxVolume) { volume = Math.min(maxVolume, volume + .05f); } - + public void fadeOut() { volume = Math.max(0, volume - .05f); } - + public boolean isFaded() { return volume == 0; } - + @Override public float getPitch() { return pitch; } - - public void stop() { - setDone(); + + public void stopSound() { + stop(); } - + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java index 8cb03c361..6cd3cc491 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java @@ -31,22 +31,22 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE te.queueGeneratorUpdate()); } @@ -91,19 +91,19 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE 0) speed = MathHelper.clamp(speed, 80, 64 * 20); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java index 16da67993..fc1730c97 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java @@ -78,11 +78,11 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements if (!AllBlocks.ENCASED_FAN.has(blockState)) shouldGenerate = false; - if (shouldGenerate && blockState.get(EncasedFanBlock.FACING) != Direction.DOWN) + if (shouldGenerate && blockState.getValue(EncasedFanBlock.FACING) != Direction.DOWN) shouldGenerate = false; if (shouldGenerate) - shouldGenerate = world != null && world.isBlockPowered(pos) && world.isBlockPresent(pos.down()) && blockBelowIsHot(); + shouldGenerate = level != null && level.hasNeighborSignal(worldPosition) && level.isLoaded(worldPosition.below()) && blockBelowIsHot(); if (shouldGenerate == isGenerator) return; @@ -91,19 +91,19 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements } public boolean blockBelowIsHot() { - if (world == null) + if (level == null) return false; - BlockState checkState = world.getBlockState(pos.down()); + BlockState checkState = level.getBlockState(worldPosition.below()); if (!checkState.getBlock() - .isIn(AllBlockTags.FAN_HEATERS.tag)) + .is(AllBlockTags.FAN_HEATERS.tag)) return false; - if (checkState.contains(BlazeBurnerBlock.HEAT_LEVEL) && !checkState.get(BlazeBurnerBlock.HEAT_LEVEL) + if (checkState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && !checkState.getValue(BlazeBurnerBlock.HEAT_LEVEL) .isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) return false; - if (checkState.contains(BlockStateProperties.LIT) && !checkState.get(BlockStateProperties.LIT)) + if (checkState.hasProperty(BlockStateProperties.LIT) && !checkState.getValue(BlockStateProperties.LIT)) return false; return true; @@ -117,18 +117,18 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements @Nullable @Override public World getAirCurrentWorld() { - return world; + return level; } @Override public BlockPos getAirCurrentPos() { - return pos; + return worldPosition; } @Override public Direction getAirflowOriginSide() { return this.getBlockState() - .get(EncasedFanBlock.FACING); + .getValue(EncasedFanBlock.FACING); } @Override @@ -136,14 +136,14 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements float speed = getSpeed(); if (speed == 0) return null; - Direction facing = getBlockState().get(BlockStateProperties.FACING); + Direction facing = getBlockState().getValue(BlockStateProperties.FACING); speed = convertToDirection(speed, facing); return speed > 0 ? facing : facing.getOpposite(); } @Override public boolean isSourceRemoved() { - return removed; + return remove; } @Override @@ -154,11 +154,11 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements } public void updateChute() { - Direction direction = getBlockState().get(EncasedFanBlock.FACING); + Direction direction = getBlockState().getValue(EncasedFanBlock.FACING); if (!direction.getAxis() .isVertical()) return; - TileEntity poweredChute = world.getTileEntity(pos.offset(direction)); + TileEntity poweredChute = level.getBlockEntity(worldPosition.relative(direction)); if (!(poweredChute instanceof ChuteTileEntity)) return; ChuteTileEntity chuteTE = (ChuteTileEntity) poweredChute; @@ -176,7 +176,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements public void tick() { super.tick(); - boolean server = !world.isRemote || isVirtual(); + boolean server = !level.isClientSide || isVirtual(); if (server && airCurrentUpdateCooldown-- <= 0) { airCurrentUpdateCooldown = AllConfigs.SERVER.kinetics.fanBlockCheckRate.get(); 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..9b6956c4d 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,11 @@ package com.simibubi.create.content.contraptions.components.fan; import static net.minecraft.state.properties.BlockStateProperties.FACING; +import com.jozufozu.flywheel.backend.material.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 com.simibubi.create.foundation.render.AllMaterialSpecs; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -18,14 +19,17 @@ 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); + direction = blockState.getValue(FACING); opposite = direction.getOpposite(); shaft = getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, opposite).createInstance(); - fan = getRotatingMaterial().getModel(AllBlockPartials.ENCASED_FAN_INNER, blockState, opposite).createInstance(); + fan = modelManager.defaultCutout() + .material(AllMaterialSpecs.ROTATING) + .getModel(AllBlockPartials.ENCASED_FAN_INNER, blockState, opposite) + .createInstance(); setup(shaft); setup(fan, getFanSpeed()); @@ -41,17 +45,17 @@ public class FanInstance extends KineticTileInstance { } @Override - protected void update() { + public void update() { updateRotation(shaft); updateRotation(fan, getFanSpeed()); } @Override public void updateLight() { - BlockPos behind = pos.offset(opposite); + BlockPos behind = pos.relative(opposite); relight(behind, shaft); - BlockPos inFront = pos.offset(direction); + BlockPos inFront = pos.relative(direction); relight(inFront, fan); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java index b25a7d0d5..f37c808c2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java @@ -4,7 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; @@ -24,7 +24,7 @@ import net.minecraft.world.World; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class NozzleBlock extends ProperDirectionalBlock { +public class NozzleBlock extends WrenchableDirectionalBlock { public NozzleBlock(Properties p_i48415_1_) { super(p_i48415_1_); @@ -47,37 +47,37 @@ public class NozzleBlock extends ProperDirectionalBlock { @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - return getDefaultState().with(FACING, context.getFace()); + return defaultBlockState().setValue(FACING, context.getClickedFace()); } @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.NOZZLE.get(state.get(FACING)); + return AllShapes.NOZZLE.get(state.getValue(FACING)); } @Override public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; - if (fromPos.equals(pos.offset(state.get(FACING).getOpposite()))) - if (!isValidPosition(state, worldIn, pos)) { + if (fromPos.equals(pos.relative(state.getValue(FACING).getOpposite()))) + if (!canSurvive(state, worldIn, pos)) { worldIn.destroyBlock(pos, true); return; } } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - Direction towardsFan = state.get(FACING).getOpposite(); - TileEntity te = worldIn.getTileEntity(pos.offset(towardsFan)); + public boolean canSurvive(BlockState state, IWorldReader worldIn, BlockPos pos) { + Direction towardsFan = state.getValue(FACING).getOpposite(); + TileEntity te = worldIn.getBlockEntity(pos.relative(towardsFan)); return te instanceof IAirCurrentSource && ((IAirCurrentSource) te).getAirflowOriginSide() == towardsFan.getOpposite(); } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } 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..1ca0d1ee5 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); @@ -61,7 +61,7 @@ public class NozzleTileEntity extends SmartTileEntity { @Override public void initialize() { - fanPos = pos.offset(getBlockState().get(NozzleBlock.FACING) + fanPos = worldPosition.relative(getBlockState().getValue(NozzleBlock.FACING) .getOpposite()); super.initialize(); } @@ -74,29 +74,28 @@ public class NozzleTileEntity extends SmartTileEntity { if (this.range != range) setRange(range); - Vector3d center = VecHelper.getCenterOf(pos); - if (world.isRemote && range != 0) { - if (world.rand.nextInt( + Vector3d center = VecHelper.getCenterOf(worldPosition); + if (level.isClientSide && range != 0) { + if (level.random.nextInt( MathHelper.clamp((AllConfigs.SERVER.kinetics.fanPushDistance.get() - (int) range), 1, 10)) == 0) { - Vector3d start = VecHelper.offsetRandomly(center, world.rand, pushing ? 1 : range / 2); + Vector3d start = VecHelper.offsetRandomly(center, level.random, pushing ? 1 : range / 2); Vector3d motion = center.subtract(start) .normalize() .scale(MathHelper.clamp(range * (pushing ? .025f : 1f), 0, .5f) * (pushing ? -1 : 1)); - world.addParticle(ParticleTypes.POOF, start.x, start.y, start.z, motion.x, motion.y, motion.z); + level.addParticle(ParticleTypes.POOF, start.x, start.y, start.z, motion.x, motion.y, motion.z); } } for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { Entity entity = iterator.next(); - Vector3d diff = entity.getPositionVec() - .subtract(center); + Vector3d diff = entity.position() + .subtract(center); - if (!(entity instanceof PlayerEntity) && world.isRemote) + if (!(entity instanceof PlayerEntity) && level.isClientSide) continue; double distance = diff.length(); - if (distance > range || entity.isSneaking() - || (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) { + if (distance > range || entity.isShiftKeyDown() || AirCurrent.isPlayerCreativeFlying(entity)) { iterator.remove(); continue; } @@ -106,11 +105,11 @@ public class NozzleTileEntity extends SmartTileEntity { float factor = (entity instanceof ItemEntity) ? 1 / 128f : 1 / 32f; Vector3d pushVec = diff.normalize() - .scale((range - distance) * (pushing ? 1 : -1)); - entity.setMotion(entity.getMotion() + .scale((range - distance) * (pushing ? 1 : -1)); + entity.setDeltaMovement(entity.getDeltaMovement() .add(pushVec.scale(factor))); entity.fallDistance = 0; - entity.velocityChanged = true; + entity.hurtMarked = true; } } @@ -123,7 +122,7 @@ public class NozzleTileEntity extends SmartTileEntity { } private float calcRange() { - TileEntity te = world.getTileEntity(fanPos); + TileEntity te = level.getBlockEntity(fanPos); if (!(te instanceof IAirCurrentSource)) return 0; @@ -145,18 +144,16 @@ public class NozzleTileEntity extends SmartTileEntity { if (range == 0) return; - Vector3d center = VecHelper.getCenterOf(pos); - AxisAlignedBB bb = new AxisAlignedBB(center, center).grow(range / 2f); + Vector3d center = VecHelper.getCenterOf(worldPosition); + AxisAlignedBB bb = new AxisAlignedBB(center, center).inflate(range / 2f); - for (Entity entity : world.getEntitiesWithinAABB(Entity.class, bb)) { - Vector3d diff = entity.getPositionVec() - .subtract(center); + for (Entity entity : level.getEntitiesOfClass(Entity.class, bb)) { + Vector3d diff = entity.position() + .subtract(center); double distance = diff.length(); - if (distance > range || entity.isSneaking() - || (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) { + if (distance > range || entity.isShiftKeyDown() || AirCurrent.isPlayerCreativeFlying(entity)) continue; - } boolean canSee = canSee(entity); if (!canSee) { @@ -175,8 +172,8 @@ public class NozzleTileEntity extends SmartTileEntity { iterator.remove(); } - if (!pushing && pushingEntities.size() > 256 && !world.isRemote) { - world.createExplosion(null, center.x, center.y, center.z, 2, Mode.NONE); + if (!pushing && pushingEntities.size() > 256 && !level.isClientSide) { + level.explode(null, center.x, center.y, center.z, 2, Mode.NONE); for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { Entity entity = iterator.next(); entity.remove(); @@ -187,10 +184,10 @@ public class NozzleTileEntity extends SmartTileEntity { } private boolean canSee(Entity entity) { - RayTraceContext context = new RayTraceContext(entity.getPositionVec(), VecHelper.getCenterOf(pos), + RayTraceContext context = new RayTraceContext(entity.position(), VecHelper.getCenterOf(worldPosition), BlockMode.COLLIDER, FluidMode.NONE, entity); - return pos.equals(world.rayTraceBlocks(context) - .getPos()); + return worldPosition.equals(level.clip(context) + .getBlockPos()); } } 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..499f6c8ff 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,26 +3,26 @@ 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.InWorldProcessing.SplashingWrapper; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; 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) - .test(inv.getStackInSlot(0)); + .test(inv.getItem(0)); } @Override 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..5c20fe6db 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,19 +6,19 @@ 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.Instancer; +import com.jozufozu.flywheel.backend.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; @@ -45,33 +45,33 @@ 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); + facing = blockState.getValue(HORIZONTAL_FACING); shaft = setup(shaftModel().createInstance()); BlockState referenceState = blockState.rotate(Rotation.CLOCKWISE_90); - wheel = getTransformMaterial().getModel(AllBlockPartials.FLYWHEEL, referenceState, referenceState.get(HORIZONTAL_FACING)).createInstance(); + wheel = getTransformMaterial().getModel(AllBlockPartials.FLYWHEEL, referenceState, referenceState.getValue(HORIZONTAL_FACING)).createInstance(); connection = FlywheelBlock.getConnection(blockState); if (connection != null) { - connectedLeft = blockState.get(FlywheelBlock.CONNECTION) == FlywheelBlock.ConnectionState.LEFT; + connectedLeft = blockState.getValue(FlywheelBlock.CONNECTION) == FlywheelBlock.ConnectionState.LEFT; boolean flipAngle = connection.getAxis() == Direction.Axis.X ^ connection.getAxisDirection() == Direction.AxisDirection.NEGATIVE; 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(); } @@ -95,48 +95,48 @@ public class FlyWheelInstance extends KineticTileInstance im private void animate(float angle) { MatrixStack ms = new MatrixStack(); - MatrixStacker msr = MatrixStacker.of(ms); + MatrixTransformStack msr = MatrixTransformStack.of(ms); msr.translate(getInstancePosition()); if (connection != null) { float rotation = angle * connectorAngleMult; - ms.push(); + ms.pushPose(); rotateToFacing(msr, connection); - ms.push(); + ms.pushPose(); transformConnector(msr, true, true, rotation, connectedLeft); upperRotating.setTransform(ms); - ms.pop(); + ms.popPose(); - ms.push(); + ms.pushPose(); transformConnector(msr, false, true, rotation, connectedLeft); lowerRotating.setTransform(ms); - ms.pop(); + ms.popPose(); - ms.push(); + ms.pushPose(); transformConnector(msr, true, false, rotation, connectedLeft); upperSliding.setTransform(ms); - ms.pop(); + ms.popPose(); - ms.push(); + ms.pushPose(); transformConnector(msr, false, false, rotation, connectedLeft); lowerSliding.setTransform(ms); - ms.pop(); + ms.popPose(); - ms.pop(); + ms.popPose(); } msr.centre() - .rotate(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, facing.getAxis()), AngleHelper.rad(angle)) + .rotate(Direction.get(Direction.AxisDirection.POSITIVE, facing.getAxis()), AngleHelper.rad(angle)) .unCentre(); wheel.setTransform(ms); } @Override - protected void update() { + public void update() { updateRotation(shaft); } @@ -145,7 +145,7 @@ public class FlyWheelInstance extends KineticTileInstance im relight(pos, shaft, wheel); if (connection != null) { - relight(this.pos.offset(connection), connectors.stream()); + relight(this.pos.relative(connection), connectors.stream()); } } @@ -158,12 +158,12 @@ 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); } - protected void transformConnector(MatrixStacker ms, boolean upper, boolean rotating, float angle, boolean flip) { + protected void transformConnector(MatrixTransformStack ms, boolean upper, boolean rotating, float angle, boolean flip) { float shift = upper ? 1 / 4f : -1 / 8f; float offset = upper ? 1 / 4f : 1 / 4f; float radians = (float) (angle / 180 * Math.PI); @@ -189,7 +189,7 @@ public class FlyWheelInstance extends KineticTileInstance im ms.translate(9 / 16f, 0, 0); } - protected void rotateToFacing(MatrixStacker buffer, Direction facing) { + protected void rotateToFacing(MatrixTransformStack buffer, Direction facing) { buffer.centre() .rotate(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing))) .unCentre(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelBlock.java index 607dcdd19..71762f6fa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelBlock.java @@ -29,12 +29,12 @@ public class FlywheelBlock extends HorizontalKineticBlock { public FlywheelBlock(Properties properties) { super(properties); - setDefaultState(getDefaultState().with(CONNECTION, ConnectionState.NONE)); + registerDefaultState(defaultBlockState().setValue(CONNECTION, ConnectionState.NONE)); } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(CONNECTION)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(CONNECTION)); } @Override @@ -46,8 +46,8 @@ public class FlywheelBlock extends HorizontalKineticBlock { public BlockState getStateForPlacement(BlockItemUseContext context) { Direction preferred = getPreferredHorizontalFacing(context); if (preferred != null) - return getDefaultState().with(HORIZONTAL_FACING, preferred.getOpposite()); - return this.getDefaultState().with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing()); + return defaultBlockState().setValue(HORIZONTAL_FACING, preferred.getOpposite()); + return this.defaultBlockState().setValue(HORIZONTAL_FACING, context.getHorizontalDirection()); } public static boolean isConnected(BlockState state) { @@ -55,37 +55,37 @@ public class FlywheelBlock extends HorizontalKineticBlock { } public static Direction getConnection(BlockState state) { - Direction facing = state.get(HORIZONTAL_FACING); - ConnectionState connection = state.get(CONNECTION); + Direction facing = state.getValue(HORIZONTAL_FACING); + ConnectionState connection = state.getValue(CONNECTION); if (connection == ConnectionState.LEFT) - return facing.rotateYCCW(); + return facing.getCounterClockWise(); if (connection == ConnectionState.RIGHT) - return facing.rotateY(); + return facing.getClockWise(); return null; } public static void setConnection(World world, BlockPos pos, BlockState state, Direction direction) { - Direction facing = state.get(HORIZONTAL_FACING); + Direction facing = state.getValue(HORIZONTAL_FACING); ConnectionState connection = ConnectionState.NONE; - if (direction == facing.rotateY()) + if (direction == facing.getClockWise()) connection = ConnectionState.RIGHT; - if (direction == facing.rotateYCCW()) + if (direction == facing.getCounterClockWise()) connection = ConnectionState.LEFT; - world.setBlockState(pos, state.with(CONNECTION, connection), 18); + world.setBlock(pos, state.setValue(CONNECTION, connection), 18); AllTriggers.triggerForNearbyPlayers(AllTriggers.FLYWHEEL, world, pos, 4); } @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face == state.get(HORIZONTAL_FACING).getOpposite(); + return face == state.getValue(HORIZONTAL_FACING).getOpposite(); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(HORIZONTAL_FACING).getAxis(); + return state.getValue(HORIZONTAL_FACING).getAxis(); } @Override @@ -94,23 +94,23 @@ public class FlywheelBlock extends HorizontalKineticBlock { if (connection == null) return super.onWrenched(state ,context); - if (context.getFace().getAxis() == state.get(HORIZONTAL_FACING).getAxis()) + if (context.getClickedFace().getAxis() == state.getValue(HORIZONTAL_FACING).getAxis()) return ActionResultType.PASS; - World world = context.getWorld(); - BlockPos enginePos = context.getPos().offset(connection, 2); + World world = context.getLevel(); + BlockPos enginePos = context.getClickedPos().relative(connection, 2); BlockState engine = world.getBlockState(enginePos); if (engine.getBlock() instanceof FurnaceEngineBlock) ((FurnaceEngineBlock) engine.getBlock()).withTileEntityDo(world, enginePos, EngineTileEntity::detachWheel); - return super.onWrenched(state.with(CONNECTION, ConnectionState.NONE), context); + return super.onWrenched(state.setValue(CONNECTION, ConnectionState.NONE), context); } public enum ConnectionState implements IStringSerializable { NONE, LEFT, RIGHT; @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelGenerator.java index 13dc7759d..9244651ad 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelGenerator.java @@ -17,14 +17,14 @@ public class FlywheelGenerator extends SpecialBlockStateGen { @Override protected int getYRotation(BlockState state) { - return horizontalAngle(state.get(FlywheelBlock.HORIZONTAL_FACING)) + 90; + return horizontalAngle(state.getValue(FlywheelBlock.HORIZONTAL_FACING)) + 90; } @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { return prov.models() - .getExistingFile(prov.modLoc("block/" + ctx.getName() + "/casing_" + state.get(FlywheelBlock.CONNECTION) - .getString())); + .getExistingFile(prov.modLoc("block/" + ctx.getName() + "/casing_" + state.getValue(FlywheelBlock.CONNECTION) + .getSerializedName())); } } 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..6eac080f0 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.getLevel())) return; BlockState blockState = te.getBlockState(); FlywheelTileEntity wte = (FlywheelTileEntity) te; @@ -44,16 +44,16 @@ public class FlywheelRenderer extends KineticTileEntityRenderer { float speed = wte.visualSpeed.get(partialTicks) * 3 / 10f; float angle = wte.angle + speed * partialTicks; - IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); + IVertexBuilder vb = buffer.getBuffer(RenderType.solid()); if (FlywheelBlock.isConnected(blockState)) { Direction connection = FlywheelBlock.getConnection(blockState); - light = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, te.getPos() - .offset(connection)); + light = WorldRenderer.getLightColor(te.getLevel(), blockState, te.getBlockPos() + .relative(connection)); float rotation = connection.getAxis() == Axis.X ^ connection.getAxisDirection() == AxisDirection.NEGATIVE ? -angle : angle; - boolean flip = blockState.get(FlywheelBlock.CONNECTION) == ConnectionState.LEFT; + boolean flip = blockState.getValue(FlywheelBlock.CONNECTION) == ConnectionState.LEFT; transformConnector( rotateToFacing(PartialBufferer.get(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, blockState), connection), true, true, @@ -77,9 +77,9 @@ public class FlywheelRenderer extends KineticTileEntityRenderer { private void renderFlywheel(KineticTileEntity te, MatrixStack ms, int light, BlockState blockState, float angle, IVertexBuilder vb) { BlockState referenceState = blockState.rotate(Rotation.CLOCKWISE_90); - Direction facing = referenceState.get(BlockStateProperties.HORIZONTAL_FACING); + Direction facing = referenceState.getValue(BlockStateProperties.HORIZONTAL_FACING); SuperByteBuffer wheel = PartialBufferer.getFacing(AllBlockPartials.FLYWHEEL, referenceState, facing); - kineticRotationTransform(wheel, te, blockState.get(HORIZONTAL_FACING) + kineticRotationTransform(wheel, te, blockState.getValue(HORIZONTAL_FACING) .getAxis(), AngleHelper.rad(angle), light); wheel.renderInto(ms, vb); } @@ -87,7 +87,7 @@ public class FlywheelRenderer extends KineticTileEntityRenderer { @Override protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { return PartialBufferer.getFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), te.getBlockState() - .get(BlockStateProperties.HORIZONTAL_FACING) + .getValue(BlockStateProperties.HORIZONTAL_FACING) .getOpposite()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java index b27ccb01c..ece43296c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java @@ -40,7 +40,7 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity { @Override public float getGeneratedSpeed() { - return convertToDirection(generatedSpeed, getBlockState().get(FlywheelBlock.HORIZONTAL_FACING)); + return convertToDirection(generatedSpeed, getBlockState().getValue(FlywheelBlock.HORIZONTAL_FACING)); } @Override @@ -50,7 +50,7 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity { @Override public AxisAlignedBB makeRenderBoundingBox() { - return super.makeRenderBoundingBox().grow(2); + return super.makeRenderBoundingBox().inflate(2); } @Override @@ -76,7 +76,7 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity { public void tick() { super.tick(); - if (world.isRemote) { + if (level.isClientSide) { float targetSpeed = isVirtual() ? speed : getGeneratedSpeed(); visualSpeed.target(targetSpeed); visualSpeed.tick(); 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..483c3f0da 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; @@ -29,8 +29,8 @@ public abstract class EngineBlock extends HorizontalBlock implements IWrenchable } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - return isValidPosition(state, worldIn, pos, state.get(HORIZONTAL_FACING)); + public boolean canSurvive(BlockState state, IWorldReader worldIn, BlockPos pos) { + return isValidPosition(state, worldIn, pos, state.getValue(FACING)); } @Override @@ -48,24 +48,24 @@ public abstract class EngineBlock extends HorizontalBlock implements IWrenchable @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - Direction facing = context.getFace(); - return getDefaultState().with(HORIZONTAL_FACING, - facing.getAxis().isVertical() ? context.getPlacementHorizontalFacing().getOpposite() : facing); + Direction facing = context.getClickedFace(); + return defaultBlockState().setValue(FACING, + facing.getAxis().isVertical() ? context.getHorizontalDirection().getOpposite() : facing); } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(HORIZONTAL_FACING)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(FACING)); } @Override public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; if (fromPos.equals(getBaseBlockPos(state, pos))) { - if (!isValidPosition(state, worldIn, pos)) { + if (!canSurvive(state, worldIn, pos)) { worldIn.destroyBlock(pos, true); return; } @@ -79,7 +79,7 @@ public abstract class EngineBlock extends HorizontalBlock implements IWrenchable for (Direction otherFacing : Iterate.horizontalDirections) { if (otherFacing == facing) continue; - BlockPos otherPos = baseBlockPos.offset(otherFacing); + BlockPos otherPos = baseBlockPos.relative(otherFacing); BlockState otherState = world.getBlockState(otherPos); if (otherState.getBlock() instanceof EngineBlock && getBaseBlockPos(otherState, otherPos).equals(baseBlockPos)) @@ -90,7 +90,7 @@ public abstract class EngineBlock extends HorizontalBlock implements IWrenchable } public static BlockPos getBaseBlockPos(BlockState state, BlockPos pos) { - return pos.offset(state.get(HORIZONTAL_FACING).getOpposite()); + return pos.relative(state.getValue(FACING).getOpposite()); } @Nullable 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..cb02e4da7 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,12 +1,12 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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; import net.minecraft.block.Block; import net.minecraft.state.properties.BlockStateProperties; @@ -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 @@ -27,14 +27,14 @@ public class EngineInstance extends TileEntityInstance { EngineBlock engineBlock = (EngineBlock) block; PartialModel frame = engineBlock.getFrameModel(); - Direction facing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); + Direction facing = blockState.getValue(BlockStateProperties.HORIZONTAL_FACING); this.frame = getTransformMaterial().getModel(frame, blockState).createInstance(); float angle = AngleHelper.rad(AngleHelper.horizontalAngle(facing)); MatrixStack ms = new MatrixStack(); - MatrixStacker msr = MatrixStacker.of(ms); + MatrixTransformStack msr = MatrixTransformStack.of(ms); msr.translate(getInstancePosition()) .nudge(tile.hashCode()) 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..a91ba53d3 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,16 +1,15 @@ 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; import net.minecraft.block.Block; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction; @@ -24,22 +23,22 @@ 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.getLevel())) return; Block block = te.getBlockState() - .getBlock(); + .getBlock(); if (block instanceof EngineBlock) { EngineBlock engineBlock = (EngineBlock) block; PartialModel frame = engineBlock.getFrameModel(); if (frame != null) { Direction facing = te.getBlockState() - .get(EngineBlock.HORIZONTAL_FACING); + .getValue(EngineBlock.FACING); float angle = AngleHelper.rad(AngleHelper.horizontalAngle(facing)); PartialBufferer.get(frame, te.getBlockState()) .rotateCentered(Direction.UP, angle) .translate(0, 0, -1) - .light(WorldRenderer.getLightmapCoordinates(te.getWorld(), te.getBlockState(), te.getPos())) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); } } } 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..43eb4ee7c 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; @@ -37,7 +37,7 @@ public class EngineTileEntity extends SmartTileEntity implements IInstanceRender @OnlyIn(Dist.CLIENT) public AxisAlignedBB getRenderBoundingBox() { if (cachedBoundingBox == null) { - cachedBoundingBox = super.getRenderBoundingBox().grow(1.5f); + cachedBoundingBox = super.getRenderBoundingBox().inflate(1.5f); } return cachedBoundingBox; } @@ -45,7 +45,7 @@ public class EngineTileEntity extends SmartTileEntity implements IInstanceRender @Override public void lazyTick() { super.lazyTick(); - if (world.isRemote) + if (level.isClientSide) return; if (poweredWheel != null && poweredWheel.isRemoved()) poweredWheel = null; @@ -54,23 +54,23 @@ public class EngineTileEntity extends SmartTileEntity implements IInstanceRender } public void attachWheel() { - Direction engineFacing = getBlockState().get(EngineBlock.HORIZONTAL_FACING); - BlockPos wheelPos = pos.offset(engineFacing, 2); - BlockState wheelState = world.getBlockState(wheelPos); + Direction engineFacing = getBlockState().getValue(EngineBlock.FACING); + BlockPos wheelPos = worldPosition.relative(engineFacing, 2); + BlockState wheelState = level.getBlockState(wheelPos); if (!AllBlocks.FLYWHEEL.has(wheelState)) return; - Direction wheelFacing = wheelState.get(FlywheelBlock.HORIZONTAL_FACING); - if (wheelFacing.getAxis() != engineFacing.rotateY().getAxis()) + Direction wheelFacing = wheelState.getValue(FlywheelBlock.HORIZONTAL_FACING); + if (wheelFacing.getAxis() != engineFacing.getClockWise().getAxis()) return; if (FlywheelBlock.isConnected(wheelState) && FlywheelBlock.getConnection(wheelState) != engineFacing.getOpposite()) return; - TileEntity te = world.getTileEntity(wheelPos); + TileEntity te = level.getBlockEntity(wheelPos); if (te.isRemoved()) return; if (te instanceof FlywheelTileEntity) { if (!FlywheelBlock.isConnected(wheelState)) - FlywheelBlock.setConnection(world, te.getPos(), te.getBlockState(), engineFacing.getOpposite()); + FlywheelBlock.setConnection(level, te.getBlockPos(), te.getBlockState(), engineFacing.getOpposite()); poweredWheel = (FlywheelTileEntity) te; refreshWheelSpeed(); } @@ -80,14 +80,14 @@ public class EngineTileEntity extends SmartTileEntity implements IInstanceRender if (poweredWheel == null || poweredWheel.isRemoved()) return; poweredWheel.setRotation(0, 0); - FlywheelBlock.setConnection(world, poweredWheel.getPos(), poweredWheel.getBlockState(), null); + FlywheelBlock.setConnection(level, poweredWheel.getBlockPos(), poweredWheel.getBlockState(), null); poweredWheel = null; } @Override - public void remove() { + public void setRemoved() { detachWheel(); - super.remove(); + super.setRemoved(); } protected void refreshWheelSpeed() { @@ -96,4 +96,5 @@ public class EngineTileEntity extends SmartTileEntity implements IInstanceRender poweredWheel.setRotation(appliedSpeed, appliedCapacity); } + } 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..6c034f883 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; @@ -38,7 +38,7 @@ public class FurnaceEngineBlock extends EngineBlock implements ITE, Float> blockModifiers = new HashMap<>(); + + public void register(IRegistryDelegate block, float modifier) { + this.blockModifiers.put(block, modifier); + } + + public float getModifierOrDefault(BlockState state, float defaultValue) { + return blockModifiers.getOrDefault(state.getBlock().delegate, defaultValue); + } + + public float getModifier(BlockState state) { + return getModifierOrDefault(state, 1f); + } + + public static void register() { + INSTANCE.register(Blocks.BLAST_FURNACE.delegate, 2f); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineTileEntity.java index 947e03081..03f22efe0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineTileEntity.java @@ -1,7 +1,7 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.block.BlockStressValues; import net.minecraft.block.AbstractFurnaceBlock; import net.minecraft.block.BlockState; @@ -21,15 +21,15 @@ public class FurnaceEngineTileEntity extends EngineTileEntity { } public void updateFurnace() { - BlockState state = world.getBlockState(EngineBlock.getBaseBlockPos(getBlockState(), pos)); + BlockState state = level.getBlockState(EngineBlock.getBaseBlockPos(getBlockState(), worldPosition)); if (!(state.getBlock() instanceof AbstractFurnaceBlock)) return; - float modifier = state.getBlock() == Blocks.BLAST_FURNACE ? 2 : 1; - boolean active = state.contains(AbstractFurnaceBlock.LIT) && state.get(AbstractFurnaceBlock.LIT); + float modifier = FurnaceEngineModifiers.INSTANCE.getModifier(state); + boolean active = state.hasProperty(AbstractFurnaceBlock.LIT) && state.getValue(AbstractFurnaceBlock.LIT); float speed = active ? 16 * modifier : 0; float capacity = - (float) (active ? AllConfigs.SERVER.kinetics.stressValues.getCapacityOf(AllBlocks.FURNACE_ENGINE.get()) + (float) (active ? BlockStressValues.getCapacity(AllBlocks.FURNACE_ENGINE.get()) : 0); appliedCapacity = capacity; 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..afd79ba80 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.material.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/MillingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillingRecipe.java index 0bc0460c7..123fc1133 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillingRecipe.java @@ -21,7 +21,7 @@ public class MillingRecipe extends AbstractCrushingRecipe { if (inv.isEmpty()) return false; return ingredients.get(0) - .test(inv.getStackInSlot(0)); + .test(inv.getItem(0)); } @Override 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..e880796ce 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 @@ -54,11 +54,11 @@ public class MillstoneBlock extends KineticBlock implements ITE { @@ -80,7 +80,7 @@ public class MillstoneBlock extends KineticBlock implements ITE { ItemHelper.dropContents(worldIn, pos, te.inputInv); ItemHelper.dropContents(worldIn, pos, te.outputInv); }); - worldIn.removeTileEntity(pos); + worldIn.removeBlockEntity(pos); } } @@ -142,9 +139,9 @@ public class MillstoneBlock extends KineticBlock implements ITE getTileEntityClass() { return MillstoneTileEntity.class; } - + @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(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/millstone/MillstoneTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneTileEntity.java index d9c9fe512..0466512df 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneTileEntity.java @@ -5,6 +5,8 @@ import java.util.Optional; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.foundation.sound.SoundScapes; +import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.utility.VecHelper; @@ -19,6 +21,8 @@ import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; +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.IItemHandler; @@ -41,13 +45,28 @@ public class MillstoneTileEntity extends KineticTileEntity { outputInv = new ItemStackHandler(9); capability = LazyOptional.of(MillstoneInventoryHandler::new); } - + @Override public void addBehaviours(List behaviours) { behaviours.add(new DirectBeltInputBehaviour(this)); super.addBehaviours(behaviours); } + @Override + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + super.tickAudio(); + + if (getSpeed() == 0) + return; + if (inputInv.getStackInSlot(0) + .isEmpty()) + return; + + float pitch = MathHelper.clamp((Math.abs(getSpeed()) / 256f) + .45f, .85f, 1f); + SoundScapes.play(AmbienceGroup.MILLING, worldPosition, pitch); + } + @Override public void tick() { super.tick(); @@ -62,7 +81,7 @@ public class MillstoneTileEntity extends KineticTileEntity { if (timer > 0) { timer -= getProcessingSpeed(); - if (world.isRemote) { + if (level.isClientSide) { spawnParticles(); return; } @@ -76,8 +95,8 @@ public class MillstoneTileEntity extends KineticTileEntity { return; RecipeWrapper inventoryIn = new RecipeWrapper(inputInv); - if (lastRecipe == null || !lastRecipe.matches(inventoryIn, world)) { - Optional recipe = AllRecipeTypes.MILLING.find(inventoryIn, world); + if (lastRecipe == null || !lastRecipe.matches(inventoryIn, level)) { + Optional recipe = AllRecipeTypes.MILLING.find(inventoryIn, level); if (!recipe.isPresent()) { timer = 100; sendData(); @@ -94,16 +113,16 @@ public class MillstoneTileEntity extends KineticTileEntity { } @Override - public void remove() { - super.remove(); + public void setRemoved() { + super.setRemoved(); capability.invalidate(); } - + private void process() { RecipeWrapper inventoryIn = new RecipeWrapper(inputInv); - if (lastRecipe == null || !lastRecipe.matches(inventoryIn, world)) { - Optional recipe = AllRecipeTypes.MILLING.find(inventoryIn, world); + if (lastRecipe == null || !lastRecipe.matches(inventoryIn, level)) { + Optional recipe = AllRecipeTypes.MILLING.find(inventoryIn, level); if (!recipe.isPresent()) return; lastRecipe = recipe.get(); @@ -115,7 +134,7 @@ public class MillstoneTileEntity extends KineticTileEntity { lastRecipe.rollResults() .forEach(stack -> ItemHandlerHelper.insertItemStacked(outputInv, stack, false)); sendData(); - markDirty(); + setChanged(); } public void spawnParticles() { @@ -124,14 +143,14 @@ public class MillstoneTileEntity extends KineticTileEntity { return; ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot); - float angle = world.rand.nextFloat() * 360; + float angle = level.random.nextFloat() * 360; Vector3d offset = new Vector3d(0, 0, 0.5f); offset = VecHelper.rotate(offset, angle, Axis.Y); Vector3d target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y); - Vector3d center = offset.add(VecHelper.getCenterOf(pos)); - target = VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f); - world.addParticle(data, center.x, center.y, center.z, target.x, target.y, target.z); + Vector3d center = offset.add(VecHelper.getCenterOf(worldPosition)); + target = VecHelper.offsetRandomly(target.subtract(offset), level.random, 1 / 128f); + level.addParticle(data, center.x, center.y, center.z, target.x, target.y, target.z); } @Override @@ -166,9 +185,9 @@ public class MillstoneTileEntity extends KineticTileEntity { tester.setStackInSlot(0, stack); RecipeWrapper inventoryIn = new RecipeWrapper(tester); - if (lastRecipe != null && lastRecipe.matches(inventoryIn, world)) + if (lastRecipe != null && lastRecipe.matches(inventoryIn, level)) return true; - return AllRecipeTypes.MILLING.find(inventoryIn, world) + return AllRecipeTypes.MILLING.find(inventoryIn, level) .isPresent(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/BasinOperatorBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/BasinOperatorBlockItem.java deleted file mode 100644 index e6831212e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/BasinOperatorBlockItem.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.simibubi.create.content.contraptions.components.mixer; - -import com.simibubi.create.AllBlocks; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.item.BlockItem; -import net.minecraft.item.BlockItemUseContext; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; - -public class BasinOperatorBlockItem extends BlockItem { - - public BasinOperatorBlockItem(Block block, Properties builder) { - super(block, builder); - } - - @Override - public ActionResultType tryPlace(BlockItemUseContext context) { - BlockPos placedOnPos = context.getPos() - .offset(context.getFace() - .getOpposite()); - BlockState placedOnState = context.getWorld() - .getBlockState(placedOnPos); - if (AllBlocks.BASIN.has(placedOnState) || AllBlocks.BELT.has(placedOnState) - || AllBlocks.DEPOT.has(placedOnState) || AllBlocks.WEIGHTED_EJECTOR.has(placedOnState)) { - if (context.getWorld() - .getBlockState(placedOnPos.up(2)) - .getMaterial() - .isReplaceable()) - context = BlockItemUseContext.func_221536_a(context, placedOnPos.up(2), Direction.UP); - else - return ActionResultType.FAIL; - } - - return super.tryPlace(context); - } - -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerBlock.java index 1d20436b9..5e618fef9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerBlock.java @@ -31,8 +31,8 @@ public class MechanicalMixerBlock extends KineticBlock implements ITE bte.setAreFluidsMoving(running && runningTicks <= 20)); } @@ -116,15 +117,16 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { if (runningTicks >= 40) { running = false; runningTicks = 0; + basinChecker.scheduleUpdate(); return; } float speed = Math.abs(getSpeed()); - if (running && world != null) { - if (world.isRemote && runningTicks == 20) + if (running && level != null) { + if (level.isClientSide && runningTicks == 20) renderParticles(); - if ((!world.isRemote || isVirtual()) && runningTicks == 20) { + if ((!level.isClientSide || isVirtual()) && runningTicks == 20) { if (processingTicks < 0) { processingTicks = MathHelper.clamp((MathHelper.log2((int) (512 / speed))) * 15 + 1, 1, 512); @@ -136,7 +138,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { .isEmpty() || !tanks.getSecond() .isEmpty()) - world.playSound(null, pos, SoundEvents.BLOCK_BUBBLE_COLUMN_WHIRLPOOL_AMBIENT, + level.playSound(null, worldPosition, SoundEvents.BUBBLE_COLUMN_WHIRLPOOL_AMBIENT, SoundCategory.BLOCKS, .75f, speed < 65 ? .75f : 1.5f); } @@ -158,13 +160,13 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { public void renderParticles() { Optional basin = getBasin(); - if (!basin.isPresent() || world == null) + if (!basin.isPresent() || level == null) return; for (SmartInventory inv : basin.get() .getInvs()) { for (int slot = 0; slot < inv.getSlots(); slot++) { - ItemStack stackInSlot = inv.getStackInSlot(slot); + ItemStack stackInSlot = inv.getItem(slot); if (stackInSlot.isEmpty()) continue; ItemParticleData data = new ItemParticleData(ParticleTypes.ITEM, stackInSlot); @@ -185,14 +187,14 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { } protected void spillParticle(IParticleData data) { - float angle = world.rand.nextFloat() * 360; + float angle = level.random.nextFloat() * 360; Vector3d offset = new Vector3d(0, 0, 0.25f); offset = VecHelper.rotate(offset, angle, Axis.Y); Vector3d target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y) .add(0, .25f, 0); - Vector3d center = offset.add(VecHelper.getCenterOf(pos)); - target = VecHelper.offsetRandomly(target.subtract(offset), world.rand, 1 / 128f); - world.addParticle(data, center.x, center.y - 1.75f, center.z, target.x, target.y, target.z); + Vector3d center = offset.add(VecHelper.getCenterOf(worldPosition)); + target = VecHelper.offsetRandomly(target.subtract(offset), level.random, 1 / 128f); + level.addParticle(data, center.x, center.y - 1.75f, center.z, target.x, target.y, target.z); } @Override @@ -226,10 +228,10 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { @Override protected boolean matchStaticFilters(IRecipe r) { - return ((r.getSerializer() == IRecipeSerializer.CRAFTING_SHAPELESS + return ((r.getSerializer() == IRecipeSerializer.SHAPELESS_RECIPE && AllConfigs.SERVER.recipes.allowShapelessInMixer.get() && r.getIngredients() - .size() > 1) - || r.getType() == AllRecipeTypes.MIXING.type); + .size() > 1 + && !MechanicalPressTileEntity.canCompress(r)) || r.getType() == AllRecipeTypes.MIXING.getType()); } @Override @@ -280,7 +282,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { if (slow && AnimationTickHolder.getTicks() % 2 == 0) return; if (runningTicks == 20) - AllSoundEvents.MIXING.playAt(world, pos, .75f, 1, true); + AllSoundEvents.MIXING.playAt(level, worldPosition, .75f, 1, true); } } 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..b2fe1b653 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.material.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; @@ -66,7 +66,7 @@ public class MixerInstance extends ShaftlessCogInstance implements IDynamicInsta public void updateLight() { super.updateLight(); - relight(pos.down(), mixerHead); + relight(pos.below(), mixerHead); relight(pos, mixerPole); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorBlock.java index 7239a505e..0d137fe2e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorBlock.java @@ -24,7 +24,7 @@ public class CreativeMotorBlock extends DirectionalKineticBlock { @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.MOTOR_BLOCK.get(state.get(FACING)); + return AllShapes.MOTOR_BLOCK.get(state.getValue(FACING)); } @Override @@ -36,21 +36,21 @@ public class CreativeMotorBlock extends DirectionalKineticBlock { public BlockState getStateForPlacement(BlockItemUseContext context) { Direction preferred = getPreferredFacing(context); if ((context.getPlayer() != null && context.getPlayer() - .isSneaking()) || preferred == null) + .isShiftKeyDown()) || preferred == null) return super.getStateForPlacement(context); - return getDefaultState().with(FACING, preferred); + return defaultBlockState().setValue(FACING, preferred); } // IRotate: @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face == state.get(FACING); + return face == state.getValue(FACING); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(FACING) + return state.getValue(FACING) .getAxis(); } @@ -60,7 +60,7 @@ public class CreativeMotorBlock extends DirectionalKineticBlock { } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorGenerator.java index a26c54d41..032783bb6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorGenerator.java @@ -14,20 +14,20 @@ public class CreativeMotorGenerator extends SpecialBlockStateGen { @Override protected int getXRotation(BlockState state) { - return state.get(CreativeMotorBlock.FACING) == Direction.DOWN ? 180 : 0; + return state.getValue(CreativeMotorBlock.FACING) == Direction.DOWN ? 180 : 0; } @Override protected int getYRotation(BlockState state) { - return state.get(CreativeMotorBlock.FACING) + return state.getValue(CreativeMotorBlock.FACING) .getAxis() - .isVertical() ? 0 : horizontalAngle(state.get(CreativeMotorBlock.FACING)); + .isVertical() ? 0 : horizontalAngle(state.getValue(CreativeMotorBlock.FACING)); } @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - return state.get(CreativeMotorBlock.FACING) + return state.getValue(CreativeMotorBlock.FACING) .getAxis() .isVertical() ? AssetLookup.partialBaseModel(ctx, prov, "vertical") : AssetLookup.partialBaseModel(ctx, prov); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorTileEntity.java index 1f0168b87..4509f6ff8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorTileEntity.java @@ -28,7 +28,7 @@ public class CreativeMotorTileEntity extends GeneratingKineticTileEntity { Integer max = AllConfigs.SERVER.kinetics.maxMotorSpeed.get(); CenteredSideValueBoxTransform slot = new CenteredSideValueBoxTransform( - (motor, side) -> motor.get(CreativeMotorBlock.FACING) == side.getOpposite()); + (motor, side) -> motor.getValue(CreativeMotorBlock.FACING) == side.getOpposite()); generatedSpeed = new ScrollValueBehaviour(Lang.translate("generic.speed"), this, slot); generatedSpeed.between(-max, max); @@ -51,7 +51,7 @@ public class CreativeMotorTileEntity extends GeneratingKineticTileEntity { public float getGeneratedSpeed() { if (!AllBlocks.CREATIVE_MOTOR.has(getBlockState())) return 0; - return convertToDirection(generatedSpeed.getValue(), getBlockState().get(CreativeMotorBlock.FACING)); + return convertToDirection(generatedSpeed.getValue(), getBlockState().getValue(CreativeMotorBlock.FACING)); } public static int step(StepContext context) { 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..1af77a41f 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,10 @@ 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.advancement.AllTriggers; 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 +63,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()); @@ -83,6 +84,7 @@ public class BeltPressingCallbacks { handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left)); } + AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, pressTe.getLevel(), pressTe.getBlockPos(), 4); pressTe.sendData(); return HOLD; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressBlock.java index 8de328a78..e05d44501 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressBlock.java @@ -33,8 +33,8 @@ public class MechanicalPressBlock extends HorizontalKineticBlock implements ITE< } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - return !AllBlocks.BASIN.has(worldIn.getBlockState(pos.down())); + public boolean canSurvive(BlockState state, IWorldReader worldIn, BlockPos pos) { + return !AllBlocks.BASIN.has(worldIn.getBlockState(pos.below())); } @Override @@ -46,19 +46,19 @@ public class MechanicalPressBlock extends HorizontalKineticBlock implements ITE< public BlockState getStateForPlacement(BlockItemUseContext context) { Direction prefferedSide = getPreferredHorizontalFacing(context); if (prefferedSide != null) - return getDefaultState().with(HORIZONTAL_FACING, prefferedSide); + return defaultBlockState().setValue(HORIZONTAL_FACING, prefferedSide); return super.getStateForPlacement(context); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(HORIZONTAL_FACING) + return state.getValue(HORIZONTAL_FACING) .getAxis(); } @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.get(HORIZONTAL_FACING) + return face.getAxis() == state.getValue(HORIZONTAL_FACING) .getAxis(); } @@ -68,7 +68,7 @@ public class MechanicalPressBlock extends HorizontalKineticBlock implements ITE< } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } 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..a310c7c1d 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,20 +2,18 @@ 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; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.util.math.BlockPos; public class MechanicalPressRenderer extends KineticTileEntityRenderer { @@ -24,7 +22,7 @@ public class MechanicalPressRenderer extends KineticTileEntityRenderer { } @Override - public boolean isGlobalRenderer(KineticTileEntity te) { + public boolean shouldRenderOffScreen(KineticTileEntity te) { return true; } @@ -33,17 +31,15 @@ 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.getLevel())) return; - BlockPos pos = te.getPos(); BlockState blockState = te.getBlockState(); - int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, pos); float renderedHeadOffset = ((MechanicalPressTileEntity) te).getRenderedHeadOffset(partialTicks); - SuperByteBuffer headRender = PartialBufferer.getFacing(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState, blockState.get(HORIZONTAL_FACING)); + SuperByteBuffer headRender = PartialBufferer.getFacing(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState, blockState.getValue(HORIZONTAL_FACING)); headRender.translate(0, -renderedHeadOffset, 0) - .light(packedLightmapCoords) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); } @Override 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..059067cfd 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 @@ -4,13 +4,15 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; 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; @@ -30,12 +32,14 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.ICraftingRecipe; import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.item.crafting.Ingredient; import net.minecraft.nbt.CompoundNBT; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; @@ -85,7 +89,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { if (clientPacket) { NBTHelper.iterateCompoundList(compound.getList("ParticleItems", NBT.TAG_COMPOUND), - c -> pressedItems.add(ItemStack.read(c))); + c -> pressedItems.add(ItemStack.of(c))); spawnParticles(); } } @@ -106,8 +110,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { @Override public AxisAlignedBB makeRenderBoundingBox() { - return new AxisAlignedBB(pos).expand(0, -1.5, 0) - .expand(0, 1, 0); + return new AxisAlignedBB(worldPosition).expandTowards(0, -1.5, 0) + .expandTowards(0, 1, 0); } public float getRenderedHeadOffset(float partialTicks) { @@ -141,8 +145,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { public void tick() { super.tick(); - if (!running || world == null) { - if (hasWorld() && !world.isRemote) { + if (!running || level == null) { + if (hasLevel() && !level.isClientSide) { if (getSpeed() == 0) return; @@ -150,13 +154,13 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { entityScanCooldown--; if (entityScanCooldown <= 0) { entityScanCooldown = ENTITY_SCAN; - if (TileEntityBehaviour.get(world, pos.down(2), TransportedItemStackHandlerBehaviour.TYPE) != null) + if (TileEntityBehaviour.get(level, worldPosition.below(2), TransportedItemStackHandlerBehaviour.TYPE) != null) return; - if (AllBlocks.BASIN.has(world.getBlockState(pos.down(2)))) + if (AllBlocks.BASIN.has(level.getBlockState(worldPosition.below(2)))) return; - for (ItemEntity itemEntity : world.getEntitiesWithinAABB(ItemEntity.class, - new AxisAlignedBB(pos.down()).shrink(.125f))) { + for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, + new AxisAlignedBB(worldPosition.below()).deflate(.125f))) { if (!itemEntity.isAlive() || !itemEntity.isOnGround()) continue; ItemStack stack = itemEntity.getItem(); @@ -172,7 +176,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { return; } - if (world.isRemote && runningTicks == -CYCLE / 2) { + if (level.isClientSide && runningTicks == -CYCLE / 2) { prevRunningTicks = CYCLE / 2; return; } @@ -183,21 +187,25 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { if (onBasin()) applyCompactingOnBasin(); - if (world.getBlockState(pos.down(2)).getSoundType() == SoundType.CLOTH) - AllSoundEvents.MECHANICAL_PRESS_ACTIVATION_ON_BELT.playOnServer(world, pos); + if (level.getBlockState(worldPosition.below(2)).getSoundType() == SoundType.WOOL) + AllSoundEvents.MECHANICAL_PRESS_ACTIVATION_ON_BELT.playOnServer(level, worldPosition); else - AllSoundEvents.MECHANICAL_PRESS_ACTIVATION.playOnServer(world, pos, .5f, .75f + (Math.abs(getSpeed()) / 1024f)); - - if (!world.isRemote) + AllSoundEvents.MECHANICAL_PRESS_ACTIVATION.playOnServer(level, worldPosition, .5f, .75f + (Math.abs(getSpeed()) / 1024f)); + + if (!level.isClientSide) sendData(); } - if (!world.isRemote && runningTicks > CYCLE) { + if (!level.isClientSide && runningTicks > CYCLE) { finished = true; running = false; - if (onBasin() && matchBasinRecipe(currentRecipe)) + if (onBasin() && matchBasinRecipe(currentRecipe) + && getBasin().filter(BasinTileEntity::canContinueProcessing) + .isPresent()) startProcessingBasin(); + else + basinChecker.scheduleUpdate(); pressedItems.clear(); sendData(); @@ -209,13 +217,13 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { if (prevRunningTicks < CYCLE / 2 && runningTicks >= CYCLE / 2) { runningTicks = CYCLE / 2; // Pause the ticks until a packet is received - if (world.isRemote && !isVirtual()) + if (level.isClientSide && !isVirtual()) runningTicks = -(CYCLE / 2); } } protected void applyCompactingOnBasin() { - if (world.isRemote) + if (level.isClientSide) return; pressedItems.clear(); applyBasinRecipe(); @@ -224,7 +232,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { .getInputInventory(); if (basin.isPresent()) { for (int slot = 0; slot < inputs.getSlots(); slot++) { - ItemStack stackInSlot = inputs.getStackInSlot(slot); + ItemStack stackInSlot = inputs.getItem(slot); if (stackInSlot.isEmpty()) continue; pressedItems.add(stackInSlot); @@ -234,12 +242,12 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { } protected void applyPressingInWorld() { - AxisAlignedBB bb = new AxisAlignedBB(pos.down(1)); + AxisAlignedBB bb = new AxisAlignedBB(worldPosition.below(1)); boolean bulk = canProcessInBulk(); pressedItems.clear(); - if (world.isRemote) + if (level.isClientSide) return; - for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) { + for (Entity entity : level.getEntities(null, bb)) { if (!(entity instanceof ItemEntity)) continue; if (!entity.isAlive() || !entity.isOnGround()) @@ -258,15 +266,15 @@ 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); - created.setDefaultPickupDelay(); - created.setMotion(VecHelper.offsetRandomly(Vector3d.ZERO, Create.random, .05f)); - world.addEntity(created); + new ItemEntity(level, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), result); + created.setDefaultPickUpDelay(); + created.setDeltaMovement(VecHelper.offsetRandomly(Vector3d.ZERO, Create.RANDOM, .05f)); + level.addFreshEntity(created); } item.shrink(1); } - AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, world, pos, 4); + AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, level, worldPosition, 4); entityScanCooldown = 0; if (!bulk) @@ -289,35 +297,35 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { return; if (mode == Mode.BASIN) - pressedItems.forEach(stack -> makeCompactingParticleEffect(VecHelper.getCenterOf(pos.down(2)), stack)); + pressedItems.forEach(stack -> makeCompactingParticleEffect(VecHelper.getCenterOf(worldPosition.below(2)), stack)); if (mode == Mode.BELT) - pressedItems.forEach(stack -> makePressingParticleEffect(VecHelper.getCenterOf(pos.down(2)) + pressedItems.forEach(stack -> makePressingParticleEffect(VecHelper.getCenterOf(worldPosition.below(2)) .add(0, 8 / 16f, 0), stack)); if (mode == Mode.WORLD) - pressedItems.forEach(stack -> makePressingParticleEffect(VecHelper.getCenterOf(pos.down(1)) + pressedItems.forEach(stack -> makePressingParticleEffect(VecHelper.getCenterOf(worldPosition.below(1)) .add(0, -1 / 4f, 0), stack)); pressedItems.clear(); } public void makePressingParticleEffect(Vector3d pos, ItemStack stack) { - if (world == null || !world.isRemote) + if (level == null || !level.isClientSide) return; for (int i = 0; i < 20; i++) { - Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, world.rand, .125f) - .mul(1, 0, 1); - world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), pos.x, pos.y - .25f, pos.z, motion.x, + Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, level.random, .125f) + .multiply(1, 0, 1); + level.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), pos.x, pos.y - .25f, pos.z, motion.x, motion.y + .125f, motion.z); } } public void makeCompactingParticleEffect(Vector3d pos, ItemStack stack) { - if (world == null || !world.isRemote) + if (level == null || !level.isClientSide) return; for (int i = 0; i < 20; i++) { - Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, world.rand, .175f) - .mul(1, 0, 1); - world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), pos.x, pos.y, pos.z, motion.x, + Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, level.random, .175f) + .multiply(1, 0, 1); + level.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), pos.x, pos.y, pos.z, motion.x, motion.y + .25f, motion.z); } } @@ -325,11 +333,28 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { private static final RecipeWrapper pressingInv = new RecipeWrapper(new ItemStackHandler(1)); public Optional getRecipe(ItemStack item) { - pressingInv.setInventorySlotContents(0, item); - return AllRecipeTypes.PRESSING.find(pressingInv, world); + Optional assemblyRecipe = + SequencedAssemblyRecipe.getRecipe(level, item, AllRecipeTypes.PRESSING.getType(), PressingRecipe.class); + if (assemblyRecipe.isPresent()) + return assemblyRecipe; + + pressingInv.setItem(0, item); + return AllRecipeTypes.PRESSING.find(pressingInv, level); } - public static boolean canCompress(NonNullList ingredients) { + private static final List RECIPE_DENY_LIST = + ImmutableList.of(new ResourceLocation("occultism", "spirit_trade")); + + public static boolean canCompress(IRecipe recipe) { + NonNullList ingredients = recipe.getIngredients(); + if (!(recipe instanceof ICraftingRecipe)) + return false; + + IRecipeSerializer serializer = recipe.getSerializer(); + for (ResourceLocation denied : RECIPE_DENY_LIST) + if (serializer != null && denied.equals(serializer.getRegistryName())) + return false; + return AllConfigs.SERVER.recipes.allowShapedSquareInPress.get() && (ingredients.size() == 4 || ingredients.size() == 9) && ItemHelper.condenseIngredients(ingredients) .size() == 1; @@ -337,8 +362,8 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { @Override protected boolean matchStaticFilters(IRecipe recipe) { - return (recipe instanceof ICraftingRecipe && canCompress(recipe.getIngredients())) - || recipe.getType() == AllRecipeTypes.COMPACTING.type; + return (recipe instanceof ICraftingRecipe && canCompress(recipe)) + || recipe.getType() == AllRecipeTypes.COMPACTING.getType(); } @Override 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..500295183 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,11 @@ package com.simibubi.create.content.contraptions.components.press; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +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,15 +17,16 @@ 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; - pressHead = dispatcher.getOrientedMaterial() + pressHead = dispatcher.defaultSolid() + .material(Materials.ORIENTED) .getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState) .createInstance(); - Quaternion q = Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(blockState.get(MechanicalPressBlock.HORIZONTAL_FACING))); + Quaternion q = Vector3f.YP.rotationDegrees(AngleHelper.horizontalAngle(blockState.getValue(MechanicalPressBlock.HORIZONTAL_FACING))); pressHead.setRotation(q); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressingRecipe.java index 481acc8e0..f68c4abeb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressingRecipe.java @@ -1,16 +1,29 @@ package com.simibubi.create.content.contraptions.components.press; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + import javax.annotation.ParametersAreNonnullByDefault; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; +import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.foundation.utility.Lang; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.text.ITextComponent; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.wrapper.RecipeWrapper; @ParametersAreNonnullByDefault -public class PressingRecipe extends ProcessingRecipe { +public class PressingRecipe extends ProcessingRecipe implements IAssemblyRecipe { public PressingRecipe(ProcessingRecipeParams params) { super(AllRecipeTypes.PRESSING, params); @@ -21,16 +34,36 @@ public class PressingRecipe extends ProcessingRecipe { if (inv.isEmpty()) return false; return ingredients.get(0) - .test(inv.getStackInSlot(0)); + .test(inv.getItem(0)); } @Override protected int getMaxInputCount() { return 1; } - + @Override protected int getMaxOutputCount() { return 2; } + + @Override + public void addAssemblyIngredients(List list) {} + + @Override + @OnlyIn(Dist.CLIENT) + public ITextComponent getDescriptionForAssembly() { + return Lang.translate("recipe.assembly.pressing"); + } + + @Override + public void addRequiredMachines(Set list) { + list.add(AllBlocks.MECHANICAL_PRESS.get()); + } + + @Override + public Supplier> getJEISubCategory() { + return () -> SequencedAssemblySubCategory.AssemblyPressing::new; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/CuttingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/CuttingRecipe.java index bb76d1cab..0933bec29 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/CuttingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/CuttingRecipe.java @@ -1,16 +1,29 @@ package com.simibubi.create.content.contraptions.components.saw; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + import javax.annotation.ParametersAreNonnullByDefault; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; +import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.foundation.utility.Lang; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.text.ITextComponent; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.wrapper.RecipeWrapper; @ParametersAreNonnullByDefault -public class CuttingRecipe extends ProcessingRecipe { +public class CuttingRecipe extends ProcessingRecipe implements IAssemblyRecipe { public CuttingRecipe(ProcessingRecipeParams params) { super(AllRecipeTypes.CUTTING, params); @@ -21,9 +34,9 @@ public class CuttingRecipe extends ProcessingRecipe { if (inv.isEmpty()) return false; return ingredients.get(0) - .test(inv.getStackInSlot(0)); + .test(inv.getItem(0)); } - + @Override protected int getMaxInputCount() { return 1; @@ -34,4 +47,23 @@ public class CuttingRecipe extends ProcessingRecipe { return 4; } + @Override + public void addAssemblyIngredients(List list) {} + + @Override + @OnlyIn(Dist.CLIENT) + public ITextComponent getDescriptionForAssembly() { + return Lang.translate("recipe.assembly.cutting"); + } + + @Override + public void addRequiredMachines(Set list) { + list.add(AllBlocks.MECHANICAL_SAW.get()); + } + + @Override + public Supplier> getJEISubCategory() { + return () -> SequencedAssemblySubCategory.AssemblyCutting::new; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawBlock.java index a4458acd7..cebba49a6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawBlock.java @@ -33,7 +33,7 @@ import net.minecraft.world.World; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class SawBlock extends DirectionalAxisKineticBlock implements ITE { - public static DamageSource damageSourceSaw = new DamageSource("create.mechanical_saw").setDamageBypassesArmor(); + public static DamageSource damageSourceSaw = new DamageSource("create.mechanical_saw").bypassArmor(); public SawBlock(Properties properties) { super(properties); @@ -42,10 +42,10 @@ public class SawBlock extends DirectionalAxisKineticBlock implements ITE { if (te.getSpeed() == 0) return; - entityIn.attackEntityFrom(damageSourceSaw, (float) DrillBlock.getDamage(te.getSpeed())); + entityIn.hurt(damageSourceSaw, (float) DrillBlock.getDamage(te.getSpeed())); }); } @Override - public void onLanded(IBlockReader worldIn, Entity entityIn) { - super.onLanded(worldIn, entityIn); + public void updateEntityAfterFallOn(IBlockReader worldIn, Entity entityIn) { + super.updateEntityAfterFallOn(worldIn, entityIn); if (!(entityIn instanceof ItemEntity)) return; - if (entityIn.world.isRemote) + if (entityIn.level.isClientSide) return; - BlockPos pos = entityIn.getBlockPos(); - withTileEntityDo(entityIn.world, pos, te -> { + BlockPos pos = entityIn.blockPosition(); + withTileEntityDo(entityIn.level, pos, te -> { if (te.getSpeed() == 0) return; te.insertItem((ItemEntity) entityIn); @@ -88,33 +88,33 @@ public class SawBlock extends DirectionalAxisKineticBlock implements ITE ItemHelper.dropContents(worldIn, pos, te.inventory)); TileEntityBehaviour.destroy(worldIn, pos, FilteringBehaviour.TYPE); - worldIn.removeTileEntity(pos); + worldIn.removeBlockEntity(pos); } @Override @@ -123,7 +123,7 @@ public class SawBlock extends DirectionalAxisKineticBlock implements ITE ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { String path = "block/" + ctx.getName() + "/"; - String orientation = state.get(SawBlock.FACING) + String orientation = state.getValue(SawBlock.FACING) .getAxis() .isVertical() ? "vertical" : "horizontal"; 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..59fcc7589 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.material.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,15 +15,15 @@ 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() { - if (blockState.get(FACING).getAxis().isHorizontal()) { - BlockState referenceState = blockState.rotate(tile.getWorld(), tile.getPos(), Rotation.CLOCKWISE_180); - Direction facing = referenceState.get(FACING); + protected Instancer getModel() { + if (blockState.getValue(FACING).getAxis().isHorizontal()) { + BlockState referenceState = blockState.rotate(tile.getLevel(), tile.getBlockPos(), Rotation.CLOCKWISE_180); + Direction facing = referenceState.getValue(FACING); return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, referenceState, facing); } else { return getRotatingMaterial().getModel(shaft()); 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..4f52cd5d8 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.jozufozu.flywheel.util.transform.MatrixTransformStack; 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,18 @@ 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.getLevel())) + 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) { @@ -77,38 +79,43 @@ public class SawRenderer extends SafeTileEntityRenderer { partial = AllBlockPartials.SAW_BLADE_VERTICAL_INACTIVE; } - if (!blockState.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE)) - MatrixStacker.of(ms) - .centre() - .rotateY(90) - .unCentre(); + if (!blockState.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE)) + 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.cutoutMipped())); } protected void renderShaft(SawTileEntity te, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { KineticTileEntityRenderer.renderRotatingBuffer(te, getRotatedModel(te), ms, - buffer.getBuffer(RenderType.getSolid()), light); + buffer.getBuffer(RenderType.solid()), light); } protected void renderItems(SawTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { boolean processingMode = te.getBlockState() - .get(SawBlock.FACING) == Direction.UP; + .getValue(SawBlock.FACING) == Direction.UP; if (processingMode && !te.inventory.isEmpty()) { boolean alongZ = !te.getBlockState() - .get(SawBlock.AXIS_ALONG_FIRST_COORDINATE); - ms.push(); + .getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); + ms.pushPose(); boolean moving = te.inventory.recipeDuration != 0; float offset = moving ? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration : 0; float processingSpeed = MathHelper.clamp(Math.abs(te.getSpeed()) / 32, 1, 128); - if (moving) - offset = MathHelper.clamp(offset + ((-partialTicks + .5f) * processingSpeed) / te.inventory.recipeDuration, 0, 1); + if (moving) { + offset = MathHelper + .clamp(offset + ((-partialTicks + .5f) * processingSpeed) / te.inventory.recipeDuration, 0.125f, 1f); + if (!te.inventory.appliedRecipe) + offset += 1; + offset /= 2; + } if (te.getSpeed() == 0) offset = .5f; @@ -122,47 +129,48 @@ public class SawRenderer extends SafeTileEntityRenderer { ItemRenderer itemRenderer = Minecraft.getInstance() .getItemRenderer(); - IBakedModel modelWithOverrides = itemRenderer.getItemModelWithOverrides(stack, te.getWorld(), null); + IBakedModel modelWithOverrides = itemRenderer.getModel(stack, te.getLevel(), null); boolean blockItem = modelWithOverrides.isGui3d(); ms.translate(alongZ ? offset : .5, blockItem ? .925f : 13f / 16f, alongZ ? .5 : offset); ms.scale(.5f, .5f, .5f); if (alongZ) - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(90)); - ms.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(90)); - itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.FIXED, light, overlay, ms, buffer); + ms.mulPose(Vector3f.YP.rotationDegrees(90)); + ms.mulPose(Vector3f.XP.rotationDegrees(90)); + itemRenderer.renderStatic(stack, ItemCameraTransforms.TransformType.FIXED, light, overlay, ms, buffer); break; } - ms.pop(); + ms.popPose(); } } protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { 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, - getRenderedBlockState(te)); + if (state.getValue(FACING) + .getAxis() + .isHorizontal()) + return PartialBufferer.getFacing(AllBlockPartials.SHAFT_HALF, + state.rotate(te.getLevel(), te.getBlockPos(), Rotation.CLOCKWISE_180)); + return CreateClient.BUFFER_CACHE.renderBlockIn(KineticTileEntityRenderer.KINETIC_TILE, + getRenderedBlockState(te)); } protected BlockState getRenderedBlockState(KineticTileEntity te) { 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); + Direction facing = state.getValue(SawBlock.FACING); - Vector3d facingVec = Vector3d.of(context.state.get(SawBlock.FACING) - .getDirectionVec()); + Vector3d facingVec = Vector3d.atLowerCornerOf(context.state.getValue(SawBlock.FACING) + .getNormal()); facingVec = context.rotation.apply(facingVec); - Direction closestToFacing = Direction.getFacingFromVector(facingVec.x, facingVec.y, facingVec.z); + Direction closestToFacing = Direction.getNearest(facingVec.x, facingVec.y, facingVec.z); boolean horizontal = closestToFacing.getAxis() .isHorizontal(); @@ -171,6 +179,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 +192,23 @@ public class SawRenderer extends SafeTileEntityRenderer { superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_VERTICAL_INACTIVE, state); } - for (MatrixStack m : matrixStacks) { - 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(); - } + MatrixStack m = matrices.getModel(); + m.pushPose(); + MatrixTransformStack.of(m) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)); + if (!SawBlock.isHorizontal(state)) + MatrixTransformStack.of(m) + .rotateZ(state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 0 : 90); + MatrixTransformStack.of(m) + .unCentre(); - superBuffer - .light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); + superBuffer.transform(m) + .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.cutoutMipped())); + + m.popPose(); } } 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 f7eca3cc1..768f795e3 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 @@ -3,21 +3,26 @@ package com.simibubi.create.content.contraptions.components.saw; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.Random; import java.util.function.Predicate; import java.util.stream.Collectors; import javax.annotation.ParametersAreNonnullByDefault; +import com.google.common.collect.ImmutableList; 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.itemAssembly.SequencedAssemblyRecipe; 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.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.TreeCutter; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.recipe.RecipeConditions; @@ -31,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; @@ -49,10 +56,13 @@ import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.LazyValue; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.AxisAlignedBB; 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; @@ -62,21 +72,26 @@ import net.minecraftforge.items.IItemHandler; @MethodsReturnNonnullByDefault public class SawTileEntity extends BlockBreakingKineticTileEntity { + private static final AxisAlignedBB RENDER_BOX = new AxisAlignedBB(0, 0, 0, 1, 1, 1); + private static final Object cuttingRecipesKey = new Object(); public static final LazyValue> woodcuttingRecipeType = - new LazyValue<>(() -> Registry.RECIPE_TYPE.getOrDefault(new ResourceLocation("druidcraft", "woodcutting"))); + new LazyValue<>(() -> Registry.RECIPE_TYPE.get(new ResourceLocation("druidcraft", "woodcutting"))); public ProcessingInventory inventory; private int recipeIndex; private final LazyOptional invProvider; private FilteringBehaviour filtering; + private ItemStack playEvent; + public SawTileEntity(TileEntityType type) { super(type); - inventory = new ProcessingInventory(this::start); + inventory = new ProcessingInventory(this::start).withSlotLimit(!AllConfigs.SERVER.recipes.bulkCutting.get()); inventory.remainingTime = -1; recipeIndex = 0; invProvider = LazyOptional.of(() -> inventory); + playEvent = ItemStack.EMPTY; } @Override @@ -92,6 +107,11 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { compound.put("Inventory", inventory.serializeNBT()); compound.putInt("RecipeIndex", recipeIndex); super.write(compound, clientPacket); + + if (!clientPacket || playEvent.isEmpty()) + return; + compound.put("PlayEvent", playEvent.serializeNBT()); + playEvent = ItemStack.EMPTY; } @Override @@ -99,6 +119,38 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { super.fromTag(state, compound, clientPacket); inventory.deserializeNBT(compound.getCompound("Inventory")); recipeIndex = compound.getInt("RecipeIndex"); + if (compound.contains("PlayEvent")) + playEvent = ItemStack.of(compound.getCompound("PlayEvent")); + } + + @Override + protected AxisAlignedBB makeRenderBoundingBox() { + return RENDER_BOX.inflate(.125f) + .move(worldPosition); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + super.tickAudio(); + if (getSpeed() == 0) + return; + + if (!playEvent.isEmpty()) { + boolean isWood = false; + Item item = playEvent.getItem(); + if (item instanceof BlockItem) { + Block block = ((BlockItem) item).getBlock(); + isWood = block.getSoundType(block.defaultBlockState(), level, worldPosition, null) == SoundType.WOOD; + } + spawnEventParticles(playEvent); + playEvent = ItemStack.EMPTY; + if (!isWood) + AllSoundEvents.SAW_ACTIVATE_STONE.playAt(level, worldPosition, 3, 1, true); + else + AllSoundEvents.SAW_ACTIVATE_WOOD.playAt(level, worldPosition, 3, 1, true); + return; + } } @Override @@ -117,24 +169,26 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { return; } - float processingSpeed = MathHelper.clamp(Math.abs(getSpeed()) / 32, 1, 128); + float processingSpeed = MathHelper.clamp(Math.abs(getSpeed()) / 24, 1, 128); inventory.remainingTime -= processingSpeed; if (inventory.remainingTime > 0) spawnParticles(inventory.getStackInSlot(0)); - if (world.isRemote && !isVirtual()) - return; - - if (inventory.remainingTime < 20 && !inventory.appliedRecipe) { + if (inventory.remainingTime < 5 && !inventory.appliedRecipe) { + if (level.isClientSide && !isVirtual()) + return; + playEvent = inventory.getStackInSlot(0); applyRecipe(); inventory.appliedRecipe = true; + inventory.recipeDuration = 20; + inventory.remainingTime = 20; sendData(); return; } Vector3d itemMovement = getItemMovementVec(); - Direction itemMovementFacing = Direction.getFacingFromVector(itemMovement.x, itemMovement.y, itemMovement.z); + Direction itemMovementFacing = Direction.getNearest(itemMovement.x, itemMovement.y, itemMovement.z); if (inventory.remainingTime > 0) return; inventory.remainingTime = 0; @@ -156,12 +210,14 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { } } - BlockPos nextPos = pos.add(itemMovement.x, itemMovement.y, itemMovement.z); - DirectBeltInputBehaviour behaviour = TileEntityBehaviour.get(world, nextPos, DirectBeltInputBehaviour.TYPE); + BlockPos nextPos = worldPosition.offset(itemMovement.x, itemMovement.y, itemMovement.z); + DirectBeltInputBehaviour behaviour = TileEntityBehaviour.get(level, nextPos, DirectBeltInputBehaviour.TYPE); if (behaviour != null) { boolean changed = false; if (!behaviour.canInsertFromSide(itemMovementFacing)) return; + if (level.isClientSide && !isVirtual()) + return; for (int slot = 0; slot < inventory.getSlots(); slot++) { ItemStack stack = inventory.getStackInSlot(slot); if (stack.isEmpty()) @@ -173,14 +229,14 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { changed = true; } if (changed) { - markDirty(); + setChanged(); sendData(); } return; } // Eject Items - Vector3d outPos = VecHelper.getCenterOf(pos) + Vector3d outPos = VecHelper.getCenterOf(worldPosition) .add(itemMovement.scale(.5f) .add(0, .5, 0)); Vector3d outMotion = itemMovement.scale(.0625) @@ -189,20 +245,20 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { ItemStack stack = inventory.getStackInSlot(slot); if (stack.isEmpty()) continue; - ItemEntity entityIn = new ItemEntity(world, outPos.x, outPos.y, outPos.z, stack); - entityIn.setMotion(outMotion); - world.addEntity(entityIn); + ItemEntity entityIn = new ItemEntity(level, outPos.x, outPos.y, outPos.z, stack); + entityIn.setDeltaMovement(outMotion); + level.addFreshEntity(entityIn); } inventory.clear(); - world.updateComparatorOutputLevel(pos, getBlockState().getBlock()); + level.updateNeighbourForOutputSignal(worldPosition, getBlockState().getBlock()); inventory.remainingTime = -1; sendData(); } @Override - public void remove() { + public void setRemoved() { invProvider.invalidate(); - super.remove(); + super.setRemoved(); } @Override @@ -212,6 +268,26 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { return super.getCapability(cap, side); } + protected void spawnEventParticles(ItemStack stack) { + if (stack == null || stack.isEmpty()) + return; + + IParticleData particleData = null; + if (stack.getItem() instanceof BlockItem) + particleData = new BlockParticleData(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() + .defaultBlockState()); + else + particleData = new ItemParticleData(ParticleTypes.ITEM, stack); + + Random r = level.random; + Vector3d v = VecHelper.getCenterOf(this.worldPosition) + .add(0, 5 / 16f, 0); + for (int i = 0; i < 10; i++) { + Vector3d m = VecHelper.offsetRandomly(new Vector3d(0, 0.25f, 0), r, .125f); + level.addParticle(particleData, v.x, v.y, v.z, m.x, m.y, m.y); + } + } + protected void spawnParticles(ItemStack stack) { if (stack == null || stack.isEmpty()) return; @@ -220,23 +296,25 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { float speed = 1; if (stack.getItem() instanceof BlockItem) particleData = new BlockParticleData(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() - .getDefaultState()); + .defaultBlockState()); else { particleData = new ItemParticleData(ParticleTypes.ITEM, stack); speed = .125f; } - Random r = world.rand; + Random r = level.random; Vector3d vec = getItemMovementVec(); - Vector3d pos = VecHelper.getCenterOf(this.pos); + Vector3d pos = VecHelper.getCenterOf(this.worldPosition); float offset = inventory.recipeDuration != 0 ? (float) (inventory.remainingTime) / inventory.recipeDuration : 0; - offset -= .5f; - world.addParticle(particleData, pos.getX() + -vec.x * offset, pos.getY() + .45f, pos.getZ() + -vec.z * offset, + offset /= 2; + if (inventory.appliedRecipe) + offset -= .5f; + level.addParticle(particleData, pos.x() + -vec.x * offset, pos.y() + .45f, pos.z() + -vec.z * offset, -vec.x * speed, r.nextFloat() * speed, -vec.z * speed); } public Vector3d getItemMovementVec() { - boolean alongX = !getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE); + boolean alongX = !getBlockState().getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); int offset = getSpeed() < 0 ? -1 : 1; return new Vector3d(offset * (alongX ? 1 : 0), 0, offset * (alongX ? 0 : -1)); } @@ -259,8 +337,8 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { List results = new LinkedList(); if (recipe instanceof CuttingRecipe) results = ((CuttingRecipe) recipe).rollResults(); - else if (recipe instanceof StonecuttingRecipe || recipe.getType() == woodcuttingRecipeType.getValue()) - results.add(recipe.getRecipeOutput() + else if (recipe instanceof StonecuttingRecipe || recipe.getType() == woodcuttingRecipeType.get()) + results.add(recipe.getResultItem() .copy()); for (int i = 0; i < results.size(); i++) { @@ -268,26 +346,24 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { ItemHelper.addToList(stack, list); } } - for (int slot = 0; slot < list.size() && slot + 1 < inventory.getSlots(); slot++) + for (int slot = 0; slot < list.size() && slot + 1 < inventory.getSlots(); slot++) { inventory.setStackInSlot(slot + 1, list.get(slot)); + } } private List> getRecipes() { - /* - * Predicate> types = - * AllConfigs.SERVER.recipes.allowStonecuttingOnSaw.get() ? - * RecipeConditions.isOfType(IRecipeType.STONECUTTING, - * AllRecipeTypes.CUTTING.getType()) : - * RecipeConditions.isOfType(AllRecipeTypes.CUTTING.getType()); - * - */ + Optional assemblyRecipe = SequencedAssemblyRecipe.getRecipe(level, inventory.getStackInSlot(0), + AllRecipeTypes.CUTTING.getType(), CuttingRecipe.class); + if (assemblyRecipe.isPresent() && filtering.test(assemblyRecipe.get() + .getResultItem())) + return ImmutableList.of(assemblyRecipe.get()); Predicate> types = RecipeConditions.isOfType(AllRecipeTypes.CUTTING.getType(), AllConfigs.SERVER.recipes.allowStonecuttingOnSaw.get() ? IRecipeType.STONECUTTING : null, - AllConfigs.SERVER.recipes.allowWoodcuttingOnSaw.get() ? woodcuttingRecipeType.getValue() : null); + AllConfigs.SERVER.recipes.allowWoodcuttingOnSaw.get() ? woodcuttingRecipeType.get() : null); - List> startedSearch = RecipeFinder.get(cuttingRecipesKey, world, types); + List> startedSearch = RecipeFinder.get(cuttingRecipesKey, level, types); return startedSearch.stream() .filter(RecipeConditions.outputMatchesFilter(filtering)) .filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))) @@ -301,13 +377,16 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { return; if (!entity.isAlive()) return; - if (world.isRemote) + if (level.isClientSide) return; inventory.clear(); - inventory.insertItem(0, entity.getItem() + ItemStack remainder = inventory.insertItem(0, entity.getItem() .copy(), false); - entity.remove(); + if (remainder.isEmpty()) + entity.remove(); + else + entity.setItem(remainder); } public void start(ItemStack inserted) { @@ -315,12 +394,12 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { return; if (inventory.isEmpty()) return; - if (world.isRemote && !isVirtual()) + if (level.isClientSide && !isVirtual()) return; List> recipes = getRecipes(); boolean valid = !recipes.isEmpty(); - int time = 100; + int time = 50; if (recipes.isEmpty()) { inventory.remainingTime = inventory.recipeDuration = 10; @@ -347,35 +426,43 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { } protected boolean canProcess() { - return getBlockState().get(SawBlock.FACING) == Direction.UP; + return getBlockState().getValue(SawBlock.FACING) == Direction.UP; } // Block Breaker @Override protected boolean shouldRun() { - return getBlockState().get(SawBlock.FACING) + return getBlockState().getValue(SawBlock.FACING) .getAxis() .isHorizontal(); } @Override protected BlockPos getBreakingPos() { - return getPos().offset(getBlockState().get(SawBlock.FACING)); + return getBlockPos().relative(getBlockState().getValue(SawBlock.FACING)); } @Override public void onBlockBroken(BlockState stateToBreak) { + Optional dynamicTree = TreeCutter.findDynamicTree(stateToBreak.getBlock(), breakingPos); + if (dynamicTree.isPresent()) { + dynamicTree.get().destroyBlocks(level, null, this::dropItemFromCutTree); + return; + } + super.onBlockBroken(stateToBreak); - TreeCutter.findTree(world, breakingPos).destroyBlocks(world, null, this::dropItemFromCutTree); + TreeCutter.findTree(level, breakingPos) + .destroyBlocks(level, null, this::dropItemFromCutTree); } public void dropItemFromCutTree(BlockPos pos, ItemStack stack) { - float distance = (float) Math.sqrt(pos.distanceSq(breakingPos)); + float distance = (float) Math.sqrt(pos.distSqr(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)); - world.addEntity(entity); + ItemEntity entity = new ItemEntity(level, dropPos.x, dropPos.y, dropPos.z, stack); + entity.setDeltaMovement(Vector3d.atLowerCornerOf(breakingPos.subtract(this.worldPosition)) + .scale(distance / 20f)); + level.addFreshEntity(entity); } @Override @@ -385,7 +472,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.is(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(stateToBreak) + || stateToBreak.is(BlockTags.LEAVES)) return true; Block block = stateToBreak.getBlock(); if (block instanceof BambooBlock) @@ -402,11 +490,13 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { return true; if (block instanceof ChorusPlantBlock) return true; + if (TreeCutter.canDynamicTreeCutFrom(block)) + return true; return false; } @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..4dcd0080e 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.defineId(AbstractContraptionEntity.class, DataSerializers.BOOLEAN); public final Map collidingEntities; @@ -76,7 +77,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit this.contraption = contraption; if (contraption == null) return; - if (world.isRemote) + if (level.isClientSide) return; contraption.onEntityCreated(this); } @@ -86,7 +87,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } protected void contraptionInitialize() { - contraption.onEntityInitialize(world, this); + contraption.onEntityInitialize(level, this); initialized = true; } @@ -96,32 +97,32 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit public void addSittingPassenger(Entity passenger, int seatIndex) { passenger.startRiding(this, true); - if (world.isRemote) + if (level.isClientSide) return; contraption.getSeatMapping() - .put(passenger.getUniqueID(), seatIndex); + .put(passenger.getUUID(), seatIndex); AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), - new ContraptionSeatMappingPacket(getEntityId(), contraption.getSeatMapping())); + new ContraptionSeatMappingPacket(getId(), contraption.getSeatMapping())); } @Override protected void removePassenger(Entity passenger) { Vector3d transformedVector = getPassengerPosition(passenger, 1); super.removePassenger(passenger); - if (world.isRemote) + if (level.isClientSide) return; if (transformedVector != null) passenger.getPersistentData() .put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector)); contraption.getSeatMapping() - .remove(passenger.getUniqueID()); + .remove(passenger.getUUID()); AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), - new ContraptionSeatMappingPacket(getEntityId(), contraption.getSeatMapping())); + new ContraptionSeatMappingPacket(getId(), contraption.getSeatMapping())); } @Override - public void updatePassengerPosition(Entity passenger, IMoveCallback callback) { - if (!isPassenger(passenger)) + public void positionRider(Entity passenger, IMoveCallback callback) { + if (!hasPassenger(passenger)) return; Vector3d transformedVector = getPassengerPosition(passenger, 1); if (transformedVector == null) @@ -130,7 +131,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } protected Vector3d getPassengerPosition(Entity passenger, float partialTicks) { - UUID id = passenger.getUniqueID(); + UUID id = passenger.getUUID(); if (passenger instanceof OrientedContraptionEntity) { BlockPos localPos = contraption.getBearingPosOf(id); if (localPos != null) @@ -140,18 +141,18 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } AxisAlignedBB bb = passenger.getBoundingBox(); - double ySize = bb.getYSize(); + double ySize = bb.getYsize(); BlockPos seat = contraption.getSeatOf(id); if (seat == null) return null; - Vector3d transformedVector = toGlobalVector(Vector3d.of(seat) - .add(.5, passenger.getYOffset() + ySize - .15f, .5), partialTicks).add(VecHelper.getCenterOf(BlockPos.ZERO)) + Vector3d transformedVector = toGlobalVector(Vector3d.atLowerCornerOf(seat) + .add(.5, passenger.getMyRidingOffset() + ySize - .15f, .5), partialTicks).add(VecHelper.getCenterOf(BlockPos.ZERO)) .subtract(0.5, ySize, 0.5); return transformedVector; } @Override - protected boolean canFitPassenger(Entity p_184219_1_) { + protected boolean canAddPassenger(Entity p_184219_1_) { if (p_184219_1_ instanceof OrientedContraptionEntity) return true; return contraption.getSeatMapping() @@ -164,7 +165,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit int indexOfSeat = contraption.getSeats() .indexOf(localPos); if (indexOfSeat == -1) - return false; + return contraption.interactors.containsKey(localPos) + && contraption.interactors.get(localPos).handlePlayerInteraction(player, interactionHand, localPos, this); // Eject potential existing passenger Entity toDismount = null; @@ -174,7 +176,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit continue; for (Entity entity : getPassengers()) { if (!entry.getKey() - .equals(entity.getUniqueID())) + .equals(entity.getUUID())) continue; if (entity instanceof PlayerEntity) return false; @@ -182,14 +184,14 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } } - if (toDismount != null && !world.isRemote) { + if (toDismount != null && !level.isClientSide) { Vector3d transformedVector = getPassengerPosition(toDismount, 1); toDismount.stopRiding(); if (transformedVector != null) - toDismount.setPositionAndUpdate(transformedVector.x, transformedVector.y, transformedVector.z); + toDismount.teleportTo(transformedVector.x, transformedVector.y, transformedVector.z); } - if (world.isRemote) + if (level.isClientSide) return true; addSittingPassenger(player, indexOfSeat); return true; @@ -227,14 +229,14 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit .incrementAndGet() > 3) iterator.remove(); - prevPosX = getX(); - prevPosY = getY(); - prevPosZ = getZ(); + xo = getX(); + yo = getY(); + zo = getZ(); prevPosInvalid = false; if (!initialized) contraptionInitialize(); - contraption.onEntityTick(world); + contraption.onEntityTick(level); tickContraption(); super.tick(); } @@ -248,7 +250,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit public void tickActors() { boolean stalledPreviously = contraption.stalled; - if (!world.isRemote) + if (!level.isClientSide) contraption.stalled = false; ticking = true; @@ -285,7 +287,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit contraption.stalled |= context.stall; } if (!isAlive()) { - contraption.stop(world); + contraption.stop(level); return; } ticking = false; @@ -293,7 +295,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit for (Entity entity : getPassengers()) { if (!(entity instanceof OrientedContraptionEntity)) continue; - if (!contraption.stabilizedSubContraptions.containsKey(entity.getUniqueID())) + if (!contraption.stabilizedSubContraptions.containsKey(entity.getUUID())) continue; OrientedContraptionEntity orientedCE = (OrientedContraptionEntity) entity; if (orientedCE.contraption != null && orientedCE.contraption.stalled) { @@ -302,10 +304,10 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } } - if (!world.isRemote) { + if (!level.isClientSide) { if (!stalledPreviously && contraption.stalled) onContraptionStalled(); - dataManager.set(STALLED, contraption.stalled); + entityData.set(STALLED, contraption.stalled); return; } @@ -314,7 +316,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit protected void onContraptionStalled() { AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), - new ContraptionStallPacket(getEntityId(), getX(), getY(), getZ(), getStalledAngle())); + new ContraptionStallPacket(getId(), getX(), getY(), getZ(), getStalledAngle())); } protected boolean shouldActorTrigger(MovementContext context, BlockInfo blockInfo, MovementBehaviour actor, @@ -332,11 +334,11 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } public void move(double x, double y, double z) { - setPosition(getX() + x, getY() + y, getZ() + z); + setPos(getX() + x, getY() + y, getZ() + z); } public Vector3d getAnchorVec() { - return getPositionVec(); + return position(); } public float getYawOffset() { @@ -344,15 +346,15 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } @Override - public void setPosition(double x, double y, double z) { - super.setPosition(x, y, z); + public void setPos(double x, double y, double z) { + super.setPos(x, y, z); if (contraption == null) return; AxisAlignedBB cbox = contraption.bounds; if (cbox == null) return; Vector3d actualVec = getAnchorVec(); - setBoundingBox(cbox.offset(actualVec)); + setBoundingBox(cbox.move(actualVec)); } public static float yawFromVector(Vector3d vec) { @@ -367,16 +369,16 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit @SuppressWarnings("unchecked") EntityType.Builder entityBuilder = (EntityType.Builder) builder; - return entityBuilder.size(1, 1); + return entityBuilder.sized(1, 1); } @Override - protected void registerData() { - this.dataManager.register(STALLED, false); + protected void defineSynchedData() { + this.entityData.define(STALLED, false); } @Override - public IPacket createSpawnPacket() { + public IPacket getAddEntityPacket() { return NetworkHooks.getEntitySpawningPacket(this); } @@ -391,23 +393,23 @@ 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() + ")"); - buffer.writeCompoundTag(new CompoundNBT()); + Create.LOGGER.warn("Could not send Contraption Spawn Data (Packet too big): " + + getContraption().getType().id + " @" + position() + " (" + getUUID().toString() + ")"); + buffer.writeNbt(new CompoundNBT()); return; } } catch (IOException e) { e.printStackTrace(); - buffer.writeCompoundTag(new CompoundNBT()); + buffer.writeNbt(new CompoundNBT()); return; } - buffer.writeCompoundTag(compound); + buffer.writeNbt(compound); } @Override - protected final void writeAdditional(CompoundNBT compound) { + protected final void addAdditionalSaveData(CompoundNBT compound) { writeAdditional(compound, false); } @@ -420,22 +422,22 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit @Override public void readSpawnData(PacketBuffer additionalData) { - readAdditional(additionalData.readCompoundTag(), true); + readAdditional(additionalData.readNbt(), true); } @Override - protected final void readAdditional(CompoundNBT compound) { + protected final void readAdditionalSaveData(CompoundNBT compound) { readAdditional(compound, false); } protected void readAdditional(CompoundNBT compound, boolean spawnData) { if (compound.isEmpty()) return; - + initialized = compound.getBoolean("Initialized"); - contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"), spawnData); + contraption = Contraption.fromNBT(level, compound.getCompound("Contraption"), spawnData); contraption.entity = this; - dataManager.set(STALLED, compound.getBoolean("Stalled")); + entityData.set(STALLED, compound.getBoolean("Stalled")); } public void disassemble() { @@ -448,44 +450,45 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit StructureTransform transform = makeStructureTransform(); AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), - new ContraptionDisassemblyPacket(this.getEntityId(), transform)); + new ContraptionDisassemblyPacket(this.getId(), transform)); - contraption.addBlocksToWorld(world, transform); - contraption.addPassengersToWorld(world, transform, getPassengers()); + contraption.addBlocksToWorld(level, transform); + contraption.addPassengersToWorld(level, transform, getPassengers()); for (Entity entity : getPassengers()) { if (!(entity instanceof OrientedContraptionEntity)) continue; - UUID id = entity.getUniqueID(); + UUID id = entity.getUUID(); if (!contraption.stabilizedSubContraptions.containsKey(id)) continue; BlockPos transformed = transform.apply(contraption.stabilizedSubContraptions.get(id) .getConnectedPos()); - entity.setPosition(transformed.getX(), transformed.getY(), transformed.getZ()); + entity.setPos(transformed.getX(), transformed.getY(), transformed.getZ()); ((AbstractContraptionEntity) entity).disassemble(); } - removePassengers(); + ejectPassengers(); moveCollidedEntitiesOnDisassembly(transform); + AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, blockPosition()); } private void moveCollidedEntitiesOnDisassembly(StructureTransform transform) { for (Entity entity : collidingEntities.keySet()) { - Vector3d localVec = toLocalVector(entity.getPositionVec(), 0); + Vector3d localVec = toLocalVector(entity.position(), 0); Vector3d transformed = transform.apply(localVec); - if (world.isRemote) - entity.setPosition(transformed.x, transformed.y + 1 / 16f, transformed.z); + if (level.isClientSide) + entity.setPos(transformed.x, transformed.y + 1 / 16f, transformed.z); else - entity.setPositionAndUpdate(transformed.x, transformed.y + 1 / 16f, transformed.z); + entity.teleportTo(transformed.x, transformed.y + 1 / 16f, transformed.z); } } @SuppressWarnings("deprecation") @Override public void remove(boolean keepData) { - if (!world.isRemote && !removed && contraption != null) { + if (!level.isClientSide && !removed && contraption != null) { if (!ticking) - contraption.stop(world); + contraption.stop(level); } if (contraption != null) contraption.onEntityRemoved(this); @@ -495,21 +498,21 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit protected abstract StructureTransform makeStructureTransform(); @Override - public void onKillCommand() { - removePassengers(); - super.onKillCommand(); + public void kill() { + ejectPassengers(); + super.kill(); } @Override protected void outOfWorld() { - removePassengers(); + ejectPassengers(); super.outOfWorld(); } @Override public void onRemovedFromWorld() { super.onRemovedFromWorld(); - if (world != null && world.isRemote) + if (level != null && level.isClientSide) return; getPassengers().forEach(Entity::remove); } @@ -522,12 +525,12 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } public boolean isStalled() { - return dataManager.get(STALLED); + return entityData.get(STALLED); } @OnlyIn(Dist.CLIENT) static void handleStallPacket(ContraptionStallPacket packet) { - Entity entity = Minecraft.getInstance().world.getEntityByID(packet.entityID); + Entity entity = Minecraft.getInstance().level.getEntity(packet.entityID); if (!(entity instanceof AbstractContraptionEntity)) return; AbstractContraptionEntity ce = (AbstractContraptionEntity) entity; @@ -536,7 +539,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit @OnlyIn(Dist.CLIENT) static void handleDisassemblyPacket(ContraptionDisassemblyPacket packet) { - Entity entity = Minecraft.getInstance().world.getEntityByID(packet.entityID); + Entity entity = Minecraft.getInstance().level.getEntity(packet.entityID); if (!(entity instanceof AbstractContraptionEntity)) return; AbstractContraptionEntity ce = (AbstractContraptionEntity) entity; @@ -549,8 +552,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit @Override @SuppressWarnings("deprecation") - public CompoundNBT writeWithoutTypeId(CompoundNBT nbt) { - Vector3d vec = getPositionVec(); + public CompoundNBT saveWithoutId(CompoundNBT nbt) { + Vector3d vec = position(); List passengers = getPassengers(); for (Entity entity : passengers) { @@ -558,43 +561,43 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit entity.removed = true; // Gather passengers into same chunk when saving - Vector3d prevVec = entity.getPositionVec(); - entity.setPos(vec.x, prevVec.y, vec.z); + Vector3d prevVec = entity.position(); + entity.setPosRaw(vec.x, prevVec.y, vec.z); // Super requires all passengers to not be removed in order to write them to the // tag entity.removed = false; } - CompoundNBT tag = super.writeWithoutTypeId(nbt); + CompoundNBT tag = super.saveWithoutId(nbt); return tag; } @Override // Make sure nothing can move contraptions out of the way - public void setMotion(Vector3d motionIn) {} + public void setDeltaMovement(Vector3d motionIn) {} @Override - public PushReaction getPushReaction() { + public PushReaction getPistonPushReaction() { return PushReaction.IGNORE; } public void setContraptionMotion(Vector3d vec) { - super.setMotion(vec); + super.setDeltaMovement(vec); } @Override - public boolean canBeCollidedWith() { + public boolean isPickable() { return false; } @Override - public boolean attackEntityFrom(DamageSource source, float amount) { + public boolean hurt(DamageSource source, float amount) { return false; } public Vector3d getPrevPositionVec() { - return prevPosInvalid ? getPositionVec() : new Vector3d(prevPosX, prevPosY, prevPosZ); + return prevPosInvalid ? position() : new Vector3d(xo, yo, zo); } public abstract ContraptionRotationState getRotationState(); @@ -604,13 +607,13 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return Vector3d.ZERO; Vector3d contactPoint = toGlobalVector(toLocalVector(globalContactPoint, 0), 1); return contactPoint.subtract(globalContactPoint) - .add(getPositionVec().subtract(getPrevPositionVec())); + .add(position().subtract(getPrevPositionVec())); } public boolean canCollideWith(Entity e) { if (e instanceof PlayerEntity && e.isSpectator()) return false; - if (e.noClip) + if (e.noPhysics) return false; if (e instanceof HangingEntity) return false; @@ -622,21 +625,21 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return false; if (e instanceof ProjectileEntity) return false; - if (e.getRidingEntity() != null) + if (e.getVehicle() != null) return false; - Entity riding = this.getRidingEntity(); + Entity riding = this.getVehicle(); while (riding != null) { if (riding == e) return false; - riding = riding.getRidingEntity(); + riding = riding.getVehicle(); } - return e.getPushReaction() == PushReaction.NORMAL; + return e.getPistonPushReaction() == PushReaction.NORMAL; } @Override - public boolean isOnePlayerRiding() { + public boolean hasOnePlayerPassenger() { return false; } @@ -676,23 +679,24 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } - // @Override //TODO find 1.16 replacement - // public void updateAquatics() { - /* - * Override this with an empty method to reduce enormous calculation time when contraptions are in water - * WARNING: THIS HAS A BUNCH OF SIDE EFFECTS! - * - Fluids will not try to change contraption movement direction - * - this.inWater and this.isInWater() will return unreliable data - * - entities riding a contraption will not cause water splashes (seats are their own entity so this should be fine) - * - fall distance is not reset when the contraption is in water - * - this.eyesInWater and this.canSwim() will always be false - * - swimming state will never be updated - */ - // extinguish(); - // } @Override - public void setFire(int p_70015_1_) { + protected boolean updateInWaterStateAndDoFluidPushing() { + /* + * Override this with an empty method to reduce enormous calculation time when contraptions are in water + * WARNING: THIS HAS A BUNCH OF SIDE EFFECTS! + * - Fluids will not try to change contraption movement direction + * - this.inWater and this.isInWater() will return unreliable data + * - entities riding a contraption will not cause water splashes (seats are their own entity so this should be fine) + * - fall distance is not reset when the contraption is in water + * - this.eyesInWater and this.canSwim() will always be false + * - swimming state will never be updated + */ + return false; + } + + @Override + public void setSecondsOnFire(int p_70015_1_) { // Contraptions no longer catch fire } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java index 51eb14340..0f1972ad4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java @@ -22,7 +22,7 @@ public class AssemblyException extends Exception { nbt.putString("Component", ITextComponent.Serializer.toJson(exception.component)); if (exception.hasPosition()) nbt.putLong("Position", exception.getPosition() - .toLong()); + .asLong()); compound.put("LastException", nbt); } @@ -35,7 +35,7 @@ public class AssemblyException extends Exception { String string = nbt.getString("Component"); AssemblyException exception = new AssemblyException(ITextComponent.Serializer.fromJson(string)); if (nbt.contains("Position")) - exception.position = BlockPos.fromLong(nbt.getLong("Position")); + exception.position = BlockPos.of(nbt.getLong("Position")); return exception; } @@ -51,7 +51,7 @@ public class AssemblyException extends Exception { public static AssemblyException unmovableBlock(BlockPos pos, BlockState state) { AssemblyException e = new AssemblyException("unmovableBlock", pos.getX(), pos.getY(), pos.getZ(), new TranslationTextComponent(state.getBlock() - .getTranslationKey())); + .getDescriptionId())); e.position = pos; return e; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java new file mode 100644 index 000000000..ba3966261 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java @@ -0,0 +1,427 @@ +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; +import com.simibubi.create.content.contraptions.components.crank.HandCrankBlock; +import com.simibubi.create.content.contraptions.components.fan.NozzleBlock; +import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingTileEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingTileEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; +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.ContraptionMovementSetting; + +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; +import net.minecraft.block.CarpetBlock; +import net.minecraft.block.DoorBlock; +import net.minecraft.block.FenceGateBlock; +import net.minecraft.block.FlowerPotBlock; +import net.minecraft.block.GrindstoneBlock; +import net.minecraft.block.HorizontalBlock; +import net.minecraft.block.HorizontalFaceBlock; +import net.minecraft.block.LadderBlock; +import net.minecraft.block.RedstoneDiodeBlock; +import net.minecraft.block.RedstoneWallTorchBlock; +import net.minecraft.block.RedstoneWireBlock; +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.World; + +public class BlockMovementChecks { + + 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 = Create.asResource("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()) + return false; + if (state.getCollisionShape(world, pos) + .isEmpty()) + return false; + return true; + } + + private static boolean isMovementAllowedFallback(BlockState state, World world, BlockPos pos) { + Block block = state.getBlock(); + if (block instanceof AbstractChassisBlock) + return true; + if (state.getDestroySpeed(world, pos) == -1) + return false; + if (state.getBlock().getTags().contains(NON_MOVABLE)) + return false; + if (ContraptionMovementSetting.get(state.getBlock()) == ContraptionMovementSetting.UNMOVABLE) + return false; + + // Move controllers only when they aren't moving + if (block instanceof MechanicalPistonBlock && state.getValue(MechanicalPistonBlock.STATE) != PistonState.MOVING) + return true; + if (block instanceof MechanicalBearingBlock) { + TileEntity te = world.getBlockEntity(pos); + if (te instanceof MechanicalBearingTileEntity) + return !((MechanicalBearingTileEntity) te).isRunning(); + } + if (block instanceof WindmillBearingBlock) { + TileEntity te = world.getBlockEntity(pos); + if (te instanceof WindmillBearingTileEntity) + return !((WindmillBearingTileEntity) te).isRunning(); + } + if (block instanceof ClockworkBearingBlock) { + TileEntity te = world.getBlockEntity(pos); + if (te instanceof ClockworkBearingTileEntity) + return !((ClockworkBearingTileEntity) te).isRunning(); + } + if (block instanceof PulleyBlock) { + TileEntity te = world.getBlockEntity(pos); + if (te instanceof PulleyTileEntity) + return !((PulleyTileEntity) te).running; + } + + if (AllBlocks.BELT.has(state)) + return true; + if (state.getBlock() instanceof GrindstoneBlock) + return true; + return state.getPistonPushReaction() != PushReaction.BLOCK; + } + + private static boolean isBrittleFallback(BlockState state) { + Block block = state.getBlock(); + if (state.hasProperty(BlockStateProperties.HANGING)) + return true; + + if (block instanceof LadderBlock) + return true; + if (block instanceof TorchBlock) + return true; + if (block instanceof AbstractSignBlock) + return true; + if (block instanceof AbstractPressurePlateBlock) + return true; + if (block instanceof HorizontalFaceBlock && !(block instanceof GrindstoneBlock)) + return true; + if (block instanceof CartAssemblerBlock) + return false; + if (block instanceof AbstractRailBlock) + return true; + if (block instanceof RedstoneDiodeBlock) + return true; + if (block instanceof RedstoneWireBlock) + return true; + if (block instanceof CarpetBlock) + return true; + return AllBlockTags.BRITTLE.tag.contains(block); + } + + private static boolean isBlockAttachedTowardsFallback(BlockState state, World world, BlockPos pos, + Direction direction) { + Block block = state.getBlock(); + if (block instanceof LadderBlock) + return state.getValue(LadderBlock.FACING) == direction.getOpposite(); + if (block instanceof WallTorchBlock) + return state.getValue(WallTorchBlock.FACING) == direction.getOpposite(); + if (block instanceof WallSignBlock) + return state.getValue(WallSignBlock.FACING) == direction.getOpposite(); + if (block instanceof StandingSignBlock) + return direction == Direction.DOWN; + if (block instanceof AbstractPressurePlateBlock) + return direction == Direction.DOWN; + if (block instanceof DoorBlock) { + if (state.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER && direction == Direction.UP) + return true; + return direction == Direction.DOWN; + } + if (block instanceof BedBlock) { + Direction facing = state.getValue(BedBlock.FACING); + if (state.getValue(BedBlock.PART) == BedPart.HEAD) + facing = facing.getOpposite(); + return direction == facing; + } + if (block instanceof RedstoneLinkBlock) + return direction.getOpposite() == state.getValue(RedstoneLinkBlock.FACING); + if (block instanceof FlowerPotBlock) + return direction == Direction.DOWN; + if (block instanceof RedstoneDiodeBlock) + return direction == Direction.DOWN; + if (block instanceof RedstoneWireBlock) + return direction == Direction.DOWN; + if (block instanceof CarpetBlock) + return direction == Direction.DOWN; + if (block instanceof RedstoneWallTorchBlock) + return state.getValue(RedstoneWallTorchBlock.FACING) == direction.getOpposite(); + if (block instanceof TorchBlock) + return direction == Direction.DOWN; + if (block instanceof HorizontalFaceBlock) { + AttachFace attachFace = state.getValue(HorizontalFaceBlock.FACE); + if (attachFace == AttachFace.CEILING) + return direction == Direction.UP; + if (attachFace == AttachFace.FLOOR) + return direction == Direction.DOWN; + if (attachFace == AttachFace.WALL) + return direction.getOpposite() == state.getValue(HorizontalFaceBlock.FACING); + } + if (state.hasProperty(BlockStateProperties.HANGING)) + return direction == (state.getValue(BlockStateProperties.HANGING) ? Direction.UP : Direction.DOWN); + if (block instanceof AbstractRailBlock) + return direction == Direction.DOWN; + if (block instanceof AttachedActorBlock) + return direction == state.getValue(HarvesterBlock.FACING) + .getOpposite(); + if (block instanceof HandCrankBlock) + return direction == state.getValue(HandCrankBlock.FACING) + .getOpposite(); + if (block instanceof NozzleBlock) + return direction == state.getValue(NozzleBlock.FACING) + .getOpposite(); + if (block instanceof EngineBlock) + return direction == state.getValue(EngineBlock.FACING) + .getOpposite(); + if (block instanceof BellBlock) { + BellAttachment attachment = state.getValue(BlockStateProperties.BELL_ATTACHMENT); + if (attachment == BellAttachment.FLOOR) + return direction == Direction.DOWN; + if (attachment == BellAttachment.CEILING) + return direction == Direction.UP; + return direction == state.getValue(HorizontalBlock.FACING); + } + if (state.getBlock() instanceof SailBlock) + return direction.getAxis() != state.getValue(SailBlock.FACING) + .getAxis(); + if (state.getBlock() instanceof FluidTankBlock) + return FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(direction)); + if (AllBlocks.STICKER.has(state) && state.getValue(StickerBlock.EXTENDED)) { + return direction == state.getValue(StickerBlock.FACING) + && !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite()); + } + return false; + } + + private static boolean isNotSupportiveFallback(BlockState state, Direction facing) { + if (AllBlocks.MECHANICAL_DRILL.has(state)) + return state.getValue(BlockStateProperties.FACING) == facing; + if (AllBlocks.MECHANICAL_BEARING.has(state)) + return state.getValue(BlockStateProperties.FACING) == facing; + if (AllBlocks.CART_ASSEMBLER.has(state)) + return Direction.DOWN == facing; + if (AllBlocks.MECHANICAL_SAW.has(state)) + return state.getValue(BlockStateProperties.FACING) == facing; + if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(state)) + return state.getValue(PortableStorageInterfaceBlock.FACING) == facing; + if (state.getBlock() instanceof AttachedActorBlock) + return state.getValue(BlockStateProperties.HORIZONTAL_FACING) == facing; + if (AllBlocks.ROPE_PULLEY.has(state)) + return facing == Direction.DOWN; + if (state.getBlock() instanceof CarpetBlock) + return facing == Direction.UP; + if (state.getBlock() instanceof SailBlock) + return facing.getAxis() == state.getValue(SailBlock.FACING) + .getAxis(); + if (AllBlocks.PISTON_EXTENSION_POLE.has(state)) + return facing.getAxis() != state.getValue(BlockStateProperties.FACING) + .getAxis(); + if (AllBlocks.MECHANICAL_PISTON_HEAD.has(state)) + return facing.getAxis() != state.getValue(BlockStateProperties.FACING) + .getAxis(); + if (AllBlocks.STICKER.has(state) && !state.getValue(StickerBlock.EXTENDED)) + return facing == state.getValue(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/BlockMovementTraits.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java deleted file mode 100644 index 5a47573fe..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java +++ /dev/null @@ -1,260 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTags.AllBlockTags; -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; -import com.simibubi.create.content.contraptions.components.crank.HandCrankBlock; -import com.simibubi.create.content.contraptions.components.fan.NozzleBlock; -import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; -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 net.minecraft.block.AbstractPressurePlateBlock; -import net.minecraft.block.AbstractRailBlock; -import net.minecraft.block.AbstractSignBlock; -import net.minecraft.block.BellBlock; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.CarpetBlock; -import net.minecraft.block.DoorBlock; -import net.minecraft.block.FenceGateBlock; -import net.minecraft.block.FlowerPotBlock; -import net.minecraft.block.GrindstoneBlock; -import net.minecraft.block.HorizontalBlock; -import net.minecraft.block.HorizontalFaceBlock; -import net.minecraft.block.LadderBlock; -import net.minecraft.block.RedstoneDiodeBlock; -import net.minecraft.block.RedstoneWallTorchBlock; -import net.minecraft.block.RedstoneWireBlock; -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.BellAttachment; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.World; - -public class BlockMovementTraits { - - public static boolean movementNecessary(BlockState state, World world, BlockPos pos) { - if (isBrittle(state)) - return true; - if (state.getBlock() instanceof FenceGateBlock) - return true; - if (state.getMaterial() - .isReplaceable()) - return false; - if (state.getCollisionShape(world, pos) - .isEmpty()) - return false; - return true; - } - - public static boolean movementAllowed(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)) - return false; - - // Move controllers only when they aren't moving - if (block instanceof MechanicalPistonBlock && state.get(MechanicalPistonBlock.STATE) != PistonState.MOVING) - return true; - if (block instanceof MechanicalBearingBlock) { - TileEntity te = world.getTileEntity(pos); - if (te instanceof MechanicalBearingTileEntity) - return !((MechanicalBearingTileEntity) te).isRunning(); - } - if (block instanceof WindmillBearingBlock) { - TileEntity te = world.getTileEntity(pos); - if (te instanceof WindmillBearingTileEntity) - return !((WindmillBearingTileEntity) te).isRunning(); - } - if (block instanceof ClockworkBearingBlock) { - TileEntity te = world.getTileEntity(pos); - if (te instanceof ClockworkBearingTileEntity) - return !((ClockworkBearingTileEntity) te).isRunning(); - } - if (block instanceof PulleyBlock) { - TileEntity te = world.getTileEntity(pos); - if (te instanceof PulleyTileEntity) - return !((PulleyTileEntity) te).running; - } - - if (AllBlocks.BELT.has(state)) - return true; - if (state.getBlock() instanceof GrindstoneBlock) - return true; - 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) { - Block block = state.getBlock(); - if (state.contains(BlockStateProperties.HANGING)) - return true; - - if (block instanceof LadderBlock) - return true; - if (block instanceof TorchBlock) - return true; - if (block instanceof AbstractSignBlock) - return true; - if (block instanceof AbstractPressurePlateBlock) - return true; - if (block instanceof HorizontalFaceBlock && !(block instanceof GrindstoneBlock)) - return true; - if (block instanceof CartAssemblerBlock) - return false; - if (block instanceof AbstractRailBlock) - return true; - if (block instanceof RedstoneDiodeBlock) - return true; - if (block instanceof RedstoneWireBlock) - return true; - if (block instanceof CarpetBlock) - return true; - 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) { - Block block = state.getBlock(); - if (block instanceof LadderBlock) - return state.get(LadderBlock.FACING) == direction.getOpposite(); - if (block instanceof WallTorchBlock) - return state.get(WallTorchBlock.HORIZONTAL_FACING) == direction.getOpposite(); - if (block instanceof WallSignBlock) - return state.get(WallSignBlock.FACING) == direction.getOpposite(); - if (block instanceof StandingSignBlock) - return direction == Direction.DOWN; - if (block instanceof AbstractPressurePlateBlock) - return direction == Direction.DOWN; - if (block instanceof DoorBlock) - return direction == Direction.DOWN; - if (block instanceof RedstoneLinkBlock) - return direction.getOpposite() == state.get(RedstoneLinkBlock.FACING); - if (block instanceof FlowerPotBlock) - return direction == Direction.DOWN; - if (block instanceof RedstoneDiodeBlock) - return direction == Direction.DOWN; - if (block instanceof RedstoneWireBlock) - return direction == Direction.DOWN; - if (block instanceof CarpetBlock) - return direction == Direction.DOWN; - if (block instanceof RedstoneWallTorchBlock) - return state.get(RedstoneWallTorchBlock.FACING) == direction.getOpposite(); - if (block instanceof TorchBlock) - return direction == Direction.DOWN; - if (block instanceof HorizontalFaceBlock) { - AttachFace attachFace = state.get(HorizontalFaceBlock.FACE); - if (attachFace == AttachFace.CEILING) - return direction == Direction.UP; - if (attachFace == AttachFace.FLOOR) - return direction == Direction.DOWN; - if (attachFace == AttachFace.WALL) - return direction.getOpposite() == state.get(HorizontalFaceBlock.HORIZONTAL_FACING); - } - if (state.contains(BlockStateProperties.HANGING)) - return direction == (state.get(BlockStateProperties.HANGING) ? Direction.UP : Direction.DOWN); - if (block instanceof AbstractRailBlock) - return direction == Direction.DOWN; - if (block instanceof AttachedActorBlock) - return direction == state.get(HarvesterBlock.HORIZONTAL_FACING) - .getOpposite(); - if (block instanceof HandCrankBlock) - return direction == state.get(HandCrankBlock.FACING) - .getOpposite(); - if (block instanceof NozzleBlock) - return direction == state.get(NozzleBlock.FACING) - .getOpposite(); - if (block instanceof EngineBlock) - return direction == state.get(EngineBlock.HORIZONTAL_FACING) - .getOpposite(); - if (block instanceof BellBlock) { - BellAttachment attachment = state.get(BlockStateProperties.BELL_ATTACHMENT); - if (attachment == BellAttachment.FLOOR) - return direction == Direction.DOWN; - if (attachment == BellAttachment.CEILING) - return direction == Direction.UP; - return direction == state.get(HorizontalBlock.HORIZONTAL_FACING); - } - if (state.getBlock() instanceof SailBlock) - return direction.getAxis() != state.get(SailBlock.FACING) - .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()); - } - 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) { - if (AllBlocks.MECHANICAL_DRILL.has(state)) - return state.get(BlockStateProperties.FACING) == facing; - if (AllBlocks.MECHANICAL_BEARING.has(state)) - return state.get(BlockStateProperties.FACING) == facing; - if (AllBlocks.CART_ASSEMBLER.has(state)) - return Direction.DOWN == facing; - if (AllBlocks.MECHANICAL_SAW.has(state)) - return state.get(BlockStateProperties.FACING) == facing; - if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(state)) - return state.get(PortableStorageInterfaceBlock.FACING) == facing; - if (state.getBlock() instanceof AttachedActorBlock) - return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing; - if (AllBlocks.ROPE_PULLEY.has(state)) - return facing == Direction.DOWN; - if (state.getBlock() instanceof CarpetBlock) - return facing == Direction.UP; - if (state.getBlock() instanceof SailBlock) - return facing.getAxis() == state.get(SailBlock.FACING) - .getAxis(); - if (AllBlocks.PISTON_EXTENSION_POLE.has(state)) - return facing.getAxis() != state.get(BlockStateProperties.FACING) - .getAxis(); - if (AllBlocks.MECHANICAL_PISTON_HEAD.has(state)) - return facing.getAxis() != state.get(BlockStateProperties.FACING) - .getAxis(); - if (AllBlocks.STICKER.has(state) && !state.get(StickerBlock.EXTENDED)) - return facing == state.get(StickerBlock.FACING); - return isBrittle(state); - } - -} 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..819efe7a9 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 @@ -22,9 +22,13 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; +import com.simibubi.create.AllInteractionBehaviours; + 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 +52,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 +61,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 +75,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; @@ -85,9 +86,9 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; +import net.minecraft.network.DebugPacketSender; 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; @@ -104,6 +105,7 @@ import net.minecraft.village.PointOfInterestType; import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; +import net.minecraft.world.server.ServerWorld; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.Constants.BlockFlags; @@ -121,7 +123,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; @@ -132,6 +134,7 @@ public abstract class Contraption { protected Map storage; protected Map fluidStorage; protected List> actors; + protected Map interactors; protected Set> superglue; protected List seats; protected Map seatMapping; @@ -155,6 +158,7 @@ public abstract class Contraption { storage = new HashMap<>(); seats = new ArrayList<>(); actors = new ArrayList<>(); + interactors = new HashMap<>(); superglue = new HashSet<>(); seatMapping = new HashMap<>(); fluidStorage = new HashMap<>(); @@ -170,7 +174,7 @@ public abstract class Contraption { public ContraptionWorld getContraptionWorld() { if (world == null) - world = new ContraptionWorld(entity.world, this); + world = new ContraptionWorld(entity.level, this); return world; } @@ -212,7 +216,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; @@ -232,7 +236,7 @@ public abstract class Contraption { for (BlockFace blockFace : pendingSubContraptions) { Direction face = blockFace.getFace(); StabilizedContraption subContraption = new StabilizedContraption(face); - World world = entity.world; + World world = entity.level; BlockPos pos = blockFace.getPos(); try { if (!subContraption.assemble(world, pos)) @@ -241,12 +245,11 @@ 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); - stabilizedSubContraptions.put(movedContraption.getUniqueID(), new BlockFace(toLocalPos(pos), face)); + movedContraption.setPos(anchor.getX() + .5f, anchor.getY(), anchor.getZ() + .5f); + world.addFreshEntity(movedContraption); + stabilizedSubContraptions.put(movedContraption.getUUID(), new BlockFace(toLocalPos(pos), face)); } // Gather itemhandlers of mounted storage @@ -254,7 +257,8 @@ 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() @@ -273,13 +277,13 @@ public abstract class Contraption { } public void onEntityInitialize(World world, AbstractContraptionEntity contraptionEntity) { - if (world.isRemote) + if (world.isClientSide) return; - for (OrientedContraptionEntity orientedCE : world.getEntitiesWithinAABB(OrientedContraptionEntity.class, + for (OrientedContraptionEntity orientedCE : world.getEntitiesOfClass(OrientedContraptionEntity.class, contraptionEntity.getBoundingBox() - .grow(1))) - if (stabilizedSubContraptions.containsKey(orientedCE.getUniqueID())) + .inflate(1))) + if (stabilizedSubContraptions.containsKey(orientedCE.getUUID())) orientedCE.startRiding(contraptionEntity); for (BlockPos seatPos : getSeats()) { @@ -294,7 +298,7 @@ public abstract class Contraption { } public void onEntityTick(World world) { - fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isRemote)); + fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isClientSide)); } /** move the first block in frontier queue */ @@ -307,12 +311,12 @@ public abstract class Contraption { if (World.isOutsideBuildHeight(pos)) return true; - if (!world.isBlockPresent(pos)) + if (!world.isLoaded(pos)) throw AssemblyException.unloadedChunk(pos); 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); @@ -332,18 +336,18 @@ public abstract class Contraption { if (AllBlocks.GANTRY_SHAFT.has(state)) moveGantryShaft(world, pos, frontier, visited, state); - if (AllBlocks.STICKER.has(state) && state.get(StickerBlock.EXTENDED)) { - Direction offset = state.get(StickerBlock.FACING); - BlockPos attached = pos.offset(offset); + if (AllBlocks.STICKER.has(state) && state.getValue(StickerBlock.EXTENDED)) { + Direction offset = state.getValue(StickerBlock.FACING); + BlockPos attached = pos.relative(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,15 +369,8 @@ 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(); + BlockPos posDown = pos.below(); BlockState stateBelow = world.getBlockState(posDown); if (!visited.contains(posDown) && AllBlocks.CART_ASSEMBLER.has(stateBelow)) frontier.add(posDown); @@ -382,7 +379,7 @@ public abstract class Contraption { // Slime blocks and super glue drag adjacent blocks if possible for (Direction offset : Iterate.directions) { - BlockPos offsetPos = pos.offset(offset); + BlockPos offsetPos = pos.relative(offset); BlockState blockState = world.getBlockState(offsetPos); if (isAnchoringBlockAt(offsetPos)) continue; @@ -395,24 +392,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) { + if (state.getPistonPushReaction() == PushReaction.PUSH_ONLY + || blockState.getPistonPushReaction() == 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)); @@ -427,21 +424,22 @@ public abstract class Contraption { protected void movePistonHead(World world, BlockPos pos, Queue frontier, Set visited, BlockState state) { - Direction direction = state.get(MechanicalPistonHeadBlock.FACING); - BlockPos offset = pos.offset(direction.getOpposite()); + Direction direction = state.getValue(MechanicalPistonHeadBlock.FACING); + BlockPos offset = pos.relative(direction.getOpposite()); if (!visited.contains(offset)) { BlockState blockState = world.getBlockState(offset); - if (isExtensionPole(blockState) && blockState.get(PistonExtensionPoleBlock.FACING) + if (isExtensionPole(blockState) && blockState.getValue(PistonExtensionPoleBlock.FACING) .getAxis() == direction.getAxis()) frontier.add(offset); if (blockState.getBlock() instanceof MechanicalPistonBlock) { - Direction pistonFacing = blockState.get(MechanicalPistonBlock.FACING); - if (pistonFacing == direction && blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) + Direction pistonFacing = blockState.getValue(MechanicalPistonBlock.FACING); + if (pistonFacing == direction + && blockState.getValue(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) frontier.add(offset); } } - if (state.get(MechanicalPistonHeadBlock.TYPE) == PistonType.STICKY) { - BlockPos attached = pos.offset(direction); + if (state.getValue(MechanicalPistonHeadBlock.TYPE) == PistonType.STICKY) { + BlockPos attached = pos.relative(direction); if (!visited.contains(attached)) frontier.add(attached); } @@ -449,21 +447,21 @@ public abstract class Contraption { protected void movePistonPole(World world, BlockPos pos, Queue frontier, Set visited, BlockState state) { - for (Direction d : Iterate.directionsInAxis(state.get(PistonExtensionPoleBlock.FACING) + for (Direction d : Iterate.directionsInAxis(state.getValue(PistonExtensionPoleBlock.FACING) .getAxis())) { - BlockPos offset = pos.offset(d); + BlockPos offset = pos.relative(d); if (!visited.contains(offset)) { BlockState blockState = world.getBlockState(offset); - if (isExtensionPole(blockState) && blockState.get(PistonExtensionPoleBlock.FACING) + if (isExtensionPole(blockState) && blockState.getValue(PistonExtensionPoleBlock.FACING) .getAxis() == d.getAxis()) frontier.add(offset); - if (isPistonHead(blockState) && blockState.get(MechanicalPistonHeadBlock.FACING) + if (isPistonHead(blockState) && blockState.getValue(MechanicalPistonHeadBlock.FACING) .getAxis() == d.getAxis()) frontier.add(offset); if (blockState.getBlock() instanceof MechanicalPistonBlock) { - Direction pistonFacing = blockState.get(MechanicalPistonBlock.FACING); + Direction pistonFacing = blockState.getValue(MechanicalPistonBlock.FACING); if (pistonFacing == d || pistonFacing == d.getOpposite() - && blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) + && blockState.getValue(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) frontier.add(offset); } } @@ -472,14 +470,14 @@ public abstract class Contraption { protected void moveGantryPinion(World world, BlockPos pos, Queue frontier, Set visited, BlockState state) { - BlockPos offset = pos.offset(state.get(GantryCarriageBlock.FACING)); + BlockPos offset = pos.relative(state.getValue(GantryCarriageBlock.FACING)); if (!visited.contains(offset)) frontier.add(offset); Axis rotationAxis = ((IRotate) state.getBlock()).getRotationAxis(state); for (Direction d : Iterate.directionsInAxis(rotationAxis)) { - offset = pos.offset(d); + offset = pos.relative(d); BlockState offsetState = world.getBlockState(offset); - if (AllBlocks.GANTRY_SHAFT.has(offsetState) && offsetState.get(GantryShaftBlock.FACING) + if (AllBlocks.GANTRY_SHAFT.has(offsetState) && offsetState.getValue(GantryShaftBlock.FACING) .getAxis() == d.getAxis()) if (!visited.contains(offset)) frontier.add(offset); @@ -489,30 +487,31 @@ public abstract class Contraption { protected void moveGantryShaft(World world, BlockPos pos, Queue frontier, Set visited, BlockState state) { for (Direction d : Iterate.directions) { - BlockPos offset = pos.offset(d); + BlockPos offset = pos.relative(d); if (!visited.contains(offset)) { BlockState offsetState = world.getBlockState(offset); - Direction facing = state.get(GantryShaftBlock.FACING); + Direction facing = state.getValue(GantryShaftBlock.FACING); if (d.getAxis() == facing.getAxis() && AllBlocks.GANTRY_SHAFT.has(offsetState) - && offsetState.get(GantryShaftBlock.FACING) == facing) + && offsetState.getValue(GantryShaftBlock.FACING) == facing) frontier.add(offset); - else if (AllBlocks.GANTRY_CARRIAGE.has(offsetState) && offsetState.get(GantryCarriageBlock.FACING) == d) + else if (AllBlocks.GANTRY_CARRIAGE.has(offsetState) + && offsetState.getValue(GantryCarriageBlock.FACING) == d) frontier.add(offset); } } } private void moveWindmillBearing(BlockPos pos, Queue frontier, Set visited, BlockState state) { - Direction facing = state.get(WindmillBearingBlock.FACING); - BlockPos offset = pos.offset(facing); + Direction facing = state.getValue(WindmillBearingBlock.FACING); + BlockPos offset = pos.relative(facing); if (!visited.contains(offset)) frontier.add(offset); } private void moveBearing(BlockPos pos, Queue frontier, Set visited, BlockState state) { - Direction facing = state.get(MechanicalBearingBlock.FACING); + Direction facing = state.getValue(MechanicalBearingBlock.FACING); if (!canBeStabilized(facing, pos.subtract(anchor))) { - BlockPos offset = pos.offset(facing); + BlockPos offset = pos.relative(facing); if (!visited.contains(offset)) frontier.add(offset); return; @@ -532,7 +531,7 @@ public abstract class Contraption { private void moveSeat(World world, BlockPos pos) { BlockPos local = toLocalPos(pos); getSeats().add(local); - List seatsEntities = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos)); + List seatsEntities = world.getEntitiesOfClass(SeatEntity.class, new AxisAlignedBB(pos)); if (!seatsEntities.isEmpty()) { SeatEntity seat = seatsEntities.get(0); List passengers = seat.getPassengers(); @@ -545,8 +544,8 @@ public abstract class Contraption { int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get(); BlockPos ropePos = pos; while (limit-- >= 0) { - ropePos = ropePos.down(); - if (!world.isBlockPresent(ropePos)) + ropePos = ropePos.below(); + if (!world.isLoaded(ropePos)) break; BlockState ropeState = world.getBlockState(ropePos); Block block = ropeState.getBlock(); @@ -561,21 +560,21 @@ public abstract class Contraption { private boolean moveMechanicalPiston(World world, BlockPos pos, Queue frontier, Set visited, BlockState state) throws AssemblyException { - Direction direction = state.get(MechanicalPistonBlock.FACING); - PistonState pistonState = state.get(MechanicalPistonBlock.STATE); + Direction direction = state.getValue(MechanicalPistonBlock.FACING); + PistonState pistonState = state.getValue(MechanicalPistonBlock.STATE); if (pistonState == PistonState.MOVING) return false; - BlockPos offset = pos.offset(direction.getOpposite()); + BlockPos offset = pos.relative(direction.getOpposite()); if (!visited.contains(offset)) { BlockState poleState = world.getBlockState(offset); - if (AllBlocks.PISTON_EXTENSION_POLE.has(poleState) && poleState.get(PistonExtensionPoleBlock.FACING) + if (AllBlocks.PISTON_EXTENSION_POLE.has(poleState) && poleState.getValue(PistonExtensionPoleBlock.FACING) .getAxis() == direction.getAxis()) frontier.add(offset); } if (pistonState == PistonState.EXTENDED || MechanicalPistonBlock.isStickyPiston(state)) { - offset = pos.offset(direction); + offset = pos.relative(direction); if (!visited.contains(offset)) frontier.add(offset); } @@ -585,7 +584,7 @@ public abstract class Contraption { private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, Queue frontier, Set visited) { - TileEntity te = world.getTileEntity(pos); + TileEntity te = world.getBlockEntity(pos); if (!(te instanceof ChassisTileEntity)) return false; ChassisTileEntity chassis = (ChassisTileEntity) te; @@ -602,23 +601,23 @@ public abstract class Contraption { protected Pair capture(World world, BlockPos pos) { BlockState blockstate = world.getBlockState(pos); if (blockstate.getBlock() instanceof ChestBlock) - blockstate = blockstate.with(ChestBlock.TYPE, ChestType.SINGLE); + blockstate = blockstate.setValue(ChestBlock.TYPE, ChestType.SINGLE); if (AllBlocks.ADJUSTABLE_CRATE.has(blockstate)) - blockstate = blockstate.with(AdjustableCrateBlock.DOUBLE, false); + blockstate = blockstate.setValue(AdjustableCrateBlock.DOUBLE, false); if (AllBlocks.REDSTONE_CONTACT.has(blockstate)) - blockstate = blockstate.with(RedstoneContactBlock.POWERED, true); + blockstate = blockstate.setValue(RedstoneContactBlock.POWERED, true); if (blockstate.getBlock() instanceof AbstractButtonBlock) { - blockstate = blockstate.with(AbstractButtonBlock.POWERED, false); - world.getPendingBlockTicks() + blockstate = blockstate.setValue(AbstractButtonBlock.POWERED, false); + world.getBlockTicks() .scheduleTick(pos, blockstate.getBlock(), -1); } if (blockstate.getBlock() instanceof PressurePlateBlock) { - blockstate = blockstate.with(PressurePlateBlock.POWERED, false); - world.getPendingBlockTicks() + blockstate = blockstate.setValue(PressurePlateBlock.POWERED, false); + world.getBlockTicks() .scheduleTick(pos, blockstate.getBlock(), -1); } CompoundNBT compoundnbt = getTileEntityNBT(world, pos); - TileEntity tileentity = world.getTileEntity(pos); + TileEntity tileentity = world.getBlockEntity(pos); return Pair.of(new BlockInfo(pos, blockstate, compoundnbt), tileentity); } @@ -629,7 +628,7 @@ public abstract class Contraption { if (blocks.put(localPos, blockInfo) != null) return; - bounds = bounds.union(new AxisAlignedBB(localPos)); + bounds = bounds.minmax(new AxisAlignedBB(localPos)); TileEntity te = pair.getValue(); if (te != null && MountedStorage.canUseAsStorage(te)) @@ -638,6 +637,8 @@ public abstract class Contraption { fluidStorage.put(localPos, new MountedFluidStorage(te)); if (AllMovementBehaviours.contains(captured.state.getBlock())) actors.add(MutablePair.of(blockInfo, null)); + if (AllInteractionBehaviours.contains(captured.state.getBlock())) + interactors.put(localPos, AllInteractionBehaviours.of(captured.state.getBlock())); if (te instanceof CreativeCrateTileEntity && ((CreativeCrateTileEntity) te).getBehaviour(FilteringBehaviour.TYPE) .getFilter() @@ -647,10 +648,10 @@ public abstract class Contraption { @Nullable protected CompoundNBT getTileEntityNBT(World world, BlockPos pos) { - TileEntity tileentity = world.getTileEntity(pos); + TileEntity tileentity = world.getBlockEntity(pos); if (tileentity == null) return null; - CompoundNBT nbt = tileentity.write(new CompoundNBT()); + CompoundNBT nbt = tileentity.save(new CompoundNBT()); nbt.remove("x"); nbt.remove("y"); nbt.remove("z"); @@ -674,7 +675,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) { @@ -702,19 +703,19 @@ public abstract class Contraption { }); superglue.clear(); - NBTHelper.iterateCompoundList(nbt.getList("Superglue", NBT.TAG_COMPOUND), c -> superglue - .add(Pair.of(NBTUtil.readBlockPos(c.getCompound("Pos")), Direction.byIndex(c.getByte("Direction"))))); + NBTHelper.iterateCompoundList(nbt.getList("Superglue", NBT.TAG_COMPOUND), c -> superglue.add( + Pair.of(NBTUtil.readBlockPos(c.getCompound("Pos")), Direction.from3DDataValue(c.getByte("Direction"))))); seats.clear(); NBTHelper.iterateCompoundList(nbt.getList("Seats", NBT.TAG_COMPOUND), c -> seats.add(NBTUtil.readBlockPos(c))); seatMapping.clear(); NBTHelper.iterateCompoundList(nbt.getList("Passengers", NBT.TAG_COMPOUND), - c -> seatMapping.put(NBTUtil.readUniqueId(NBTHelper.getINBT(c, "Id")), c.getInt("Seat"))); + c -> seatMapping.put(NBTUtil.loadUUID(NBTHelper.getINBT(c, "Id")), c.getInt("Seat"))); stabilizedSubContraptions.clear(); NBTHelper.iterateCompoundList(nbt.getList("SubContraptions", NBT.TAG_COMPOUND), - c -> stabilizedSubContraptions.put(c.getUniqueId("Id"), BlockFace.fromNBT(c.getCompound("Location")))); + c -> stabilizedSubContraptions.put(c.getUUID("Id"), BlockFace.fromNBT(c.getCompound("Location")))); storage.clear(); NBTHelper.iterateCompoundList(nbt.getList("Storage", NBT.TAG_COMPOUND), c -> storage @@ -724,6 +725,14 @@ public abstract class Contraption { NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", NBT.TAG_COMPOUND), c -> fluidStorage .put(NBTUtil.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data")))); + interactors.clear(); + NBTHelper.iterateCompoundList(nbt.getList("Interactors", NBT.TAG_COMPOUND), c -> { + BlockPos pos = NBTUtil.readBlockPos(c.getCompound("Pos")); + MovingInteractionBehaviour behaviour = AllInteractionBehaviours.of(getBlocks().get(pos).state.getBlock()); + if (behaviour != null) + interactors.put(pos, behaviour); + }); + if (spawnData) fluidStorage.forEach((pos, mfs) -> { TileEntity tileEntity = presentTileEntities.get(pos); @@ -748,7 +757,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")) @@ -782,7 +791,7 @@ public abstract class Contraption { CompoundNBT c = new CompoundNBT(); c.put("Pos", NBTUtil.writeBlockPos(glueEntry.getKey())); c.putByte("Direction", (byte) glueEntry.getValue() - .getIndex()); + .get3DDataValue()); superglueNBT.add(c); } @@ -808,17 +817,24 @@ public abstract class Contraption { fluidStorageNBT.add(c); } + ListNBT interactorNBT = new ListNBT(); + for (BlockPos pos : interactors.keySet()) { + CompoundNBT c = new CompoundNBT(); + c.put("Pos", NBTUtil.writeBlockPos(pos)); + interactorNBT.add(c); + } + nbt.put("Seats", NBTHelper.writeCompoundList(getSeats(), NBTUtil::writeBlockPos)); nbt.put("Passengers", NBTHelper.writeCompoundList(getSeatMapping().entrySet(), e -> { CompoundNBT tag = new CompoundNBT(); - tag.put("Id", NBTUtil.fromUuid(e.getKey())); + tag.put("Id", NBTUtil.createUUID(e.getKey())); tag.putInt("Seat", e.getValue()); return tag; })); nbt.put("SubContraptions", NBTHelper.writeCompoundList(stabilizedSubContraptions.entrySet(), e -> { CompoundNBT tag = new CompoundNBT(); - tag.putUniqueId("Id", e.getKey()); + tag.putUUID("Id", e.getKey()); tag.put("Location", e.getValue() .serializeNBT()); return tag; @@ -826,6 +842,7 @@ public abstract class Contraption { nbt.put("Blocks", blocksNBT); nbt.put("Actors", actorsNBT); + nbt.put("Interactors", interactorNBT); nbt.put("Superglue", superglueNBT); nbt.put("Storage", storageNBT); nbt.put("FluidStorage", fluidStorageNBT); @@ -851,7 +868,7 @@ public abstract class Contraption { for (BlockInfo block : this.blocks.values()) { int id = palette.idFor(block.state); CompoundNBT c = new CompoundNBT(); - c.putLong("Pos", block.pos.toLong()); + c.putLong("Pos", block.pos.asLong()); c.putInt("State", id); if (block.nbt != null) c.put("Data", block.nbt); @@ -859,7 +876,7 @@ public abstract class Contraption { } ListNBT paletteNBT = new ListNBT(); - palette.writePaletteToList(paletteNBT); + palette.write(paletteNBT); compound.put("Palette", paletteNBT); compound.put("BlockList", blockList); @@ -889,7 +906,7 @@ public abstract class Contraption { this.blocks.put(info.pos, info); - if (world.isRemote) { + if (world.isClientSide) { Block block = info.state.getBlock(); CompoundNBT tag = info.nbt; MovementBehaviour movementBehaviour = AllMovementBehaviours.of(block); @@ -900,10 +917,10 @@ public abstract class Contraption { tag.putInt("y", info.pos.getY()); tag.putInt("z", info.pos.getZ()); - TileEntity te = TileEntity.createFromTag(info.state, tag); + TileEntity te = TileEntity.loadStatic(info.state, tag); if (te == null) return; - te.setLocation(new ContraptionTileWorld(world, te, info), te.getPos()); + te.setLevelAndPosition(new ContraptionTileWorld(world, te, info), te.getBlockPos()); if (te instanceof KineticTileEntity) ((KineticTileEntity) te).setSpeed(0); te.getBlockState(); @@ -922,8 +939,8 @@ public abstract class Contraption { } private static BlockInfo readBlockInfo(CompoundNBT blockListEntry, HashMapPalette palette) { - return new BlockInfo(BlockPos.fromLong(blockListEntry.getLong("Pos")), - Objects.requireNonNull(palette.get(blockListEntry.getInt("State"))), + return new BlockInfo(BlockPos.of(blockListEntry.getLong("Pos")), + Objects.requireNonNull(palette.valueFor(blockListEntry.getInt("State"))), blockListEntry.contains("Data") ? blockListEntry.getCompound("Data") : null); } @@ -944,47 +961,61 @@ 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); + BlockPos add = block.pos.offset(anchor) + .offset(offset); if (customBlockRemoval(world, add, block.state)) continue; BlockState oldState = world.getBlockState(add); Block blockIn = oldState.getBlock(); if (block.state.getBlock() != blockIn) iterator.remove(); - world.removeTileEntity(add); + world.removeBlockEntity(add); int flags = BlockFlags.IS_MOVING | BlockFlags.NO_NEIGHBOR_DROPS | BlockFlags.UPDATE_NEIGHBORS | BlockFlags.BLOCK_UPDATE | BlockFlags.RERENDER_MAIN_THREAD; - if (blockIn instanceof IWaterLoggable && oldState.contains(BlockStateProperties.WATERLOGGED) - && oldState.get(BlockStateProperties.WATERLOGGED) - .booleanValue()) { - world.setBlockState(add, Blocks.WATER.getDefaultState(), flags); + if (blockIn instanceof IWaterLoggable && oldState.hasProperty(BlockStateProperties.WATERLOGGED) + && oldState.getValue(BlockStateProperties.WATERLOGGED)) { + world.setBlock(add, Blocks.WATER.defaultBlockState(), flags); continue; } - world.setBlockState(add, Blocks.AIR.getDefaultState(), flags); + world.setBlock(add, Blocks.AIR.defaultBlockState(), flags); } } for (BlockInfo block : blocks.values()) { - BlockPos add = block.pos.add(anchor) - .add(offset); + BlockPos add = block.pos.offset(anchor) + .offset(offset); // if (!shouldUpdateAfterMovement(block)) // 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 + world.sendBlockUpdated(add, block.state, Blocks.AIR.defaultBlockState(), flags); + + // when the blockstate is set to air, the block's POI data is removed, but markAndNotifyBlock tries to + // remove it again, so to prevent an error from being logged by double-removal we add the POI data back now + // (code copied from ServerWorld.onBlockStateChange) + ServerWorld serverWorld = (ServerWorld) world; + PointOfInterestType.forState(block.state) + .ifPresent(poiType -> { + world.getServer() + .execute(() -> { + serverWorld.getPoiManager() + .add(add, poiType); + DebugPacketSender.sendPoiAddedPacket(serverWorld, add); + }); + }); + + world.markAndNotifyBlock(add, world.getChunkAt(add), block.state, Blocks.AIR.defaultBlockState(), flags, + 512); + block.state.updateIndirectNeighbourShapes(world, add, flags & -2); } } 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); @@ -995,27 +1026,27 @@ public abstract class Contraption { if (nonBrittles) for (Direction face : Iterate.directions) - state = state.updatePostPlacement(face, world.getBlockState(targetPos.offset(face)), world, - targetPos, targetPos.offset(face)); + state = state.updateShape(face, world.getBlockState(targetPos.relative(face)), world, targetPos, + targetPos.relative(face)); BlockState blockState = world.getBlockState(targetPos); - if (blockState.getBlockHardness(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) + if (blockState.getDestroySpeed(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) .isEmpty() && !blockState.getCollisionShape(world, targetPos) .isEmpty())) { if (targetPos.getY() == 0) - targetPos = targetPos.up(); - world.playEvent(2001, targetPos, Block.getStateId(state)); - Block.spawnDrops(state, world, targetPos, null); + targetPos = targetPos.above(); + world.levelEvent(2001, targetPos, Block.getId(state)); + Block.dropResources(state, world, targetPos, null); continue; } - if (state.getBlock() instanceof IWaterLoggable && state.contains(BlockStateProperties.WATERLOGGED)) { + if (state.getBlock() instanceof IWaterLoggable && state.hasProperty(BlockStateProperties.WATERLOGGED)) { FluidState FluidState = world.getFluidState(targetPos); - state = state.with(BlockStateProperties.WATERLOGGED, FluidState.getFluid() == Fluids.WATER); + state = state.setValue(BlockStateProperties.WATERLOGGED, FluidState.getType() == Fluids.WATER); } world.destroyBlock(targetPos, true); - world.setBlockState(targetPos, state, 3 | BlockFlags.IS_MOVING); + world.setBlock(targetPos, state, 3 | BlockFlags.IS_MOVING); boolean verticalRotation = transform.rotationAxis == null || transform.rotationAxis.isHorizontal(); verticalRotation = verticalRotation && transform.rotation != Rotation.NONE; @@ -1024,7 +1055,7 @@ public abstract class Contraption { world.destroyBlock(targetPos, true); } - TileEntity tileEntity = world.getTileEntity(targetPos); + TileEntity tileEntity = world.getBlockEntity(targetPos); CompoundNBT tag = block.nbt; if (tileEntity != null) tag = NBTProcessors.process(tileEntity, tag, false); @@ -1039,9 +1070,9 @@ public abstract class Contraption { } if (tileEntity instanceof FluidTankTileEntity && tag.contains("LastKnownPos")) - tag.put("LastKnownPos", NBTUtil.writeBlockPos(BlockPos.ZERO.down())); + tag.put("LastKnownPos", NBTUtil.writeBlockPos(BlockPos.ZERO.below())); - tileEntity.fromTag(block.state, tag); + tileEntity.load(block.state, tag); if (storage.containsKey(block.pos)) { MountedStorage mountedStorage = storage.get(block.pos); @@ -1055,6 +1086,8 @@ public abstract class Contraption { mountedStorage.addStorageToWorld(tileEntity); } } + + transform.apply(tileEntity); } } for (BlockInfo block : blocks.values()) { @@ -1065,8 +1098,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); @@ -1076,8 +1111,8 @@ public abstract class Contraption { SuperGlueEntity entity = new SuperGlueEntity(world, targetPos, targetFacing); if (entity.onValidSurface()) { - if (!world.isRemote) - world.addEntity(entity); + if (!world.isClientSide) + world.addFreshEntity(entity); } } } @@ -1086,7 +1121,7 @@ public abstract class Contraption { for (Entity seatedEntity : seatedEntities) { if (getSeatMapping().isEmpty()) continue; - Integer seatIndex = getSeatMapping().get(seatedEntity.getUniqueID()); + Integer seatIndex = getSeatMapping().get(seatedEntity.getUUID()); BlockPos seatPos = getSeats().get(seatIndex); seatPos = transform.apply(seatPos); if (!(world.getBlockState(seatPos) @@ -1189,6 +1224,10 @@ public abstract class Contraption { return actors; } + public Map getInteractors() { + return interactors; + } + public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) { MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos); if (mountedFluidStorage != null) @@ -1200,6 +1239,11 @@ public abstract class Contraption { return new EmptyLighter(this); } + public void invalidateColliders() { + simplifiedEntityColliders = Optional.empty(); + gatherBBsOffThread(); + } + private void gatherBBsOffThread() { getContraptionWorld(); simplifiedEntityColliderProvider = CompletableFuture.supplyAsync(() -> { @@ -1210,11 +1254,11 @@ public abstract class Contraption { VoxelShape collisionShape = info.state.getCollisionShape(world, localPos); if (collisionShape.isEmpty()) continue; - combinedShape = VoxelShapes.combine(combinedShape, - collisionShape.withOffset(localPos.getX(), localPos.getY(), localPos.getZ()), IBooleanFunction.OR); + combinedShape = VoxelShapes.joinUnoptimized(combinedShape, + collisionShape.move(localPos.getX(), localPos.getY(), localPos.getZ()), IBooleanFunction.OR); } - return combinedShape.simplify() - .toBoundingBoxList(); + return combinedShape.optimize() + .toAabbs(); }) .thenAccept(r -> { simplifiedEntityColliders = Optional.of(r); @@ -1235,7 +1279,7 @@ public abstract class Contraption { 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); @@ -1263,14 +1307,34 @@ public abstract class Contraption { @Override public BlockState getBlockState(BlockPos pos) { - if (!pos.equals(te.getPos())) - return Blocks.AIR.getDefaultState(); + if (!pos.equals(te.getBlockPos())) + return Blocks.AIR.defaultBlockState(); return info.state; } @Override - public boolean isBlockPresent(BlockPos pos) { - return pos.equals(te.getPos()); + public boolean isLoaded(BlockPos pos) { + return pos.equals(te.getBlockPos()); + } + } + + 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/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java index 0c0bee7e1..f07a194b1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java @@ -1,7 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import static net.minecraft.entity.Entity.collideBoundingBoxHeuristically; -import static net.minecraft.entity.Entity.horizontalMag; +import static net.minecraft.entity.Entity.getHorizontalDistanceSqr; import java.util.ArrayList; import java.util.List; @@ -60,7 +60,7 @@ public class ContraptionCollider { } static void collideEntities(AbstractContraptionEntity contraptionEntity) { - World world = contraptionEntity.getEntityWorld(); + World world = contraptionEntity.getCommandSenderWorld(); Contraption contraption = contraptionEntity.getContraption(); AxisAlignedBB bounds = contraptionEntity.getBoundingBox(); @@ -69,7 +69,7 @@ public class ContraptionCollider { if (bounds == null) return; - Vector3d contraptionPosition = contraptionEntity.getPositionVec(); + Vector3d contraptionPosition = contraptionEntity.position(); Vector3d contraptionMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec()); Vector3d anchorVec = contraptionEntity.getAnchorVec(); ContraptionRotationState rotation = null; @@ -77,8 +77,8 @@ public class ContraptionCollider { // After death, multiple refs to the client player may show up in the area boolean skipClientPlayer = false; - List entitiesWithinAABB = world.getEntitiesWithinAABB(Entity.class, bounds.grow(2) - .expand(0, 32, 0), contraptionEntity::canCollideWith); + List entitiesWithinAABB = world.getEntitiesOfClass(Entity.class, bounds.inflate(2) + .expandTowards(0, 32, 0), contraptionEntity::canCollideWith); for (Entity entity : entitiesWithinAABB) { PlayerType playerType = getPlayerType(entity); @@ -86,7 +86,7 @@ public class ContraptionCollider { continue; if (playerType == PlayerType.SERVER && entity instanceof ServerPlayerEntity) { - ((ServerPlayerEntity) entity).connection.floatingTickCount = 0; + ((ServerPlayerEntity) entity).connection.aboveGroundTickCount = 0; continue; } @@ -102,30 +102,30 @@ public class ContraptionCollider { Matrix3d rotationMatrix = rotation.asMatrix(); // Transform entity position and motion to local space - Vector3d entityPosition = entity.getPositionVec(); + Vector3d entityPosition = entity.position(); AxisAlignedBB entityBounds = entity.getBoundingBox(); - Vector3d motion = entity.getMotion(); + Vector3d motion = entity.getDeltaMovement(); float yawOffset = rotation.getYawOffset(); Vector3d position = getWorldToLocalTranslation(entity, anchorVec, rotationMatrix, yawOffset); // Prepare entity bounds - AxisAlignedBB localBB = entityBounds.offset(position) - .grow(1.0E-7D); + AxisAlignedBB localBB = entityBounds.move(position) + .inflate(1.0E-7D); OrientedBB obb = new OrientedBB(localBB); obb.setRotation(rotationMatrix); motion = motion.subtract(contraptionMotion); motion = rotationMatrix.transform(motion); - // Use simplified bbs when present + // Use simplified bbs when present final Vector3d motionCopy = motion; List collidableBBs = contraption.simplifiedEntityColliders.orElseGet(() -> { // Else find 'nearby' individual block shapes to collide with List bbs = new ArrayList<>(); ReuseableStream potentialHits = - getPotentiallyCollidedShapes(world, contraption, localBB.expand(motionCopy)); - potentialHits.createStream() - .forEach(shape -> shape.toBoundingBoxList() + getPotentiallyCollidedShapes(world, contraption, localBB.expandTowards(motionCopy)); + potentialHits.getStream() + .forEach(shape -> shape.toAabbs() .forEach(bbs::add)); return bbs; @@ -147,12 +147,12 @@ public class ContraptionCollider { Vector3d currentResponse = collisionResponse.getValue(); Vector3d currentCenter = obbCenter.add(currentResponse); - if (Math.abs(currentCenter.x - bb.getCenter().x) - entityBounds.getXSize() - 1 > bb.getXSize() / 2) + if (Math.abs(currentCenter.x - bb.getCenter().x) - entityBounds.getXsize() - 1 > bb.getXsize() / 2) continue; - if (Math.abs((currentCenter.y + motion.y) - bb.getCenter().y) - entityBounds.getYSize() - - 1 > bb.getYSize() / 2) + if (Math.abs((currentCenter.y + motion.y) - bb.getCenter().y) - entityBounds.getYsize() + - 1 > bb.getYsize() / 2) continue; - if (Math.abs(currentCenter.z - bb.getCenter().z) - entityBounds.getZSize() - 1 > bb.getZSize() / 2) + if (Math.abs(currentCenter.z - bb.getCenter().z) - entityBounds.getZsize() - 1 > bb.getZsize() / 2) continue; obb.setCenter(currentCenter); @@ -169,7 +169,7 @@ public class ContraptionCollider { Vector3d collisionPosition = intersect.getCollisionPosition(); if (!isTemporal) { - Vector3d separation = intersect.asSeparationVec(entity.stepHeight); + Vector3d separation = intersect.asSeparationVec(entity.maxUpStep); if (separation != null && !separation.equals(Vector3d.ZERO)) { collisionResponse.setValue(currentResponse.add(separation)); timeOfImpact = 0; @@ -198,12 +198,12 @@ public class ContraptionCollider { // Re-run collisions with horizontal offset collisionResponse.setValue(collisionResponse.getValue() - .mul(129 / 128f, 0, 129 / 128f)); + .multiply(129 / 128f, 0, 129 / 128f)); continue; } // Resolve collision - Vector3d entityMotion = entity.getMotion(); + Vector3d entityMotion = entity.getDeltaMovement(); Vector3d entityMotionNoTemporal = entityMotion; Vector3d collisionNormal = normal.getValue(); Vector3d collisionLocation = location.getValue(); @@ -230,7 +230,7 @@ public class ContraptionCollider { double slide = 0; if (!collisionLocation.equals(Vector3d.ZERO)) { - collisionLocation = collisionLocation.add(entity.getPositionVec() + collisionLocation = collisionLocation.add(entity.position() .add(entity.getBoundingBox() .getCenter()) .scale(.5f)); @@ -250,8 +250,8 @@ public class ContraptionCollider { boolean anyCollision = hardCollision || temporalCollision; if (bounce > 0 && hasNormal && anyCollision && bounceEntity(entity, collisionNormal, contraptionEntity, bounce)) { - entity.world.playSound(playerType == PlayerType.CLIENT ? (PlayerEntity) entity : null, - entity.getX(), entity.getY(), entity.getZ(), SoundEvents.BLOCK_SLIME_BLOCK_FALL, + entity.level.playSound(playerType == PlayerType.CLIENT ? (PlayerEntity) entity : null, + entity.getX(), entity.getY(), entity.getZ(), SoundEvents.SLIME_BLOCK_FALL, SoundCategory.BLOCKS, .5f, 1); continue; } @@ -259,53 +259,53 @@ public class ContraptionCollider { if (temporalCollision) { double idealVerticalMotion = motionResponse.y; if (idealVerticalMotion != entityMotion.y) { - entity.setMotion(entityMotion.mul(1, 0, 1) + entity.setDeltaMovement(entityMotion.multiply(1, 0, 1) .add(0, idealVerticalMotion, 0)); - entityMotion = entity.getMotion(); + entityMotion = entity.getDeltaMovement(); } } if (hardCollision) { - double motionX = entityMotion.getX(); - double motionY = entityMotion.getY(); - double motionZ = entityMotion.getZ(); - double intersectX = totalResponse.getX(); - double intersectY = totalResponse.getY(); - double intersectZ = totalResponse.getZ(); + double motionX = entityMotion.x(); + double motionY = entityMotion.y(); + double motionZ = entityMotion.z(); + double intersectX = totalResponse.x(); + double intersectY = totalResponse.y(); + double intersectZ = totalResponse.z(); double horizonalEpsilon = 1 / 128f; if (motionX != 0 && Math.abs(intersectX) > horizonalEpsilon && motionX > 0 == intersectX < 0) - entityMotion = entityMotion.mul(0, 1, 1); + entityMotion = entityMotion.multiply(0, 1, 1); if (motionY != 0 && intersectY != 0 && motionY > 0 == intersectY < 0) - entityMotion = entityMotion.mul(1, 0, 1) + entityMotion = entityMotion.multiply(1, 0, 1) .add(0, contraptionMotion.y, 0); if (motionZ != 0 && Math.abs(intersectZ) > horizonalEpsilon && motionZ > 0 == intersectZ < 0) - entityMotion = entityMotion.mul(1, 1, 0); + entityMotion = entityMotion.multiply(1, 1, 0); } if (bounce == 0 && slide > 0 && hasNormal && anyCollision && rotation.hasVerticalRotation()) { - double slideFactor = collisionNormal.mul(1, 0, 1) + double slideFactor = collisionNormal.multiply(1, 0, 1) .length() * 1.25f; - Vector3d motionIn = entityMotionNoTemporal.mul(0, .9, 0) + Vector3d motionIn = entityMotionNoTemporal.multiply(0, .9, 0) .add(0, -.01f, 0); - Vector3d slideNormal = collisionNormal.crossProduct(motionIn.crossProduct(collisionNormal)) + Vector3d slideNormal = collisionNormal.cross(motionIn.cross(collisionNormal)) .normalize(); - Vector3d newMotion = entityMotion.mul(.85, 0, .85) + Vector3d newMotion = entityMotion.multiply(.85, 0, .85) .add(slideNormal.scale((.2f + slide) * motionIn.length() * slideFactor) .add(0, -.1f - collisionNormal.y * .125f, 0)); - entity.setMotion(newMotion); - entityMotion = entity.getMotion(); + entity.setDeltaMovement(newMotion); + entityMotion = entity.getDeltaMovement(); } if (!hardCollision && surfaceCollision.isFalse()) continue; Vector3d allowedMovement = getAllowedMovement(totalResponse, entity); - entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y, + entity.setPos(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y, entityPosition.z + allowedMovement.z); - entityPosition = entity.getPositionVec(); + entityPosition = entity.position(); - entity.velocityChanged = true; + entity.hurtMarked = true; Vector3d contactPointMotion = Vector3d.ZERO; if (surfaceCollision.isTrue()) { @@ -316,21 +316,21 @@ public class ContraptionCollider { if (canWalk) entity.onGround = true; if (entity instanceof ItemEntity) - entityMotion = entityMotion.mul(.5f, 1, .5f); + entityMotion = entityMotion.multiply(.5f, 1, .5f); } contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition); allowedMovement = getAllowedMovement(contactPointMotion, entity); - entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y, + entity.setPos(entityPosition.x + allowedMovement.x, entityPosition.y, entityPosition.z + allowedMovement.z); } - entity.setMotion(entityMotion); + entity.setDeltaMovement(entityMotion); if (playerType != PlayerType.CLIENT) continue; - double d0 = entity.getX() - entity.prevPosX - contactPointMotion.x; - double d1 = entity.getZ() - entity.prevPosZ - contactPointMotion.z; + double d0 = entity.getX() - entity.xo - contactPointMotion.x; + double d1 = entity.getZ() - entity.zo - contactPointMotion.z; float limbSwing = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F; if (limbSwing > 1.0F) limbSwing = 1.0F; @@ -342,15 +342,15 @@ public class ContraptionCollider { static boolean bounceEntity(Entity entity, Vector3d normal, AbstractContraptionEntity contraption, double factor) { if (factor == 0) return false; - if (entity.bypassesLandingEffects()) + if (entity.isSuppressingBounce()) return false; - Vector3d contactPointMotion = contraption.getContactPointMotion(entity.getPositionVec()); - Vector3d motion = entity.getMotion().subtract(contactPointMotion); - Vector3d deltav = normal.scale(factor*2*motion.dotProduct(normal)); - if (deltav.dotProduct(deltav) < 0.1f) + Vector3d contactPointMotion = contraption.getContactPointMotion(entity.position()); + Vector3d motion = entity.getDeltaMovement().subtract(contactPointMotion); + Vector3d deltav = normal.scale(factor*2*motion.dot(normal)); + if (deltav.dot(deltav) < 0.1f) return false; - entity.setMotion(entity.getMotion().subtract(deltav)); + entity.setDeltaMovement(entity.getDeltaMovement().subtract(deltav)); return true; } @@ -363,8 +363,8 @@ public class ContraptionCollider { } public static Vector3d getWorldToLocalTranslation(Entity entity, Vector3d anchorVec, Matrix3d rotationMatrix, float yawOffset) { - Vector3d entityPosition = entity.getPositionVec(); - Vector3d centerY = new Vector3d(0, entity.getBoundingBox().getYSize() / 2, 0); + Vector3d entityPosition = entity.position(); + Vector3d centerY = new Vector3d(0, entity.getBoundingBox().getYsize() / 2, 0); Vector3d position = entityPosition; position = position.add(centerY); position = position.subtract(VecHelper.CENTER_OF_ORIGIN); @@ -399,38 +399,38 @@ public class ContraptionCollider { /** From Entity#getAllowedMovement **/ static Vector3d getAllowedMovement(Vector3d movement, Entity e) { AxisAlignedBB bb = e.getBoundingBox(); - ISelectionContext ctx = ISelectionContext.forEntity(e); - World world = e.world; + ISelectionContext ctx = ISelectionContext.of(e); + World world = e.level; VoxelShape voxelshape = world.getWorldBorder() - .getShape(); + .getCollisionShape(); Stream stream = - VoxelShapes.compare(voxelshape, VoxelShapes.create(bb.shrink(1.0E-7D)), IBooleanFunction.AND) + VoxelShapes.joinIsNotEmpty(voxelshape, VoxelShapes.create(bb.deflate(1.0E-7D)), IBooleanFunction.AND) ? Stream.empty() : Stream.of(voxelshape); - Stream stream1 = world.getEntityCollisions(e, bb.expand(movement), entity -> false); // FIXME: 1.15 equivalent translated correctly? + Stream stream1 = world.getEntityCollisions(e, bb.expandTowards(movement), entity -> false); // FIXME: 1.15 equivalent translated correctly? ReuseableStream reuseablestream = new ReuseableStream<>(Stream.concat(stream1, stream)); - Vector3d allowedMovement = movement.lengthSquared() == 0.0D ? movement + Vector3d allowedMovement = movement.lengthSqr() == 0.0D ? movement : collideBoundingBoxHeuristically(e, movement, bb, world, ctx, reuseablestream); boolean xDifferent = movement.x != allowedMovement.x; boolean yDifferent = movement.y != allowedMovement.y; boolean zDifferent = movement.z != allowedMovement.z; boolean notMovingUp = e.isOnGround() || yDifferent && movement.y < 0.0D; - if (e.stepHeight > 0.0F && notMovingUp && (xDifferent || zDifferent)) { - Vector3d allowedStep = collideBoundingBoxHeuristically(e, new Vector3d(movement.x, (double) e.stepHeight, movement.z), + if (e.maxUpStep > 0.0F && notMovingUp && (xDifferent || zDifferent)) { + Vector3d allowedStep = collideBoundingBoxHeuristically(e, new Vector3d(movement.x, (double) e.maxUpStep, movement.z), bb, world, ctx, reuseablestream); - Vector3d allowedStepGivenMovement = collideBoundingBoxHeuristically(e, new Vector3d(0.0D, (double) e.stepHeight, 0.0D), - bb.expand(movement.x, 0.0D, movement.z), world, ctx, reuseablestream); - if (allowedStepGivenMovement.y < (double) e.stepHeight) { + Vector3d allowedStepGivenMovement = collideBoundingBoxHeuristically(e, new Vector3d(0.0D, (double) e.maxUpStep, 0.0D), + bb.expandTowards(movement.x, 0.0D, movement.z), world, ctx, reuseablestream); + if (allowedStepGivenMovement.y < (double) e.maxUpStep) { Vector3d vec3 = collideBoundingBoxHeuristically(e, new Vector3d(movement.x, 0.0D, movement.z), - bb.offset(allowedStepGivenMovement), world, ctx, reuseablestream).add(allowedStepGivenMovement); - if (horizontalMag(vec3) > horizontalMag(allowedStep)) { + bb.move(allowedStepGivenMovement), world, ctx, reuseablestream).add(allowedStepGivenMovement); + if (getHorizontalDistanceSqr(vec3) > getHorizontalDistanceSqr(allowedStep)) { allowedStep = vec3; } } - if (horizontalMag(allowedStep) > horizontalMag(allowedMovement)) { + if (getHorizontalDistanceSqr(allowedStep) > getHorizontalDistanceSqr(allowedMovement)) { return allowedStep.add(collideBoundingBoxHeuristically(e, new Vector3d(0.0D, -allowedStep.y + movement.y, 0.0D), - bb.offset(allowedStep), world, ctx, reuseablestream)); + bb.move(allowedStep), world, ctx, reuseablestream)); } } @@ -440,7 +440,7 @@ public class ContraptionCollider { private static PlayerType getPlayerType(Entity entity) { if (!(entity instanceof PlayerEntity)) return PlayerType.NONE; - if (!entity.world.isRemote) + if (!entity.level.isClientSide) return PlayerType.SERVER; MutableBoolean isClient = new MutableBoolean(false); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> isClient.setValue(isClientPlayerEntity(entity))); @@ -455,17 +455,17 @@ public class ContraptionCollider { private static ReuseableStream getPotentiallyCollidedShapes(World world, Contraption contraption, AxisAlignedBB localBB) { - double height = localBB.getYSize(); - double width = localBB.getXSize(); + double height = localBB.getYsize(); + double width = localBB.getXsize(); double horizontalFactor = (height > width && width != 0) ? height / width : 1; double verticalFactor = (width > height && height != 0) ? width / height : 1; - AxisAlignedBB blockScanBB = localBB.grow(0.5f); - blockScanBB = blockScanBB.grow(horizontalFactor, verticalFactor, horizontalFactor); + AxisAlignedBB blockScanBB = localBB.inflate(0.5f); + blockScanBB = blockScanBB.inflate(horizontalFactor, verticalFactor, horizontalFactor); BlockPos min = new BlockPos(blockScanBB.minX, blockScanBB.minY, blockScanBB.minZ); BlockPos max = new BlockPos(blockScanBB.maxX, blockScanBB.maxY, blockScanBB.maxZ); - ReuseableStream potentialHits = new ReuseableStream<>(BlockPos.getAllInBox(min, max) + ReuseableStream potentialHits = new ReuseableStream<>(BlockPos.betweenClosedStream(min, max) .filter(contraption.getBlocks()::containsKey) .map(p -> { BlockState blockState = contraption.getBlocks() @@ -473,7 +473,7 @@ public class ContraptionCollider { BlockPos pos = contraption.getBlocks() .get(p).pos; VoxelShape collisionShape = blockState.getCollisionShape(world, p); - return collisionShape.withOffset(pos.getX(), pos.getY(), pos.getZ()); + return collisionShape.move(pos.getX(), pos.getY(), pos.getZ()); }) .filter(Predicates.not(VoxelShape::isEmpty))); @@ -484,11 +484,11 @@ public class ContraptionCollider { if (!contraptionEntity.supportsTerrainCollision()) return false; - World world = contraptionEntity.getEntityWorld(); - Vector3d motion = contraptionEntity.getMotion(); + World world = contraptionEntity.getCommandSenderWorld(); + Vector3d motion = contraptionEntity.getDeltaMovement(); TranslatingContraption contraption = (TranslatingContraption) contraptionEntity.getContraption(); AxisAlignedBB bounds = contraptionEntity.getBoundingBox(); - Vector3d position = contraptionEntity.getPositionVec(); + Vector3d position = contraptionEntity.position(); BlockPos gridPos = new BlockPos(position); if (contraption == null) @@ -498,37 +498,37 @@ public class ContraptionCollider { if (motion.equals(Vector3d.ZERO)) return false; - Direction movementDirection = Direction.getFacingFromVector(motion.x, motion.y, motion.z); + Direction movementDirection = Direction.getNearest(motion.x, motion.y, motion.z); // Blocks in the world if (movementDirection.getAxisDirection() == AxisDirection.POSITIVE) - gridPos = gridPos.offset(movementDirection); + gridPos = gridPos.relative(movementDirection); if (isCollidingWithWorld(world, contraption, gridPos, movementDirection)) return true; // Other moving Contraptions - for (ControlledContraptionEntity otherContraptionEntity : world.getEntitiesWithinAABB( - ControlledContraptionEntity.class, bounds.grow(1), e -> !e.equals(contraptionEntity))) { + for (ControlledContraptionEntity otherContraptionEntity : world.getEntitiesOfClass( + ControlledContraptionEntity.class, bounds.inflate(1), e -> !e.equals(contraptionEntity))) { if (!otherContraptionEntity.supportsTerrainCollision()) continue; - Vector3d otherMotion = otherContraptionEntity.getMotion(); + Vector3d otherMotion = otherContraptionEntity.getDeltaMovement(); TranslatingContraption otherContraption = (TranslatingContraption) otherContraptionEntity.getContraption(); AxisAlignedBB otherBounds = otherContraptionEntity.getBoundingBox(); - Vector3d otherPosition = otherContraptionEntity.getPositionVec(); + Vector3d otherPosition = otherContraptionEntity.position(); if (otherContraption == null) return false; if (otherBounds == null) return false; - if (!bounds.offset(motion) - .intersects(otherBounds.offset(otherMotion))) + if (!bounds.move(motion) + .intersects(otherBounds.move(otherMotion))) continue; for (BlockPos colliderPos : contraption.getColliders(world, movementDirection)) { - colliderPos = colliderPos.add(gridPos) + colliderPos = colliderPos.offset(gridPos) .subtract(new BlockPos(otherPosition)); if (!otherContraption.getBlocks() .containsKey(colliderPos)) @@ -543,9 +543,9 @@ public class ContraptionCollider { public static boolean isCollidingWithWorld(World world, TranslatingContraption contraption, BlockPos anchor, Direction movementDirection) { for (BlockPos pos : contraption.getColliders(world, movementDirection)) { - BlockPos colliderPos = pos.add(anchor); + BlockPos colliderPos = pos.offset(anchor); - if (!world.isBlockPresent(colliderPos)) + if (!world.isLoaded(colliderPos)) return true; BlockState collidedState = world.getBlockState(colliderPos); 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..8be7f7b41 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 @@ -2,63 +2,44 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.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 - public ResourceLocation getEntityTexture(C entity) { + public ResourceLocation getTextureLocation(C entity) { return null; } @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); Contraption contraption = entity.getContraption(); if (contraption != null) { - ContraptionRenderDispatcher.render(entity, ms, buffers, msLocal, contraption); + ContraptionRenderDispatcher.renderFromEntity(entity, contraption, 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/ContraptionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandler.java index a21df0650..ef0a9dedd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandler.java @@ -27,8 +27,8 @@ public class ContraptionHandler { static WorldAttached> queuedAdditions; static { - loadedContraptions = new WorldAttached<>(HashMap::new); - queuedAdditions = new WorldAttached<>(() -> ObjectLists.synchronize(new ObjectArrayList<>())); + loadedContraptions = new WorldAttached<>($ -> new HashMap<>()); + queuedAdditions = new WorldAttached<>($ -> ObjectLists.synchronize(new ObjectArrayList<>())); } public static void tick(World world) { @@ -36,7 +36,7 @@ public class ContraptionHandler { List queued = queuedAdditions.get(world); for (AbstractContraptionEntity contraptionEntity : queued) - map.put(contraptionEntity.getEntityId(), new WeakReference<>(contraptionEntity)); + map.put(contraptionEntity.getId(), new WeakReference<>(contraptionEntity)); queued.clear(); Collection> values = map.values(); @@ -58,14 +58,14 @@ public class ContraptionHandler { } public static void entitiesWhoJustDismountedGetSentToTheRightLocation(LivingEntity entityLiving, World world) { - if (world.isRemote) + if (world.isClientSide) return; CompoundNBT data = entityLiving.getPersistentData(); if (!data.contains("ContraptionDismountLocation")) return; Vector3d position = VecHelper.readNBT(data.getList("ContraptionDismountLocation", NBT.TAG_DOUBLE)); - if (entityLiving.getRidingEntity() == null) - entityLiving.setPositionAndUpdate(position.x, position.y, position.z); + if (entityLiving.getVehicle() == null) + entityLiving.teleportTo(position.x, position.y, position.z); data.remove("ContraptionDismountLocation"); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java index 3ab9bb670..deb7ec47c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java @@ -52,8 +52,8 @@ public class ContraptionHandlerClient { } float limbSwing = data.getFloat("OverrideLimbSwing"); - remotePlayer.prevPosX = remotePlayer.getX() - (limbSwing / 4); - remotePlayer.prevPosZ = remotePlayer.getZ(); + remotePlayer.xo = remotePlayer.getX() - (limbSwing / 4); + remotePlayer.zo = remotePlayer.getZ(); } @SubscribeEvent @@ -65,20 +65,20 @@ public class ContraptionHandlerClient { return; if (player.isPassenger()) return; - if (mc.world == null) + if (mc.level == null) return; if (!event.isUseItem()) return; Vector3d origin = RaycastHelper.getTraceOrigin(player); - double reach = mc.playerController.getBlockReachDistance(); - if (mc.objectMouseOver != null && mc.objectMouseOver.getHitVec() != null) - reach = Math.min(mc.objectMouseOver.getHitVec() + double reach = mc.gameMode.getPickRange(); + if (mc.hitResult != null && mc.hitResult.getLocation() != null) + reach = Math.min(mc.hitResult.getLocation() .distanceTo(origin), reach); Vector3d target = RaycastHelper.getTraceTarget(player, reach, origin); - for (AbstractContraptionEntity contraptionEntity : mc.world - .getEntitiesWithinAABB(AbstractContraptionEntity.class, new AxisAlignedBB(origin, target))) { + for (AbstractContraptionEntity contraptionEntity : mc.level + .getEntitiesOfClass(AbstractContraptionEntity.class, new AxisAlignedBB(origin, target))) { Vector3d localOrigin = contraptionEntity.toLocalVector(origin, 1); Vector3d localTarget = contraptionEntity.toLocalVector(target, 1); @@ -91,10 +91,10 @@ public class ContraptionHandlerClient { if (blockInfo == null) return false; BlockState state = blockInfo.state; - VoxelShape raytraceShape = state.getShape(Minecraft.getInstance().world, BlockPos.ZERO.down()); + VoxelShape raytraceShape = state.getShape(Minecraft.getInstance().level, BlockPos.ZERO.below()); if (raytraceShape.isEmpty()) return false; - BlockRayTraceResult rayTrace = raytraceShape.rayTrace(localOrigin, localTarget, p); + BlockRayTraceResult rayTrace = raytraceShape.clip(localOrigin, localTarget, p); if (rayTrace != null) { mutableResult.setValue(rayTrace); return true; @@ -107,8 +107,8 @@ public class ContraptionHandlerClient { BlockRayTraceResult rayTraceResult = mutableResult.getValue(); Hand hand = event.getHand(); - Direction face = rayTraceResult.getFace(); - BlockPos pos = rayTraceResult.getPos(); + Direction face = rayTraceResult.getDirection(); + BlockPos pos = rayTraceResult.getBlockPos(); if (!contraptionEntity.handlePlayerInteraction(player, pos, face, hand)) return; 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..7b130e908 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; @@ -24,7 +24,7 @@ public abstract class ContraptionLighter implements Light lightVolume = new LightVolume(contraptionBoundsToVolume(bounds.copy())); - lightVolume.initialize(contraption.entity.world); + lightVolume.initialize(contraption.entity.level); scheduleRebuild = true; startListening(); @@ -32,7 +32,7 @@ public abstract class ContraptionLighter implements Light public void tick(RenderedContraption owner) { if (scheduleRebuild) { - lightVolume.initialize(owner.contraption.entity.world); + lightVolume.initialize(owner.contraption.entity.level); scheduleRebuild = false; } } @@ -62,4 +62,8 @@ public abstract class ContraptionLighter implements Light return bounds; } + + public GridAlignedBB getBounds() { + return bounds; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java index bff9499dd..28d9dc99b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java @@ -29,7 +29,7 @@ public class ContraptionWorld extends WrappedWorld { if (blockInfo != null) return blockInfo.state; - return Blocks.AIR.getDefaultState(); + return Blocks.AIR.defaultBlockState(); } @Override @@ -43,7 +43,7 @@ public class ContraptionWorld extends WrappedWorld { } @Override - public void playSound(double x, double y, double z, SoundEvent p_184134_7_, SoundCategory p_184134_8_, float p_184134_9_, float p_184134_10_, boolean p_184134_11_) { - world.playSound(x, y, z, p_184134_7_, p_184134_8_, p_184134_9_, p_184134_10_, p_184134_11_); + public void playLocalSound(double x, double y, double z, SoundEvent p_184134_7_, SoundCategory p_184134_8_, float p_184134_9_, float p_184134_10_, boolean p_184134_11_) { + world.playLocalSound(x, y, z, p_184134_7_, p_184134_8_, p_184134_9_, p_184134_10_, p_184134_11_); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java index 4d70938b2..c27d87133 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java @@ -2,10 +2,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -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); @@ -51,7 +52,7 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { @Override public Vector3d getContactPointMotion(Vector3d globalContactPoint) { if (contraption instanceof TranslatingContraption) - return getMotion(); + return getDeltaMovement(); return super.getContactPointMotion(globalContactPoint); } @@ -123,19 +124,20 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { } @Override - public void setPositionAndUpdate(double p_70634_1_, double p_70634_3_, double p_70634_5_) {} + public void teleportTo(double p_70634_1_, double p_70634_3_, double p_70634_5_) {} @Override @OnlyIn(Dist.CLIENT) - public void setPositionAndRotationDirect(double x, double y, double z, float yw, float pt, int inc, boolean t) {} + public void lerpTo(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)) + if (!level.isLoaded(controllerPos)) return; IControlContraption controller = getController(); if (controller == null) { @@ -144,11 +146,11 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { } if (!controller.isAttachedTo(this)) { controller.attach(this); - if (world.isRemote) - setPosition(getX(), getY(), getZ()); + if (level.isClientSide) + setPos(getX(), getY(), getZ()); } - Vector3d motion = getMotion(); + Vector3d motion = getDeltaMovement(); move(motion.x, motion.y, motion.z); if (ContraptionCollider.collideBlocks(this)) getController().collided(); @@ -166,12 +168,12 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { BearingContraption bc = (BearingContraption) contraption; Direction facing = bc.getFacing(); Vector3d activeAreaOffset = actor.getActiveAreaOffset(context); - if (!activeAreaOffset.mul(VecHelper.axisAlingedPlaneOf(Vector3d.of(facing.getDirectionVec()))) + if (!activeAreaOffset.multiply(VecHelper.axisAlingedPlaneOf(Vector3d.atLowerCornerOf(facing.getNormal()))) .equals(Vector3d.ZERO)) 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.atLowerCornerOf(facing.getNormal()).scale(angleDelta / 360.0); context.relativeMotion = context.motion; int timer = context.data.getInt("StationaryTimer"); if (timer > 0) { @@ -186,9 +188,9 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { protected IControlContraption getController() { if (controllerPos == null) return null; - if (!world.isBlockPresent(controllerPos)) + if (!level.isLoaded(controllerPos)) return null; - TileEntity te = world.getTileEntity(controllerPos); + TileEntity te = level.getBlockEntity(controllerPos); if (!(te instanceof IControlContraption)) return null; return (IControlContraption) te; @@ -218,7 +220,7 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { @Override protected void handleStallInformation(float x, float y, float z, float angle) { - setPos(x, y, z); + setPosRaw(x, y, z); this.angle = angle; } @@ -229,8 +231,8 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { Axis axis = getRotationAxis(); for (MatrixStack stack : matrixStacks) - MatrixStacker.of(stack) - .nudge(getEntityId()) + MatrixTransformStack.of(stack) + .nudge(getId()) .centre() .rotate(angle, axis) .unCentre(); 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..02d7e94cc 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 @@ -2,10 +2,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import java.util.function.BiPredicate; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.block.BlockState; import net.minecraft.state.properties.BlockStateProperties; @@ -21,13 +21,13 @@ public class DirectionalExtenderScrollOptionSlot extends CenteredSideValueBoxTra @Override protected Vector3d getLocalOffset(BlockState state) { return super.getLocalOffset(state) - .add(Vector3d.of(state.get(BlockStateProperties.FACING).getDirectionVec()).scale(-2 / 16f)); + .add(Vector3d.atLowerCornerOf(state.getValue(BlockStateProperties.FACING).getNormal()).scale(-2 / 16f)); } @Override protected void rotate(BlockState state, MatrixStack ms) { if (!getSide().getAxis().isHorizontal()) - MatrixStacker.of(ms).rotateY(AngleHelper.horizontalAngle(state.get(BlockStateProperties.FACING)) - 90); + MatrixTransformStack.of(ms).rotateY(AngleHelper.horizontalAngle(state.getValue(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/IDisplayAssemblyExceptions.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java index 2bbd13f3a..80c154e7e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java @@ -24,15 +24,16 @@ public interface IDisplayAssemblyExceptions { if (!tooltip.isEmpty()) tooltip.add(StringTextComponent.EMPTY); - tooltip.add(IHaveGoggleInformation.componentSpacing.copy().append(Lang.translate("gui.assembly.exception").formatted(TextFormatting.GOLD))); + tooltip.add(IHaveGoggleInformation.componentSpacing.plainCopy().append(Lang.translate("gui.assembly.exception").withStyle(TextFormatting.GOLD))); - String text = TooltipHelper.getUnformattedDeepText(e.component); + String text = e.component.getString(); Arrays.stream(text.split("\n")) .forEach(l -> TooltipHelper.cutStringTextComponent(l, GRAY, WHITE) - .forEach(c -> tooltip.add(IHaveGoggleInformation.componentSpacing.copy().append(c)))); + .forEach(c -> tooltip.add(IHaveGoggleInformation.componentSpacing.plainCopy().append(c)))); return true; } AssemblyException getLastAssemblyException(); + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableTE.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableTE.java new file mode 100644 index 000000000..64d77b497 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableTE.java @@ -0,0 +1,7 @@ +package com.simibubi.create.content.contraptions.components.structureMovement; + +public interface ITransformableTE { + + void transform(StructureTransform transform); + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedFluidStorage.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedFluidStorage.java index 1709ae7d9..8ef8f2a3a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedFluidStorage.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedFluidStorage.java @@ -63,7 +63,7 @@ public class MountedFluidStorage { else if (sendPacket) { sendPacket = false; AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), - new ContraptionFluidPacket(entity.getEntityId(), pos, tank.getFluid())); + new ContraptionFluidPacket(entity.getId(), pos, tank.getFluid())); packetCooldown = 8; } return; 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..cc9769c8a 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) { @@ -60,21 +62,21 @@ public class MountedStorage { // Split double chests if (te.getType() == TileEntityType.CHEST || te.getType() == TileEntityType.TRAPPED_CHEST) { if (te.getBlockState() - .get(ChestBlock.TYPE) != ChestType.SINGLE) - te.getWorld() - .setBlockState(te.getPos(), te.getBlockState() - .with(ChestBlock.TYPE, ChestType.SINGLE)); - te.updateContainingBlockInfo(); + .getValue(ChestBlock.TYPE) != ChestType.SINGLE) + te.getLevel() + .setBlockAndUpdate(te.getBlockPos(), te.getBlockState() + .setValue(ChestBlock.TYPE, ChestType.SINGLE)); + te.clearCache(); } // Split double flexcrates if (AllTileEntities.ADJUSTABLE_CRATE.is(te)) { if (te.getBlockState() - .get(AdjustableCrateBlock.DOUBLE)) - te.getWorld() - .setBlockState(te.getPos(), te.getBlockState() - .with(AdjustableCrateBlock.DOUBLE, false)); - te.updateContainingBlockInfo(); + .getValue(AdjustableCrateBlock.DOUBLE)) + te.getLevel() + .setBlockAndUpdate(te.getBlockPos(), te.getBlockState() + .setValue(AdjustableCrateBlock.DOUBLE, false)); + te.clearCache(); } IItemHandler teHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) @@ -144,7 +146,7 @@ public class MountedStorage { storage.valid = true; if (nbt.contains("Bottomless")) { - ItemStack providedStack = ItemStack.read(nbt.getCompound("ProvidedStack")); + ItemStack providedStack = ItemStack.of(nbt.getCompound("ProvidedStack")); storage.handler = new BottomlessItemHandler(() -> providedStack); return storage; } 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..08b834108 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,11 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import javax.annotation.Nullable; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.jozufozu.flywheel.backend.material.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.config.AllConfigs; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.entity.item.ItemEntity; @@ -32,15 +34,19 @@ public abstract class MovementBehaviour { } public void dropItem(MovementContext context, ItemStack stack) { - ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, stack, false); + ItemStack remainder; + if (AllConfigs.SERVER.kinetics.moveItemsToStorage.get()) + remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, stack, false); + else + remainder = stack; if (remainder.isEmpty()) return; Vector3d vec = context.position; ItemEntity itemEntity = new ItemEntity(context.world, vec.x, vec.y, vec.z, remainder); - itemEntity.setMotion(context.motion.add(0, 0.5f, 0) - .scale(context.world.rand.nextFloat() * .3f)); - context.world.addEntity(itemEntity); + itemEntity.setDeltaMovement(context.motion.add(0, 0.5f, 0) + .scale(context.world.random.nextFloat() * .3f)); + context.world.addFreshEntity(itemEntity); } public void stopMoving(MovementContext context) { @@ -60,12 +66,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/MovementContext.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementContext.java index fa26f9ca1..bfad9ad5a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementContext.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementContext.java @@ -49,7 +49,7 @@ public class MovementContext { public float getAnimationSpeed() { int modifier = 1000; double length = -motion.length(); - if (world.isRemote && contraption.stalled) + if (world.isClientSide && contraption.stalled) return 700; if (Math.abs(length) < 1 / 512f) return 0; @@ -75,7 +75,7 @@ public class MovementContext { nbt.put("Position", VecHelper.writeNBT(position)); nbt.putBoolean("Stall", stall); nbt.putBoolean("FirstMovement", firstMovement); - nbt.put("Data", data); + nbt.put("Data", data.copy()); return nbt; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java new file mode 100644 index 000000000..67eeb10ff --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.contraptions.components.structureMovement; + +import org.apache.commons.lang3.tuple.MutablePair; + +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.feature.template.Template.BlockInfo; + +public abstract class MovingInteractionBehaviour { + + public MovingInteractionBehaviour() {} + + protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index, BlockInfo info, + MovementContext ctx) { + contraptionEntity.contraption.actors.remove(index); + contraptionEntity.contraption.actors.add(index, MutablePair.of(info, ctx)); + ContraptionRenderDispatcher.invalidate(contraptionEntity.contraption); + } + + protected void setContraptionBlockData(AbstractContraptionEntity contraptionEntity, BlockPos pos, BlockInfo info) { + contraptionEntity.contraption.blocks.put(pos, info); + ContraptionRenderDispatcher.invalidate(contraptionEntity.contraption); + } + + public boolean handlePlayerInteraction(PlayerEntity player, Hand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + return true; + } + +} 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..800ee2a59 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) { @@ -14,7 +14,7 @@ public class NonStationaryLighter extends ContraptionLigh GridAlignedBB contraptionBounds = getContraptionBounds(); if (!contraptionBounds.sameAs(bounds)) { - lightVolume.move(contraption.entity.world, contraptionBoundsToVolume(contraptionBounds)); + lightVolume.move(contraption.entity.level, contraptionBoundsToVolume(contraptionBounds)); bounds = contraptionBounds; startListening(); @@ -25,7 +25,7 @@ public class NonStationaryLighter extends ContraptionLigh public GridAlignedBB getContraptionBounds() { GridAlignedBB bb = GridAlignedBB.from(contraption.bounds); - bb.translate(contraption.entity.getBlockPos()); + bb.translate(contraption.entity.blockPosition()); return bb; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java index 49b4d3594..47c10d668 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java @@ -7,20 +7,22 @@ import java.util.UUID; import javax.annotation.Nullable; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; +import com.simibubi.create.content.contraptions.components.structureMovement.train.MinecartSim2020; 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.item.ItemHelper; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.block.AbstractRailBlock; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -34,6 +36,7 @@ import net.minecraft.nbt.ListNBT; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.state.properties.RailShape; import net.minecraft.tags.BlockTags; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -52,12 +55,12 @@ import net.minecraftforge.common.util.LazyOptional; */ public class OrientedContraptionEntity extends AbstractContraptionEntity { - private static final Ingredient FUEL_ITEMS = Ingredient.fromItems(Items.COAL, Items.CHARCOAL); + private static final Ingredient FUEL_ITEMS = Ingredient.of(Items.COAL, Items.CHARCOAL); private static final DataParameter> COUPLING = - EntityDataManager.createKey(OrientedContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID); + EntityDataManager.defineId(OrientedContraptionEntity.class, DataSerializers.OPTIONAL_UUID); private static final DataParameter INITIAL_ORIENTATION = - EntityDataManager.createKey(OrientedContraptionEntity.class, DataSerializers.DIRECTION); + EntityDataManager.defineId(OrientedContraptionEntity.class, DataSerializers.DIRECTION); protected Vector3d motionBeforeStall; protected boolean forceAngle; @@ -84,18 +87,17 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { initialYawOffset = -1; } - public static OrientedContraptionEntity create(World world, Contraption contraption, - Optional initialOrientation) { + public static OrientedContraptionEntity create(World world, Contraption contraption, 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; @@ -103,16 +105,16 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } public void setInitialOrientation(Direction direction) { - dataManager.set(INITIAL_ORIENTATION, direction); + entityData.set(INITIAL_ORIENTATION, direction); } public Direction getInitialOrientation() { - return dataManager.get(INITIAL_ORIENTATION); + return entityData.get(INITIAL_ORIENTATION); } public void deferOrientation(Direction newInitialAngle) { - dataManager.set(INITIAL_ORIENTATION, Direction.UP); - yaw = initialYawOffset = newInitialAngle.getHorizontalAngle(); + entityData.set(INITIAL_ORIENTATION, Direction.UP); + yaw = initialYawOffset = newInitialAngle.toYRot(); } @Override @@ -121,15 +123,15 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } public float getInitialYaw() { - return (isInitialOrientationPresent() ? dataManager.get(INITIAL_ORIENTATION) : Direction.SOUTH) - .getHorizontalAngle(); + return (isInitialOrientationPresent() ? entityData.get(INITIAL_ORIENTATION) : Direction.SOUTH) + .toYRot(); } @Override - protected void registerData() { - super.registerData(); - dataManager.register(COUPLING, Optional.empty()); - dataManager.register(INITIAL_ORIENTATION, Direction.UP); + protected void defineSynchedData() { + super.defineSynchedData(); + entityData.define(COUPLING, Optional.empty()); + entityData.define(INITIAL_ORIENTATION, Direction.UP); } @Override @@ -150,7 +152,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { @Override public void stopRiding() { - if (!world.isRemote && isAlive()) + if (!level.isClientSide && isAlive()) disassemble(); super.stopRiding(); } @@ -174,10 +176,10 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { motionBeforeStall = new Vector3d(vecNBT.getDouble(0), vecNBT.getDouble(1), vecNBT.getDouble(2)); if (!motionBeforeStall.equals(Vector3d.ZERO)) targetYaw = prevYaw = yaw += yawFromVector(motionBeforeStall); - setMotion(Vector3d.ZERO); + setDeltaMovement(Vector3d.ZERO); } - setCouplingId(compound.contains("OnCoupling") ? compound.getUniqueId("OnCoupling") : null); + setCouplingId(compound.contains("OnCoupling") ? compound.getUUID("OnCoupling") : null); } @Override @@ -186,9 +188,9 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { if (motionBeforeStall != null) compound.put("CachedMotion", - newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); + newDoubleList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); - Direction optional = dataManager.get(INITIAL_ORIENTATION); + Direction optional = entityData.get(INITIAL_ORIENTATION); if (optional.getAxis() .isHorizontal()) NBTHelper.writeEnum(compound, "InitialOrientation", optional); @@ -202,18 +204,18 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { compound.putFloat("Pitch", pitch); if (getCouplingId() != null) - compound.putUniqueId("OnCoupling", getCouplingId()); + compound.putUUID("OnCoupling", getCouplingId()); } @Override - public void notifyDataManagerChange(DataParameter key) { - super.notifyDataManagerChange(key); + public void onSyncedDataUpdated(DataParameter key) { + super.onSyncedDataUpdated(key); if (key == INITIAL_ORIENTATION && isInitialOrientationPresent() && !manuallyPlaced) startAtInitialYaw(); } public boolean isInitialOrientationPresent() { - return dataManager.get(INITIAL_ORIENTATION) + return entityData.get(INITIAL_ORIENTATION) .getAxis() .isHorizontal(); } @@ -230,30 +232,30 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { @Override public Vector3d applyRotation(Vector3d localPos, float partialTicks) { localPos = VecHelper.rotate(localPos, getInitialYaw(), Axis.Y); - localPos = VecHelper.rotate(localPos, getPitch(partialTicks), Axis.Z); - localPos = VecHelper.rotate(localPos, getYaw(partialTicks), Axis.Y); + localPos = VecHelper.rotate(localPos, getViewXRot(partialTicks), Axis.Z); + localPos = VecHelper.rotate(localPos, getViewYRot(partialTicks), Axis.Y); return localPos; } @Override public Vector3d reverseRotation(Vector3d localPos, float partialTicks) { - localPos = VecHelper.rotate(localPos, -getYaw(partialTicks), Axis.Y); - localPos = VecHelper.rotate(localPos, -getPitch(partialTicks), Axis.Z); + localPos = VecHelper.rotate(localPos, -getViewYRot(partialTicks), Axis.Y); + localPos = VecHelper.rotate(localPos, -getViewXRot(partialTicks), Axis.Z); localPos = VecHelper.rotate(localPos, -getInitialYaw(), Axis.Y); return localPos; } - public float getYaw(float partialTicks) { + public float getViewYRot(float partialTicks) { return -(partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw)); } - public float getPitch(float partialTicks) { + public float getViewXRot(float partialTicks) { return partialTicks == 1.0F ? pitch : angleLerp(partialTicks, prevPitch, pitch); } @Override protected void tickContraption() { - Entity e = getRidingEntity(); + Entity e = getVehicle(); if (e == null) return; @@ -267,8 +269,8 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } Entity riding = e; - while (riding.getRidingEntity() != null && !(contraption instanceof StabilizedContraption)) - riding = riding.getRidingEntity(); + while (riding.getVehicle() != null && !(contraption instanceof StabilizedContraption)) + riding = riding.getVehicle(); boolean isOnCoupling = false; UUID couplingId = getCouplingId(); @@ -287,22 +289,22 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { LazyOptional capability = riding.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY); if (capability.isPresent()) { - if (!world.isRemote()) + if (!level.isClientSide()) capability.orElse(null) .setStalledExternally(isStalled); } else { if (isStalled) { if (!wasStalled) - motionBeforeStall = riding.getMotion(); - riding.setMotion(0, 0, 0); + motionBeforeStall = riding.getDeltaMovement(); + riding.setDeltaMovement(0, 0, 0); } if (wasStalled && !isStalled) { - riding.setMotion(motionBeforeStall); + riding.setDeltaMovement(motionBeforeStall); motionBeforeStall = Vector3d.ZERO; } } - if (world.isRemote) + if (level.isClientSide) return; if (!isStalled()) { @@ -326,10 +328,10 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { Vector3d positionVec = coupledCarts.getFirst() .cart() - .getPositionVec(); + .position(); Vector3d coupledVec = coupledCarts.getSecond() .cart() - .getPositionVec(); + .position(); double diffX = positionVec.x - coupledVec.x; double diffY = positionVec.y - coupledVec.y; @@ -340,7 +342,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { yaw = (float) (MathHelper.atan2(diffZ, diffX) * 180 / Math.PI); pitch = (float) (Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 / Math.PI); - if (getCouplingId().equals(riding.getUniqueID())) { + if (getCouplingId().equals(riding.getUUID())) { pitch *= -1; yaw += 180; } @@ -357,7 +359,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { return false; OrientedContraptionEntity parent = (OrientedContraptionEntity) riding; prevYaw = yaw; - yaw = -parent.getYaw(1); + yaw = -parent.getViewYRot(1); return false; } @@ -366,26 +368,26 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { return false; boolean rotating = false; - Vector3d movementVector = riding.getMotion(); - Vector3d locationDiff = riding.getPositionVec() - .subtract(riding.prevPosX, riding.prevPosY, riding.prevPosZ); + Vector3d movementVector = riding.getDeltaMovement(); + Vector3d locationDiff = riding.position() + .subtract(riding.xo, riding.yo, riding.zo); if (!(riding instanceof AbstractMinecartEntity)) movementVector = locationDiff; Vector3d motion = movementVector.normalize(); - if (!isInitialOrientationPresent() && !world.isRemote) { - if (locationDiff.length() > 0) { - Direction facingFromVector = - Direction.getFacingFromVector(locationDiff.x, locationDiff.y, locationDiff.z); - if (initialYawOffset != -1) - facingFromVector = Direction.fromAngle(facingFromVector.getHorizontalAngle() - initialYawOffset); - if (facingFromVector.getAxis() - .isHorizontal()) - setInitialOrientation(facingFromVector); - } - } - if (!rotationLock) { + if (riding instanceof AbstractMinecartEntity) { + AbstractMinecartEntity minecartEntity = (AbstractMinecartEntity) riding; + BlockPos railPosition = minecartEntity.getCurrentRailPosition(); + BlockState blockState = level.getBlockState(railPosition); + if (blockState.getBlock() instanceof AbstractRailBlock) { + AbstractRailBlock abstractRailBlock = (AbstractRailBlock) blockState.getBlock(); + RailShape railDirection = + abstractRailBlock.getRailDirection(blockState, level, railPosition, minecartEntity); + motion = VecHelper.project(motion, MinecartSim2020.getRailVec(railDirection)); + } + } + if (motion.length() > 0) { targetYaw = yawFromVector(motion); if (targetYaw < 0) @@ -395,7 +397,10 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } prevYaw = yaw; - yaw = angleLerp(0.4f, yaw, targetYaw); + float maxApproachSpeed = (float) (motion.length() * 12f / (Math.max(1, getBoundingBox().getXsize() / 6f))); + float approach = AngleHelper.getShortestAngleDiff(yaw, targetYaw); + approach = MathHelper.clamp(approach, -maxApproachSpeed, maxApproachSpeed); + yaw += approach; if (Math.abs(AngleHelper.getShortestAngleDiff(yaw, targetYaw)) < 1f) yaw = targetYaw; else @@ -422,15 +427,15 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { int i = MathHelper.floor(furnaceCart.getX()); int j = MathHelper.floor(furnaceCart.getY()); int k = MathHelper.floor(furnaceCart.getZ()); - if (furnaceCart.world.getBlockState(new BlockPos(i, j - 1, k)) - .isIn(BlockTags.RAILS)) + if (furnaceCart.level.getBlockState(new BlockPos(i, j - 1, k)) + .is(BlockTags.RAILS)) --j; BlockPos blockpos = new BlockPos(i, j, k); - BlockState blockstate = this.world.getBlockState(blockpos); - if (furnaceCart.canUseRail() && blockstate.isIn(BlockTags.RAILS)) + BlockState blockstate = this.level.getBlockState(blockpos); + if (furnaceCart.canUseRail() && blockstate.is(BlockTags.RAILS)) if (fuel > 1) - riding.setMotion(riding.getMotion() + riding.setDeltaMovement(riding.getDeltaMovement() .normalize() .scale(1)); if (fuel < 5 && contraption != null) { @@ -452,11 +457,11 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { UUID couplingId = getCouplingId(); if (couplingId == null) return null; - MinecartController controller = CapabilityMinecartController.getIfPresent(world, couplingId); + MinecartController controller = CapabilityMinecartController.getIfPresent(level, couplingId); if (controller == null || !controller.isPresent()) return null; UUID coupledCart = controller.getCoupledCart(true); - MinecartController coupledController = CapabilityMinecartController.getIfPresent(world, coupledCart); + MinecartController coupledController = CapabilityMinecartController.getIfPresent(level, coupledCart); if (coupledController == null || !coupledController.isPresent()) return null; return Couple.create(controller, coupledController); @@ -475,18 +480,18 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } @Override - public CompoundNBT writeWithoutTypeId(CompoundNBT nbt) { - return isSerializingFurnaceCart ? nbt : super.writeWithoutTypeId(nbt); + public CompoundNBT saveWithoutId(CompoundNBT nbt) { + return isSerializingFurnaceCart ? nbt : super.saveWithoutId(nbt); } @Nullable public UUID getCouplingId() { - Optional uuid = dataManager.get(COUPLING); + Optional uuid = entityData.get(COUPLING); return uuid == null ? null : uuid.isPresent() ? uuid.get() : null; } public void setCouplingId(UUID id) { - dataManager.set(COUPLING, Optional.ofNullable(id)); + entityData.set(COUPLING, Optional.ofNullable(id)); } @Override @@ -514,25 +519,25 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { @OnlyIn(Dist.CLIENT) public void doLocalTransforms(float partialTicks, MatrixStack[] matrixStacks) { float angleInitialYaw = getInitialYaw(); - float angleYaw = getYaw(partialTicks); - float anglePitch = getPitch(partialTicks); + float angleYaw = getViewYRot(partialTicks); + float anglePitch = getViewXRot(partialTicks); for (MatrixStack stack : matrixStacks) stack.translate(-.5f, 0, -.5f); - Entity ridingEntity = getRidingEntity(); + Entity ridingEntity = getVehicle(); if (ridingEntity instanceof AbstractMinecartEntity) repositionOnCart(partialTicks, matrixStacks, ridingEntity); else if (ridingEntity instanceof AbstractContraptionEntity) { - if (ridingEntity.getRidingEntity() instanceof AbstractMinecartEntity) - repositionOnCart(partialTicks, matrixStacks, ridingEntity.getRidingEntity()); + if (ridingEntity.getVehicle() instanceof AbstractMinecartEntity) + repositionOnCart(partialTicks, matrixStacks, ridingEntity.getVehicle()); else repositionOnContraption(partialTicks, matrixStacks, ridingEntity); } for (MatrixStack stack : matrixStacks) - MatrixStacker.of(stack) - .nudge(getEntityId()) + MatrixTransformStack.of(stack) + .nudge(getId()) .centre() .rotateY(angleYaw) .rotateZ(anglePitch) @@ -553,7 +558,8 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { private void repositionOnCart(float partialTicks, MatrixStack[] matrixStacks, Entity ridingEntity) { Vector3d cartPos = getCartOffset(partialTicks, ridingEntity); - if (cartPos == Vector3d.ZERO) return; + if (cartPos == Vector3d.ZERO) + return; for (MatrixStack stack : matrixStacks) stack.translate(cartPos.x, cartPos.y, cartPos.z); @@ -563,9 +569,9 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { private Vector3d getContraptionOffset(float partialTicks, Entity ridingEntity) { AbstractContraptionEntity parent = (AbstractContraptionEntity) ridingEntity; Vector3d passengerPosition = parent.getPassengerPosition(this, partialTicks); - double x = passengerPosition.x - MathHelper.lerp(partialTicks, this.lastTickPosX, this.getX()); - double y = passengerPosition.y - MathHelper.lerp(partialTicks, this.lastTickPosY, this.getY()); - double z = passengerPosition.z - MathHelper.lerp(partialTicks, this.lastTickPosZ, this.getZ()); + double x = passengerPosition.x - MathHelper.lerp(partialTicks, this.xOld, this.getX()); + double y = passengerPosition.y - MathHelper.lerp(partialTicks, this.yOld, this.getY()); + double z = passengerPosition.z - MathHelper.lerp(partialTicks, this.zOld, this.getZ()); return new Vector3d(x, y, z); } @@ -573,14 +579,14 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { @OnlyIn(Dist.CLIENT) private Vector3d getCartOffset(float partialTicks, Entity ridingEntity) { AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity; - double cartX = MathHelper.lerp(partialTicks, cart.lastTickPosX, cart.getX()); - double cartY = MathHelper.lerp(partialTicks, cart.lastTickPosY, cart.getY()); - double cartZ = MathHelper.lerp(partialTicks, cart.lastTickPosZ, cart.getZ()); + double cartX = MathHelper.lerp(partialTicks, cart.xOld, cart.getX()); + double cartY = MathHelper.lerp(partialTicks, cart.yOld, cart.getY()); + double cartZ = MathHelper.lerp(partialTicks, cart.zOld, cart.getZ()); Vector3d cartPos = cart.getPos(cartX, cartY, cartZ); if (cartPos != null) { - Vector3d cartPosFront = cart.getPosOffset(cartX, cartY, cartZ, (double) 0.3F); - Vector3d cartPosBack = cart.getPosOffset(cartX, cartY, cartZ, (double) -0.3F); + Vector3d cartPosFront = cart.getPosOffs(cartX, cartY, cartZ, (double) 0.3F); + Vector3d cartPosBack = cart.getPosOffs(cartX, cartY, cartZ, (double) -0.3F); if (cartPosFront == null) cartPosFront = cartPos; if (cartPosBack == null) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java index d1cfea7c5..a2fa2b4ab 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java @@ -15,7 +15,7 @@ public class OrientedContraptionEntityRenderer extends ContraptionEntityRenderer if (!super.shouldRender(entity, p_225626_2_, p_225626_3_, p_225626_5_, p_225626_7_)) return false; if (entity.getContraption() - .getType() == ContraptionType.MOUNTED && entity.getRidingEntity() == null) + .getType() == ContraptionType.MOUNTED && entity.getVehicle() == null) return false; return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java index 1d47d2554..67aab845a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java @@ -27,9 +27,11 @@ import net.minecraft.state.properties.BellAttachment; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.Half; import net.minecraft.state.properties.SlabType; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; +import net.minecraft.util.Mirror; import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; @@ -41,27 +43,33 @@ public class StructureTransform { int angle; Axis rotationAxis; BlockPos offset; + Mirror mirror; - private StructureTransform(BlockPos offset, int angle, Axis axis, Rotation rotation) { + private StructureTransform(BlockPos offset, int angle, Axis axis, Rotation rotation, Mirror mirror) { this.offset = offset; this.angle = angle; rotationAxis = axis; this.rotation = rotation; + this.mirror = mirror; + } + + public StructureTransform(BlockPos offset, Axis axis, Rotation rotation, Mirror mirror) { + this(offset, rotation == Rotation.NONE ? 0 : (4 - rotation.ordinal())*90, axis, rotation, mirror); } public StructureTransform(BlockPos offset, float xRotation, float yRotation, float zRotation) { this.offset = offset; if (xRotation != 0) { rotationAxis = Axis.X; - angle = (int) (Math.round(xRotation / 90) * 90); + angle = Math.round(xRotation / 90) * 90; } if (yRotation != 0) { rotationAxis = Axis.Y; - angle = (int) (Math.round(yRotation / 90) * 90); + angle = Math.round(yRotation / 90) * 90; } if (zRotation != 0) { rotationAxis = Axis.Z; - angle = (int) (Math.round(zRotation / 90) * 90); + angle = Math.round(zRotation / 90) * 90; } angle %= 360; @@ -76,22 +84,33 @@ public class StructureTransform { if (angle == 180) this.rotation = Rotation.CLOCKWISE_180; + mirror = Mirror.NONE; } - public Vector3d apply(Vector3d localVec) { + public Vector3d applyWithoutOffset(Vector3d localVec) { Vector3d vec = localVec; + if (mirror != null) + vec = VecHelper.mirrorCentered(vec, mirror); if (rotationAxis != null) vec = VecHelper.rotateCentered(vec, angle, rotationAxis); - vec = vec.add(Vector3d.of(offset)); return vec; } + public Vector3d apply(Vector3d localVec) { + return applyWithoutOffset(localVec).add(Vector3d.atLowerCornerOf(offset)); + } + + public BlockPos applyWithoutOffset(BlockPos localPos) { + return new BlockPos(applyWithoutOffset(VecHelper.getCenterOf(localPos))); + } + public BlockPos apply(BlockPos localPos) { - Vector3d vec = VecHelper.getCenterOf(localPos); - if (rotationAxis != null) - vec = VecHelper.rotateCentered(vec, angle, rotationAxis); - localPos = new BlockPos(vec); - return localPos.add(offset); + return applyWithoutOffset(localPos).offset(offset); + } + + public void apply(TileEntity te) { + if (te instanceof ITransformableTE) + ((ITransformableTE) te).transform(this); } /** @@ -100,15 +119,18 @@ public class StructureTransform { * horizontal axes */ public BlockState apply(BlockState state) { + if (mirror != null) + state = state.mirror(mirror); + Block block = state.getBlock(); if (rotationAxis == Axis.Y) { if (block instanceof BellBlock) { - if (state.get(BlockStateProperties.BELL_ATTACHMENT) == BellAttachment.DOUBLE_WALL) { - state = state.with(BlockStateProperties.BELL_ATTACHMENT, BellAttachment.SINGLE_WALL); + if (state.getValue(BlockStateProperties.BELL_ATTACHMENT) == BellAttachment.DOUBLE_WALL) { + state = state.setValue(BlockStateProperties.BELL_ATTACHMENT, BellAttachment.SINGLE_WALL); } - return state.with(HorizontalFaceBlock.HORIZONTAL_FACING, - rotation.rotate(state.get(HorizontalFaceBlock.HORIZONTAL_FACING))); + return state.setValue(HorizontalFaceBlock.FACING, + rotation.rotate(state.getValue(HorizontalFaceBlock.FACING))); } return state.rotate(rotation); } @@ -117,30 +139,30 @@ public class StructureTransform { return rotateChassis(state); if (block instanceof HorizontalFaceBlock) { - Direction stateFacing = state.get(HorizontalFaceBlock.HORIZONTAL_FACING); - AttachFace stateFace = state.get(FACE); + Direction stateFacing = state.getValue(HorizontalFaceBlock.FACING); + AttachFace stateFace = state.getValue(FACE); Direction forcedAxis = rotationAxis == Axis.Z ? Direction.EAST : Direction.SOUTH; if (stateFacing.getAxis() == rotationAxis && stateFace == AttachFace.WALL) return state; for (int i = 0; i < rotation.ordinal(); i++) { - stateFace = state.get(FACE); - stateFacing = state.get(HorizontalFaceBlock.HORIZONTAL_FACING); + stateFace = state.getValue(FACE); + stateFacing = state.getValue(HorizontalFaceBlock.FACING); - boolean b = state.get(FACE) == AttachFace.CEILING; - state = state.with(HORIZONTAL_FACING, b ? forcedAxis : forcedAxis.getOpposite()); + boolean b = state.getValue(FACE) == AttachFace.CEILING; + state = state.setValue(HORIZONTAL_FACING, b ? forcedAxis : forcedAxis.getOpposite()); if (stateFace != AttachFace.WALL) { - state = state.with(FACE, AttachFace.WALL); + state = state.setValue(FACE, AttachFace.WALL); continue; } if (stateFacing.getAxisDirection() == AxisDirection.POSITIVE) { - state = state.with(FACE, AttachFace.FLOOR); + state = state.setValue(FACE, AttachFace.FLOOR); continue; } - state = state.with(FACE, AttachFace.CEILING); + state = state.setValue(FACE, AttachFace.CEILING); } return state; @@ -157,51 +179,51 @@ public class StructureTransform { return state; } - if (state.contains(FACING)) { - Direction newFacing = transformFacing(state.get(FACING)); - if (state.contains(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) { + if (state.hasProperty(FACING)) { + Direction newFacing = transformFacing(state.getValue(FACING)); + if (state.hasProperty(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) { if (rotationAxis == newFacing.getAxis() && rotation.ordinal() % 2 == 1) state = state.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE); } - state = state.with(FACING, newFacing); + state = state.setValue(FACING, newFacing); - } else if (state.contains(AXIS)) { - state = state.with(AXIS, transformAxis(state.get(AXIS))); + } else if (state.hasProperty(AXIS)) { + state = state.setValue(AXIS, transformAxis(state.getValue(AXIS))); } else if (halfTurn) { - if (state.contains(FACING)) { - Direction stateFacing = state.get(FACING); + if (state.hasProperty(FACING)) { + Direction stateFacing = state.getValue(FACING); if (stateFacing.getAxis() == rotationAxis) return state; } - if (state.contains(HORIZONTAL_FACING)) { - Direction stateFacing = state.get(HORIZONTAL_FACING); + if (state.hasProperty(HORIZONTAL_FACING)) { + Direction stateFacing = state.getValue(HORIZONTAL_FACING); if (stateFacing.getAxis() == rotationAxis) return state; } state = state.rotate(rotation); - if (state.contains(SlabBlock.TYPE) && state.get(SlabBlock.TYPE) != SlabType.DOUBLE) - state = state.with(SlabBlock.TYPE, - state.get(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM); + if (state.hasProperty(SlabBlock.TYPE) && state.getValue(SlabBlock.TYPE) != SlabType.DOUBLE) + state = state.setValue(SlabBlock.TYPE, + state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM); } return state; } protected BlockState transformStairs(BlockState state, boolean halfTurn) { - if (state.get(StairsBlock.FACING) + if (state.getValue(StairsBlock.FACING) .getAxis() != rotationAxis) { for (int i = 0; i < rotation.ordinal(); i++) { - Direction direction = state.get(StairsBlock.FACING); - Half half = state.get(StairsBlock.HALF); + Direction direction = state.getValue(StairsBlock.FACING); + Half half = state.getValue(StairsBlock.HALF); if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ half == Half.BOTTOM ^ direction.getAxis() == Axis.Z) state = state.cycle(StairsBlock.HALF); else - state = state.with(StairsBlock.FACING, direction.getOpposite()); + state = state.setValue(StairsBlock.FACING, direction.getOpposite()); } } else { if (halfTurn) { @@ -212,14 +234,14 @@ public class StructureTransform { } protected BlockState transformBelt(BlockState state, boolean halfTurn) { - Direction initialDirection = state.get(BeltBlock.HORIZONTAL_FACING); + Direction initialDirection = state.getValue(BeltBlock.HORIZONTAL_FACING); boolean diagonal = - state.get(BeltBlock.SLOPE) == BeltSlope.DOWNWARD || state.get(BeltBlock.SLOPE) == BeltSlope.UPWARD; + state.getValue(BeltBlock.SLOPE) == BeltSlope.DOWNWARD || state.getValue(BeltBlock.SLOPE) == BeltSlope.UPWARD; if (!diagonal) { for (int i = 0; i < rotation.ordinal(); i++) { - Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); - BeltSlope slope = state.get(BeltBlock.SLOPE); + Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); boolean vertical = slope == BeltSlope.VERTICAL; boolean horizontal = slope == BeltSlope.HORIZONTAL; boolean sideways = slope == BeltSlope.SIDEWAYS; @@ -229,7 +251,7 @@ public class StructureTransform { if (vertical) { if (direction.getAxis() == rotationAxis) { - newDirection = direction.rotateYCCW(); + newDirection = direction.getCounterClockWise(); newSlope = BeltSlope.SIDEWAYS; } else { newSlope = BeltSlope.HORIZONTAL; @@ -244,7 +266,7 @@ public class StructureTransform { if (direction.getAxis() == rotationAxis) newSlope = BeltSlope.HORIZONTAL; else - newDirection = direction.rotateYCCW(); + newDirection = direction.getCounterClockWise(); } if (horizontal) { @@ -255,50 +277,52 @@ public class StructureTransform { newDirection = direction.getOpposite(); } - state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection); - state = state.with(BeltBlock.SLOPE, newSlope); + state = state.setValue(BeltBlock.HORIZONTAL_FACING, newDirection); + state = state.setValue(BeltBlock.SLOPE, newSlope); } } else if (initialDirection.getAxis() != rotationAxis) { for (int i = 0; i < rotation.ordinal(); i++) { - Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); + Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING); Direction newDirection = direction.getOpposite(); - BeltSlope slope = state.get(BeltBlock.SLOPE); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); boolean upward = slope == BeltSlope.UPWARD; boolean downward = slope == BeltSlope.DOWNWARD; // Rotate diagonal if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ downward ^ direction.getAxis() == Axis.Z) { - state = state.with(BeltBlock.SLOPE, upward ? BeltSlope.DOWNWARD : BeltSlope.UPWARD); + state = state.setValue(BeltBlock.SLOPE, upward ? BeltSlope.DOWNWARD : BeltSlope.UPWARD); } else { - state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection); + state = state.setValue(BeltBlock.HORIZONTAL_FACING, newDirection); } } } else if (halfTurn) { - Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); + Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING); Direction newDirection = direction.getOpposite(); - BeltSlope slope = state.get(BeltBlock.SLOPE); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); boolean vertical = slope == BeltSlope.VERTICAL; if (diagonal) { - state = state.with(BeltBlock.SLOPE, slope == BeltSlope.UPWARD ? BeltSlope.DOWNWARD + state = state.setValue(BeltBlock.SLOPE, slope == BeltSlope.UPWARD ? BeltSlope.DOWNWARD : slope == BeltSlope.DOWNWARD ? BeltSlope.UPWARD : slope); } else if (vertical) { - state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection); + state = state.setValue(BeltBlock.HORIZONTAL_FACING, newDirection); } } return state; } public Axis transformAxis(Axis axisIn) { - Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axisIn); + Direction facing = Direction.get(AxisDirection.POSITIVE, axisIn); facing = transformFacing(facing); Axis axis = facing.getAxis(); return axis; } public Direction transformFacing(Direction facing) { + if (mirror != null) + facing = mirror.mirror(facing); for (int i = 0; i < rotation.ordinal(); i++) facing = DirectionHelper.rotateAround(facing, rotationAxis); return facing; @@ -308,23 +332,23 @@ public class StructureTransform { if (rotation == Rotation.NONE) return state; - BlockState rotated = state.with(AXIS, transformAxis(state.get(AXIS))); + BlockState rotated = state.setValue(AXIS, transformAxis(state.getValue(AXIS))); AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock(); for (Direction face : Iterate.directions) { BooleanProperty glueableSide = block.getGlueableSide(rotated, face); if (glueableSide != null) - rotated = rotated.with(glueableSide, false); + rotated = rotated.setValue(glueableSide, false); } for (Direction face : Iterate.directions) { BooleanProperty glueableSide = block.getGlueableSide(state, face); - if (glueableSide == null || !state.get(glueableSide)) + if (glueableSide == null || !state.getValue(glueableSide)) continue; Direction rotatedFacing = transformFacing(face); BooleanProperty rotatedGlueableSide = block.getGlueableSide(rotated, rotatedFacing); if (rotatedGlueableSide != null) - rotated = rotated.with(rotatedGlueableSide, true); + rotated = rotated.setValue(rotatedGlueableSide, true); } return rotated; @@ -335,8 +359,10 @@ public class StructureTransform { int readAngle = buffer.readInt(); int axisIndex = buffer.readVarInt(); int rotationIndex = buffer.readVarInt(); + int mirrorIndex = buffer.readVarInt(); return new StructureTransform(readBlockPos, readAngle, axisIndex == -1 ? null : Axis.values()[axisIndex], - rotationIndex == -1 ? null : Rotation.values()[rotationIndex]); + rotationIndex == -1 ? null : Rotation.values()[rotationIndex], + mirrorIndex == -1 ? null : Mirror.values()[mirrorIndex]); } public void writeToBuffer(PacketBuffer buffer) { @@ -344,6 +370,7 @@ public class StructureTransform { buffer.writeInt(angle); buffer.writeVarInt(rotationAxis == null ? -1 : rotationAxis.ordinal()); buffer.writeVarInt(rotation == null ? -1 : rotation.ordinal()); + buffer.writeVarInt(mirror == null ? - 1 : mirror.ordinal()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TranslatingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TranslatingContraption.java index a692a112a..a28788f0e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TranslatingContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TranslatingContraption.java @@ -22,7 +22,7 @@ public abstract class TranslatingContraption extends Contraption { cachedColliderDirection = movementDirection; for (BlockInfo info : getBlocks().values()) { - BlockPos offsetPos = info.pos.offset(movementDirection); + BlockPos offsetPos = info.pos.relative(movementDirection); if (info.state.getCollisionShape(world, offsetPos) .isEmpty()) continue; 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/BearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingBlock.java index 66e55acbe..daa19daa7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingBlock.java @@ -19,12 +19,12 @@ public abstract class BearingBlock extends DirectionalKineticBlock { @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face == state.get(FACING).getOpposite(); + return face == state.getValue(FACING).getOpposite(); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(FACING).getAxis(); + return state.getValue(FACING).getAxis(); } @Override @@ -35,8 +35,8 @@ public abstract class BearingBlock extends DirectionalKineticBlock { @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { ActionResultType resultType = super.onWrenched(state, context); - if (!context.getWorld().isRemote && resultType.isAccepted()) { - TileEntity te = context.getWorld().getTileEntity(context.getPos()); + if (!context.getLevel().isClientSide && resultType.consumesAction()) { + TileEntity te = context.getLevel().getBlockEntity(context.getClickedPos()); if (te instanceof MechanicalBearingTileEntity) { ((MechanicalBearingTileEntity) te).disassemble(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java index 8e1e60aa6..871ce7a0f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java @@ -34,7 +34,7 @@ public class BearingContraption extends Contraption { @Override public boolean assemble(World world, BlockPos pos) throws AssemblyException { - BlockPos offset = pos.offset(facing); + BlockPos offset = pos.relative(facing); if (!searchMovedStructure(world, offset, null)) return false; startMoving(world); @@ -53,7 +53,7 @@ public class BearingContraption extends Contraption { @Override protected boolean isAnchoringBlockAt(BlockPos pos) { - return pos.equals(anchor.offset(facing.getOpposite())); + return pos.equals(anchor.relative(facing.getOpposite())); } @Override @@ -68,14 +68,14 @@ public class BearingContraption extends Contraption { public CompoundNBT writeNBT(boolean spawnPacket) { CompoundNBT tag = super.writeNBT(spawnPacket); tag.putInt("Sails", sailBlocks); - tag.putInt("Facing", facing.getIndex()); + tag.putInt("Facing", facing.get3DDataValue()); return tag; } @Override public void readNBT(World world, CompoundNBT tag, boolean spawnData) { sailBlocks = tag.getInt("Sails"); - facing = Direction.byIndex(tag.getInt("Facing")); + facing = Direction.from3DDataValue(tag.getInt("Facing")); super.readNBT(world, tag, spawnData); } 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..f9ce8806d 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.material.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,12 +23,12 @@ 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; - Direction facing = blockState.get(BlockStateProperties.FACING); - rotationAxis = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector(); + Direction facing = blockState.getValue(BlockStateProperties.FACING); + rotationAxis = Direction.get(Direction.AxisDirection.POSITIVE, axis).step(); blockOrientation = getBlockStateOrientation(facing); @@ -44,9 +44,9 @@ public class BearingInstance e public void beginFrame() { float interpolatedAngle = bearing.getInterpolatedAngle(AnimationTickHolder.getPartialTicks() - 1); - Quaternion rot = rotationAxis.getDegreesQuaternion(interpolatedAngle); + Quaternion rot = rotationAxis.rotationDegrees(interpolatedAngle); - rot.multiply(blockOrientation); + rot.mul(blockOrientation); topInstance.setRotation(rot); } @@ -67,12 +67,12 @@ public class BearingInstance e Quaternion orientation; if (facing.getAxis().isHorizontal()) { - orientation = Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(facing.getOpposite())); + orientation = Vector3f.YP.rotationDegrees(AngleHelper.horizontalAngle(facing.getOpposite())); } else { - orientation = Quaternion.IDENTITY.copy(); + orientation = Quaternion.ONE.copy(); } - orientation.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-90 - AngleHelper.verticalAngle(facing))); + orientation.mul(Vector3f.XP.rotationDegrees(-90 - AngleHelper.verticalAngle(facing))); return orientation; } } 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..e8521f53b 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,13 +26,13 @@ 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.getLevel())) return; super.renderSafe(te, partialTicks, ms, buffer, light, overlay); IBearingTileEntity bearingTe = (IBearingTileEntity) te; final Direction facing = te.getBlockState() - .get(BlockStateProperties.FACING); + .getValue(BlockStateProperties.FACING); PartialModel top = bearingTe.isWoodenTop() ? AllBlockPartials.BEARING_TOP_WOODEN : AllBlockPartials.BEARING_TOP; SuperByteBuffer superBuffer = PartialBufferer.get(top, te.getBlockState()); @@ -45,13 +45,13 @@ public class BearingRenderer extends KineticTileEntityRenderer { superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite()))); superBuffer.rotateCentered(Direction.EAST, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing))); - superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + superBuffer.renderInto(ms, buffer.getBuffer(RenderType.solid())); } @Override protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { return PartialBufferer.getFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), te.getBlockState() - .get(BearingBlock.FACING) + .getValue(BearingBlock.FACING) .getOpposite()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingBlock.java index 125950656..240e1a23f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingBlock.java @@ -26,14 +26,14 @@ public class ClockworkBearingBlock extends BearingBlock implements ITE { if (te.running) { te.disassemble(); @@ -55,8 +55,8 @@ public class ClockworkBearingBlock extends BearingBlock implements ITE contraption; try { - contraption = ClockworkContraption.assembleClockworkAt(world, pos, direction); + contraption = ClockworkContraption.assembleClockworkAt(level, worldPosition, direction); lastException = null; } catch (AssemblyException e) { lastException = e; @@ -228,25 +230,25 @@ public class ClockworkBearingTileEntity extends KineticTileEntity .getBlocks() .isEmpty()) return; - BlockPos anchor = pos.offset(direction); + BlockPos anchor = worldPosition.relative(direction); contraption.getLeft() - .removeBlocksFromWorld(world, BlockPos.ZERO); - hourHand = ControlledContraptionEntity.create(world, this, contraption.getLeft()); - hourHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); + .removeBlocksFromWorld(level, BlockPos.ZERO); + hourHand = ControlledContraptionEntity.create(level, this, contraption.getLeft()); + hourHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); hourHand.setRotationAxis(direction.getAxis()); - world.addEntity(hourHand); + level.addFreshEntity(hourHand); - AllTriggers.triggerForNearbyPlayers(AllTriggers.CLOCKWORK_BEARING, world, pos, 5); + AllTriggers.triggerForNearbyPlayers(AllTriggers.CLOCKWORK_BEARING, level, worldPosition, 5); if (contraption.getRight() != null) { - anchor = pos.offset(direction, contraption.getRight().offset + 1); + anchor = worldPosition.relative(direction, contraption.getRight().offset + 1); contraption.getRight() - .removeBlocksFromWorld(world, BlockPos.ZERO); - minuteHand = ControlledContraptionEntity.create(world, this, contraption.getRight()); - minuteHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); + .removeBlocksFromWorld(level, BlockPos.ZERO); + minuteHand = ControlledContraptionEntity.create(level, this, contraption.getRight()); + minuteHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); minuteHand.setRotationAxis(direction.getAxis()); - world.addEntity(minuteHand); + level.addFreshEntity(minuteHand); } // Run @@ -282,17 +284,17 @@ public class ClockworkBearingTileEntity extends KineticTileEntity return; ClockworkContraption cc = (ClockworkContraption) contraption.getContraption(); - markDirty(); - Direction facing = getBlockState().get(BlockStateProperties.FACING); - BlockPos anchor = pos.offset(facing, cc.offset + 1); + setChanged(); + Direction facing = getBlockState().getValue(BlockStateProperties.FACING); + BlockPos anchor = worldPosition.relative(facing, cc.offset + 1); if (cc.handType == HandType.HOUR) { this.hourHand = contraption; - hourHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); + hourHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); } else { this.minuteHand = contraption; - minuteHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); + minuteHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); } - if (!world.isRemote) { + if (!level.isClientSide) { this.running = true; sendData(); } @@ -354,15 +356,15 @@ public class ClockworkBearingTileEntity extends KineticTileEntity @Override public void onStall() { - if (!world.isRemote) + if (!level.isClientSide) sendData(); } @Override - public void remove() { - if (!world.isRemote) + public void setRemoved() { + if (!level.isClientSide) disassemble(); - super.remove(); + super.setRemoved(); } @Override @@ -413,11 +415,11 @@ public class ClockworkBearingTileEntity extends KineticTileEntity @Override public BlockPos getBlockPosition() { - return pos; + return worldPosition; } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java index 949228ba9..7c0af2c70 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java @@ -31,12 +31,12 @@ public class ClockworkContraption extends Contraption { private void ignoreBlocks(Set blocks, BlockPos anchor) { for (BlockPos blockPos : blocks) - ignoreBlocks.add(anchor.add(blockPos)); + ignoreBlocks.add(anchor.offset(blockPos)); } @Override protected boolean isAnchoringBlockAt(BlockPos pos) { - return pos.equals(anchor.offset(facing.getOpposite(), offset + 1)); + return pos.equals(anchor.relative(facing.getOpposite(), offset + 1)); } public static Pair assembleClockworkAt(World world, BlockPos pos, @@ -51,7 +51,7 @@ public class ClockworkContraption extends Contraption { if (!hourArm.assemble(world, pos)) return null; for (int i = 0; i < 16; i++) { - BlockPos offsetPos = BlockPos.ZERO.offset(direction, i); + BlockPos offsetPos = BlockPos.ZERO.relative(direction, i); if (hourArm.getBlocks() .containsKey(offsetPos)) continue; @@ -89,7 +89,7 @@ public class ClockworkContraption extends Contraption { @Override public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) throws AssemblyException { - return super.searchMovedStructure(world, pos.offset(direction, offset + 1), null); + return super.searchMovedStructure(world, pos.relative(direction, offset + 1), null); } @Override @@ -105,7 +105,7 @@ public class ClockworkContraption extends Contraption { @Override public CompoundNBT writeNBT(boolean spawnPacket) { CompoundNBT tag = super.writeNBT(spawnPacket); - tag.putInt("facing", facing.getIndex()); + tag.putInt("facing", facing.get3DDataValue()); tag.putInt("offset", offset); NBTHelper.writeEnum(tag, "HandType", handType); return tag; @@ -113,7 +113,7 @@ public class ClockworkContraption extends Contraption { @Override public void readNBT(World world, CompoundNBT tag, boolean spawnData) { - facing = Direction.byIndex(tag.getInt("facing")); + facing = Direction.from3DDataValue(tag.getInt("facing")); handType = NBTHelper.readEnum(tag, "HandType", HandType.class); offset = tag.getInt("offset"); super.readNBT(world, tag, spawnData); @@ -121,7 +121,7 @@ public class ClockworkContraption extends Contraption { @Override public boolean canBeStabilized(Direction facing, BlockPos localPos) { - if (BlockPos.ZERO.equals(localPos) || BlockPos.ZERO.equals(localPos.offset(facing))) + if (BlockPos.ZERO.equals(localPos) || BlockPos.ZERO.equals(localPos.relative(facing))) return false; return facing.getAxis() == this.facing.getAxis(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java index e729feae4..af8a52b22 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java @@ -15,7 +15,7 @@ public interface IBearingTileEntity extends IControlContraption { default ValueBoxTransform getMovementModeSlot() { return new DirectionalExtenderScrollOptionSlot((state, d) -> { Axis axis = d.getAxis(); - Axis bearingAxis = state.get(BearingBlock.FACING) + Axis bearingAxis = state.getValue(BearingBlock.FACING) .getAxis(); return bearingAxis != axis; }); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingBlock.java index 9bf59c537..005f57692 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingBlock.java @@ -25,15 +25,15 @@ public class MechanicalBearingBlock extends BearingBlock implements ITE { if (te.running) { 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..650fda752 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 @@ -60,10 +60,10 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity } @Override - public void remove() { - if (!world.isRemote) + public void setRemoved() { + if (!level.isClientSide) disassemble(); - super.remove(); + super.setRemoved(); } @Override @@ -80,7 +80,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity super.fromTag(state, compound, clientPacket); return; } - + float angleBefore = angle; running = compound.getBoolean("Running"); angle = compound.getFloat("Angle"); @@ -108,18 +108,18 @@ 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); + .stop(level); } } public float getAngularSpeed() { - float speed = (isWindmill() ? getGeneratedSpeed() : getSpeed()) * 3 / 10f; + float speed = convertToAngular(isWindmill() ? getGeneratedSpeed() : getSpeed()); if (getSpeed() == 0) speed = 0; - if (world.isRemote) { + if (level.isClientSide) { speed *= ServerSpeedProvider.get(); speed += clientAngleDiff / 3f; } @@ -137,18 +137,18 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity @Override public BlockPos getBlockPosition() { - return pos; + return worldPosition; } public void assemble() { - if (!(world.getBlockState(pos) + if (!(level.getBlockState(worldPosition) .getBlock() instanceof BearingBlock)) return; - Direction direction = getBlockState().get(FACING); + Direction direction = getBlockState().getValue(FACING); BearingContraption contraption = new BearingContraption(isWindmill(), direction); try { - if (!contraption.assemble(world, pos)) + if (!contraption.assemble(level, worldPosition)) return; lastException = null; @@ -159,18 +159,18 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity } if (isWindmill()) - AllTriggers.triggerForNearbyPlayers(AllTriggers.WINDMILL, world, pos, 5); + AllTriggers.triggerForNearbyPlayers(AllTriggers.WINDMILL, level, worldPosition, 5); if (contraption.getSailBlocks() >= 16 * 8) - AllTriggers.triggerForNearbyPlayers(AllTriggers.MAXED_WINDMILL, world, pos, 5); + AllTriggers.triggerForNearbyPlayers(AllTriggers.MAXED_WINDMILL, level, worldPosition, 5); - contraption.removeBlocksFromWorld(world, BlockPos.ZERO); - movedContraption = ControlledContraptionEntity.create(world, this, contraption); - BlockPos anchor = pos.offset(direction); - movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); + contraption.removeBlocksFromWorld(level, BlockPos.ZERO); + movedContraption = ControlledContraptionEntity.create(level, this, contraption); + BlockPos anchor = worldPosition.relative(direction); + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); movedContraption.setRotationAxis(direction.getAxis()); - world.addEntity(movedContraption); - - AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(world, pos); + level.addFreshEntity(movedContraption); + + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); running = true; angle = 0; @@ -186,7 +186,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity applyRotation(); if (movedContraption != null) { movedContraption.disassemble(); - AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(world, pos); + AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, worldPosition); } movedContraption = null; @@ -201,10 +201,10 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity super.tick(); prevAngle = angle; - if (world.isRemote) + if (level.isClientSide) clientAngleDiff /= 2; - if (!world.isRemote && assembleNextTick) { + if (!level.isClientSide && assembleNextTick) { assembleNextTick = false; if (running) { boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE @@ -214,16 +214,15 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity .isEmpty())) { if (movedContraption != null) movedContraption.getContraption() - .stop(world); + .stop(level); disassemble(); + return; } - return; } else { if (speed == 0 && !isWindmill()) return; assemble(); } - return; } if (!running) @@ -245,7 +244,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity @Override public void lazyTick() { super.lazyTick(); - if (movedContraption != null && !world.isRemote) + if (movedContraption != null && !level.isClientSide) sendData(); } @@ -254,8 +253,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity return; movedContraption.setAngle(angle); BlockState blockState = getBlockState(); - if (blockState.contains(BlockStateProperties.FACING)) - movedContraption.setRotationAxis(blockState.get(BlockStateProperties.FACING) + if (blockState.hasProperty(BlockStateProperties.FACING)) + movedContraption.setRotationAxis(blockState.getValue(BlockStateProperties.FACING) .getAxis()); } @@ -264,14 +263,14 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity BlockState blockState = getBlockState(); if (!(contraption.getContraption() instanceof BearingContraption)) return; - if (!blockState.contains(FACING)) + if (!blockState.hasProperty(FACING)) return; this.movedContraption = contraption; - markDirty(); - BlockPos anchor = pos.offset(blockState.get(FACING)); - movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); - if (!world.isRemote) { + setChanged(); + BlockPos anchor = worldPosition.relative(blockState.getValue(FACING)); + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + if (!level.isClientSide) { this.running = true; sendData(); } @@ -279,7 +278,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity @Override public void onStall() { - if (!world.isRemote) + if (!level.isClientSide) sendData(); } @@ -314,7 +313,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity if (!(state.getBlock() instanceof BearingBlock)) return false; - BlockState attachedState = world.getBlockState(pos.offset(state.get(BearingBlock.FACING))); + BlockState attachedState = level.getBlockState(worldPosition.relative(state.getValue(BearingBlock.FACING))); if (attachedState.getMaterial() .isReplaceable()) return false; @@ -323,7 +322,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..75370e103 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 @@ -10,7 +10,7 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import com.simibubi.create.foundation.utility.DyeHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.placement.IPlacementHelper; @@ -41,7 +41,7 @@ import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -public class SailBlock extends ProperDirectionalBlock { +public class SailBlock extends WrenchableDirectionalBlock { public static SailBlock frame(Properties properties) { return new SailBlock(properties, true); @@ -63,19 +63,19 @@ public class SailBlock extends ProperDirectionalBlock { @Override public BlockState getStateForPlacement(BlockItemUseContext context) { BlockState state = super.getStateForPlacement(context); - return state.with(FACING, state.get(FACING).getOpposite()); + return state.setValue(FACING, state.getValue(FACING).getOpposite()); } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - ItemStack heldItem = player.getHeldItem(hand); + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { + ItemStack heldItem = player.getItemInHand(hand); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); if (placementHelper.matchesItem(heldItem)) return placementHelper.getOffset(player, world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); if (heldItem.getItem() instanceof ShearsItem) { - if (!world.isRemote) + if (!world.isClientSide) applyDye(state, world, pos, null); return ActionResultType.SUCCESS; } @@ -85,9 +85,9 @@ public class SailBlock extends ProperDirectionalBlock { for (DyeColor color : DyeColor.values()) { if (!heldItem.getItem() - .isIn(DyeHelper.getTagOfDye(color))) + .is(DyeHelper.getTagOfDye(color))) continue; - if (!world.isRemote) + if (!world.isClientSide) applyDye(state, world, pos, color); return ActionResultType.SUCCESS; } @@ -97,28 +97,28 @@ 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() - .with(FACING, state.get(FACING)); + (color == null ? AllBlocks.SAIL_FRAME : AllBlocks.DYED_SAILS.get(color)).getDefaultState() + .setValue(FACING, state.getValue(FACING)); // Dye the block itself if (state != newState) { - world.setBlockState(pos, newState); + world.setBlockAndUpdate(pos, newState); return; } // Dye all adjacent for (Direction d : Iterate.directions) { - if (d.getAxis() == state.get(FACING) + if (d.getAxis() == state.getValue(FACING) .getAxis()) continue; - BlockPos offset = pos.offset(d); + BlockPos offset = pos.relative(d); BlockState adjacentState = world.getBlockState(offset); Block block = adjacentState.getBlock(); if (!(block instanceof SailBlock) || ((SailBlock) block).frame) continue; if (state == adjacentState) continue; - world.setBlockState(offset, newState); + world.setBlockAndUpdate(offset, newState); return; } @@ -135,10 +135,10 @@ public class SailBlock extends ProperDirectionalBlock { visited.add(currentPos); for (Direction d : Iterate.directions) { - if (d.getAxis() == state.get(FACING) + if (d.getAxis() == state.getValue(FACING) .getAxis()) continue; - BlockPos offset = currentPos.offset(d); + BlockPos offset = currentPos.relative(d); if (visited.contains(offset)) continue; BlockState adjacentState = world.getBlockState(offset); @@ -146,7 +146,7 @@ public class SailBlock extends ProperDirectionalBlock { if (!(block instanceof SailBlock) || ((SailBlock) block).frame && color != null) continue; if (state != adjacentState) - world.setBlockState(offset, newState); + world.setBlockAndUpdate(offset, newState); frontier.add(offset); visited.add(offset); } @@ -155,13 +155,13 @@ public class SailBlock extends ProperDirectionalBlock { @Override public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, ISelectionContext p_220053_4_) { - return (frame ? AllShapes.SAIL_FRAME : AllShapes.SAIL).get(state.get(FACING)); + return (frame ? AllShapes.SAIL_FRAME : AllShapes.SAIL).get(state.getValue(FACING)); } @Override public VoxelShape getCollisionShape(BlockState state, IBlockReader p_220071_2_, BlockPos p_220071_3_, ISelectionContext p_220071_4_) { if (frame) - return AllShapes.SAIL_FRAME_COLLISION.get(state.get(FACING)); + return AllShapes.SAIL_FRAME_COLLISION.get(state.getValue(FACING)); return getShape(state, p_220071_2_, p_220071_3_, p_220071_4_); } @@ -174,31 +174,31 @@ public class SailBlock extends ProperDirectionalBlock { return pickBlock; } - public void onFallenUpon(World p_180658_1_, BlockPos p_180658_2_, Entity p_180658_3_, float p_180658_4_) { + public void fallOn(World p_180658_1_, BlockPos p_180658_2_, Entity p_180658_3_, float p_180658_4_) { if (frame) - super.onFallenUpon(p_180658_1_, p_180658_2_, p_180658_3_, p_180658_4_); - super.onFallenUpon(p_180658_1_, p_180658_2_, p_180658_3_, 0); + super.fallOn(p_180658_1_, p_180658_2_, p_180658_3_, p_180658_4_); + super.fallOn(p_180658_1_, p_180658_2_, p_180658_3_, 0); } - public void onLanded(IBlockReader p_176216_1_, Entity p_176216_2_) { - if (frame || p_176216_2_.bypassesLandingEffects()) { - super.onLanded(p_176216_1_, p_176216_2_); + public void updateEntityAfterFallOn(IBlockReader p_176216_1_, Entity p_176216_2_) { + if (frame || p_176216_2_.isSuppressingBounce()) { + super.updateEntityAfterFallOn(p_176216_1_, p_176216_2_); } else { this.bounce(p_176216_2_); } } private void bounce(Entity p_226860_1_) { - Vector3d Vector3d = p_226860_1_.getMotion(); + Vector3d Vector3d = p_226860_1_.getDeltaMovement(); if (Vector3d.y < 0.0D) { double d0 = p_226860_1_ instanceof LivingEntity ? 1.0D : 0.8D; - p_226860_1_.setMotion(Vector3d.x, -Vector3d.y * (double) 0.26F * d0, Vector3d.z); + p_226860_1_.setDeltaMovement(Vector3d.x, -Vector3d.y * (double) 0.26F * d0, Vector3d.z); } } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } @@ -216,12 +216,12 @@ public class SailBlock extends ProperDirectionalBlock { @Override public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) { - List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(SailBlock.FACING).getAxis(), dir -> world.getBlockState(pos.offset(dir)).getMaterial().isReplaceable()); + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), state.getValue(SailBlock.FACING).getAxis(), dir -> world.getBlockState(pos.relative(dir)).getMaterial().isReplaceable()); if (directions.isEmpty()) return PlacementOffset.fail(); else { - return PlacementOffset.success(pos.offset(directions.get(0)), s -> s.with(FACING, state.get(FACING))); + return PlacementOffset.success(pos.relative(directions.get(0)), s -> s.setValue(FACING, state.getValue(FACING))); } } } 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..67de1bc5f 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,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +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,17 +23,19 @@ 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; - facing = blockState.get(BlockStateProperties.FACING); - rotationAxis = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, facing.getAxis()).getUnitVector(); + facing = blockState.getValue(BlockStateProperties.FACING); + rotationAxis = Direction.get(Direction.AxisDirection.POSITIVE, facing.getAxis()).step(); blockOrientation = BearingInstance.getBlockStateOrientation(facing); - topInstance = modelManager.getOrientedMaterial().getModel(AllBlockPartials.BEARING_TOP, blockState).createInstance(); + topInstance = materialManager.defaultSolid() + .material(Materials.ORIENTED) + .getModel(AllBlockPartials.BEARING_TOP, blockState).createInstance(); topInstance.setPosition(context.localPos) .setRotation(blockOrientation) @@ -42,9 +46,9 @@ public class StabilizedBearingInstance extends ActorInstance { public void beginFrame() { float counterRotationAngle = StabilizedBearingMovementBehaviour.getCounterRotationAngle(context, facing, AnimationTickHolder.getPartialTicks()); - Quaternion rotation = rotationAxis.getDegreesQuaternion(counterRotationAngle); + Quaternion rotation = rotationAxis.rotationDegrees(counterRotationAngle); - rotation.multiply(blockOrientation); + rotation.mul(blockOrientation); topInstance.setRotation(rotation); } 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..2e03a363e 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.material.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,11 +32,11 @@ 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); + Direction facing = context.state.getValue(BlockStateProperties.FACING); PartialModel top = AllBlockPartials.BEARING_TOP; SuperByteBuffer superBuffer = PartialBufferer.get(top, context.state); float renderPartialTicks = AnimationTickHolder.getPartialTicks(); @@ -44,20 +45,22 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { Quaternion orientation = BearingInstance.getBlockStateOrientation(facing); // rotate against parent - float angle = getCounterRotationAngle(context, facing, renderPartialTicks) * facing.getAxisDirection().getOffset(); + float angle = getCounterRotationAngle(context, facing, renderPartialTicks) * facing.getAxisDirection().getStep(); - Quaternion rotation = facing.getUnitVector().getDegreesQuaternion(angle); + Quaternion rotation = facing.step().rotationDegrees(angle); - rotation.multiply(orientation); + rotation.mul(orientation); orientation = rotation; + superBuffer.transform(matrices.getModel()); superBuffer.rotateCentered(orientation); // render - superBuffer.light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)); - superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + superBuffer + .light(matrices.getWorld(), + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid())); } @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) { @@ -85,11 +88,11 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { } else if (entity instanceof OrientedContraptionEntity) { OrientedContraptionEntity orientedCE = (OrientedContraptionEntity) entity; if (axis.isVertical()) - offset = -orientedCE.getYaw(renderPartialTicks); + offset = -orientedCE.getViewYRot(renderPartialTicks); else { if (orientedCE.isInitialOrientationPresent() && orientedCE.getInitialOrientation() .getAxis() == axis) - offset = -orientedCE.getPitch(renderPartialTicks); + offset = -orientedCE.getViewXRot(renderPartialTicks); } } return offset; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java index 4eec742bc..e3f96872d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java @@ -23,7 +23,7 @@ public class StabilizedContraption extends Contraption { @Override public boolean assemble(World world, BlockPos pos) throws AssemblyException { - BlockPos offset = pos.offset(facing); + BlockPos offset = pos.relative(facing); if (!searchMovedStructure(world, offset, null)) return false; startMoving(world); @@ -45,13 +45,13 @@ public class StabilizedContraption extends Contraption { @Override public CompoundNBT writeNBT(boolean spawnPacket) { CompoundNBT tag = super.writeNBT(spawnPacket); - tag.putInt("Facing", facing.getIndex()); + tag.putInt("Facing", facing.get3DDataValue()); return tag; } @Override public void readNBT(World world, CompoundNBT tag, boolean spawnData) { - facing = Direction.byIndex(tag.getInt("Facing")); + facing = Direction.from3DDataValue(tag.getInt("Facing")); super.readNBT(world, tag, spawnData); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingBlock.java index 0f5bb749f..0c6e037f9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingBlock.java @@ -25,15 +25,15 @@ public class WindmillBearingBlock extends BearingBlock implements ITE { if (te.running) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingTileEntity.java index ccd717284..d61a227ed 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingTileEntity.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.be import java.util.List; +import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; @@ -41,7 +42,8 @@ public class WindmillBearingTileEntity extends MechanicalBearingTileEntity { return 0; if (movedContraption == null) return lastGeneratedSpeed; - int sails = ((BearingContraption) movedContraption.getContraption()).getSailBlocks() / 8; + int sails = ((BearingContraption) movedContraption.getContraption()).getSailBlocks() + / AllConfigs.SERVER.kinetics.windmillSailsPerRPM.get(); return MathHelper.clamp(sails, 1, 16) * getAngleSpeedDirection(); } @@ -82,7 +84,7 @@ public class WindmillBearingTileEntity extends MechanicalBearingTileEntity { private void onDirectionChanged() { if (!running) return; - if (!world.isRemote) + if (!level.isClientSide) updateGeneratedRotation(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java index 2156411af..7ba1ceba3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java @@ -42,51 +42,51 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock implements } @Override - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - if (!player.isAllowEdit()) + if (!player.mayBuild()) return ActionResultType.PASS; - ItemStack heldItem = player.getHeldItem(handIn); + ItemStack heldItem = player.getItemInHand(handIn); boolean isSlimeBall = heldItem.getItem() - .isIn(Tags.Items.SLIMEBALLS) || AllItems.SUPER_GLUE.isIn(heldItem); + .is(Tags.Items.SLIMEBALLS) || AllItems.SUPER_GLUE.isIn(heldItem); - BooleanProperty affectedSide = getGlueableSide(state, hit.getFace()); + BooleanProperty affectedSide = getGlueableSide(state, hit.getDirection()); if (affectedSide == null) return ActionResultType.PASS; - if (isSlimeBall && state.get(affectedSide)) { + if (isSlimeBall && state.getValue(affectedSide)) { for (Direction face : Iterate.directions) { BooleanProperty glueableSide = getGlueableSide(state, face); - if (glueableSide != null && !state.get(glueableSide) && glueAllowedOnSide(worldIn, pos, state, face)) { - if (worldIn.isRemote) { - Vector3d vec = hit.getHitVec(); + if (glueableSide != null && !state.getValue(glueableSide) && glueAllowedOnSide(worldIn, pos, state, face)) { + if (worldIn.isClientSide) { + Vector3d vec = hit.getLocation(); worldIn.addParticle(ParticleTypes.ITEM_SLIME, vec.x, vec.y, vec.z, 0, 0, 0); return ActionResultType.SUCCESS; } AllSoundEvents.SLIME_ADDED.playOnServer(worldIn, pos, .5f, 1); - state = state.with(glueableSide, true); + state = state.setValue(glueableSide, true); } } - if (!worldIn.isRemote) - worldIn.setBlockState(pos, state); + if (!worldIn.isClientSide) + worldIn.setBlockAndUpdate(pos, state); return ActionResultType.SUCCESS; } - if ((!heldItem.isEmpty() || !player.isSneaking()) && !isSlimeBall) + if ((!heldItem.isEmpty() || !player.isShiftKeyDown()) && !isSlimeBall) return ActionResultType.PASS; - if (state.get(affectedSide) == isSlimeBall) + if (state.getValue(affectedSide) == isSlimeBall) return ActionResultType.PASS; - if (!glueAllowedOnSide(worldIn, pos, state, hit.getFace())) + if (!glueAllowedOnSide(worldIn, pos, state, hit.getDirection())) return ActionResultType.PASS; - if (worldIn.isRemote) { - Vector3d vec = hit.getHitVec(); + if (worldIn.isClientSide) { + Vector3d vec = hit.getLocation(); worldIn.addParticle(ParticleTypes.ITEM_SLIME, vec.x, vec.y, vec.z, 0, 0, 0); return ActionResultType.SUCCESS; } AllSoundEvents.SLIME_ADDED.playOnServer(worldIn, pos, .5f, 1); - worldIn.setBlockState(pos, state.with(affectedSide, isSlimeBall)); + worldIn.setBlockAndUpdate(pos, state.setValue(affectedSide, isSlimeBall)); return ActionResultType.SUCCESS; } @@ -100,17 +100,17 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock implements for (Direction face : Iterate.directions) { BooleanProperty glueableSide = getGlueableSide(rotated, face); if (glueableSide != null) - rotated = rotated.with(glueableSide, false); + rotated = rotated.setValue(glueableSide, false); } for (Direction face : Iterate.directions) { BooleanProperty glueableSide = getGlueableSide(state, face); - if (glueableSide == null || !state.get(glueableSide)) + if (glueableSide == null || !state.getValue(glueableSide)) continue; Direction rotatedFacing = rotation.rotate(face); BooleanProperty rotatedGlueableSide = getGlueableSide(rotated, rotatedFacing); if (rotatedGlueableSide != null) - rotated = rotated.with(rotatedGlueableSide, true); + rotated = rotated.setValue(rotatedGlueableSide, true); } return rotated; @@ -125,17 +125,17 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock implements for (Direction face : Iterate.directions) { BooleanProperty glueableSide = getGlueableSide(mirrored, face); if (glueableSide != null) - mirrored = mirrored.with(glueableSide, false); + mirrored = mirrored.setValue(glueableSide, false); } for (Direction face : Iterate.directions) { BooleanProperty glueableSide = getGlueableSide(state, face); - if (glueableSide == null || !state.get(glueableSide)) + if (glueableSide == null || !state.getValue(glueableSide)) continue; Direction mirroredFacing = mirrorIn.mirror(face); BooleanProperty mirroredGlueableSide = getGlueableSide(mirrored, mirroredFacing); if (mirroredGlueableSide != null) - mirrored = mirrored.with(mirroredGlueableSide, true); + mirrored = mirrored.setValue(mirroredGlueableSide, true); } return mirrored; 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..5477f449e 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,15 +35,15 @@ 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() { - return Pair.of(te.getPos(), 1); + return Pair.of(te.getBlockPos(), 1); } protected Set createSelection(ChassisTileEntity chassis) { @@ -88,8 +88,8 @@ public class ChassisRangeDisplay { public static void tick() { PlayerEntity player = Minecraft.getInstance().player; - World world = Minecraft.getInstance().world; - boolean hasWrench = AllItems.WRENCH.isIn(player.getHeldItemMainhand()); + World world = Minecraft.getInstance().level; + boolean hasWrench = AllItems.WRENCH.isIn(player.getMainHandItem()); for (Iterator iterator = entries.keySet() .iterator(); iterator.hasNext();) { @@ -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,18 +107,18 @@ public class ChassisRangeDisplay { if (group == lastHoveredGroup) lastHoveredGroup = null; } - CreateClient.outliner.keep(group.getOutlineKey()); + CreateClient.OUTLINER.keep(group.getOutlineKey()); } if (!hasWrench) return; - RayTraceResult over = Minecraft.getInstance().objectMouseOver; + RayTraceResult over = Minecraft.getInstance().hitResult; if (!(over instanceof BlockRayTraceResult)) return; BlockRayTraceResult ray = (BlockRayTraceResult) over; - BlockPos pos = ray.getPos(); - TileEntity tileEntity = world.getTileEntity(pos); + BlockPos pos = ray.getBlockPos(); + TileEntity tileEntity = world.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) return; if (!(tileEntity instanceof ChassisTileEntity)) @@ -131,7 +131,7 @@ public class ChassisRangeDisplay { GroupEntry existingGroupForPos = getExistingGroupForPos(pos); if (existingGroupForPos != null) { for (ChassisTileEntity included : existingGroupForPos.includedTEs) - entries.remove(included.getPos()); + entries.remove(included.getBlockPos()); existingGroupForPos.timer = DISPLAY_TIME; return; } @@ -147,11 +147,11 @@ public class ChassisRangeDisplay { private static boolean tickEntry(Entry entry, boolean hasWrench) { ChassisTileEntity chassisTileEntity = entry.te; - World teWorld = chassisTileEntity.getWorld(); - World world = Minecraft.getInstance().world; + World teWorld = chassisTileEntity.getLevel(); + World world = Minecraft.getInstance().level; if (chassisTileEntity.isRemoved() || teWorld == null || teWorld != world - || !world.isBlockPresent(chassisTileEntity.getPos())) { + || !world.isLoaded(chassisTileEntity.getBlockPos())) { return true; } @@ -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.getBlockPos()); - groupEntries.forEach(entry -> CreateClient.outliner.remove(entry.getOutlineKey())); + groupEntries.forEach(entry -> CreateClient.OUTLINER.remove(entry.getOutlineKey())); groupEntries.clear(); entries.clear(); groupEntries.add(hoveredGroup); @@ -183,10 +183,10 @@ public class ChassisRangeDisplay { } // Display an individual chassis and kill any group selections that contained it - BlockPos pos = chassis.getPos(); + BlockPos pos = chassis.getBlockPos(); GroupEntry entry = getExistingGroupForPos(pos); if (entry != null) - CreateClient.outliner.remove(entry.getOutlineKey()); + CreateClient.OUTLINER.remove(entry.getOutlineKey()); groupEntries.clear(); entries.clear(); @@ -197,7 +197,7 @@ public class ChassisRangeDisplay { private static GroupEntry getExistingGroupForPos(BlockPos pos) { for (GroupEntry groupEntry : groupEntries) for (ChassisTileEntity chassis : groupEntry.includedTEs) - if (pos.equals(chassis.getPos())) + if (pos.equals(chassis.getBlockPos())) return groupEntry; return null; } 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..a5590caf6 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; @@ -73,20 +73,20 @@ public class ChassisTileEntity extends SmartTileEntity { } protected boolean isRadial() { - return world.getBlockState(pos).getBlock() instanceof RadialChassisBlock; + return level.getBlockState(worldPosition).getBlock() instanceof RadialChassisBlock; } public List collectChassisGroup() { Queue frontier = new LinkedList<>(); List collected = new ArrayList<>(); Set visited = new HashSet<>(); - frontier.add(pos); + frontier.add(worldPosition); while (!frontier.isEmpty()) { BlockPos current = frontier.poll(); if (visited.contains(current)) continue; visited.add(current); - TileEntity tileEntity = world.getTileEntity(current); + TileEntity tileEntity = level.getBlockEntity(current); if (tileEntity instanceof ChassisTileEntity) { ChassisTileEntity chassis = (ChassisTileEntity) tileEntity; collected.add(chassis); @@ -101,20 +101,20 @@ public class ChassisTileEntity extends SmartTileEntity { BlockState state = getBlockState(); if (!(state.getBlock() instanceof AbstractChassisBlock)) return false; - Axis axis = state.get(AbstractChassisBlock.AXIS); + Axis axis = state.getValue(AbstractChassisBlock.AXIS); if (isRadial()) { // Collect chain of radial chassis for (int offset : new int[] { -1, 1 }) { - Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); - BlockPos currentPos = pos.offset(direction, offset); - if (!world.isBlockPresent(currentPos)) + Direction direction = Direction.get(AxisDirection.POSITIVE, axis); + BlockPos currentPos = worldPosition.relative(direction, offset); + if (!level.isLoaded(currentPos)) return false; - BlockState neighbourState = world.getBlockState(currentPos); + BlockState neighbourState = level.getBlockState(currentPos); if (!AllBlocks.RADIAL_CHASSIS.has(neighbourState)) continue; - if (axis != neighbourState.get(BlockStateProperties.AXIS)) + if (axis != neighbourState.getValue(BlockStateProperties.AXIS)) continue; if (!visited.contains(currentPos)) frontier.add(currentPos); @@ -125,18 +125,18 @@ public class ChassisTileEntity extends SmartTileEntity { // Collect group of connected linear chassis for (Direction offset : Iterate.directions) { - BlockPos current = pos.offset(offset); + BlockPos current = worldPosition.relative(offset); if (visited.contains(current)) continue; - if (!world.isBlockPresent(current)) + if (!level.isLoaded(current)) return false; - BlockState neighbourState = world.getBlockState(current); + BlockState neighbourState = level.getBlockState(current); if (!LinearChassisBlock.isChassis(neighbourState)) continue; if (!LinearChassisBlock.sameKind(state, neighbourState)) continue; - if (neighbourState.get(AXIS) != axis) + if (neighbourState.getValue(AXIS) != axis) continue; frontier.add(current); @@ -149,30 +149,30 @@ public class ChassisTileEntity extends SmartTileEntity { List positions = new ArrayList<>(); BlockState state = getBlockState(); AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock(); - Axis axis = state.get(AbstractChassisBlock.AXIS); - Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); + Axis axis = state.getValue(AbstractChassisBlock.AXIS); + Direction facing = Direction.get(AxisDirection.POSITIVE, axis); int chassisRange = visualize ? range.scrollableValue : getRange(); for (int offset : new int[] { 1, -1 }) { if (offset == -1) facing = facing.getOpposite(); - boolean sticky = state.get(block.getGlueableSide(state, facing)); + boolean sticky = state.getValue(block.getGlueableSide(state, facing)); for (int i = 1; i <= chassisRange; i++) { - BlockPos current = pos.offset(facing, i); - BlockState currentState = world.getBlockState(current); + BlockPos current = worldPosition.relative(facing, i); + BlockState currentState = level.getBlockState(current); if (forcedMovement != facing && !sticky) break; // Ignore replaceable Blocks and Air-like - if (!BlockMovementTraits.movementNecessary(currentState, world, current)) + if (!BlockMovementChecks.isMovementNecessary(currentState, level, 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; } } @@ -182,48 +182,48 @@ public class ChassisTileEntity extends SmartTileEntity { private List getIncludedBlockPositionsRadial(Direction forcedMovement, boolean visualize) { List positions = new ArrayList<>(); - BlockState state = world.getBlockState(pos); - Axis axis = state.get(AbstractChassisBlock.AXIS); + BlockState state = level.getBlockState(worldPosition); + Axis axis = state.getValue(AbstractChassisBlock.AXIS); AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock(); int chassisRange = visualize ? range.scrollableValue : getRange(); for (Direction facing : Iterate.directions) { if (facing.getAxis() == axis) continue; - if (!state.get(block.getGlueableSide(state, facing))) + if (!state.getValue(block.getGlueableSide(state, facing))) continue; - BlockPos startPos = pos.offset(facing); + BlockPos startPos = worldPosition.relative(facing); List localFrontier = new LinkedList<>(); Set localVisited = new HashSet<>(); localFrontier.add(startPos); while (!localFrontier.isEmpty()) { BlockPos searchPos = localFrontier.remove(0); - BlockState searchedState = world.getBlockState(searchPos); + BlockState searchedState = level.getBlockState(searchPos); if (localVisited.contains(searchPos)) continue; - if (!searchPos.withinDistance(pos, chassisRange + .5f)) + if (!searchPos.closerThan(worldPosition, chassisRange + .5f)) continue; - if (!BlockMovementTraits.movementNecessary(searchedState, world, searchPos)) + if (!BlockMovementChecks.isMovementNecessary(searchedState, level, searchPos)) continue; - if (BlockMovementTraits.isBrittle(searchedState)) + if (BlockMovementChecks.isBrittle(searchedState)) continue; localVisited.add(searchPos); - if (!searchPos.equals(pos)) + if (!searchPos.equals(worldPosition)) positions.add(searchPos); for (Direction offset : Iterate.directions) { if (offset.getAxis() == axis) continue; - if (searchPos.equals(pos) && offset != facing) + if (searchPos.equals(worldPosition) && offset != facing) continue; - if (BlockMovementTraits.notSupportive(searchedState, offset)) + if (BlockMovementChecks.isNotSupportive(searchedState, offset)) continue; - localFrontier.add(searchPos.offset(offset)); + localFrontier.add(searchPos.relative(offset)); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/LinearChassisBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/LinearChassisBlock.java index c10ea95da..3c35b4573 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/LinearChassisBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/LinearChassisBlock.java @@ -25,54 +25,54 @@ public class LinearChassisBlock extends AbstractChassisBlock { public LinearChassisBlock(Properties properties) { super(properties); - setDefaultState(getDefaultState().with(STICKY_TOP, false) - .with(STICKY_BOTTOM, false)); + registerDefaultState(defaultBlockState().setValue(STICKY_TOP, false) + .setValue(STICKY_BOTTOM, false)); } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(STICKY_TOP, STICKY_BOTTOM); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - BlockPos placedOnPos = context.getPos() - .offset(context.getFace() + BlockPos placedOnPos = context.getClickedPos() + .relative(context.getClickedFace() .getOpposite()); - BlockState blockState = context.getWorld() + BlockState blockState = context.getLevel() .getBlockState(placedOnPos); if (context.getPlayer() == null || !context.getPlayer() - .isSneaking()) { + .isShiftKeyDown()) { if (isChassis(blockState)) - return getDefaultState().with(AXIS, blockState.get(AXIS)); - return getDefaultState().with(AXIS, context.getNearestLookingDirection() + return defaultBlockState().setValue(AXIS, blockState.getValue(AXIS)); + return defaultBlockState().setValue(AXIS, context.getNearestLookingDirection() .getAxis()); } return super.getStateForPlacement(context); } @Override - public BlockState updatePostPlacement(BlockState state, Direction side, BlockState other, IWorld p_196271_4_, + public BlockState updateShape(BlockState state, Direction side, BlockState other, IWorld p_196271_4_, BlockPos p_196271_5_, BlockPos p_196271_6_) { BooleanProperty property = getGlueableSide(state, side); - if (property == null || !sameKind(state, other) || state.get(AXIS) != other.get(AXIS)) + if (property == null || !sameKind(state, other) || state.getValue(AXIS) != other.getValue(AXIS)) return state; - return state.with(property, false); + return state.setValue(property, false); } @Override public BooleanProperty getGlueableSide(BlockState state, Direction face) { - if (face.getAxis() != state.get(AXIS)) + if (face.getAxis() != state.getValue(AXIS)) return null; return face.getAxisDirection() == AxisDirection.POSITIVE ? STICKY_TOP : STICKY_BOTTOM; } @Override protected boolean glueAllowedOnSide(IBlockReader world, BlockPos pos, BlockState state, Direction side) { - BlockState other = world.getBlockState(pos.offset(side)); - return !sameKind(other, state) || state.get(AXIS) != other.get(AXIS); + BlockState other = world.getBlockState(pos.relative(side)); + return !sameKind(other, state) || state.getValue(AXIS) != other.getValue(AXIS); } public static boolean isChassis(BlockState state) { @@ -92,20 +92,20 @@ public class LinearChassisBlock extends AbstractChassisBlock { if (glueableSide == null) return AllBlocks.LINEAR_CHASSIS.has(state) ? AllSpriteShifts.CHASSIS_SIDE : AllSpriteShifts.SECONDARY_CHASSIS_SIDE; - return state.get(glueableSide) ? AllSpriteShifts.CHASSIS_STICKY : AllSpriteShifts.CHASSIS; + return state.getValue(glueableSide) ? AllSpriteShifts.CHASSIS_STICKY : AllSpriteShifts.CHASSIS; } @Override protected Direction getUpDirection(IBlockDisplayReader reader, BlockPos pos, BlockState state, Direction face) { - Axis axis = state.get(AXIS); + Axis axis = state.getValue(AXIS); if (face.getAxis() == axis) return super.getUpDirection(reader, pos, state, face); - return Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); + return Direction.get(AxisDirection.POSITIVE, axis); } @Override protected Direction getRightDirection(IBlockDisplayReader reader, BlockPos pos, BlockState state, Direction face) { - Axis axis = state.get(AXIS); + Axis axis = state.getValue(AXIS); return axis != face.getAxis() && axis.isHorizontal() ? (face.getAxis() .isHorizontal() ? Direction.DOWN : (axis == Axis.X ? Direction.NORTH : Direction.EAST)) : super.getRightDirection(reader, pos, state, face); @@ -113,7 +113,7 @@ public class LinearChassisBlock extends AbstractChassisBlock { @Override protected boolean reverseUVsHorizontally(BlockState state, Direction face) { - Axis axis = state.get(AXIS); + Axis axis = state.getValue(AXIS); boolean side = face.getAxis() != axis; if (side && axis == Axis.X && face.getAxis() .isHorizontal()) @@ -128,7 +128,7 @@ public class LinearChassisBlock extends AbstractChassisBlock { @Override public boolean reverseUVs(BlockState state, Direction face) { - Axis axis = state.get(AXIS); + Axis axis = state.getValue(AXIS); boolean end = face.getAxis() == axis; if (end && axis.isHorizontal() && (face.getAxisDirection() == AxisDirection.POSITIVE)) return true; @@ -140,10 +140,10 @@ public class LinearChassisBlock extends AbstractChassisBlock { @Override public boolean connectsTo(BlockState state, BlockState other, IBlockDisplayReader reader, BlockPos pos, BlockPos otherPos, Direction face) { - Axis axis = state.get(AXIS); + Axis axis = state.getValue(AXIS); boolean superConnect = face.getAxis() == axis ? super.connectsTo(state, other, reader, pos, otherPos, face) : sameKind(state, other); - return superConnect && axis == other.get(AXIS); + return superConnect && axis == other.getValue(AXIS); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/RadialChassisBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/RadialChassisBlock.java index 852c168bb..a54bc4c65 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/RadialChassisBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/RadialChassisBlock.java @@ -16,19 +16,19 @@ public class RadialChassisBlock extends AbstractChassisBlock { public RadialChassisBlock(Properties properties) { super(properties); - setDefaultState(getDefaultState().with(STICKY_EAST, false).with(STICKY_SOUTH, false).with(STICKY_NORTH, false) - .with(STICKY_WEST, false)); + registerDefaultState(defaultBlockState().setValue(STICKY_EAST, false).setValue(STICKY_SOUTH, false).setValue(STICKY_NORTH, false) + .setValue(STICKY_WEST, false)); } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(STICKY_NORTH, STICKY_EAST, STICKY_SOUTH, STICKY_WEST); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override public BooleanProperty getGlueableSide(BlockState state, Direction face) { - Axis axis = state.get(AXIS); + Axis axis = state.getValue(AXIS); if (axis == Axis.X) { if (face == Direction.NORTH) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java index 277223c95..fab3a2e05 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.ch import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -25,46 +25,46 @@ import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; -public class StickerBlock extends ProperDirectionalBlock implements ITE { +public class StickerBlock extends WrenchableDirectionalBlock implements ITE { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty EXTENDED = BlockStateProperties.EXTENDED; public StickerBlock(Properties p_i48415_1_) { super(p_i48415_1_); - setDefaultState(getDefaultState().with(POWERED, false) - .with(EXTENDED, false)); + registerDefaultState(defaultBlockState().setValue(POWERED, false) + .setValue(EXTENDED, false)); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { Direction nearestLookingDirection = context.getNearestLookingDirection(); - boolean shouldPower = context.getWorld() - .isBlockPowered(context.getPos()); + boolean shouldPower = context.getLevel() + .hasNeighborSignal(context.getClickedPos()); Direction facing = context.getPlayer() != null && context.getPlayer() - .isSneaking() ? nearestLookingDirection : nearestLookingDirection.getOpposite(); + .isShiftKeyDown() ? nearestLookingDirection : nearestLookingDirection.getOpposite(); - return getDefaultState().with(FACING, facing) - .with(POWERED, shouldPower); + return defaultBlockState().setValue(FACING, facing) + .setValue(POWERED, shouldPower); } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(POWERED, EXTENDED)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED, EXTENDED)); } @Override public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; - boolean previouslyPowered = state.get(POWERED); - if (previouslyPowered != worldIn.isBlockPowered(pos)) { + boolean previouslyPowered = state.getValue(POWERED); + if (previouslyPowered != worldIn.hasNeighborSignal(pos)) { state = state.cycle(POWERED); - if (state.get(POWERED)) + if (state.getValue(POWERED)) state = state.cycle(EXTENDED); - worldIn.setBlockState(pos, state, 2); + worldIn.setBlock(pos, state, 2); } } @@ -92,52 +92,52 @@ public class StickerBlock extends ProperDirectionalBlock implements ITE 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(); - fakeWorld = tile.getWorld() != Minecraft.getInstance().world; - facing = blockState.get(StickerBlock.FACING); - offset = blockState.get(StickerBlock.EXTENDED) ? 1 : 0; + fakeWorld = tile.getLevel() != Minecraft.getInstance().level; + facing = blockState.getValue(StickerBlock.FACING); + offset = blockState.getValue(StickerBlock.EXTENDED) ? 1 : 0; animateHead(offset); } @@ -42,7 +42,7 @@ public class StickerInstance extends TileEntityInstance imple if (fakeWorld) offset = this.offset; - if (MathHelper.epsilonEquals(offset, lastOffset)) + if (MathHelper.equal(offset, lastOffset)) return; animateHead(offset); @@ -52,7 +52,7 @@ public class StickerInstance extends TileEntityInstance imple private void animateHead(float offset) { MatrixStack stack = new MatrixStack(); - MatrixStacker.of(stack) + MatrixTransformStack.of(stack) .translate(getInstancePosition()) .nudge(tile.hashCode()) .centre() 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..91ef67f06 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,16 +26,16 @@ 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.getLevel())) return; BlockState state = te.getBlockState(); SuperByteBuffer head = PartialBufferer.get(AllBlockPartials.STICKER_HEAD, state); - float offset = te.piston.getValue(AnimationTickHolder.getPartialTicks(te.getWorld())); + float offset = te.piston.getValue(AnimationTickHolder.getPartialTicks(te.getLevel())); - if (te.getWorld() != Minecraft.getInstance().world && !te.isVirtual()) - offset = state.get(StickerBlock.EXTENDED) ? 1 : 0; + if (te.getLevel() != Minecraft.getInstance().level && !te.isVirtual()) + offset = state.getValue(StickerBlock.EXTENDED) ? 1 : 0; - Direction facing = state.get(StickerBlock.FACING); + Direction facing = state.getValue(StickerBlock.FACING); head.matrixStacker() .nudge(te.hashCode()) .centre() @@ -45,7 +45,7 @@ public class StickerRenderer extends SafeTileEntityRenderer { .translate(0, (offset * offset) * 4 / 16f, 0); head.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .renderInto(ms, buffer.getBuffer(RenderType.solid())); } } 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..6e85209da 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; @@ -39,26 +39,26 @@ public class StickerTileEntity extends SmartTileEntity implements IInstanceRende @Override public void initialize() { super.initialize(); - if (!world.isRemote) + if (!level.isClientSide) return; piston.startWithValue(isBlockStateExtended() ? 1 : 0); } public boolean isBlockStateExtended() { BlockState blockState = getBlockState(); - boolean extended = AllBlocks.STICKER.has(blockState) && blockState.get(StickerBlock.EXTENDED); + boolean extended = AllBlocks.STICKER.has(blockState) && blockState.getValue(StickerBlock.EXTENDED); return extended; } @Override public void tick() { super.tick(); - if (!world.isRemote) + if (!level.isClientSide) return; piston.tickChaser(); if (isAttachedToBlock() && piston.getValue(0) != piston.getValue() && piston.getValue() == 1) { - SuperGlueItem.spawnParticles(world, pos, getBlockState().get(StickerBlock.FACING), true); + SuperGlueItem.spawnParticles(level, worldPosition, getBlockState().getValue(StickerBlock.FACING), true); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(true)); } @@ -70,15 +70,15 @@ 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() { BlockState blockState = getBlockState(); if (!AllBlocks.STICKER.has(blockState)) return false; - Direction direction = blockState.get(StickerBlock.FACING); - return SuperGlueEntity.isValidFace(world, pos.offset(direction), direction.getOpposite()); + Direction direction = blockState.getValue(StickerBlock.FACING); + return SuperGlueEntity.isValidFace(level, worldPosition.relative(direction), direction.getOpposite()); } @Override @@ -90,7 +90,8 @@ public class StickerTileEntity extends SmartTileEntity implements IInstanceRende @OnlyIn(Dist.CLIENT) public void playSound(boolean attach) { - AllSoundEvents.SLIME_ADDED.play(world, Minecraft.getInstance().player, pos, 0.35f, attach ? 0.75f : 0.2f); + AllSoundEvents.SLIME_ADDED.play(level, Minecraft.getInstance().player, worldPosition, 0.35f, attach ? 0.75f : 0.2f); } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageBlock.java index 849bfb36b..1c818a8ca 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageBlock.java @@ -31,22 +31,22 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements } @Override - public boolean isValidPosition(BlockState state, IWorldReader world, BlockPos pos) { - Direction direction = state.get(FACING); - BlockState shaft = world.getBlockState(pos.offset(direction.getOpposite())); - return AllBlocks.GANTRY_SHAFT.has(shaft) && shaft.get(GantryShaftBlock.FACING) + public boolean canSurvive(BlockState state, IWorldReader world, BlockPos pos) { + Direction direction = state.getValue(FACING); + BlockState shaft = world.getBlockState(pos.relative(direction.getOpposite())); + return AllBlocks.GANTRY_SHAFT.has(shaft) && shaft.getValue(GantryShaftBlock.FACING) .getAxis() != direction.getAxis(); } @Override - public void updateDiagonalNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags, int count) { - super.updateDiagonalNeighbors(stateIn, worldIn, pos, flags, count); + public void updateIndirectNeighbourShapes(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags, int count) { + super.updateIndirectNeighbourShapes(stateIn, worldIn, pos, flags, count); withTileEntityDo(worldIn, pos, GantryCarriageTileEntity::checkValidGantryShaft); } @Override - public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { - super.onBlockAdded(state, worldIn, pos, oldState, isMoving); + public void onPlace(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, worldIn, pos, oldState, isMoving); } @Override @@ -56,14 +56,14 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements @Override protected Direction getFacingForPlacement(BlockItemUseContext context) { - return context.getFace(); + return context.getClickedFace(); } - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - if (!player.isAllowEdit() || player.isSneaking()) + if (!player.mayBuild() || player.isShiftKeyDown()) return ActionResultType.PASS; - if (player.getHeldItem(handIn) + if (player.getItemInHand(handIn) .isEmpty()) { withTileEntityDo(worldIn, pos, te -> te.checkValidGantryShaft()); return ActionResultType.SUCCESS; @@ -74,25 +74,25 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements @Override public BlockState getStateForPlacement(BlockItemUseContext context) { BlockState stateForPlacement = super.getStateForPlacement(context); - Direction opposite = stateForPlacement.get(FACING) + Direction opposite = stateForPlacement.getValue(FACING) .getOpposite(); - return cycleAxisIfNecessary(stateForPlacement, opposite, context.getWorld() - .getBlockState(context.getPos() - .offset(opposite))); + return cycleAxisIfNecessary(stateForPlacement, opposite, context.getLevel() + .getBlockState(context.getClickedPos() + .relative(opposite))); } @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block p_220069_4_, BlockPos updatePos, boolean p_220069_6_) { - if (updatePos.equals(pos.offset(state.get(FACING) - .getOpposite())) && !isValidPosition(state, world, pos)) + if (updatePos.equals(pos.relative(state.getValue(FACING) + .getOpposite())) && !canSurvive(state, world, pos)) world.destroyBlock(pos, true); } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState otherState, IWorld world, + public BlockState updateShape(BlockState state, Direction direction, BlockState otherState, IWorld world, BlockPos pos, BlockPos p_196271_6_) { - if (state.get(FACING) != direction.getOpposite()) + if (state.getValue(FACING) != direction.getOpposite()) return state; return cycleAxisIfNecessary(state, direction, otherState); } @@ -100,7 +100,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements protected BlockState cycleAxisIfNecessary(BlockState state, Direction direction, BlockState otherState) { if (!AllBlocks.GANTRY_SHAFT.has(otherState)) return state; - if (otherState.get(GantryShaftBlock.FACING) + if (otherState.getValue(GantryShaftBlock.FACING) .getAxis() == direction.getAxis()) return state; if (isValidGantryShaftAxis(state, otherState)) @@ -109,7 +109,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements } public static boolean isValidGantryShaftAxis(BlockState pinionState, BlockState gantryState) { - return getValidGantryShaftAxis(pinionState) == gantryState.get(GantryShaftBlock.FACING) + return getValidGantryShaftAxis(pinionState) == gantryState.getValue(GantryShaftBlock.FACING) .getAxis(); } @@ -118,7 +118,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements return Axis.Y; IRotate block = (IRotate) state.getBlock(); Axis rotationAxis = block.getRotationAxis(state); - Axis facingAxis = state.get(FACING) + Axis facingAxis = state.getValue(FACING) .getAxis(); for (Axis axis : Iterate.axes) if (axis != rotationAxis && axis != facingAxis) @@ -127,7 +127,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements } public static Axis getValidGantryPinionAxis(BlockState state, Axis shaftAxis) { - Axis facingAxis = state.get(FACING) + Axis facingAxis = state.getValue(FACING) .getAxis(); for (Axis axis : Iterate.axes) if (axis != shaftAxis && axis != facingAxis) 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..5a4d957f5 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,16 +1,16 @@ package com.simibubi.create.content.contraptions.components.structureMovement.gantry; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -29,22 +29,22 @@ 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() .getModel(AllBlockPartials.GANTRY_COGS, blockState) .createInstance(); - facing = blockState.get(GantryCarriageBlock.FACING); - alongFirst = blockState.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); + facing = blockState.getValue(GantryCarriageBlock.FACING); + alongFirst = blockState.getValue(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); rotationAxis = KineticTileEntityRenderer.getRotationAxisOf(tile); rotationMult = getRotationMultiplier(getGantryAxis(), facing); - visualPos = facing.getAxisDirection() == Direction.AxisDirection.POSITIVE ? tile.getPos() - : tile.getPos() - .offset(facing.getOpposite()); + visualPos = facing.getAxisDirection() == Direction.AxisDirection.POSITIVE ? tile.getBlockPos() + : tile.getBlockPos() + .relative(facing.getOpposite()); animateCogs(getCogAngle()); } @@ -53,7 +53,7 @@ public class GantryCarriageInstance extends ShaftInstance implements IDynamicIns public void beginFrame() { float cogAngle = getCogAngle(); - if (MathHelper.epsilonEquals(cogAngle, lastAngle)) return; + if (MathHelper.equal(cogAngle, lastAngle)) return; animateCogs(cogAngle); } @@ -64,14 +64,14 @@ public class GantryCarriageInstance extends ShaftInstance implements IDynamicIns private void animateCogs(float cogAngle) { MatrixStack ms = new MatrixStack(); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .translate(getInstancePosition()) .centre() .rotateY(AngleHelper.horizontalAngle(facing)) .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) .rotateY(alongFirst ^ facing.getAxis() == Direction.Axis.Z ? 90 : 0) .translate(0, -9 / 16f, 0) - .multiply(Vector3f.POSITIVE_X.getRadialQuaternion(-cogAngle)) + .multiply(Vector3f.XP.rotation(-cogAngle)) .translate(0, 9 / 16f, 0) .unCentre(); 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..63efd4fc7 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,15 +32,15 @@ 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.getLevel())) return; BlockState state = te.getBlockState(); - Direction facing = state.get(GantryCarriageBlock.FACING); - Boolean alongFirst = state.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); + Direction facing = state.getValue(GantryCarriageBlock.FACING); + Boolean alongFirst = state.getValue(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); Axis rotationAxis = getRotationAxisOf(te); - BlockPos visualPos = facing.getAxisDirection() == AxisDirection.POSITIVE ? te.getPos() - : te.getPos() - .offset(facing.getOpposite()); + BlockPos visualPos = facing.getAxisDirection() == AxisDirection.POSITIVE ? te.getBlockPos() + : te.getBlockPos() + .relative(facing.getOpposite()); float angleForTe = getAngleForTe(te, visualPos, rotationAxis); Axis gantryAxis = Axis.X; @@ -62,17 +62,17 @@ public class GantryCarriageRenderer extends KineticTileEntityRenderer { .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) .rotateY(alongFirst ^ facing.getAxis() == Axis.Z ? 90 : 0) .translate(0, -9 / 16f, 0) - .multiply(Vector3f.POSITIVE_X.getRadialQuaternion(-angleForTe)) + .multiply(Vector3f.XP.rotation(-angleForTe)) .translate(0, 9 / 16f, 0) .unCentre(); cogs.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .renderInto(ms, buffer.getBuffer(RenderType.solid())); } public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) { - float time = AnimationTickHolder.getRenderTime(te.getWorld()); + float time = AnimationTickHolder.getRenderTime(te.getLevel()); float offset = getRotationOffsetForPosition(te, pos, axis); return ((time * te.getSpeed() * 3f / 20 + offset) % 360) / 180 * (float) Math.PI; } 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..7e516d2dc 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,12 +37,12 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp if (shouldAssemble()) queueAssembly(); } - + @Override public void initialize() { super.initialize(); - if (!getBlockState().isValidPosition(world, pos)) - world.destroyBlock(pos, true); + if (!getBlockState().canSurvive(level, worldPosition)) + level.destroyBlock(worldPosition, true); } public void queueAssembly() { @@ -52,7 +53,7 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp public void tick() { super.tick(); - if (world.isRemote) + if (level.isClientSide) return; if (assembleNextTick) { @@ -71,10 +72,10 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp if (!(blockState.getBlock() instanceof GantryCarriageBlock)) return; - Direction direction = blockState.get(FACING); + Direction direction = blockState.getValue(FACING); GantryContraption contraption = new GantryContraption(direction); - TileEntity shaftTe = world.getTileEntity(pos.offset(direction.getOpposite())); + TileEntity shaftTe = level.getBlockEntity(worldPosition.relative(direction.getOpposite())); if (!(shaftTe instanceof GantryShaftTileEntity)) return; BlockState shaftState = shaftTe.getBlockState(); @@ -82,14 +83,14 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp return; float pinionMovementSpeed = ((GantryShaftTileEntity) shaftTe).getPinionMovementSpeed(); - Direction shaftOrientation = shaftState.get(GantryShaftBlock.FACING); + Direction shaftOrientation = shaftState.getValue(GantryShaftBlock.FACING); Direction movementDirection = shaftOrientation; if (pinionMovementSpeed < 0) movementDirection = movementDirection.getOpposite(); try { lastException = null; - if (!contraption.assemble(world, pos)) + if (!contraption.assemble(level, worldPosition)) return; sendData(); @@ -98,16 +99,17 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp sendData(); return; } - if (ContraptionCollider.isCollidingWithWorld(world, contraption, pos.offset(movementDirection), + if (ContraptionCollider.isCollidingWithWorld(level, contraption, worldPosition.relative(movementDirection), movementDirection)) return; - contraption.removeBlocksFromWorld(world, BlockPos.ZERO); + contraption.removeBlocksFromWorld(level, BlockPos.ZERO); GantryContraptionEntity movedContraption = - GantryContraptionEntity.create(world, contraption, shaftOrientation); - BlockPos anchor = pos; - movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); - world.addEntity(movedContraption); + GantryContraptionEntity.create(level, contraption, shaftOrientation); + BlockPos anchor = worldPosition; + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); + level.addFreshEntity(movedContraption); } @Override @@ -132,19 +134,19 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp return defaultModifier; if (!AllBlocks.GANTRY_SHAFT.has(stateTo)) return defaultModifier; - if (!stateTo.get(GantryShaftBlock.POWERED)) + if (!stateTo.getValue(GantryShaftBlock.POWERED)) return defaultModifier; - Direction direction = Direction.getFacingFromVector(diff.getX(), diff.getY(), diff.getZ()); - if (stateFrom.get(GantryCarriageBlock.FACING) != direction.getOpposite()) + Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); + if (stateFrom.getValue(GantryCarriageBlock.FACING) != direction.getOpposite()) return defaultModifier; - return getGantryPinionModifier(stateTo.get(GantryShaftBlock.FACING), stateFrom.get(GantryCarriageBlock.FACING)); + return getGantryPinionModifier(stateTo.getValue(GantryShaftBlock.FACING), stateFrom.getValue(GantryCarriageBlock.FACING)); } public static float getGantryPinionModifier(Direction shaft, Direction pinionDirection) { Axis shaftAxis = shaft.getAxis(); float directionModifier = shaft.getAxisDirection() - .getOffset(); + .getStep(); if (shaftAxis == Axis.Y) if (pinionDirection == Direction.NORTH || pinionDirection == Direction.EAST) return -directionModifier; @@ -161,19 +163,19 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp BlockState blockState = getBlockState(); if (!(blockState.getBlock() instanceof GantryCarriageBlock)) return false; - Direction facing = blockState.get(GantryCarriageBlock.FACING) + Direction facing = blockState.getValue(GantryCarriageBlock.FACING) .getOpposite(); - BlockState shaftState = world.getBlockState(pos.offset(facing)); + BlockState shaftState = level.getBlockState(worldPosition.relative(facing)); if (!(shaftState.getBlock() instanceof GantryShaftBlock)) return false; - if (shaftState.get(GantryShaftBlock.POWERED)) + if (shaftState.getValue(GantryShaftBlock.POWERED)) return false; - TileEntity te = world.getTileEntity(pos.offset(facing)); + TileEntity te = level.getBlockEntity(worldPosition.relative(facing)); return te instanceof GantryShaftTileEntity && ((GantryShaftTileEntity) te).canAssembleOn(); } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java index df6366c73..260da29e1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java @@ -34,19 +34,19 @@ public class GantryContraption extends TranslatingContraption { @Override public CompoundNBT writeNBT(boolean spawnPacket) { CompoundNBT tag = super.writeNBT(spawnPacket); - tag.putInt("Facing", facing.getIndex()); + tag.putInt("Facing", facing.get3DDataValue()); return tag; } @Override public void readNBT(World world, CompoundNBT tag, boolean spawnData) { - facing = Direction.byIndex(tag.getInt("Facing")); + facing = Direction.from3DDataValue(tag.getInt("Facing")); super.readNBT(world, tag, spawnData); } @Override protected boolean isAnchoringBlockAt(BlockPos pos) { - return super.isAnchoringBlockAt(pos.offset(facing)); + return super.isAnchoringBlockAt(pos.relative(facing)); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java index 4066c61b4..c49b3bbe1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java @@ -51,27 +51,27 @@ public class GantryContraptionEntity extends AbstractContraptionEntity { return; double prevAxisMotion = axisMotion; - if (world.isRemote) { + if (level.isClientSide) { clientOffsetDiff *= .75f; updateClientMotion(); } checkPinionShaft(); tickActors(); - Vector3d movementVec = getMotion(); + Vector3d movementVec = getDeltaMovement(); if (ContraptionCollider.collideBlocks(this)) { - if (!world.isRemote) + if (!level.isClientSide) disassemble(); return; } - if (!isStalled() && ticksExisted > 2) + if (!isStalled() && tickCount > 2) move(movementVec.x, movementVec.y, movementVec.z); if (Math.signum(prevAxisMotion) != Math.signum(axisMotion) && prevAxisMotion != 0) - contraption.stop(world); - if (!world.isRemote && (prevAxisMotion != axisMotion || ticksExisted % 3 == 0)) + contraption.stop(level); + if (!level.isClientSide && (prevAxisMotion != axisMotion || tickCount % 3 == 0)) sendPacket(); } @@ -79,11 +79,11 @@ public class GantryContraptionEntity extends AbstractContraptionEntity { Vector3d movementVec; Direction facing = ((GantryContraption) contraption).getFacing(); Vector3d currentPosition = getAnchorVec().add(.5, .5, .5); - BlockPos gantryShaftPos = new BlockPos(currentPosition).offset(facing.getOpposite()); + BlockPos gantryShaftPos = new BlockPos(currentPosition).relative(facing.getOpposite()); - TileEntity te = world.getTileEntity(gantryShaftPos); + TileEntity te = level.getBlockEntity(gantryShaftPos); if (!(te instanceof GantryShaftTileEntity) || !AllBlocks.GANTRY_SHAFT.has(te.getBlockState())) { - if (!world.isRemote) { + if (!level.isClientSide) { setContraptionMotion(Vector3d.ZERO); disassemble(); } @@ -91,35 +91,35 @@ public class GantryContraptionEntity extends AbstractContraptionEntity { } BlockState blockState = te.getBlockState(); - Direction direction = blockState.get(GantryShaftBlock.FACING); + Direction direction = blockState.getValue(GantryShaftBlock.FACING); GantryShaftTileEntity gantryShaftTileEntity = (GantryShaftTileEntity) te; float pinionMovementSpeed = gantryShaftTileEntity.getPinionMovementSpeed(); - movementVec = Vector3d.of(direction.getDirectionVec()).scale(pinionMovementSpeed); + movementVec = Vector3d.atLowerCornerOf(direction.getNormal()).scale(pinionMovementSpeed); - if (blockState.get(GantryShaftBlock.POWERED) || pinionMovementSpeed == 0) { + if (blockState.getValue(GantryShaftBlock.POWERED) || pinionMovementSpeed == 0) { setContraptionMotion(Vector3d.ZERO); - if (!world.isRemote) + if (!level.isClientSide) disassemble(); return; } Vector3d nextPosition = currentPosition.add(movementVec); double currentCoord = direction.getAxis() - .getCoordinate(currentPosition.x, currentPosition.y, currentPosition.z); + .choose(currentPosition.x, currentPosition.y, currentPosition.z); double nextCoord = direction.getAxis() - .getCoordinate(nextPosition.x, nextPosition.y, nextPosition.z); + .choose(nextPosition.x, nextPosition.y, nextPosition.z); if ((MathHelper.floor(currentCoord) + .5f < nextCoord != (pinionMovementSpeed * direction.getAxisDirection() - .getOffset() < 0))) + .getStep() < 0))) if (!gantryShaftTileEntity.canAssembleOn()) { setContraptionMotion(Vector3d.ZERO); - if (!world.isRemote) + if (!level.isClientSide) disassemble(); return; } - if (world.isRemote) + if (level.isClientSide) return; axisMotion = pinionMovementSpeed; @@ -158,15 +158,15 @@ public class GantryContraptionEntity extends AbstractContraptionEntity { } @Override - public void setPositionAndUpdate(double p_70634_1_, double p_70634_3_, double p_70634_5_) {} + public void teleportTo(double p_70634_1_, double p_70634_3_, double p_70634_5_) {} @Override @OnlyIn(Dist.CLIENT) - public void setPositionAndRotationDirect(double x, double y, double z, float yw, float pt, int inc, boolean t) {} + public void lerpTo(double x, double y, double z, float yw, float pt, int inc, boolean t) {} @Override protected void handleStallInformation(float x, float y, float z, float angle) { - setPos(x, y, z); + setPosRaw(x, y, z); clientOffsetDiff = 0; } @@ -180,25 +180,25 @@ public class GantryContraptionEntity extends AbstractContraptionEntity { public void updateClientMotion() { float modifier = movementAxis.getAxisDirection() - .getOffset(); - setContraptionMotion(Vector3d.of(movementAxis.getDirectionVec()) + .getStep(); + setContraptionMotion(Vector3d.atLowerCornerOf(movementAxis.getNormal()) .scale((axisMotion + clientOffsetDiff * modifier / 2f) * ServerSpeedProvider.get())); } public double getAxisCoord() { Vector3d anchorVec = getAnchorVec(); return movementAxis.getAxis() - .getCoordinate(anchorVec.x, anchorVec.y, anchorVec.z); + .choose(anchorVec.x, anchorVec.y, anchorVec.z); } public void sendPacket() { AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), - new GantryContraptionUpdatePacket(getEntityId(), getAxisCoord(), axisMotion)); + new GantryContraptionUpdatePacket(getId(), getAxisCoord(), axisMotion)); } @OnlyIn(Dist.CLIENT) public static void handlePacket(GantryContraptionUpdatePacket packet) { - Entity entity = Minecraft.getInstance().world.getEntityByID(packet.entityID); + Entity entity = Minecraft.getInstance().level.getEntity(packet.entityID); if (!(entity instanceof GantryContraptionEntity)) return; GantryContraptionEntity ce = (GantryContraptionEntity) entity; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java index a70a8d1c7..8811e0208 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java @@ -27,13 +27,13 @@ public class GlueEffectPacket extends SimplePacketBase { public GlueEffectPacket(PacketBuffer buffer) { pos = buffer.readBlockPos(); - direction = Direction.byIndex(buffer.readByte()); + direction = Direction.from3DDataValue(buffer.readByte()); fullBlock = buffer.readBoolean(); } public void write(PacketBuffer buffer) { buffer.writeBlockPos(pos); - buffer.writeByte(direction.getIndex()); + buffer.writeByte(direction.get3DDataValue()); buffer.writeBoolean(fullBlock); } @@ -41,9 +41,9 @@ public class GlueEffectPacket extends SimplePacketBase { public void handle(Supplier context) { context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { Minecraft mc = Minecraft.getInstance(); - if (!mc.player.getBlockPos().withinDistance(pos, 100)) + if (!mc.player.blockPosition().closerThan(pos, 100)) return; - SuperGlueItem.spawnParticles(mc.world, pos, direction, fullBlock); + SuperGlueItem.spawnParticles(mc.level, pos, direction, fullBlock); })); context.get().setPacketHandled(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..c4c560fb9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueInstance.java @@ -0,0 +1,164 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.glue; + +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +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.entity.EntityInstance; +import com.jozufozu.flywheel.backend.material.MaterialGroup; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.backend.state.TextureRenderState; +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.jozufozu.flywheel.core.model.IModel; +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 boolean USE_ATLAS = false; + private static final ResourceLocation TEXTURE = Create.asResource("textures/entity/super_glue/slime.png"); + + private final Quaternion rotation; + protected ConditionalInstance model; + + public GlueInstance(MaterialManager materialManager, SuperGlueEntity entity) { + super(materialManager, entity); + + Instancer instancer = getInstancer(materialManager, entity); + + 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(); + } + + private Instancer getInstancer(MaterialManager materialManager, SuperGlueEntity entity) { + MaterialGroup group = USE_ATLAS ? materialManager.defaultCutout() : materialManager.cutout(TextureRenderState.get(TEXTURE)); + + return group.material(Materials.ORIENTED).model(entity.getType(), GlueModel::new); + } + + @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.getBrightness(LightType.BLOCK, pos)) + .setSkyLight(world.getBrightness(LightType.SKY, pos)); + } + + private boolean shouldShow() { + PlayerEntity player = Minecraft.getInstance().player; + + return entity.isVisible() + || AllItems.SUPER_GLUE.isIn(player.getMainHandItem()) + || AllItems.SUPER_GLUE.isIn(player.getOffhandItem()); + } + + public static class GlueModel implements IModel { + @Override + public void buffer(VecBuffer buffer) { + Vector3d diff = Vector3d.atLowerCornerOf(Direction.SOUTH.getNormal()); + Vector3d extension = diff.normalize() + .scale(1 / 32f - 1 / 128f); + + Vector3d plane = VecHelper.axisAlingedPlaneOf(diff); + Direction.Axis axis = Direction.getNearest(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); + + float minU; + float maxU; + float minV; + float maxV; + + if (USE_ATLAS) { + TextureAtlasSprite sprite = AllStitchedTextures.SUPER_GLUE.getSprite(); + minU = sprite.getU0(); + maxU = sprite.getU1(); + minV = sprite.getV0(); + maxV = sprite.getV1(); + } else { + minU = minV = 0; + maxU = maxV = 1; + } + + // pos normal uv + // inside quad + buffer.putVec3((float) a1.x, (float) a1.y, (float) a1.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(maxU, minV); + buffer.putVec3((float) a2.x, (float) a2.y, (float) a2.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(maxU, maxV); + buffer.putVec3((float) a3.x, (float) a3.y, (float) a3.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(minU, maxV); + buffer.putVec3((float) a4.x, (float) a4.y, (float) a4.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(minU, minV); + // outside quad + buffer.putVec3((float) b4.x, (float) b4.y, (float) b4.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(minU, minV); + buffer.putVec3((float) b3.x, (float) b3.y, (float) b3.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(minU, maxV); + buffer.putVec3((float) b2.x, (float) b2.y, (float) b2.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(maxU, maxV); + buffer.putVec3((float) b1.x, (float) b1.y, (float) b1.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(maxU, minV); + } + + @Override + public int vertexCount() { + return 8; + } + + @Override + public VertexFormat format() { + return Formats.UNLIT_MODEL; + } + } +} 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..c6e6ff037 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; @@ -29,6 +30,7 @@ import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.entity.EntitySize; import net.minecraft.entity.EntityType; +import net.minecraft.entity.MobEntity; import net.minecraft.entity.MoverType; import net.minecraft.entity.Pose; import net.minecraft.entity.effect.LightningBoltEntity; @@ -54,6 +56,7 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.GameRules; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.api.distmarker.Dist; @@ -64,7 +67,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; @@ -82,7 +85,7 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat } @Override - protected void registerData() {} + protected void defineSynchedData() {} public int getWidthPixels() { return 12; @@ -93,7 +96,7 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat } public void onBroken(@Nullable Entity breaker) { - playSound(SoundEvents.ENTITY_SLIME_SQUISH_SMALL, 1.0F, 1.0F); + playSound(SoundEvents.SLIME_SQUISH_SMALL, 1.0F, 1.0F); if (onValidSurface()) { AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new GlueEffectPacket(getHangingPosition(), getFacingDirection().getOpposite(), false)); @@ -109,26 +112,26 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat Validate.notNull(getFacingDirection()); if (getFacingDirection().getAxis() .isHorizontal()) { - this.rotationPitch = 0.0F; - this.rotationYaw = getFacingDirection().getHorizontalIndex() * 90; + this.xRot = 0.0F; + this.yRot = getFacingDirection().get2DDataValue() * 90; } else { - this.rotationPitch = -90 * getFacingDirection().getAxisDirection() - .getOffset(); - this.rotationYaw = 0.0F; + this.xRot = -90 * getFacingDirection().getAxisDirection() + .getStep(); + this.yRot = 0.0F; } - this.prevRotationPitch = this.rotationPitch; - this.prevRotationYaw = this.rotationYaw; + this.xRotO = this.xRot; + this.yRotO = this.yRot; this.updateBoundingBox(); } protected void updateBoundingBox() { if (this.getFacingDirection() != null) { double offset = 0.5 - 1 / 256d; - double x = hangingPosition.getX() + 0.5 - facingDirection.getXOffset() * offset; - double y = hangingPosition.getY() + 0.5 - facingDirection.getYOffset() * offset; - double z = hangingPosition.getZ() + 0.5 - facingDirection.getZOffset() * offset; - this.setPos(x, y, z); + double x = hangingPosition.getX() + 0.5 - facingDirection.getStepX() * offset; + double y = hangingPosition.getY() + 0.5 - facingDirection.getStepY() * offset; + double z = hangingPosition.getZ() + 0.5 - facingDirection.getStepZ() * offset; + this.setPosRaw(x, y, z); double w = getWidthPixels(); double h = getHeightPixels(); double l = getWidthPixels(); @@ -156,7 +159,7 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat @Override public void tick() { - if (this.validationTimer++ == 10 && !this.world.isRemote) { + if (this.validationTimer++ == 10 && !this.level.isClientSide) { this.validationTimer = 0; if (isAlive() && !this.onValidSurface()) { remove(); @@ -169,37 +172,39 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat public boolean isVisible() { if (!isAlive()) return false; - if (world instanceof WrappedWorld) + if (level instanceof WrappedWorld) return true; BlockPos pos = hangingPosition; - BlockPos pos2 = pos.offset(getFacingDirection().getOpposite()); - return isValidFace(world, pos2, getFacingDirection()) != isValidFace(world, pos, + BlockPos pos2 = pos.relative(getFacingDirection().getOpposite()); + return isValidFace(level, pos2, getFacingDirection()) != isValidFace(level, pos, getFacingDirection().getOpposite()); } public boolean onValidSurface() { BlockPos pos = hangingPosition; - BlockPos pos2 = hangingPosition.offset(getFacingDirection().getOpposite()); - if (!world.isAreaLoaded(pos, 0) || !world.isAreaLoaded(pos2, 0)) + BlockPos pos2 = hangingPosition.relative(getFacingDirection().getOpposite()); + if (pos2.getY() >= 256) + return false; + if (!level.isAreaLoaded(pos, 0) || !level.isAreaLoaded(pos2, 0)) return true; - if (!isValidFace(world, pos2, getFacingDirection()) - && !isValidFace(world, pos, getFacingDirection().getOpposite())) + if (!isValidFace(level, pos2, getFacingDirection()) + && !isValidFace(level, pos, getFacingDirection().getOpposite())) return false; - if (isSideSticky(world, pos2, getFacingDirection()) - || isSideSticky(world, pos, getFacingDirection().getOpposite())) + if (isSideSticky(level, pos2, getFacingDirection()) + || isSideSticky(level, pos, getFacingDirection().getOpposite())) return false; - return world.getEntitiesInAABBexcluding(this, getBoundingBox(), e -> e instanceof SuperGlueEntity) - .isEmpty(); + return level.getEntities(this, getBoundingBox(), e -> e instanceof SuperGlueEntity) + .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; } @@ -207,10 +212,10 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat public static boolean isSideSticky(World world, BlockPos pos, Direction direction) { BlockState state = world.getBlockState(pos); if (AllBlocks.STICKY_MECHANICAL_PISTON.has(state)) - return state.get(DirectionalKineticBlock.FACING) == direction; + return state.getValue(DirectionalKineticBlock.FACING) == direction; if (AllBlocks.STICKER.has(state)) - return state.get(DirectionalBlock.FACING) == direction; + return state.getValue(DirectionalBlock.FACING) == direction; if (state.getBlock() == Blocks.SLIME_BLOCK) return true; @@ -221,53 +226,59 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat return Direction.UP == direction; if (AllBlocks.GANTRY_CARRIAGE.has(state)) - return state.get(DirectionalKineticBlock.FACING) == direction; + return state.getValue(DirectionalKineticBlock.FACING) == direction; if (state.getBlock() instanceof BearingBlock) { - return state.get(DirectionalKineticBlock.FACING) == direction; + return state.getValue(DirectionalKineticBlock.FACING) == direction; } if (state.getBlock() instanceof AbstractChassisBlock) { BooleanProperty glueableSide = ((AbstractChassisBlock) state.getBlock()).getGlueableSide(state, direction); if (glueableSide == null) return false; - return state.get(glueableSide); + return state.getValue(glueableSide); } return false; } @Override - public boolean canBeCollidedWith() { + public boolean isPickable() { return true; } @Override - public boolean hitByEntity(Entity entity) { + public boolean skipAttackInteraction(Entity entity) { return entity instanceof PlayerEntity - ? attackEntityFrom(DamageSource.causePlayerDamage((PlayerEntity) entity), 0) + ? hurt(DamageSource.playerAttack((PlayerEntity) entity), 0) : false; } @Override - public Direction getHorizontalFacing() { + public Direction getDirection() { return this.getFacingDirection(); } @Override - public boolean attackEntityFrom(DamageSource source, float amount) { + public boolean hurt(DamageSource source, float amount) { if (this.isInvulnerableTo(source)) return false; - Entity immediateSource = source.getImmediateSource(); + + boolean mobGriefing = level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + Entity trueSource = source.getEntity(); + if (!mobGriefing && trueSource instanceof MobEntity) + return false; + + Entity immediateSource = source.getDirectEntity(); if (!isVisible() && immediateSource instanceof PlayerEntity) { - if (!AllItems.SUPER_GLUE.isIn(((PlayerEntity) immediateSource).getHeldItemMainhand())) + if (!AllItems.SUPER_GLUE.isIn(((PlayerEntity) immediateSource).getMainHandItem())) return true; } - if (isAlive() && !world.isRemote) { + if (isAlive() && !level.isClientSide) { remove(); - markVelocityChanged(); - onBroken(source.getTrueSource()); + markHurt(); + onBroken(source.getEntity()); } return true; @@ -275,15 +286,15 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat @Override public void move(MoverType typeIn, Vector3d pos) { - if (!world.isRemote && isAlive() && pos.lengthSquared() > 0.0D) { + if (!level.isClientSide && isAlive() && pos.lengthSqr() > 0.0D) { remove(); onBroken(null); } } @Override - public void addVelocity(double x, double y, double z) { - if (!world.isRemote && isAlive() && x * x + y * y + z * z > 0.0D) { + public void push(double x, double y, double z) { + if (!level.isClientSide && isAlive() && x * x + y * y + z * z > 0.0D) { remove(); onBroken(null); } @@ -300,12 +311,12 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat } @Override - public void applyEntityCollision(Entity entityIn) { - super.applyEntityCollision(entityIn); + public void push(Entity entityIn) { + super.push(entityIn); } @Override - public ActionResultType processInitialInteract(PlayerEntity player, Hand hand) { + public ActionResultType interact(PlayerEntity player, Hand hand) { if (player instanceof FakePlayer) return ActionResultType.PASS; DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { @@ -318,43 +329,43 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat private void triggerPlaceBlock(PlayerEntity player, Hand hand) { if (!(player instanceof ClientPlayerEntity)) return; - if (!(player.world instanceof ClientWorld)) + if (!(player.level instanceof ClientWorld)) return; ClientPlayerEntity cPlayer = (ClientPlayerEntity) player; Minecraft mc = Minecraft.getInstance(); RayTraceResult ray = - cPlayer.pick(mc.playerController.getBlockReachDistance(), AnimationTickHolder.getPartialTicks(), false); + cPlayer.pick(mc.gameMode.getPickRange(), AnimationTickHolder.getPartialTicks(), false); if (!(ray instanceof BlockRayTraceResult)) return; if (ray.getType() == Type.MISS) return; BlockRayTraceResult blockRay = (BlockRayTraceResult) ray; - BlockFace rayFace = new BlockFace(blockRay.getPos(), blockRay.getFace()); + BlockFace rayFace = new BlockFace(blockRay.getBlockPos(), blockRay.getDirection()); BlockFace hangingFace = new BlockFace(getHangingPosition(), getFacingDirection().getOpposite()); if (!rayFace.isEquivalent(hangingFace)) return; for (Hand handIn : Hand.values()) { - ItemStack itemstack = cPlayer.getHeldItem(handIn); + ItemStack itemstack = cPlayer.getItemInHand(handIn); int countBefore = itemstack.getCount(); ActionResultType actionResultType = - mc.playerController.func_217292_a(cPlayer, (ClientWorld) cPlayer.world, handIn, blockRay); + mc.gameMode.useItemOn(cPlayer, (ClientWorld) cPlayer.level, handIn, blockRay); if (actionResultType != ActionResultType.SUCCESS) return; - cPlayer.swingArm(handIn); - if (!itemstack.isEmpty() && (itemstack.getCount() != countBefore || mc.playerController.isInCreativeMode())) - mc.gameRenderer.itemRenderer.resetEquippedProgress(handIn); + cPlayer.swing(handIn); + if (!itemstack.isEmpty() && (itemstack.getCount() != countBefore || mc.gameMode.hasInfiniteItems())) + mc.gameRenderer.itemInHandRenderer.itemUsed(handIn); return; } } @Override - public void writeAdditional(CompoundNBT compound) { + public void addAdditionalSaveData(CompoundNBT compound) { compound.putByte("Facing", (byte) this.getFacingDirection() - .getIndex()); + .get3DDataValue()); BlockPos blockpos = this.getHangingPosition(); compound.putInt("TileX", blockpos.getX()); compound.putInt("TileY", blockpos.getY()); @@ -362,40 +373,40 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat } @Override - public void readAdditional(CompoundNBT compound) { + public void readAdditionalSaveData(CompoundNBT compound) { this.hangingPosition = new BlockPos(compound.getInt("TileX"), compound.getInt("TileY"), compound.getInt("TileZ")); - this.facingDirection = Direction.byIndex(compound.getByte("Facing")); + this.facingDirection = Direction.from3DDataValue(compound.getByte("Facing")); updateFacingWithBoundingBox(); } @Override - public ItemEntity entityDropItem(ItemStack stack, float yOffset) { + public ItemEntity spawnAtLocation(ItemStack stack, float yOffset) { float xOffset = (float) this.getFacingDirection() - .getXOffset() * 0.15F; + .getStepX() * 0.15F; float zOffset = (float) this.getFacingDirection() - .getZOffset() * 0.15F; + .getStepZ() * 0.15F; ItemEntity itementity = - new ItemEntity(this.world, this.getX() + xOffset, this.getY() + yOffset, this.getZ() + zOffset, stack); - itementity.setDefaultPickupDelay(); - this.world.addEntity(itementity); + new ItemEntity(this.level, this.getX() + xOffset, this.getY() + yOffset, this.getZ() + zOffset, stack); + itementity.setDefaultPickUpDelay(); + this.level.addFreshEntity(itementity); return itementity; } @Override - protected boolean shouldSetPosAfterLoading() { + protected boolean repositionEntityAfterLoad() { return false; } @Override - public void setPosition(double x, double y, double z) { + public void setPos(double x, double y, double z) { hangingPosition = new BlockPos(x, y, z); updateBoundingBox(); - isAirBorne = true; + hasImpulse = true; } @Override - public float getRotatedYaw(Rotation transformRotation) { + public float rotate(Rotation transformRotation) { if (this.getFacingDirection() .getAxis() != Direction.Axis.Y) { switch (transformRotation) { @@ -403,16 +414,16 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat facingDirection = facingDirection.getOpposite(); break; case COUNTERCLOCKWISE_90: - facingDirection = facingDirection.rotateYCCW(); + facingDirection = facingDirection.getCounterClockWise(); break; case CLOCKWISE_90: - facingDirection = facingDirection.rotateY(); + facingDirection = facingDirection.getClockWise(); default: break; } } - float f = MathHelper.wrapDegrees(this.rotationYaw); + float f = MathHelper.wrapDegrees(this.yRot); switch (transformRotation) { case CLOCKWISE_180: return f + 180.0F; @@ -430,8 +441,8 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat } @Override - public float getMirroredYaw(Mirror transformMirror) { - return this.getRotatedYaw(transformMirror.toRotation(this.getFacingDirection())); + public float mirror(Mirror transformMirror) { + return this.rotate(transformMirror.getRotation(this.getFacingDirection())); } public Direction getAttachedDirection(BlockPos pos) { @@ -439,10 +450,10 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat } @Override - public void onStruckByLightning(ServerWorld world, LightningBoltEntity lightningBolt) {} + public void thunderHit(ServerWorld world, LightningBoltEntity lightningBolt) {} @Override - public void recalculateSize() {} + public void refreshDimensions() {} public static EntityType.Builder build(EntityType.Builder builder) { @SuppressWarnings("unchecked") @@ -451,20 +462,20 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat } @Override - public IPacket createSpawnPacket() { + public IPacket getAddEntityPacket() { return NetworkHooks.getEntitySpawningPacket(this); } @Override public void writeSpawnData(PacketBuffer buffer) { CompoundNBT compound = new CompoundNBT(); - writeAdditional(compound); - buffer.writeCompoundTag(compound); + addAdditionalSaveData(compound); + buffer.writeNbt(compound); } @Override public void readSpawnData(PacketBuffer additionalData) { - readAdditional(additionalData.readCompoundTag()); + readAdditionalSaveData(additionalData.readNbt()); } public Direction getFacingDirection() { @@ -477,7 +488,12 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat } @Override - public boolean doesEntityNotTriggerPressurePlate() { + public boolean isIgnoringBlockTriggers() { return true; } + + @Override + public World getWorld() { + return level; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java index 89830765c..f1778657f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java @@ -35,7 +35,7 @@ import net.minecraftforge.fml.network.PacketDistributor; public class SuperGlueHandler { public static Map gatherGlue(IWorld world, BlockPos pos) { - List entities = world.getEntitiesWithinAABB(SuperGlueEntity.class, new AxisAlignedBB(pos)); + List entities = world.getEntitiesOfClass(SuperGlueEntity.class, new AxisAlignedBB(pos)); Map map = new HashMap<>(); for (SuperGlueEntity entity : entities) map.put(entity.getAttachedDirection(pos), entity); @@ -50,7 +50,7 @@ public class SuperGlueHandler { if (entity == null || world == null || pos == null) return; - if (world.isRemote()) + if (world.isClientSide()) return; Map gatheredGlue = gatherGlue(world, pos); @@ -63,50 +63,50 @@ public class SuperGlueHandler { } public static void glueInOffHandAppliesOnBlockPlace(EntityPlaceEvent event, BlockPos pos, PlayerEntity placer) { - ItemStack itemstack = placer.getHeldItemOffhand(); + ItemStack itemstack = placer.getOffhandItem(); ModifiableAttributeInstance reachAttribute = placer.getAttribute(ForgeMod.REACH_DISTANCE.get()); if (!AllItems.SUPER_GLUE.isIn(itemstack) || reachAttribute == null) return; - if (AllItems.WRENCH.isIn(placer.getHeldItemMainhand())) + if (AllItems.WRENCH.isIn(placer.getMainHandItem())) return; if (event.getPlacedAgainst() == IPlacementHelper.ID) return; double distance = reachAttribute.getValue(); Vector3d start = placer.getEyePosition(1); - Vector3d look = placer.getLook(1); + Vector3d look = placer.getViewVector(1); Vector3d end = start.add(look.x * distance, look.y * distance, look.z * distance); - World world = placer.world; + World world = placer.level; RayTraceWorld rayTraceWorld = - new RayTraceWorld(world, (p, state) -> p.equals(pos) ? Blocks.AIR.getDefaultState() : state); - BlockRayTraceResult ray = rayTraceWorld.rayTraceBlocks( + new RayTraceWorld(world, (p, state) -> p.equals(pos) ? Blocks.AIR.defaultBlockState() : state); + BlockRayTraceResult ray = rayTraceWorld.clip( new RayTraceContext(start, end, RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, placer)); - Direction face = ray.getFace(); + Direction face = ray.getDirection(); if (face == null || ray.getType() == Type.MISS) return; - if (!ray.getPos() - .offset(face) + if (!ray.getBlockPos() + .relative(face) .equals(pos)) { event.setCanceled(true); return; } - SuperGlueEntity entity = new SuperGlueEntity(world, ray.getPos(), face.getOpposite()); + SuperGlueEntity entity = new SuperGlueEntity(world, ray.getBlockPos(), face.getOpposite()); CompoundNBT compoundnbt = itemstack.getTag(); if (compoundnbt != null) - EntityType.applyItemNBT(world, placer, entity, compoundnbt); + EntityType.updateCustomEntityTag(world, placer, entity, compoundnbt); if (entity.onValidSurface()) { - if (!world.isRemote) { + if (!world.isClientSide) { entity.playPlaceSound(); - world.addEntity(entity); + world.addFreshEntity(entity); AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity), - new GlueEffectPacket(ray.getPos(), face, true)); + new GlueEffectPacket(ray.getBlockPos(), face, true)); } - itemstack.damageItem(1, placer, SuperGlueItem::onBroken); + itemstack.hurtAndBreak(1, placer, SuperGlueItem::onBroken); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueItem.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueItem.java index 98863bfaa..99811ca53 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueItem.java @@ -27,7 +27,7 @@ public class SuperGlueItem extends Item { } @Override - public boolean isDamageable() { + public boolean canBeDepleted() { return true; } @@ -42,30 +42,30 @@ public class SuperGlueItem extends Item { } @Override - public ActionResultType onItemUse(ItemUseContext context) { - BlockPos blockpos = context.getPos(); - Direction direction = context.getFace(); - BlockPos blockpos1 = blockpos.offset(direction); + public ActionResultType useOn(ItemUseContext context) { + BlockPos blockpos = context.getClickedPos(); + Direction direction = context.getClickedFace(); + BlockPos blockpos1 = blockpos.relative(direction); PlayerEntity playerentity = context.getPlayer(); - ItemStack itemstack = context.getItem(); + ItemStack itemstack = context.getItemInHand(); if (playerentity == null || !this.canPlace(playerentity, direction, itemstack, blockpos1)) return ActionResultType.FAIL; - World world = context.getWorld(); + World world = context.getLevel(); SuperGlueEntity entity = new SuperGlueEntity(world, blockpos1, direction); CompoundNBT compoundnbt = itemstack.getTag(); if (compoundnbt != null) - EntityType.applyItemNBT(world, playerentity, entity, compoundnbt); + EntityType.updateCustomEntityTag(world, playerentity, entity, compoundnbt); if (!entity.onValidSurface()) return ActionResultType.FAIL; - if (!world.isRemote) { + if (!world.isClientSide) { entity.playPlaceSound(); - world.addEntity(entity); + world.addFreshEntity(entity); } - itemstack.damageItem(1, playerentity, SuperGlueItem::onBroken); + itemstack.hurtAndBreak(1, playerentity, SuperGlueItem::onBroken); return ActionResultType.SUCCESS; } @@ -75,22 +75,22 @@ public class SuperGlueItem extends Item { } protected boolean canPlace(PlayerEntity entity, Direction facing, ItemStack stack, BlockPos pos) { - return !World.isOutsideBuildHeight(pos) && entity.canPlayerEdit(pos, facing, stack); + return !World.isOutsideBuildHeight(pos) && entity.mayUseItemAt(pos, facing, stack); } @OnlyIn(Dist.CLIENT) public static void spawnParticles(World world, BlockPos pos, Direction direction, boolean fullBlock) { - Vector3d vec = Vector3d.of(direction.getDirectionVec()); + Vector3d vec = Vector3d.atLowerCornerOf(direction.getNormal()); Vector3d plane = VecHelper.axisAlingedPlaneOf(vec); Vector3d facePos = VecHelper.getCenterOf(pos) .add(vec.scale(.5f)); - float distance = fullBlock ? 1f : .25f + .25f * (world.rand.nextFloat() - .5f); + float distance = fullBlock ? 1f : .25f + .25f * (world.random.nextFloat() - .5f); plane = plane.scale(distance); ItemStack stack = new ItemStack(Items.SLIME_BALL); for (int i = fullBlock ? 40 : 15; i > 0; i--) { - Vector3d offset = VecHelper.rotate(plane, 360 * world.rand.nextFloat(), direction.getAxis()); + Vector3d offset = VecHelper.rotate(plane, 360 * world.random.nextFloat(), direction.getAxis()); Vector3d motion = offset.normalize() .scale(1 / 16f); if (fullBlock) 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..9c2ad5ef3 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 @@ -1,18 +1,19 @@ package com.simibubi.create.content.contraptions.components.structureMovement.glue; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack.Entry; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllItems; import com.simibubi.create.Create; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; 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; @@ -29,12 +30,10 @@ import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) public class SuperGlueRenderer extends EntityRenderer { - private ResourceLocation regular = new ResourceLocation(Create.ID, "textures/entity/super_glue/slime.png"); + private ResourceLocation regular = Create.asResource("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); @@ -42,57 +41,52 @@ public class SuperGlueRenderer extends EntityRenderer { } @Override - public ResourceLocation getEntityTexture(SuperGlueEntity entity) { + public ResourceLocation getTextureLocation(SuperGlueEntity entity) { return regular; } @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.getMainHandItem()) + || AllItems.SUPER_GLUE.isIn(player.getOffhandItem()); + + 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); + super.render(entity, yaw, partialTicks, 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; - - IVertexBuilder builder = buffer.getBuffer(RenderType.getEntityCutout(getEntityTexture(entity))); + IVertexBuilder builder = buffer.getBuffer(RenderType.entityCutout(getTextureLocation(entity))); light = getBrightnessForRender(entity); Direction face = entity.getFacingDirection(); - ms.push(); - MatrixStacker.of(ms) - .rotateY(AngleHelper.horizontalAngle(face)) + ms.pushPose(); + MatrixTransformStack.of(ms) + .rotateY(AngleHelper.horizontalAngleNew(face)) .rotateX(AngleHelper.verticalAngle(face)); - Entry peek = ms.peek(); + Entry peek = ms.last(); - 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(); - } - ms.pop(); + renderQuad(builder, peek, insideQuad, light, -1); + renderQuad(builder, peek, outsideQuad, light, 1); + + ms.popPose(); } private void initQuads() { - Vector3d diff = Vector3d.of(Direction.SOUTH.getDirectionVec()); + Vector3d diff = Vector3d.atLowerCornerOf(Direction.SOUTH.getNormal()); Vector3d extension = diff.normalize() .scale(1 / 32f - 1 / 128f); Vector3d plane = VecHelper.axisAlingedPlaneOf(diff); - Axis axis = Direction.getFacingFromVector(diff.x, diff.y, diff.z) + Axis axis = Direction.getNearest(diff.x, diff.y, diff.z) .getAxis(); Vector3d start = Vector3d.ZERO.subtract(extension); @@ -111,19 +105,42 @@ 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) { BlockPos blockpos = entity.getHangingPosition(); - BlockPos blockpos2 = blockpos.offset(entity.getFacingDirection() + BlockPos blockpos2 = blockpos.relative(entity.getFacingDirection() .getOpposite()); - World world = entity.getEntityWorld(); - int light = world.isBlockPresent(blockpos) ? WorldRenderer.getLightmapCoordinates(world, blockpos) : 15; - int light2 = world.isBlockPresent(blockpos2) ? WorldRenderer.getLightmapCoordinates(world, blockpos2) : 15; + World world = entity.getCommandSenderWorld(); + int light = world.isLoaded(blockpos) ? WorldRenderer.getLightColor(world, blockpos) : 15; + int light2 = world.isLoaded(blockpos2) ? WorldRenderer.getLightColor(world, blockpos2) : 15; 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.pose(), data[5 * i], data[5 * i + 1], data[5 * i + 2]) + .color(255, 255, 255, 255) + .uv(data[5 * i + 3], data[5 * i + 4]) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(light) + .normal(matrix.normal(), 0.0f, 0.0f, normalZ) + .endVertex(); + } + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/package-info.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/package-info.java new file mode 100644 index 000000000..5fbcd335b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.simibubi.create.content.contraptions.components.structureMovement.glue; + +import javax.annotation.ParametersAreNonnullByDefault; + +import mcp.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/DoorMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/DoorMovingInteraction.java new file mode 100644 index 000000000..4f270588c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/DoorMovingInteraction.java @@ -0,0 +1,38 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction; + +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; + +import net.minecraft.block.BlockState; +import net.minecraft.block.DoorBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.state.properties.DoubleBlockHalf; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.feature.template.Template.BlockInfo; + +public class DoorMovingInteraction extends SimpleBlockMovingInteraction { + + @Override + protected BlockState handle(PlayerEntity player, Contraption contraption, BlockPos pos, BlockState currentState) { + SoundEvent sound = + currentState.getValue(DoorBlock.OPEN) ? SoundEvents.WOODEN_DOOR_CLOSE : SoundEvents.WOODEN_DOOR_OPEN; + + BlockPos otherPos = currentState.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? pos.above() : pos.below(); + BlockInfo info = contraption.getBlocks() + .get(otherPos); + if (info.state.hasProperty(DoorBlock.OPEN)) + setContraptionBlockData(contraption.entity, otherPos, + new BlockInfo(info.pos, info.state.cycle(DoorBlock.OPEN), info.nbt)); + + float pitch = player.level.random.nextFloat() * 0.1F + 0.9F; + playSound(player, sound, pitch); + return currentState.cycle(DoorBlock.OPEN); + } + + @Override + protected boolean updateColliders() { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/LeverMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/LeverMovingInteraction.java new file mode 100644 index 000000000..5101374b3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/LeverMovingInteraction.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction; + +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; + +import net.minecraft.block.BlockState; +import net.minecraft.block.LeverBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; + +public class LeverMovingInteraction extends SimpleBlockMovingInteraction { + + @Override + protected BlockState handle(PlayerEntity player, Contraption contraption, BlockPos pos, BlockState currentState) { + playSound(player, SoundEvents.LEVER_CLICK, currentState.getValue(LeverBlock.POWERED) ? 0.5f : 0.6f); + return currentState.cycle(LeverBlock.POWERED); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/SimpleBlockMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/SimpleBlockMovingInteraction.java new file mode 100644 index 000000000..05decf2a8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/SimpleBlockMovingInteraction.java @@ -0,0 +1,45 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction; + +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.MovingInteractionBehaviour; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Hand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.feature.template.Template.BlockInfo; + +public abstract class SimpleBlockMovingInteraction extends MovingInteractionBehaviour { + + @Override + public boolean handlePlayerInteraction(PlayerEntity player, Hand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + Contraption contraption = contraptionEntity.getContraption(); + BlockInfo info = contraption.getBlocks() + .get(localPos); + + BlockState newState = handle(player, contraption, localPos, info.state); + if (info.state == newState) + return false; + + setContraptionBlockData(contraptionEntity, localPos, new BlockInfo(info.pos, newState, info.nbt)); + if (updateColliders()) + contraption.invalidateColliders(); + return true; + } + + protected boolean updateColliders() { + return false; + } + + protected void playSound(PlayerEntity player, SoundEvent sound, float pitch) { + player.level.playSound(player, player.blockPosition(), sound, SoundCategory.BLOCKS, 0.3f, pitch); + } + + protected abstract BlockState handle(PlayerEntity player, Contraption contraption, BlockPos pos, + BlockState currentState); + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/TrapdoorMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/TrapdoorMovingInteraction.java new file mode 100644 index 000000000..752c96974 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/TrapdoorMovingInteraction.java @@ -0,0 +1,28 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.interaction; + +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; + +import net.minecraft.block.BlockState; +import net.minecraft.block.TrapDoorBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; + +public class TrapdoorMovingInteraction extends SimpleBlockMovingInteraction { + + @Override + protected BlockState handle(PlayerEntity player, Contraption contraption, BlockPos pos, BlockState currentState) { + SoundEvent sound = currentState.getValue(TrapDoorBlock.OPEN) ? SoundEvents.WOODEN_TRAPDOOR_CLOSE + : SoundEvents.WOODEN_TRAPDOOR_OPEN; + float pitch = player.level.random.nextFloat() * 0.1F + 0.9F; + playSound(player, sound, pitch); + return currentState.cycle(TrapDoorBlock.OPEN); + } + + @Override + protected boolean updateColliders() { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java index d3863f8ae..20dd43e65 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java @@ -1,10 +1,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mounted; -import java.util.function.Predicate; import java.util.function.Supplier; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.util.entry.BlockEntry; @@ -20,27 +18,21 @@ public enum CartAssembleRailType implements IStringSerializable { POWERED_RAIL(Blocks.POWERED_RAIL), DETECTOR_RAIL(Blocks.DETECTOR_RAIL), ACTIVATOR_RAIL(Blocks.ACTIVATOR_RAIL), - CONTROLLER_RAIL(AllBlocks.CONTROLLER_RAIL, blockState -> AllBlocks.CONTROLLER_RAIL.has(blockState) - && blockState.contains(ControllerRailBlock.BACKWARDS) && !blockState.get(ControllerRailBlock.BACKWARDS)), - CONTROLLER_RAIL_BACKWARDS(AllBlocks.CONTROLLER_RAIL, blockState -> AllBlocks.CONTROLLER_RAIL.has(blockState) - && blockState.contains(ControllerRailBlock.BACKWARDS) && blockState.get(ControllerRailBlock.BACKWARDS)) + CONTROLLER_RAIL(AllBlocks.CONTROLLER_RAIL) ; private final Supplier railBlockSupplier; private final Supplier railItemSupplier; - public final Predicate matches; CartAssembleRailType(Block block) { this.railBlockSupplier = () -> block; this.railItemSupplier = block::asItem; - this.matches = blockState -> blockState.getBlock() == getBlock(); } - CartAssembleRailType(BlockEntry block, Predicate matches) { + CartAssembleRailType(BlockEntry block) { this.railBlockSupplier = block::get; this.railItemSupplier = () -> block.get().asItem(); - this.matches = matches; } public Block getBlock() { @@ -51,8 +43,12 @@ public enum CartAssembleRailType implements IStringSerializable { return railItemSupplier.get(); } + public boolean matches(BlockState rail) { + return rail.getBlock() == railBlockSupplier.get(); + } + @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } 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..230c858a2 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,64 +42,63 @@ 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 { + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty BACKWARDS = BooleanProperty.create("backwards"); public static final Property RAIL_SHAPE = EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH); public static final Property RAIL_TYPE = EnumProperty.create("rail_type", CartAssembleRailType.class); - public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public CartAssemblerBlock(Properties properties) { super(true, properties); - setDefaultState(getDefaultState().with(POWERED, false) - .with(RAIL_TYPE, CartAssembleRailType.POWERED_RAIL)); + registerDefaultState(defaultBlockState().setValue(POWERED, false) + .setValue(BACKWARDS, false) + .setValue(RAIL_TYPE, CartAssembleRailType.POWERED_RAIL)); } public static BlockState createAnchor(BlockState state) { - Axis axis = state.get(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? Axis.Z : Axis.X; + Axis axis = state.getValue(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? Axis.Z : Axis.X; return AllBlocks.MINECART_ANCHOR.getDefaultState() - .with(BlockStateProperties.HORIZONTAL_AXIS, axis); + .setValue(BlockStateProperties.HORIZONTAL_AXIS, axis); } private static Item getRailItem(BlockState state) { - return state.get(RAIL_TYPE) + return state.getValue(RAIL_TYPE) .getItem(); } public static BlockState getRailBlock(BlockState state) { - AbstractRailBlock railBlock = (AbstractRailBlock) state.get(RAIL_TYPE) + AbstractRailBlock railBlock = (AbstractRailBlock) state.getValue(RAIL_TYPE) .getBlock(); - BlockState railState = railBlock.getDefaultState() - .with(railBlock.getShapeProperty(), state.get(RAIL_SHAPE)); - if (railState.contains(ControllerRailBlock.BACKWARDS)) { - railState = railState.with(ControllerRailBlock.BACKWARDS, state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS); - } + BlockState railState = railBlock.defaultBlockState() + .setValue(railBlock.getShapeProperty(), state.getValue(RAIL_SHAPE)); + if (railState.hasProperty(ControllerRailBlock.BACKWARDS)) + railState = railState.setValue(ControllerRailBlock.BACKWARDS, state.getValue(BACKWARDS)); return railState; } @Override - protected void fillStateContainer(Builder builder) { - builder.add(RAIL_SHAPE, POWERED, RAIL_TYPE); - super.fillStateContainer(builder); + protected void createBlockStateDefinition(Builder builder) { + builder.add(RAIL_SHAPE, POWERED, RAIL_TYPE, BACKWARDS); + super.createBlockStateDefinition(builder); } @Override @@ -134,45 +121,10 @@ public class CartAssemblerBlock extends AbstractRailBlock AbstractMinecartEntity cart) { if (!canAssembleTo(cart)) return; - if (world.isRemote) + if (world.isClientSide) 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 { @@ -188,27 +140,24 @@ public class CartAssemblerBlock extends AbstractRailBlock } public static CartAssemblerAction getActionForCart(BlockState state, AbstractMinecartEntity cart) { - CartAssembleRailType type = state.get(RAIL_TYPE); - boolean powered = state.get(POWERED); - - if (type == CartAssembleRailType.REGULAR) - return powered ? CartAssemblerAction.ASSEMBLE : CartAssemblerAction.DISASSEMBLE; - - if (type == CartAssembleRailType.ACTIVATOR_RAIL) + CartAssembleRailType type = state.getValue(RAIL_TYPE); + boolean powered = state.getValue(POWERED); + switch (type) { + case ACTIVATOR_RAIL: return powered ? CartAssemblerAction.DISASSEMBLE : CartAssemblerAction.PASS; - - if (type == CartAssembleRailType.POWERED_RAIL) - return powered ? CartAssemblerAction.ASSEMBLE_ACCELERATE : CartAssemblerAction.DISASSEMBLE_BRAKE; - - if (type == CartAssembleRailType.DETECTOR_RAIL) - return cart.getPassengers() - .isEmpty() ? CartAssemblerAction.ASSEMBLE_ACCELERATE : CartAssemblerAction.DISASSEMBLE; - - if (type == CartAssembleRailType.CONTROLLER_RAIL || type == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS) + case CONTROLLER_RAIL: return powered ? CartAssemblerAction.ASSEMBLE_ACCELERATE_DIRECTIONAL : CartAssemblerAction.DISASSEMBLE_BRAKE; - - return CartAssemblerAction.PASS; + case DETECTOR_RAIL: + return cart.getPassengers() + .isEmpty() ? CartAssemblerAction.ASSEMBLE_ACCELERATE : CartAssemblerAction.DISASSEMBLE; + case POWERED_RAIL: + return powered ? CartAssemblerAction.ASSEMBLE_ACCELERATE : CartAssemblerAction.DISASSEMBLE_BRAKE; + case REGULAR: + return powered ? CartAssemblerAction.ASSEMBLE : CartAssemblerAction.DISASSEMBLE; + default: + return CartAssemblerAction.PASS; + } } public static boolean canAssembleTo(AbstractMinecartEntity cart) { @@ -217,10 +166,10 @@ public class CartAssemblerBlock extends AbstractRailBlock @Override @Nonnull - public ActionResultType onUse(@Nonnull BlockState state, @Nonnull World world, @Nonnull BlockPos pos, + public ActionResultType use(@Nonnull BlockState state, @Nonnull World world, @Nonnull BlockPos pos, PlayerEntity player, @Nonnull Hand hand, @Nonnull BlockRayTraceResult blockRayTraceResult) { - ItemStack itemStack = player.getHeldItem(hand); + ItemStack itemStack = player.getItemInHand(hand); Item previousItem = getRailItem(state); Item heldItem = itemStack.getItem(); if (heldItem != previousItem) { @@ -231,8 +180,8 @@ public class CartAssemblerBlock extends AbstractRailBlock newType = type; if (newType == null) return ActionResultType.PASS; - world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 1, 1); - world.setBlockState(pos, state.with(RAIL_TYPE, newType)); + world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundCategory.PLAYERS, 1, 1); + world.setBlockAndUpdate(pos, state.setValue(RAIL_TYPE, newType)); if (!player.isCreative()) { itemStack.shrink(1); @@ -244,135 +193,14 @@ 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) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; - - boolean previouslyPowered = state.get(POWERED); - if (previouslyPowered != worldIn.isBlockPowered(pos)) { - worldIn.setBlockState(pos, state.cycle(POWERED), 2); - } - + boolean previouslyPowered = state.getValue(POWERED); + if (previouslyPowered != worldIn.hasNeighborSignal(pos)) + worldIn.setBlock(pos, state.cycle(POWERED), 2); super.neighborChanged(state, worldIn, pos, blockIn, fromPos, isMoving); } @@ -390,7 +218,7 @@ public class CartAssemblerBlock extends AbstractRailBlock } protected Axis getRailAxis(BlockState state) { - return state.get(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? Direction.Axis.Z : Direction.Axis.X; + return state.getValue(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? Direction.Axis.Z : Direction.Axis.X; } @Override @@ -402,12 +230,12 @@ public class CartAssemblerBlock extends AbstractRailBlock return VoxelShapes.empty(); if (entity instanceof PlayerEntity) return AllShapes.CART_ASSEMBLER_PLAYER_COLLISION.get(getRailAxis(state)); - return VoxelShapes.fullCube(); + return VoxelShapes.block(); } @Override @Nonnull - public PushReaction getPushReaction(@Nonnull BlockState state) { + public PushReaction getPistonPushReaction(@Nonnull BlockState state) { return PushReaction.BLOCK; } @@ -417,10 +245,18 @@ public class CartAssemblerBlock extends AbstractRailBlock } @Override - public boolean isValidPosition(@Nonnull BlockState state, @Nonnull IWorldReader world, @Nonnull BlockPos pos) { + public boolean canSurvive(@Nonnull BlockState state, @Nonnull IWorldReader world, @Nonnull BlockPos pos) { return false; } + @Override + public ItemRequirement getRequiredItems(BlockState state, TileEntity te) { + ArrayList reuiredItems = new ArrayList<>(); + reuiredItems.add(new ItemStack(getRailItem(state))); + reuiredItems.add(new ItemStack(asItem())); + return new ItemRequirement(ItemUseType.CONSUME, reuiredItems); + } + @Override @SuppressWarnings("deprecation") @Nonnull @@ -431,40 +267,29 @@ public class CartAssemblerBlock extends AbstractRailBlock return drops; } - @Override - public ItemRequirement getRequiredItems(BlockState state) { - ArrayList reuiredItems = new ArrayList<>(); - reuiredItems.add(new ItemStack(getRailItem(state))); - reuiredItems.add(new ItemStack(asItem())); - return new ItemRequirement(ItemUseType.CONSUME, reuiredItems); - } - @SuppressWarnings("deprecation") - public List getDropedAssembler(BlockState state, ServerWorld world, BlockPos pos, + public List getDropsNoRail(BlockState state, ServerWorld world, BlockPos pos, @Nullable TileEntity p_220077_3_, @Nullable Entity p_220077_4_, ItemStack p_220077_5_) { - return super.getDrops(state, (new LootContext.Builder(world)).withRandom(world.rand) - .withParameter(LootParameters.ORIGIN, Vector3d.of(pos)) + return super.getDrops(state, (new LootContext.Builder(world)).withRandom(world.random) + .withParameter(LootParameters.ORIGIN, Vector3d.atLowerCornerOf(pos)) .withParameter(LootParameters.TOOL, p_220077_5_) - .withNullableParameter(LootParameters.THIS_ENTITY, p_220077_4_) - .withNullableParameter(LootParameters.BLOCK_ENTITY, p_220077_3_)); + .withOptionalParameter(LootParameters.THIS_ENTITY, p_220077_4_) + .withOptionalParameter(LootParameters.BLOCK_ENTITY, p_220077_3_)); } @Override public ActionResultType onSneakWrenched(BlockState state, ItemUseContext context) { - World world = context.getWorld(); - BlockPos pos = context.getPos(); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); PlayerEntity player = context.getPlayer(); - if (world.isRemote) + if (world.isClientSide) return ActionResultType.SUCCESS; - if (player != null && !player.isCreative()) - getDropedAssembler(state, (ServerWorld) world, pos, world.getTileEntity(pos), player, context.getItem()) - .forEach(itemStack -> { - player.inventory.placeItemBackInInventory(world, itemStack); - }); - if(world instanceof ServerWorld) - state.spawnAdditionalDrops((ServerWorld) world, pos, ItemStack.EMPTY); - world.setBlockState(pos, getRailBlock(state)); + getDropsNoRail(state, (ServerWorld) world, pos, world.getBlockEntity(pos), player, context.getItemInHand()) + .forEach(itemStack -> player.inventory.placeItemBackInInventory(world, itemStack)); + if (world instanceof ServerWorld) + state.spawnAfterBreak((ServerWorld) world, pos, ItemStack.EMPTY); + world.setBlockAndUpdate(pos, getRailBlock(state)); return ActionResultType.SUCCESS; } @@ -475,9 +300,9 @@ public class CartAssemblerBlock extends AbstractRailBlock } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(BlockStateProperties.HORIZONTAL_AXIS); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override @@ -489,32 +314,57 @@ public class CartAssemblerBlock extends AbstractRailBlock } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(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) + World world = context.getLevel(); + if (world.isClientSide) 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.notifyNeighborsOfStateChange(pos.down(), this); + BlockPos pos = context.getClickedPos(); + world.setBlock(pos, rotate(state, Rotation.CLOCKWISE_90), 3); + world.updateNeighborsAt(pos.below(), this); return ActionResultType.SUCCESS; } + + @Override + public BlockState rotate(BlockState state, Rotation rotation) { + if (rotation == Rotation.NONE) + return state; + BlockState base = AllBlocks.CONTROLLER_RAIL.getDefaultState() + .setValue(ControllerRailBlock.SHAPE, state.getValue(RAIL_SHAPE)) + .setValue(ControllerRailBlock.BACKWARDS, state.getValue(BACKWARDS)) + .rotate(rotation); + return state.setValue(RAIL_SHAPE, base.getValue(ControllerRailBlock.SHAPE)) + .setValue(BACKWARDS, base.getValue(ControllerRailBlock.BACKWARDS)); + } + + @Override + public BlockState mirror(BlockState state, Mirror mirror) { + if (mirror == Mirror.NONE) + return state; + BlockState base = AllBlocks.CONTROLLER_RAIL.getDefaultState() + .setValue(ControllerRailBlock.SHAPE, state.getValue(RAIL_SHAPE)) + .setValue(ControllerRailBlock.BACKWARDS, state.getValue(BACKWARDS)) + .mirror(mirror); + return state.setValue(BACKWARDS, base.getValue(ControllerRailBlock.BACKWARDS)); + } + + public static Direction getHorizontalDirection(BlockState blockState) { + if (!(blockState.getBlock() instanceof CartAssemblerBlock)) + return Direction.SOUTH; + Direction pointingTo = getPointingTowards(blockState); + return blockState.getValue(BACKWARDS) ? pointingTo.getOpposite() : pointingTo; + } + + private static Direction getPointingTowards(BlockState state) { + switch (state.getValue(RAIL_SHAPE)) { + case EAST_WEST: + return Direction.WEST; + default: + return Direction.NORTH; + } + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlockItem.java index 78c25232b..e8678801f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlockItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlockItem.java @@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mo import javax.annotation.Nonnull; import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.block.AbstractRailBlock; @@ -13,6 +14,8 @@ import net.minecraft.item.BlockItem; import net.minecraft.item.ItemUseContext; import net.minecraft.state.properties.RailShape; import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; @@ -26,17 +29,18 @@ public class CartAssemblerBlockItem extends BlockItem { @Override @Nonnull - public ActionResultType onItemUse(ItemUseContext context) { + public ActionResultType useOn(ItemUseContext context) { if (tryPlaceAssembler(context)) { - context.getWorld().playSound(null, context.getPos(), SoundEvents.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1); + context.getLevel() + .playSound(null, context.getClickedPos(), SoundEvents.STONE_PLACE, SoundCategory.BLOCKS, 1, 1); return ActionResultType.SUCCESS; } - return super.onItemUse(context); + return super.useOn(context); } public boolean tryPlaceAssembler(ItemUseContext context) { - BlockPos pos = context.getPos(); - World world = context.getWorld(); + BlockPos pos = context.getClickedPos(); + World world = context.getLevel(); BlockState state = world.getBlockState(pos); Block block = state.getBlock(); PlayerEntity player = context.getPlayer(); @@ -48,25 +52,34 @@ public class CartAssemblerBlockItem extends BlockItem { return false; } - RailShape shape = state.get(((AbstractRailBlock) block).getShapeProperty()); + RailShape shape = state.getValue(((AbstractRailBlock) block).getShapeProperty()); if (shape != RailShape.EAST_WEST && shape != RailShape.NORTH_SOUTH) return false; BlockState newState = AllBlocks.CART_ASSEMBLER.getDefaultState() - .with(CartAssemblerBlock.RAIL_SHAPE, shape); + .setValue(CartAssemblerBlock.RAIL_SHAPE, shape); CartAssembleRailType newType = null; for (CartAssembleRailType type : CartAssembleRailType.values()) - if (type.matches.test(state)) + if (type.matches(state)) newType = type; if (newType == null) return false; - if (world.isRemote) + if (world.isClientSide) return true; - newState = newState.with(CartAssemblerBlock.RAIL_TYPE, newType); - world.setBlockState(pos, newState); + newState = newState.setValue(CartAssemblerBlock.RAIL_TYPE, newType); + if (state.hasProperty(ControllerRailBlock.BACKWARDS)) + newState = newState.setValue(CartAssemblerBlock.BACKWARDS, state.getValue(ControllerRailBlock.BACKWARDS)); + else { + Direction direction = player.getMotionDirection(); + newState = + newState.setValue(CartAssemblerBlock.BACKWARDS, direction.getAxisDirection() == AxisDirection.POSITIVE); + } + + world.setBlockAndUpdate(pos, newState); if (!player.isCreative()) - context.getItem().shrink(1); + context.getItemInHand() + .shrink(1); return true; } } \ No newline at end of file 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..80393ed1e 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,22 +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.VecHelper; 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.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.fml.common.Mod.EventBusSubscriber; +@EventBusSubscriber public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplayAssemblyExceptions { private static final int assemblyCooldown = 8; protected ScrollOptionBehaviour movementMode; private int ticksSinceMinecartUpdate; protected AssemblyException lastException; + protected AbstractMinecartEntity cartToAssemble; public CartAssemblerTileEntity(TileEntityType type) { super(type); @@ -39,6 +60,171 @@ 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 = level.getBlockState(worldPosition); + if (!AllBlocks.CART_ASSEMBLER.has(state)) + return; + CartAssemblerBlock block = (CartAssemblerBlock) state.getBlock(); + + CartAssemblerBlock.CartAssemblerAction action = CartAssemblerBlock.getActionForCart(state, cart); + if (action.shouldAssemble()) + assemble(level, worldPosition, cart); + if (action.shouldDisassemble()) + disassemble(level, worldPosition, cart); + if (action == CartAssemblerBlock.CartAssemblerAction.ASSEMBLE_ACCELERATE) { + if (cart.getDeltaMovement() + .length() > 1 / 128f) { + Direction facing = cart.getMotionDirection(); + RailShape railShape = state.getValue(CartAssemblerBlock.RAIL_SHAPE); + for (Direction d : Iterate.directionsInAxis(railShape == RailShape.EAST_WEST ? Axis.X : Axis.Z)) + if (level.getBlockState(worldPosition.relative(d)) + .isRedstoneConductor(level, worldPosition.relative(d))) + facing = d.getOpposite(); + + float speed = block.getRailMaxSpeed(state, level, worldPosition, cart); + cart.setDeltaMovement(facing.getStepX() * speed, facing.getStepY() * speed, facing.getStepZ() * speed); + } + } + if (action == CartAssemblerBlock.CartAssemblerAction.ASSEMBLE_ACCELERATE_DIRECTIONAL) { + Vector3i accelerationVector = + ControllerRailBlock.getAccelerationVector(AllBlocks.CONTROLLER_RAIL.getDefaultState() + .setValue(ControllerRailBlock.SHAPE, state.getValue(CartAssemblerBlock.RAIL_SHAPE)) + .setValue(ControllerRailBlock.BACKWARDS, state.getValue(CartAssemblerBlock.BACKWARDS))); + float speed = block.getRailMaxSpeed(state, level, worldPosition, cart); + cart.setDeltaMovement(Vector3d.atLowerCornerOf(accelerationVector) + .scale(speed)); + } + if (action == CartAssemblerBlock.CartAssemblerAction.DISASSEMBLE_BRAKE) { + Vector3d diff = VecHelper.getCenterOf(worldPosition) + .subtract(cart.position()); + cart.setDeltaMovement(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 = CartAssemblerBlock.getHorizontalDirection(getBlockState()); + + if (couplingFound) { + cart.setPos(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f); + if (!CouplingHandler.tryToCoupleCarts(null, world, cart.getId(), + contraption.connectedCart.getId())) + return; + } + + contraption.removeBlocksFromWorld(world, BlockPos.ZERO); + contraption.startMoving(world); + contraption.expandBoundsAroundAxis(Axis.Y); + + if (couplingFound) { + Vector3d diff = contraption.connectedCart.position() + .subtract(cart.position()); + initialOrientation = Direction.fromYRot(MathHelper.atan2(diff.z, diff.x) * 180 / Math.PI); + } + + OrientedContraptionEntity entity = OrientedContraptionEntity.create(world, contraption, initialOrientation); + if (couplingFound) + entity.setCouplingId(cart.getUUID()); + entity.setPos(pos.getX(), pos.getY(), pos.getZ()); + world.addFreshEntity(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) { + contraption.yaw = CartAssemblerBlock.getHorizontalDirection(getBlockState()) + .toYRot(); + 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() + .blockPosition(); + 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.ejectPassengers(); + if (cart instanceof FurnaceMinecartEntity) { + CompoundNBT nbt = cart.serializeNBT(); + nbt.putDouble("PushZ", cart.getDeltaMovement().x); + nbt.putDouble("PushX", cart.getDeltaMovement().z); + cart.deserializeNBT(nbt); + } } @Override @@ -71,27 +257,27 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay } private class CartAssemblerValueBoxTransform extends CenteredSideValueBoxTransform { - + public CartAssemblerValueBoxTransform() { super((state, d) -> { if (d.getAxis() .isVertical()) return false; - if (!state.contains(CartAssemblerBlock.RAIL_SHAPE)) + if (!state.hasProperty(CartAssemblerBlock.RAIL_SHAPE)) return false; - RailShape railShape = state.get(CartAssemblerBlock.RAIL_SHAPE); + RailShape railShape = state.getValue(CartAssemblerBlock.RAIL_SHAPE); 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 +288,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 +308,13 @@ 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; } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/ItemHandlerModifiableFromIInventory.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/ItemHandlerModifiableFromIInventory.java index 3dd313411..669bff17e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/ItemHandlerModifiableFromIInventory.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/ItemHandlerModifiableFromIInventory.java @@ -21,17 +21,17 @@ public class ItemHandlerModifiableFromIInventory implements IItemHandlerModifiab @Override public void setStackInSlot(int slot, ItemStack stack) { - inventory.setInventorySlotContents(slot, stack); + inventory.setItem(slot, stack); } @Override public int getSlots() { - return inventory.getSizeInventory(); + return inventory.getContainerSize(); } @Override public ItemStack getStackInSlot(int slot) { - return inventory.getStackInSlot(slot); + return inventory.getItem(slot); } @Override @@ -119,12 +119,12 @@ public class ItemHandlerModifiableFromIInventory implements IItemHandlerModifiab @Override public int getSlotLimit(int slot) { - return inventory.getInventoryStackLimit(); + return inventory.getMaxStackSize(); } @Override public boolean isItemValid(int slot, ItemStack stack) { - return inventory.isItemValidForSlot(slot, stack); + return inventory.canPlaceItem(slot, stack); } private void validateSlotIndex(int slot) 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..0650302bf 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 @@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mo import java.io.IOException; import java.util.List; -import java.util.Optional; import javax.annotation.Nullable; @@ -12,6 +11,7 @@ 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.ContraptionMovementSetting; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; @@ -39,7 +39,6 @@ import net.minecraft.util.Direction; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextFormatting; -import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -65,7 +64,7 @@ public class MinecartContraptionItem extends Item { private MinecartContraptionItem(Type minecartTypeIn, Properties builder) { super(builder); this.minecartType = minecartTypeIn; - DispenserBlock.registerDispenseBehavior(this, DISPENSER_BEHAVIOR); + DispenserBlock.registerBehavior(this, DISPENSER_BEHAVIOR); } // Taken and adjusted from MinecartItem @@ -73,35 +72,35 @@ public class MinecartContraptionItem extends Item { private final DefaultDispenseItemBehavior behaviourDefaultDispenseItem = new DefaultDispenseItemBehavior(); @Override - public ItemStack dispenseStack(IBlockSource source, ItemStack stack) { + public ItemStack execute(IBlockSource source, ItemStack stack) { Direction direction = source.getBlockState() - .get(DispenserBlock.FACING); - World world = source.getWorld(); - double d0 = source.getX() + (double) direction.getXOffset() * 1.125D; - double d1 = Math.floor(source.getY()) + (double) direction.getYOffset(); - double d2 = source.getZ() + (double) direction.getZOffset() * 1.125D; - BlockPos blockpos = source.getBlockPos() - .offset(direction); + .getValue(DispenserBlock.FACING); + World world = source.getLevel(); + double d0 = source.x() + (double) direction.getStepX() * 1.125D; + double d1 = Math.floor(source.y()) + (double) direction.getStepY(); + double d2 = source.z() + (double) direction.getStepZ() * 1.125D; + BlockPos blockpos = source.getPos() + .relative(direction); BlockState blockstate = world.getBlockState(blockpos); RailShape railshape = blockstate.getBlock() instanceof AbstractRailBlock ? ((AbstractRailBlock) blockstate.getBlock()).getRailDirection(blockstate, world, blockpos, null) : RailShape.NORTH_SOUTH; double d3; - if (blockstate.isIn(BlockTags.RAILS)) { + if (blockstate.is(BlockTags.RAILS)) { if (railshape.isAscending()) { d3 = 0.6D; } else { d3 = 0.1D; } } else { - if (blockstate.getMaterial() != Material.AIR || !world.getBlockState(blockpos.down()) - .isIn(BlockTags.RAILS)) { + if (blockstate.getMaterial() != Material.AIR || !world.getBlockState(blockpos.below()) + .is(BlockTags.RAILS)) { return this.behaviourDefaultDispenseItem.dispense(source, stack); } - BlockState blockstate1 = world.getBlockState(blockpos.down()); + BlockState blockstate1 = world.getBlockState(blockpos.below()); RailShape railshape1 = blockstate1.getBlock() instanceof AbstractRailBlock - ? ((AbstractRailBlock) blockstate1.getBlock()).getRailDirection(blockstate1, world, blockpos.down(), + ? ((AbstractRailBlock) blockstate1.getBlock()).getRailDirection(blockstate1, world, blockpos.below(), null) : RailShape.NORTH_SOUTH; if (direction != Direction.DOWN && railshape1.isAscending()) { @@ -111,11 +110,11 @@ public class MinecartContraptionItem extends Item { } } - AbstractMinecartEntity abstractminecartentity = AbstractMinecartEntity.create(world, d0, d1 + d3, d2, + AbstractMinecartEntity abstractminecartentity = AbstractMinecartEntity.createMinecart(world, d0, d1 + d3, d2, ((MinecartContraptionItem) stack.getItem()).minecartType); - if (stack.hasDisplayName()) - abstractminecartentity.setCustomName(stack.getDisplayName()); - world.addEntity(abstractminecartentity); + if (stack.hasCustomHoverName()) + abstractminecartentity.setCustomName(stack.getHoverName()); + world.addFreshEntity(abstractminecartentity); addContraptionToMinecart(world, stack, abstractminecartentity, direction); stack.shrink(1); @@ -123,23 +122,23 @@ public class MinecartContraptionItem extends Item { } @Override - protected void playDispenseSound(IBlockSource source) { - source.getWorld() - .playEvent(1000, source.getBlockPos(), 0); + protected void playSound(IBlockSource source) { + source.getLevel() + .levelEvent(1000, source.getPos(), 0); } }; // Taken and adjusted from MinecartItem @Override - public ActionResultType onItemUse(ItemUseContext context) { - World world = context.getWorld(); - BlockPos blockpos = context.getPos(); + public ActionResultType useOn(ItemUseContext context) { + World world = context.getLevel(); + BlockPos blockpos = context.getClickedPos(); BlockState blockstate = world.getBlockState(blockpos); - if (!blockstate.isIn(BlockTags.RAILS)) { + if (!blockstate.is(BlockTags.RAILS)) { return ActionResultType.FAIL; } else { - ItemStack itemstack = context.getItem(); - if (!world.isRemote) { + ItemStack itemstack = context.getItemInHand(); + if (!world.isClientSide) { RailShape railshape = blockstate.getBlock() instanceof AbstractRailBlock ? ((AbstractRailBlock) blockstate.getBlock()).getRailDirection(blockstate, world, blockpos, null) : RailShape.NORTH_SOUTH; @@ -149,14 +148,14 @@ public class MinecartContraptionItem extends Item { } AbstractMinecartEntity abstractminecartentity = - AbstractMinecartEntity.create(world, (double) blockpos.getX() + 0.5D, + AbstractMinecartEntity.createMinecart(world, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.0625D + d0, (double) blockpos.getZ() + 0.5D, this.minecartType); - if (itemstack.hasDisplayName()) - abstractminecartentity.setCustomName(itemstack.getDisplayName()); + if (itemstack.hasCustomHoverName()) + abstractminecartentity.setCustomName(itemstack.getHoverName()); PlayerEntity player = context.getPlayer(); - world.addEntity(abstractminecartentity); + world.addFreshEntity(abstractminecartentity); addContraptionToMinecart(world, itemstack, abstractminecartentity, - player == null ? null : player.getHorizontalFacing()); + player == null ? null : player.getDirection()); } itemstack.shrink(1); @@ -170,30 +169,27 @@ 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 = newFacing == null ? OrientedContraptionEntity.create(world, mountedContraption, intialOrientation) : OrientedContraptionEntity.createAtYaw(world, mountedContraption, intialOrientation, - newFacing.getHorizontalAngle()); + newFacing.toYRot()); contraptionEntity.startRiding(cart); - contraptionEntity.setPosition(cart.getX(), cart.getY(), cart.getZ()); - world.addEntity(contraptionEntity); + contraptionEntity.setPos(cart.getX(), cart.getY(), cart.getZ()); + world.addFreshEntity(contraptionEntity); } } @Override - public String getTranslationKey(ItemStack stack) { + public String getDescriptionId(ItemStack stack) { return "item.create.minecart_contraption"; } @Override - public void fillItemGroup(ItemGroup group, NonNullList items) {} + public void fillItemCategory(ItemGroup group, NonNullList items) {} @SubscribeEvent public static void wrenchCanBeUsedToPickUpMinecartContraptions(PlayerInteractEvent.EntityInteract event) { @@ -202,13 +198,15 @@ public class MinecartContraptionItem extends Item { if (player == null || entity == null) return; - ItemStack wrench = player.getHeldItem(event.getHand()); + ItemStack wrench = player.getItemInHand(event.getHand()); if (!AllItems.WRENCH.isIn(wrench)) return; if (entity instanceof AbstractContraptionEntity) - entity = entity.getRidingEntity(); + entity = entity.getVehicle(); if (!(entity instanceof AbstractMinecartEntity)) return; + if (!entity.isAlive()) + return; AbstractMinecartEntity cart = (AbstractMinecartEntity) entity; Type type = cart.getMinecartType(); if (type != Type.RIDEABLE && type != Type.FURNACE && type != Type.CHEST) @@ -218,21 +216,27 @@ public class MinecartContraptionItem extends Item { return; OrientedContraptionEntity contraption = (OrientedContraptionEntity) passengers.get(0); - if (event.getWorld().isRemote) { + if(ContraptionMovementSetting.isNoPickup(contraption.getContraption().getBlocks().values())) { + player.displayClientMessage(Lang.translate("contraption.minecart_contraption_illegal_pickup") + .withStyle(TextFormatting.RED), true); + return; + } + + if (event.getWorld().isClientSide) { event.setCancellationResult(ActionResultType.SUCCESS); event.setCanceled(true); return; } - ItemStack generatedStack = create(type, contraption).setDisplayName(entity.getCustomName()); + ItemStack generatedStack = create(type, contraption).setHoverName(entity.getCustomName()); try { ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput(); CompressedStreamTools.write(generatedStack.serializeNBT(), dataOutput); int estimatedPacketSize = dataOutput.toByteArray().length; if (estimatedPacketSize > 2_000_000) { - player.sendStatusMessage(Lang.translate("contraption.minecart_contraption_too_big") - .formatted(TextFormatting.RED), true); + player.displayClientMessage(Lang.translate("contraption.minecart_contraption_too_big") + .withStyle(TextFormatting.RED), true); return; } @@ -274,8 +278,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..faec44b37 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 @@ -33,7 +33,6 @@ import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.wrapper.CombinedInvWrapper; import net.minecraftforge.items.wrapper.InvWrapper; public class MountedContraption extends Contraption { @@ -53,29 +52,29 @@ 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); - if (!state.contains(RAIL_SHAPE)) + if (!state.hasProperty(RAIL_SHAPE)) return false; if (!searchMovedStructure(world, pos, null)) return false; - - Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z; + + Axis axis = state.getValue(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)); - + .setValue(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(); - frontier.add(pos.up()); + frontier.add(pos.above()); return true; } @@ -95,11 +94,11 @@ public class MountedContraption extends Contraption { if (axis.isVertical() || !VecHelper.onSameAxis(anchor, pos, axis)) continue; for (AbstractMinecartEntity abstractMinecartEntity : world - .getEntitiesWithinAABB(AbstractMinecartEntity.class, new AxisAlignedBB(pos))) { + .getEntitiesOfClass(AbstractMinecartEntity.class, new AxisAlignedBB(pos))) { if (!CartAssemblerBlock.canAssembleTo(abstractMinecartEntity)) break; connectedCart = abstractMinecartEntity; - connectedCart.setPosition(pos.getX() + .5, pos.getY(), pos.getZ() + .5f); + connectedCart.setPos(pos.getX() + .5, pos.getY(), pos.getZ() + .5f); } } @@ -118,7 +117,7 @@ public class MountedContraption extends Contraption { if (axis.isVertical() || !VecHelper.onSameAxis(anchor, pos, axis)) continue; for (AbstractMinecartEntity abstractMinecartEntity : world - .getEntitiesWithinAABB(AbstractMinecartEntity.class, new AxisAlignedBB(pos))) { + .getEntitiesOfClass(AbstractMinecartEntity.class, new AxisAlignedBB(pos))) { if (!CartAssemblerBlock.canAssembleTo(abstractMinecartEntity)) break; return true; @@ -149,18 +148,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..a4f3b1671 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 @@ -61,11 +61,11 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity movedContraption = null; } - if (world.isRemote) + if (level.isClientSide) clientOffsetDiff *= .75f; if (waitingForSpeedChange && movedContraption != null) { - if (world.isRemote) { + if (level.isClientSide) { float syncSpeed = clientOffsetDiff / 2f; offset += syncSpeed; movedContraption.setContraptionMotion(toMotionVector(syncSpeed)); @@ -75,7 +75,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity return; } - if (!world.isRemote && assembleNextTick) { + if (!level.isClientSide && assembleNextTick) { assembleNextTick = false; if (running) { if (getSpeed() == 0) @@ -114,7 +114,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity int extensionRange = getExtensionRange(); if (offset <= 0 || offset >= extensionRange) { offset = offset <= 0 ? 0 : extensionRange; - if (!world.isRemote) { + if (!level.isClientSide) { applyContraptionMotion(); applyContraptionPosition(); tryDisassemble(); @@ -130,7 +130,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity @Override public void lazyTick() { super.lazyTick(); - if (movedContraption != null && !world.isRemote) + if (movedContraption != null && !level.isClientSide) sendData(); } @@ -152,16 +152,16 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { movedContraption.getContraption() - .stop(world); + .stop(level); } } @Override - public void remove() { - this.removed = true; - if (!world.isRemote) + public void setRemoved() { + this.remove = true; + if (!level.isClientSide) disassemble(); - super.remove(); + super.setRemoved(); } @Override @@ -223,7 +223,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity protected void visitNewPosition() {} protected void tryDisassemble() { - if (removed) { + if (remove) { disassemble(); return; } @@ -241,7 +241,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity @Override public void collided() { - if (world.isRemote) { + if (level.isClientSide) { waitingForSpeedChange = true; return; } @@ -264,14 +264,14 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity if (movedContraption == null) return; Vector3d vec = toPosition(offset); - movedContraption.setPosition(vec.x, vec.y, vec.z); + movedContraption.setPos(vec.x, vec.y, vec.z); if (getSpeed() == 0 || waitingForSpeedChange) movedContraption.setContraptionMotion(Vector3d.ZERO); } public float getMovementSpeed() { - float movementSpeed = MathHelper.clamp(getSpeed() / 512f, -.49f, .49f) + clientOffsetDiff / 2f; - if (world.isRemote) + float movementSpeed = MathHelper.clamp(convertToLinear(getSpeed()), -.49f, .49f) + clientOffsetDiff / 2f; + if (level.isClientSide) movementSpeed *= ServerSpeedProvider.get(); return movementSpeed; } @@ -282,12 +282,17 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity @Override public void onStall() { - if (!world.isRemote) { + if (!level.isClientSide) { forceMove = true; sendData(); } } + public void onLengthBroken() { + offset = 0; + sendData(); + } + @Override public boolean isValid() { return !isRemoved(); @@ -296,7 +301,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity @Override public void attach(ControlledContraptionEntity contraption) { this.movedContraption = contraption; - if (!world.isRemote) { + if (!level.isClientSide) { this.running = true; sendData(); } @@ -309,6 +314,6 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity @Override public BlockPos getBlockPosition() { - return pos; + return worldPosition; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonBlock.java index 98efed20f..b936f8814 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonBlock.java @@ -50,75 +50,75 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement protected MechanicalPistonBlock(Properties properties, boolean sticky) { super(properties); - setDefaultState(getDefaultState().with(FACING, Direction.NORTH) - .with(STATE, PistonState.RETRACTED)); + registerDefaultState(defaultBlockState().setValue(FACING, Direction.NORTH) + .setValue(STATE, PistonState.RETRACTED)); isSticky = sticky; } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(STATE); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - if (!player.isAllowEdit()) + if (!player.mayBuild()) return ActionResultType.PASS; - if (player.isSneaking()) + if (player.isShiftKeyDown()) return ActionResultType.PASS; - if (!player.getHeldItem(handIn) + if (!player.getItemInHand(handIn) .getItem() - .isIn(Tags.Items.SLIMEBALLS)) { - if (player.getHeldItem(handIn) + .is(Tags.Items.SLIMEBALLS)) { + if (player.getItemInHand(handIn) .isEmpty()) { withTileEntityDo(worldIn, pos, te -> te.assembleNextTick = true); return ActionResultType.SUCCESS; } return ActionResultType.PASS; } - if (state.get(STATE) != PistonState.RETRACTED) + if (state.getValue(STATE) != PistonState.RETRACTED) return ActionResultType.PASS; - Direction direction = state.get(FACING); - if (hit.getFace() != direction) + Direction direction = state.getValue(FACING); + if (hit.getDirection() != direction) return ActionResultType.PASS; if (((MechanicalPistonBlock) state.getBlock()).isSticky) return ActionResultType.PASS; - if (worldIn.isRemote) { - Vector3d vec = hit.getHitVec(); + if (worldIn.isClientSide) { + Vector3d vec = hit.getLocation(); worldIn.addParticle(ParticleTypes.ITEM_SLIME, vec.x, vec.y, vec.z, 0, 0, 0); return ActionResultType.SUCCESS; } AllSoundEvents.SLIME_ADDED.playOnServer(worldIn, pos, .5f, 1); if (!player.isCreative()) - player.getHeldItem(handIn) + player.getItemInHand(handIn) .shrink(1); - worldIn.setBlockState(pos, AllBlocks.STICKY_MECHANICAL_PISTON.getDefaultState() - .with(FACING, direction) - .with(AXIS_ALONG_FIRST_COORDINATE, state.get(AXIS_ALONG_FIRST_COORDINATE))); + worldIn.setBlockAndUpdate(pos, AllBlocks.STICKY_MECHANICAL_PISTON.getDefaultState() + .setValue(FACING, direction) + .setValue(AXIS_ALONG_FIRST_COORDINATE, state.getValue(AXIS_ALONG_FIRST_COORDINATE))); return ActionResultType.SUCCESS; } @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block p_220069_4_, BlockPos fromPos, boolean p_220069_6_) { - Direction direction = state.get(FACING); - if (!fromPos.equals(pos.offset(direction.getOpposite()))) + Direction direction = state.getValue(FACING); + if (!fromPos.equals(pos.relative(direction.getOpposite()))) return; - if (!world.isRemote && !world.getPendingBlockTicks() - .isTickPending(pos, this)) - world.getPendingBlockTicks() + if (!world.isClientSide && !world.getBlockTicks() + .willTickThisTick(pos, this)) + world.getBlockTicks() .scheduleTick(pos, this, 0); } @Override - public void scheduledTick(BlockState state, ServerWorld worldIn, BlockPos pos, Random r) { - Direction direction = state.get(FACING); - BlockState pole = worldIn.getBlockState(pos.offset(direction.getOpposite())); + public void tick(BlockState state, ServerWorld worldIn, BlockPos pos, Random r) { + Direction direction = state.getValue(FACING); + BlockState pole = worldIn.getBlockState(pos.relative(direction.getOpposite())); if (!AllBlocks.PISTON_EXTENSION_POLE.has(pole)) return; - if (pole.get(PistonExtensionPoleBlock.FACING) + if (pole.getValue(PistonExtensionPoleBlock.FACING) .getAxis() != direction.getAxis()) return; withTileEntityDo(worldIn, pos, te -> { @@ -136,7 +136,7 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { - if (state.get(STATE) != PistonState.RETRACTED) + if (state.getValue(STATE) != PistonState.RETRACTED) return ActionResultType.PASS; return super.onWrenched(state, context); } @@ -145,28 +145,28 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement RETRACTED, MOVING, EXTENDED; @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } } @Override - public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { - Direction direction = state.get(FACING); + public void playerWillDestroy(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { + Direction direction = state.getValue(FACING); BlockPos pistonHead = null; BlockPos pistonBase = pos; boolean dropBlocks = player == null || !player.isCreative(); Integer maxPoles = maxAllowedPistonPoles(); for (int offset = 1; offset < maxPoles; offset++) { - BlockPos currentPos = pos.offset(direction, offset); + BlockPos currentPos = pos.relative(direction, offset); BlockState block = worldIn.getBlockState(currentPos); - if (isExtensionPole(block) && direction.getAxis() == block.get(BlockStateProperties.FACING) + if (isExtensionPole(block) && direction.getAxis() == block.getValue(BlockStateProperties.FACING) .getAxis()) continue; - if (isPistonHead(block) && block.get(BlockStateProperties.FACING) == direction) { + if (isPistonHead(block) && block.getValue(BlockStateProperties.FACING) == direction) { pistonHead = currentPos; } @@ -174,16 +174,16 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement } if (pistonHead != null && pistonBase != null) { - BlockPos.getAllInBox(pistonBase, pistonHead) + BlockPos.betweenClosedStream(pistonBase, pistonHead) .filter(p -> !p.equals(pos)) .forEach(p -> worldIn.destroyBlock(p, dropBlocks)); } for (int offset = 1; offset < maxPoles; offset++) { - BlockPos currentPos = pos.offset(direction.getOpposite(), offset); + BlockPos currentPos = pos.relative(direction.getOpposite(), offset); BlockState block = worldIn.getBlockState(currentPos); - if (isExtensionPole(block) && direction.getAxis() == block.get(BlockStateProperties.FACING) + if (isExtensionPole(block) && direction.getAxis() == block.getValue(BlockStateProperties.FACING) .getAxis()) { worldIn.destroyBlock(currentPos, dropBlocks); continue; @@ -192,7 +192,7 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement break; } - super.onBlockHarvested(worldIn, pos, state, player); + super.playerWillDestroy(worldIn, pos, state, player); } public static int maxAllowedPistonPoles() { @@ -202,13 +202,13 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - if (state.get(STATE) == PistonState.EXTENDED) - return AllShapes.MECHANICAL_PISTON_EXTENDED.get(state.get(FACING)); + if (state.getValue(STATE) == PistonState.EXTENDED) + return AllShapes.MECHANICAL_PISTON_EXTENDED.get(state.getValue(FACING)); - if (state.get(STATE) == PistonState.MOVING) - return AllShapes.MECHANICAL_PISTON.get(state.get(FACING)); + if (state.getValue(STATE) == PistonState.MOVING) + return AllShapes.MECHANICAL_PISTON.get(state.getValue(FACING)); - return VoxelShapes.fullCube(); + return VoxelShapes.block(); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonGenerator.java index 34e30c52c..4b3363bcf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonGenerator.java @@ -23,14 +23,14 @@ public class MechanicalPistonGenerator extends SpecialBlockStateGen { @Override protected int getXRotation(BlockState state) { - Direction facing = state.get(MechanicalPistonBlock.FACING); + Direction facing = state.getValue(MechanicalPistonBlock.FACING); return facing.getAxis() .isVertical() ? facing == Direction.DOWN ? 180 : 0 : 90; } @Override protected int getYRotation(BlockState state) { - Direction facing = state.get(MechanicalPistonBlock.FACING); + Direction facing = state.getValue(MechanicalPistonBlock.FACING); return facing.getAxis() .isVertical() ? 0 : horizontalAngle(facing) + 180; } @@ -38,12 +38,12 @@ public class MechanicalPistonGenerator extends SpecialBlockStateGen { @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - Direction facing = state.get(PistonBlock.FACING); - boolean axisAlongFirst = state.get(MechanicalPistonBlock.AXIS_ALONG_FIRST_COORDINATE); - PistonState pistonState = state.get(MechanicalPistonBlock.STATE); + Direction facing = state.getValue(PistonBlock.FACING); + boolean axisAlongFirst = state.getValue(MechanicalPistonBlock.AXIS_ALONG_FIRST_COORDINATE); + PistonState pistonState = state.getValue(MechanicalPistonBlock.STATE); String path = "block/mechanical_piston"; - String folder = pistonState == PistonState.RETRACTED ? type.getString() : pistonState.getString(); + String folder = pistonState == PistonState.RETRACTED ? type.getSerializedName() : pistonState.getSerializedName(); String partial = facing.getAxis() == Axis.X ^ axisAlongFirst ? "block_rotated" : "block"; return prov.models() diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java index fe9c50d8a..09678c268 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java @@ -5,7 +5,7 @@ import static com.simibubi.create.content.contraptions.components.structureMovem import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -30,23 +30,23 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; import net.minecraft.world.World; -public class MechanicalPistonHeadBlock extends ProperDirectionalBlock implements IWaterLoggable { +public class MechanicalPistonHeadBlock extends WrenchableDirectionalBlock implements IWaterLoggable { public static final EnumProperty TYPE = BlockStateProperties.PISTON_TYPE; public MechanicalPistonHeadBlock(Properties p_i48415_1_) { super(p_i48415_1_); - setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); + registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(TYPE, BlockStateProperties.WATERLOGGED); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override - public PushReaction getPushReaction(BlockState state) { + public PushReaction getPistonPushReaction(BlockState state) { return PushReaction.NORMAL; } @@ -57,20 +57,20 @@ public class MechanicalPistonHeadBlock extends ProperDirectionalBlock implements } @Override - public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { - Direction direction = state.get(FACING); + public void playerWillDestroy(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { + Direction direction = state.getValue(FACING); BlockPos pistonHead = pos; BlockPos pistonBase = null; for (int offset = 1; offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset++) { - BlockPos currentPos = pos.offset(direction.getOpposite(), offset); + BlockPos currentPos = pos.relative(direction.getOpposite(), offset); BlockState block = worldIn.getBlockState(currentPos); - if (isExtensionPole(block) && direction.getAxis() == block.get(BlockStateProperties.FACING) + if (isExtensionPole(block) && direction.getAxis() == block.getValue(BlockStateProperties.FACING) .getAxis()) continue; - if (MechanicalPistonBlock.isPiston(block) && block.get(BlockStateProperties.FACING) == direction) + if (MechanicalPistonBlock.isPiston(block) && block.getValue(BlockStateProperties.FACING) == direction) pistonBase = currentPos; break; @@ -78,43 +78,43 @@ public class MechanicalPistonHeadBlock extends ProperDirectionalBlock implements if (pistonHead != null && pistonBase != null) { final BlockPos basePos = pistonBase; - BlockPos.getAllInBox(pistonBase, pistonHead) + BlockPos.betweenClosedStream(pistonBase, pistonHead) .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)); + worldIn.setBlockAndUpdate(basePos, worldIn.getBlockState(basePos) + .setValue(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); } - super.onBlockHarvested(worldIn, pos, state, player); + super.playerWillDestroy(worldIn, pos, state, player); } @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.MECHANICAL_PISTON_HEAD.get(state.get(FACING)); + return AllShapes.MECHANICAL_PISTON_HEAD.get(state.getValue(FACING)); } @Override public FluidState getFluidState(BlockState state) { - return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState(); + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world, BlockPos pos, BlockPos neighbourPos) { - if (state.get(BlockStateProperties.WATERLOGGED)) { - world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + if (state.getValue(BlockStateProperties.WATERLOGGED)) { + world.getLiquidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } return state; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - FluidState FluidState = context.getWorld().getFluidState(context.getPos()); - return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER)); + FluidState FluidState = context.getLevel().getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getType() == Fluids.WATER)); } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } } 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..5ca97b096 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 @@ -45,23 +45,23 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { @Override public void assemble() throws AssemblyException { - if (!(world.getBlockState(pos) + if (!(level.getBlockState(worldPosition) .getBlock() instanceof MechanicalPistonBlock)) return; - Direction direction = getBlockState().get(BlockStateProperties.FACING); + Direction direction = getBlockState().getValue(BlockStateProperties.FACING); // Collect Construct PistonContraption contraption = new PistonContraption(direction, getMovementSpeed() < 0); - if (!contraption.assemble(world, pos)) + if (!contraption.assemble(level, worldPosition)) return; - Direction positive = Direction.getFacingFromAxis(AxisDirection.POSITIVE, direction.getAxis()); + Direction positive = Direction.get(AxisDirection.POSITIVE, direction.getAxis()); Direction movementDirection = getSpeed() > 0 ^ direction.getAxis() != Axis.Z ? positive : positive.getOpposite(); - BlockPos anchor = contraption.anchor.offset(direction, contraption.initialExtensionProgress); - if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection), + BlockPos anchor = contraption.anchor.relative(direction, contraption.initialExtensionProgress); + if (ContraptionCollider.isCollidingWithWorld(level, contraption, anchor.relative(movementDirection), movementDirection)) return; @@ -78,35 +78,35 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { sendData(); clientOffsetDiff = 0; - BlockPos startPos = BlockPos.ZERO.offset(direction, contraption.initialExtensionProgress); - contraption.removeBlocksFromWorld(world, startPos); - movedContraption = ControlledContraptionEntity.create(getWorld(), this, contraption); + BlockPos startPos = BlockPos.ZERO.relative(direction, contraption.initialExtensionProgress); + contraption.removeBlocksFromWorld(level, startPos); + movedContraption = ControlledContraptionEntity.create(getLevel(), this, contraption); applyContraptionPosition(); forceMove = true; - world.addEntity(movedContraption); - - AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(world, pos); + level.addFreshEntity(movedContraption); + + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); } @Override public void disassemble() { if (!running && movedContraption == null) return; - if (!removed) - getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), + if (!remove) + getLevel().setBlock(worldPosition, getBlockState().setValue(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3 | 16); if (movedContraption != null) { applyContraptionPosition(); movedContraption.disassemble(); - AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(world, pos); + AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, worldPosition); } running = false; movedContraption = null; sendData(); - if (removed) + if (remove) AllBlocks.MECHANICAL_PISTON.get() - .onBlockHarvested(world, pos, getBlockState(), null); + .playerWillDestroy(level, worldPosition, getBlockState(), null); } @Override @@ -118,12 +118,12 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { @Override public float getMovementSpeed() { - float movementSpeed = MathHelper.clamp(getSpeed() / 512f, -.49f, .49f); - if (world.isRemote) + float movementSpeed = MathHelper.clamp(convertToLinear(getSpeed()), -.49f, .49f); + if (level.isClientSide) movementSpeed *= ServerSpeedProvider.get(); - Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING); + Direction pistonDirection = getBlockState().getValue(BlockStateProperties.FACING); int movementModifier = pistonDirection.getAxisDirection() - .getOffset() * (pistonDirection.getAxis() == Axis.Z ? -1 : 1); + .getStep() * (pistonDirection.getAxis() == Axis.Z ? -1 : 1); movementSpeed = movementSpeed * -movementModifier + clientOffsetDiff / 2f; int extensionRange = getExtensionRange(); @@ -141,24 +141,24 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { @Override protected Vector3d toMotionVector(float speed) { - Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING); - return Vector3d.of(pistonDirection.getDirectionVec()) + Direction pistonDirection = getBlockState().getValue(BlockStateProperties.FACING); + return Vector3d.atLowerCornerOf(pistonDirection.getNormal()) .scale(speed); } @Override protected Vector3d toPosition(float offset) { - Vector3d position = Vector3d.of(getBlockState().get(BlockStateProperties.FACING) - .getDirectionVec()) + Vector3d position = Vector3d.atLowerCornerOf(getBlockState().getValue(BlockStateProperties.FACING) + .getNormal()) .scale(offset); - return position.add(Vector3d.of(movedContraption.getContraption().anchor)); + return position.add(Vector3d.atLowerCornerOf(movedContraption.getContraption().anchor)); } @Override protected ValueBoxTransform getMovementModeSlot() { return new DirectionalExtenderScrollOptionSlot((state, d) -> { Axis axis = d.getAxis(); - Axis extensionAxis = state.get(MechanicalPistonBlock.FACING) + Axis extensionAxis = state.getValue(MechanicalPistonBlock.FACING) .getAxis(); Axis shaftAxis = ((IRotate) state.getBlock()).getRotationAxis(state); return extensionAxis != axis && shaftAxis != axis; 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..5c79bd6fb 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; @@ -70,7 +70,7 @@ public class PistonContraption extends TranslatingContraption { if (blocks.size() == count) { // no new blocks added bounds = pistonExtensionCollisionBox; } else { - bounds = bounds.union(pistonExtensionCollisionBox); + bounds = bounds.minmax(pistonExtensionCollisionBox); } startMoving(world); return true; @@ -79,7 +79,7 @@ public class PistonContraption extends TranslatingContraption { private boolean collectExtensions(World world, BlockPos pos, Direction direction) throws AssemblyException { List poles = new ArrayList<>(); BlockPos actualStart = pos; - BlockState nextBlock = world.getBlockState(actualStart.offset(direction)); + BlockState nextBlock = world.getBlockState(actualStart.relative(direction)); int extensionsInFront = 0; BlockState blockState = world.getBlockState(pos); boolean sticky = isStickyPiston(blockState); @@ -87,17 +87,17 @@ public class PistonContraption extends TranslatingContraption { if (!isPiston(blockState)) return false; - if (blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) { - while (PistonExtensionPoleBlock.PlacementHelper.get().matchesAxis(nextBlock, direction.getAxis()) || isPistonHead(nextBlock) && nextBlock.get(FACING) == direction) { + if (blockState.getValue(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) { + while (PistonExtensionPoleBlock.PlacementHelper.get().matchesAxis(nextBlock, direction.getAxis()) || isPistonHead(nextBlock) && nextBlock.getValue(FACING) == direction) { - actualStart = actualStart.offset(direction); - poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null)); + actualStart = actualStart.relative(direction); + poles.add(new BlockInfo(actualStart, nextBlock.setValue(FACING, direction), null)); extensionsInFront++; if (isPistonHead(nextBlock)) break; - nextBlock = world.getBlockState(actualStart.offset(direction)); + nextBlock = world.getBlockState(actualStart.relative(direction)); if (extensionsInFront > MechanicalPistonBlock.maxAllowedPistonPoles()) throw AssemblyException.tooManyPistonPoles(); } @@ -105,32 +105,32 @@ public class PistonContraption extends TranslatingContraption { if (extensionsInFront == 0) poles.add(new BlockInfo(pos, MECHANICAL_PISTON_HEAD.getDefaultState() - .with(FACING, direction) - .with(BlockStateProperties.PISTON_TYPE, sticky ? PistonType.STICKY : PistonType.DEFAULT), null)); + .setValue(FACING, direction) + .setValue(BlockStateProperties.PISTON_TYPE, sticky ? PistonType.STICKY : PistonType.DEFAULT), null)); else poles.add(new BlockInfo(pos, PISTON_EXTENSION_POLE.getDefaultState() - .with(FACING, direction), null)); + .setValue(FACING, direction), null)); BlockPos end = pos; - nextBlock = world.getBlockState(end.offset(direction.getOpposite())); + nextBlock = world.getBlockState(end.relative(direction.getOpposite())); int extensionsInBack = 0; while (PistonExtensionPoleBlock.PlacementHelper.get().matchesAxis(nextBlock, direction.getAxis())) { - end = end.offset(direction.getOpposite()); - poles.add(new BlockInfo(end, nextBlock.with(FACING, direction), null)); + end = end.relative(direction.getOpposite()); + poles.add(new BlockInfo(end, nextBlock.setValue(FACING, direction), null)); extensionsInBack++; - nextBlock = world.getBlockState(end.offset(direction.getOpposite())); + nextBlock = world.getBlockState(end.relative(direction.getOpposite())); if (extensionsInFront + extensionsInBack > MechanicalPistonBlock.maxAllowedPistonPoles()) throw AssemblyException.tooManyPistonPoles(); } - anchor = pos.offset(direction, initialExtensionProgress + 1); + anchor = pos.relative(direction, initialExtensionProgress + 1); extensionLength = extensionsInBack + extensionsInFront; initialExtensionProgress = extensionsInFront; pistonExtensionCollisionBox = new AxisAlignedBB( - BlockPos.ZERO.offset(direction, -1), - BlockPos.ZERO.offset(direction, -extensionLength - 1)).expand(1, + BlockPos.ZERO.relative(direction, -1), + BlockPos.ZERO.relative(direction, -extensionLength - 1)).expandTowards(1, 1, 1); if (extensionLength == 0) @@ -139,7 +139,7 @@ public class PistonContraption extends TranslatingContraption { bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0); for (BlockInfo pole : poles) { - BlockPos relPos = pole.pos.offset(direction, -extensionsInFront); + BlockPos relPos = pole.pos.relative(direction, -extensionsInFront); BlockPos localPos = relPos.subtract(anchor); getBlocks().put(localPos, new BlockInfo(localPos, pole.state, null)); //pistonExtensionCollisionBox = pistonExtensionCollisionBox.union(new AxisAlignedBB(localPos)); @@ -156,34 +156,34 @@ public class PistonContraption extends TranslatingContraption { @Override protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, Queue frontier) throws AssemblyException { frontier.clear(); - boolean sticky = isStickyPiston(world.getBlockState(pos.offset(orientation, -1))); + boolean sticky = isStickyPiston(world.getBlockState(pos.relative(orientation, -1))); boolean retracting = direction != orientation; if (retracting && !sticky) return true; for (int offset = 0; offset <= AllConfigs.SERVER.kinetics.maxChassisRange.get(); offset++) { if (offset == 1 && retracting) return true; - BlockPos currentPos = pos.offset(orientation, offset + initialExtensionProgress); + BlockPos currentPos = pos.relative(orientation, offset + initialExtensionProgress); if (retracting && World.isOutsideBuildHeight(currentPos)) return true; - if (!world.isBlockPresent(currentPos)) + if (!world.isLoaded(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()) + if (isPistonHead(state) && state.getValue(FACING) == direction.getOpposite()) return true; - if (!BlockMovementTraits.movementAllowed(state, world, currentPos)) + if (!BlockMovementChecks.isMovementAllowed(state, world, currentPos)) if (retracting) return true; else throw AssemblyException.unmovableBlock(currentPos, state); - if (retracting && state.getPushReaction() == PushReaction.PUSH_ONLY) + if (retracting && state.getPistonPushReaction() == PushReaction.PUSH_ONLY) return true; frontier.add(currentPos); - if (BlockMovementTraits.notSupportive(state, orientation)) + if (BlockMovementChecks.isNotSupportive(state, orientation)) return true; } return true; @@ -191,25 +191,25 @@ public class PistonContraption extends TranslatingContraption { @Override public void addBlock(BlockPos pos, Pair capture) { - super.addBlock(pos.offset(orientation, -initialExtensionProgress), capture); + super.addBlock(pos.relative(orientation, -initialExtensionProgress), capture); } @Override public BlockPos toLocalPos(BlockPos globalPos) { return globalPos.subtract(anchor) - .offset(orientation, -initialExtensionProgress); + .relative(orientation, -initialExtensionProgress); } @Override protected boolean customBlockPlacement(IWorld world, BlockPos pos, BlockState state) { - BlockPos pistonPos = anchor.offset(orientation, -1); + BlockPos pistonPos = anchor.relative(orientation, -1); BlockState pistonState = world.getBlockState(pistonPos); - TileEntity te = world.getTileEntity(pistonPos); + TileEntity te = world.getBlockEntity(pistonPos); if (pos.equals(pistonPos)) { if (te == null || te.isRemoved()) return true; if (!isExtensionPole(state) && isPiston(pistonState)) - world.setBlockState(pistonPos, pistonState.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED), + world.setBlock(pistonPos, pistonState.setValue(MechanicalPistonBlock.STATE, PistonState.RETRACTED), 3 | 16); return true; } @@ -218,10 +218,10 @@ public class PistonContraption extends TranslatingContraption { @Override protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) { - BlockPos pistonPos = anchor.offset(orientation, -1); + BlockPos pistonPos = anchor.relative(orientation, -1); BlockState blockState = world.getBlockState(pos); if (pos.equals(pistonPos) && isPiston(blockState)) { - world.setBlockState(pos, blockState.with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66 | 16); + world.setBlock(pos, blockState.setValue(MechanicalPistonBlock.STATE, PistonState.MOVING), 66 | 16); return true; } return false; @@ -232,7 +232,7 @@ public class PistonContraption extends TranslatingContraption { super.readNBT(world, nbt, spawnData); initialExtensionProgress = nbt.getInt("InitialLength"); extensionLength = nbt.getInt("ExtensionLength"); - orientation = Direction.byIndex(nbt.getInt("Orientation")); + orientation = Direction.from3DDataValue(nbt.getInt("Orientation")); } @Override @@ -240,7 +240,7 @@ public class PistonContraption extends TranslatingContraption { CompoundNBT tag = super.writeNBT(spawnPacket); tag.putInt("InitialLength", initialExtensionProgress); tag.putInt("ExtensionLength", extensionLength); - tag.putInt("Orientation", orientation.getIndex()); + tag.putInt("Orientation", orientation.get3DDataValue()); return tag; } 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..c944cb4ec 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 @@ -10,7 +10,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.util.PoleHelper; @@ -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; @@ -43,13 +44,13 @@ import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraftforge.common.ToolType; -public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements IWrenchable, IWaterLoggable { +public class PistonExtensionPoleBlock extends WrenchableDirectionalBlock implements IWrenchable, IWaterLoggable { private static final int placementHelperId = PlacementHelpers.register(PlacementHelper.get()); public PistonExtensionPoleBlock(Properties properties) { super(properties); - setDefaultState(getDefaultState().with(FACING, Direction.UP).with(BlockStateProperties.WATERLOGGED, false)); + registerDefaultState(defaultBlockState().setValue(FACING, Direction.UP).setValue(BlockStateProperties.WATERLOGGED, false)); } @Override @@ -59,7 +60,7 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements @Override public boolean canHarvestBlock(BlockState state, IBlockReader world, BlockPos pos, PlayerEntity player) { - for (ToolType toolType : player.getHeldItemMainhand() + for (ToolType toolType : player.getMainHandItem() .getToolTypes()) { if (isToolEffective(state, toolType)) return true; @@ -71,35 +72,35 @@ 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) { + public PushReaction getPistonPushReaction(BlockState state) { return PushReaction.NORMAL; } @Override - public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { - Axis axis = state.get(FACING) + public void playerWillDestroy(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { + Axis axis = state.getValue(FACING) .getAxis(); - Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); + Direction direction = Direction.get(AxisDirection.POSITIVE, axis); BlockPos pistonHead = null; BlockPos pistonBase = null; for (int modifier : new int[] { 1, -1 }) { for (int offset = modifier; modifier * offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset += modifier) { - BlockPos currentPos = pos.offset(direction, offset); + BlockPos currentPos = pos.relative(direction, offset); BlockState block = worldIn.getBlockState(currentPos); - if (isExtensionPole(block) && axis == block.get(FACING) + if (isExtensionPole(block) && axis == block.getValue(FACING) .getAxis()) continue; - if (isPiston(block) && block.get(BlockStateProperties.FACING) + if (isPiston(block) && block.getValue(BlockStateProperties.FACING) .getAxis() == axis) pistonBase = currentPos; - if (isPistonHead(block) && block.get(BlockStateProperties.FACING) + if (isPistonHead(block) && block.getValue(BlockStateProperties.FACING) .getAxis() == axis) pistonHead = currentPos; @@ -108,42 +109,49 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements } if (pistonHead != null && pistonBase != null && worldIn.getBlockState(pistonHead) - .get(BlockStateProperties.FACING) == worldIn.getBlockState(pistonBase) - .get(BlockStateProperties.FACING)) { + .getValue(BlockStateProperties.FACING) == worldIn.getBlockState(pistonBase) + .getValue(BlockStateProperties.FACING)) { final BlockPos basePos = pistonBase; - BlockPos.getAllInBox(pistonBase, pistonHead) - .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)); + BlockPos.betweenClosedStream(pistonBase, pistonHead) + .filter(p -> !p.equals(pos) && !p.equals(basePos)) + .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); + worldIn.setBlockAndUpdate(basePos, worldIn.getBlockState(basePos) + .setValue(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); + + TileEntity te = worldIn.getBlockEntity(basePos); + if (te instanceof MechanicalPistonTileEntity) { + MechanicalPistonTileEntity baseTE = (MechanicalPistonTileEntity) te; + baseTE.offset = 0; + baseTE.onLengthBroken(); + } } - super.onBlockHarvested(worldIn, pos, state, player); + super.playerWillDestroy(worldIn, pos, state, player); } @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.FOUR_VOXEL_POLE.get(state.get(FACING) + return AllShapes.FOUR_VOXEL_POLE.get(state.getValue(FACING) .getAxis()); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - FluidState FluidState = context.getWorld() - .getFluidState(context.getPos()); - return getDefaultState().with(FACING, context.getFace() + FluidState FluidState = context.getLevel() + .getFluidState(context.getClickedPos()); + return defaultBlockState().setValue(FACING, context.getClickedFace() .getOpposite()) - .with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER)); + .setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getType() == Fluids.WATER)); } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getItemInHand(hand); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); - if (placementHelper.matchesItem(heldItem) && !player.isSneaking()) + if (placementHelper.matchesItem(heldItem) && !player.isShiftKeyDown()) return placementHelper.getOffset(player, world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); return ActionResultType.PASS; @@ -151,26 +159,26 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements @Override public FluidState getFluidState(BlockState state) { - return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) - : Fluids.EMPTY.getDefaultState(); + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) + : Fluids.EMPTY.defaultFluidState(); } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(BlockStateProperties.WATERLOGGED); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, IWorld world, BlockPos pos, BlockPos neighbourPos) { - if (state.get(BlockStateProperties.WATERLOGGED)) { - world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world, BlockPos pos, BlockPos neighbourPos) { + if (state.getValue(BlockStateProperties.WATERLOGGED)) { + world.getLiquidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } return state; } - - @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + + @Override + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } @@ -186,7 +194,7 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements private PlacementHelper(){ super( AllBlocks.PISTON_EXTENSION_POLE::has, - state -> state.get(FACING).getAxis(), + state -> state.getValue(FACING).getAxis(), FACING ); } 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..1c05d8b77 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; @@ -16,7 +16,7 @@ public class PistonLighter extends ContraptionLighter { bounds.translate(contraption.anchor); int length = contraption.extensionLength; - Vector3i direction = contraption.orientation.getDirectionVec(); + Vector3i direction = contraption.orientation.getNormal(); int shift = length / 2; int shiftX = direction.getX() * shift; 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..fae4a7b18 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.material.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,11 +37,11 @@ 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); - rotationAxis = rotatingAbout.getUnitVector(); + rotatingAbout = Direction.get(Direction.AxisDirection.POSITIVE, axis); + rotationAxis = rotatingAbout.step(); coil = getCoilModel() .createInstance() @@ -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 @@ -65,7 +66,7 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID private void transformModels() { resizeRope(); - coil.setRotation(rotationAxis.getDegreesQuaternion(offset * 180)); + coil.setRotation(rotationAxis.rotationDegrees(offset * 180)); magnet.update().get().ifPresent(data -> { int index = Math.max(0, MathHelper.floor(offset)); @@ -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(); @@ -136,7 +137,7 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID int length = MathHelper.ceil(offset); if (volume == null || bLight.length < length + 1) { - volume = GridAlignedBB.from(pos.down(length), pos); + volume = GridAlignedBB.from(pos.below(length), pos); volume.fixMinMax(); bLight = Arrays.copyOf(bLight, length + 1); @@ -187,9 +188,9 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID int top = this.pos.getY(); BlockPos.Mutable pos = new BlockPos.Mutable(); changed.forEachContained((x, y, z) -> { - pos.setPos(x, y, z); - byte block = (byte) world.getLightLevel(LightType.BLOCK, pos); - byte sky = (byte) world.getLightLevel(LightType.SKY, pos); + pos.set(x, y, z); + byte block = (byte) world.getBrightness(LightType.BLOCK, pos); + byte sky = (byte) world.getBrightness(LightType.SKY, pos); int i = top - y; 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..5599b93a4 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; @@ -36,7 +36,7 @@ public abstract class AbstractPulleyRenderer extends KineticTileEntityRenderer { } @Override - public boolean isGlobalRenderer(KineticTileEntity p_188185_1_) { + public boolean shouldRenderOffScreen(KineticTileEntity p_188185_1_) { return true; } @@ -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.getLevel())) return; super.renderSafe(te, partialTicks, ms, buffer, light, overlay); float offset = getOffset(te, partialTicks); @@ -53,18 +53,18 @@ public abstract class AbstractPulleyRenderer extends KineticTileEntityRenderer { Axis rotationAxis = ((IRotate) te.getBlockState() .getBlock()).getRotationAxis(te.getBlockState()); kineticRotationTransform(getRotatedCoil(te), te, rotationAxis, AngleHelper.rad(offset * 180), light) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .renderInto(ms, buffer.getBuffer(RenderType.solid())); - World world = te.getWorld(); + World world = te.getLevel(); BlockState blockState = te.getBlockState(); - BlockPos pos = te.getPos(); + BlockPos pos = te.getBlockPos(); SuperByteBuffer halfMagnet = PartialBufferer.get(this.halfMagnet, blockState); SuperByteBuffer halfRope = PartialBufferer.get(this.halfRope, blockState); SuperByteBuffer magnet = renderMagnet(te); SuperByteBuffer rope = renderRope(te); - IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); + IVertexBuilder vb = buffer.getBuffer(RenderType.solid()); if (running || offset == 0) renderAt(world, offset > .25f ? magnet : halfMagnet, offset, pos, ms, vb); @@ -81,8 +81,8 @@ public abstract class AbstractPulleyRenderer extends KineticTileEntityRenderer { private void renderAt(IWorld world, SuperByteBuffer partial, float offset, BlockPos pulleyPos, MatrixStack ms, IVertexBuilder buffer) { - BlockPos actualPos = pulleyPos.down((int) offset); - int light = WorldRenderer.getLightmapCoordinates(world, world.getBlockState(actualPos), actualPos); + BlockPos actualPos = pulleyPos.below((int) offset); + int light = WorldRenderer.getLightColor(world, world.getBlockState(actualPos), actualPos); partial.translate(0, -offset, 0) .light(light) .renderInto(ms, buffer); @@ -107,7 +107,7 @@ public abstract class AbstractPulleyRenderer extends KineticTileEntityRenderer { protected SuperByteBuffer getRotatedCoil(KineticTileEntity te) { BlockState blockState = te.getBlockState(); - return PartialBufferer.getFacing(getCoil(), blockState, Direction.getFacingFromAxis(AxisDirection.POSITIVE, getShaftAxis(te))); + return PartialBufferer.getFacing(getCoil(), blockState, Direction.get(AxisDirection.POSITIVE, getShaftAxis(te))); } } 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..c748a0568 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,42 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +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() { - return getOrientedMaterial().getModel(AllBlockPartials.HOSE_MAGNET, blockState); + protected Instancer getMagnetModel() { + return materialManager.defaultCutout() + .material(Materials.ORIENTED) + .getModel(AllBlockPartials.HOSE_MAGNET, blockState); } - protected InstancedModel getHalfMagnetModel() { - return getOrientedMaterial().getModel(AllBlockPartials.HOSE_HALF_MAGNET, blockState); + protected Instancer getHalfMagnetModel() { + return materialManager.defaultCutout() + .material(Materials.ORIENTED) + .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..c482ac605 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 te.assembleNextTick = true); return ActionResultType.SUCCESS; @@ -84,7 +84,7 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(BlockStateProperties.WATERLOGGED); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world, BlockPos pos, BlockPos neighbourPos) { - if (state.get(BlockStateProperties.WATERLOGGED)) { - world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + if (state.getValue(BlockStateProperties.WATERLOGGED)) { + world.getLiquidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } return state; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - FluidState FluidState = context.getWorld().getFluidState(context.getPos()); - return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER)); + FluidState FluidState = context.getLevel().getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getType() == Fluids.WATER)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java index 87cc4cacf..e148c3837 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +import com.jozufozu.flywheel.light.GridAlignedBB; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; -import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -17,9 +17,9 @@ public class PulleyLighter extends ContraptionLighter { GridAlignedBB bounds = GridAlignedBB.from(contraption.bounds); - World world = contraption.entity.world; + World world = contraption.entity.level; - BlockPos.Mutable pos = contraption.anchor.mutableCopy(); + BlockPos.Mutable pos = contraption.anchor.mutable(); while (!AllBlocks.ROPE_PULLEY.has(world.getBlockState(pos)) && pos.getY() < 256) { pos.move(0, 1, 0); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java index 4db922553..233dbe8d5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction.Axis; @@ -21,7 +21,7 @@ public class PulleyRenderer extends AbstractPulleyRenderer { @Override protected Axis getShaftAxis(KineticTileEntity te) { return te.getBlockState() - .get(PulleyBlock.HORIZONTAL_AXIS); + .getValue(PulleyBlock.HORIZONTAL_AXIS); } @Override @@ -31,12 +31,12 @@ public class PulleyRenderer extends AbstractPulleyRenderer { @Override protected SuperByteBuffer renderRope(KineticTileEntity te) { - return CreateClient.bufferCache.renderBlock(AllBlocks.ROPE.getDefaultState()); + return CreateClient.BUFFER_CACHE.renderBlock(AllBlocks.ROPE.getDefaultState()); } @Override protected SuperByteBuffer renderMagnet(KineticTileEntity te) { - return CreateClient.bufferCache.renderBlock(AllBlocks.PULLEY_MAGNET.getDefaultState()); + return CreateClient.BUFFER_CACHE.renderBlock(AllBlocks.PULLEY_MAGNET.getDefaultState()); } @Override @@ -57,7 +57,7 @@ public class PulleyRenderer extends AbstractPulleyRenderer { if (tile.movedContraption != null) { AbstractContraptionEntity e = tile.movedContraption; PulleyContraption c = (PulleyContraption) tile.movedContraption.getContraption(); - double entityPos = MathHelper.lerp(partialTicks, e.lastTickPosY, e.getY()); + double entityPos = MathHelper.lerp(partialTicks, e.yOld, e.getY()); offset = (float) -(entityPos - c.anchor.getY() - c.initialOffset); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java index 075d08335..5af548f7c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java @@ -2,7 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pu import com.simibubi.create.AllBlocks; 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.ContraptionCollider; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.piston.LinearActuatorTileEntity; @@ -35,14 +35,14 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { @Override public AxisAlignedBB makeRenderBoundingBox() { - return super.makeRenderBoundingBox().expand(0, -offset, 0); + return super.makeRenderBoundingBox().expandTowards(0, -offset, 0); } @Override - public double getMaxRenderDistanceSquared() { - return super.getMaxRenderDistanceSquared() + offset * offset; + public double getViewDistance() { + return super.getViewDistance() + offset * offset; } - + @Override public void tick() { super.tick(); @@ -52,7 +52,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { @Override protected void assemble() throws AssemblyException { - if (!(world.getBlockState(pos) + if (!(level.getBlockState(worldPosition) .getBlock() instanceof PulleyBlock)) return; if (speed == 0) @@ -60,8 +60,8 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { int maxLength = AllConfigs.SERVER.kinetics.maxRopeLength.get(); int i = 1; while (i <= maxLength) { - BlockPos ropePos = pos.down(i); - BlockState ropeState = world.getBlockState(ropePos); + BlockPos ropePos = worldPosition.below(i); + BlockState ropeState = level.getBlockState(ropePos); if (!AllBlocks.ROPE.has(ropeState) && !AllBlocks.PULLEY_MAGNET.has(ropeState)) { break; } @@ -74,15 +74,15 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { return; // Collect Construct - if (!world.isRemote) { - BlockPos anchor = pos.down(MathHelper.floor(offset + 1)); + if (!level.isClientSide) { + BlockPos anchor = worldPosition.below(MathHelper.floor(offset + 1)); initialOffset = MathHelper.floor(offset); PulleyContraption contraption = new PulleyContraption(initialOffset); - boolean canAssembleStructure = contraption.assemble(world, anchor); + boolean canAssembleStructure = contraption.assemble(level, anchor); if (canAssembleStructure) { Direction movementDirection = getSpeed() > 0 ? Direction.DOWN : Direction.UP; - if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection), + if (ContraptionCollider.isCollidingWithWorld(level, contraption, anchor.relative(movementDirection), movementDirection)) canAssembleStructure = false; } @@ -91,21 +91,21 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { return; for (i = ((int) offset); i > 0; i--) { - BlockPos offset = pos.down(i); - BlockState oldState = world.getBlockState(offset); - if (oldState.getBlock() instanceof IWaterLoggable && oldState.contains(BlockStateProperties.WATERLOGGED) - && oldState.get(BlockStateProperties.WATERLOGGED)) { - world.setBlockState(offset, Blocks.WATER.getDefaultState(), 66); + BlockPos offset = worldPosition.below(i); + BlockState oldState = level.getBlockState(offset); + if (oldState.getBlock() instanceof IWaterLoggable && oldState.hasProperty(BlockStateProperties.WATERLOGGED) + && oldState.getValue(BlockStateProperties.WATERLOGGED)) { + level.setBlock(offset, Blocks.WATER.defaultBlockState(), 66); continue; } - world.setBlockState(offset, Blocks.AIR.getDefaultState(), 66); + level.setBlock(offset, Blocks.AIR.defaultBlockState(), 66); } if (!contraption.getBlocks().isEmpty()) { - contraption.removeBlocksFromWorld(world, BlockPos.ZERO); - movedContraption = ControlledContraptionEntity.create(world, this, contraption); - movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); - world.addEntity(movedContraption); + contraption.removeBlocksFromWorld(level, BlockPos.ZERO); + movedContraption = ControlledContraptionEntity.create(level, this, contraption); + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + level.addFreshEntity(movedContraption); forceMove = true; } } @@ -123,33 +123,33 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { if (movedContraption != null) applyContraptionPosition(); - if (!world.isRemote) { - if (!removed) { + if (!level.isClientSide) { + if (!remove) { if (offset > 0) { - BlockPos magnetPos = pos.down((int) offset); - FluidState ifluidstate = world.getFluidState(magnetPos); - world.destroyBlock(magnetPos, world.getBlockState(magnetPos) - .getCollisionShape(world, magnetPos) + BlockPos magnetPos = worldPosition.below((int) offset); + FluidState ifluidstate = level.getFluidState(magnetPos); + level.destroyBlock(magnetPos, level.getBlockState(magnetPos) + .getCollisionShape(level, magnetPos) .isEmpty()); - world.setBlockState(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState() - .with(BlockStateProperties.WATERLOGGED, - Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)), + level.setBlock(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState() + .setValue(BlockStateProperties.WATERLOGGED, + Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)), 66); } boolean[] waterlog = new boolean[(int) offset]; for (int i = 1; i <= ((int) offset) - 1; i++) { - BlockPos ropePos = pos.down(i); - FluidState ifluidstate = world.getFluidState(ropePos); - waterlog[i] = ifluidstate.getFluid() == Fluids.WATER; - world.destroyBlock(ropePos, world.getBlockState(ropePos) - .getCollisionShape(world, ropePos) + BlockPos ropePos = worldPosition.below(i); + FluidState ifluidstate = level.getFluidState(ropePos); + waterlog[i] = ifluidstate.getType() == Fluids.WATER; + level.destroyBlock(ropePos, level.getBlockState(ropePos) + .getCollisionShape(level, ropePos) .isEmpty()); } for (int i = 1; i <= ((int) offset) - 1; i++) - world.setBlockState(pos.down(i), AllBlocks.ROPE.getDefaultState() - .with(BlockStateProperties.WATERLOGGED, waterlog[i]), 66); + level.setBlock(worldPosition.below(i), AllBlocks.ROPE.getDefaultState() + .setValue(BlockStateProperties.WATERLOGGED, waterlog[i]), 66); } if (movedContraption != null) @@ -168,7 +168,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { protected Vector3d toPosition(float offset) { if (movedContraption.getContraption() instanceof PulleyContraption) { PulleyContraption contraption = (PulleyContraption) movedContraption.getContraption(); - return Vector3d.of(contraption.anchor).add(0, contraption.initialOffset - offset, 0); + return Vector3d.atLowerCornerOf(contraption.anchor).add(0, contraption.initialOffset - offset, 0); } return Vector3d.ZERO; @@ -177,18 +177,18 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { @Override protected void visitNewPosition() { super.visitNewPosition(); - if (world.isRemote) + if (level.isClientSide) return; if (movedContraption != null) return; if (getSpeed() <= 0) return; - BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1); - BlockState state = world.getBlockState(posBelow); - if (!BlockMovementTraits.movementNecessary(state, world, posBelow)) + BlockPos posBelow = worldPosition.below((int) (offset + getMovementSpeed()) + 1); + BlockState state = level.getBlockState(posBelow); + if (!BlockMovementChecks.isMovementNecessary(state, level, posBelow)) return; - if (BlockMovementTraits.isBrittle(state)) + if (BlockMovementChecks.isBrittle(state)) return; disassemble(); @@ -200,7 +200,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { initialOffset = compound.getInt("InitialOffset"); super.fromTag(state, compound, clientPacket); } - + @Override public void write(CompoundNBT compound, boolean clientPacket) { compound.putInt("InitialOffset", initialOffset); @@ -209,7 +209,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { @Override protected int getExtensionRange() { - return Math.max(0, Math.min(AllConfigs.SERVER.kinetics.maxRopeLength.get(), pos.getY() - 1)); + return Math.max(0, Math.min(AllConfigs.SERVER.kinetics.maxRopeLength.get(), worldPosition.getY() - 1)); } @Override @@ -234,13 +234,13 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { boolean moving = running && (movedContraption == null || !movedContraption.isStalled()); return super.getInterpolatedOffset(moving ? partialTicks : 0.5f); } - + public void animateOffset(float forcedOffset) { offset = forcedOffset; } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return false; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/RopePulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/RopePulleyInstance.java index a3bf2dd82..a832532d2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/RopePulleyInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/RopePulleyInstance.java @@ -1,38 +1,38 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.materials.OrientedData; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; -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 RopePulleyInstance extends AbstractPulleyInstance { final PulleyTileEntity tile = (PulleyTileEntity) super.tile; - public RopePulleyInstance(InstancedTileRenderer 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..ab49754c5 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.material.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.getBrightness(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/ContraptionGroup.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionGroup.java new file mode 100644 index 000000000..582694840 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionGroup.java @@ -0,0 +1,25 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.jozufozu.flywheel.backend.material.MaterialGroup; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.backend.state.IRenderState; + +public class ContraptionGroup

extends MaterialGroup

{ + + private final RenderedContraption contraption; + + public ContraptionGroup(RenderedContraption contraption, MaterialManager

owner, IRenderState state) { + super(owner, state); + + this.contraption = contraption; + } + + @Override + public void setup(P program) { + contraption.setup(program); + } + + public static

MaterialManager.GroupFactory

forContraption(RenderedContraption c) { + return (materialManager, state) -> new ContraptionGroup<>(c, materialManager, state); + } +} 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..261aca5d5 --- /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.tile.TileInstanceManager; +import com.jozufozu.flywheel.backend.material.MaterialManager; +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/ContraptionMatrices.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java new file mode 100644 index 000000000..733ff004d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java @@ -0,0 +1,107 @@ +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.Matrix4f; + +/** + *

+ * ContraptionMatrices must be cleared and setup per-contraption per-frame + *

+ */ +public class ContraptionMatrices { + + private final MatrixStack modelViewProjection = new MatrixStack(); + private final MatrixStack viewProjection = new MatrixStack(); + private final MatrixStack model = new MatrixStack(); + private final Matrix4f world = new Matrix4f(); + private final Matrix4f light = new Matrix4f(); + + private boolean ready; + + public ContraptionMatrices() { + world.setIdentity(); + light.setIdentity(); + } + + public void setup(MatrixStack viewProjection, AbstractContraptionEntity entity) { + float partialTicks = AnimationTickHolder.getPartialTicks(); + + this.viewProjection.pushPose(); + transform(this.viewProjection, viewProjection); + model.pushPose(); + entity.doLocalTransforms(partialTicks, new MatrixStack[] { model }); + + modelViewProjection.pushPose(); + transform(modelViewProjection, viewProjection); + transform(modelViewProjection, model); + + translateToEntity(world, entity, partialTicks); + + light.set(world); + light.multiply(model + .last().pose()); + + ready = true; + } + + public void clear() { + clearStack(modelViewProjection); + clearStack(viewProjection); + clearStack(model); + world.setIdentity(); + light.setIdentity(); + ready = false; + } + + public MatrixStack getModelViewProjection() { + return modelViewProjection; + } + + public MatrixStack getViewProjection() { + return viewProjection; + } + + public MatrixStack getModel() { + return model; + } + + public Matrix4f getWorld() { + return world; + } + + public Matrix4f getLight() { + return light; + } + + public boolean isReady() { + return ready; + } + + public static void transform(MatrixStack ms, MatrixStack transform) { + ms.last().pose() + .multiply(transform.last() + .pose()); + ms.last().normal() + .mul(transform.last() + .normal()); + } + + public static void translateToEntity(Matrix4f matrix, Entity entity, float partialTicks) { + double x = MathHelper.lerp(partialTicks, entity.xOld, entity.getX()); + double y = MathHelper.lerp(partialTicks, entity.yOld, entity.getY()); + double z = MathHelper.lerp(partialTicks, entity.zOld, entity.getZ()); + matrix.setTranslation((float) x, (float) y, (float) z); + } + + public static void clearStack(MatrixStack ms) { + while (!ms.clear()) { + ms.popPose(); + } + } + +} 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..bb906a32f 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,169 +1,128 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; -import java.util.List; -import java.util.Random; +import java.util.Collection; 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.core.model.ModelUtil; +import com.jozufozu.flywheel.event.BeginFrameEvent; +import com.jozufozu.flywheel.event.GatherContextEvent; +import com.jozufozu.flywheel.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.event.RenderLayerEvent; +import com.jozufozu.flywheel.util.WorldAttached; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllMovementBehaviours; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.foundation.render.AllProgramSpecs; -import com.simibubi.create.foundation.render.Compartment; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.SuperByteBufferCache; import com.simibubi.create.foundation.render.TileEntityRenderHelper; -import com.simibubi.create.foundation.render.backend.Backend; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import net.minecraft.block.BlockRenderType; -import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.BlockModelRenderer; -import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.model.IBakedModel; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.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.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +@OnlyIn(Dist.CLIENT) +@Mod.EventBusSubscriber(Dist.CLIENT) public class ContraptionRenderDispatcher { - public static final Int2ObjectMap renderers = new Int2ObjectOpenHashMap<>(); - public static final Compartment> CONTRAPTION = new Compartment<>(); - protected static PlacementSimulationWorld renderWorld; - public static void tick() { - if (Minecraft.getInstance().isGamePaused()) return; + private static WorldAttached> WORLDS = new WorldAttached<>(SBBContraptionManager::new); - for (RenderedContraption contraption : renderers.values()) { - contraption.getLighter().tick(contraption); + /** + * Reset a contraption's renderer. + * @param contraption The contraption to invalidate. + * @return true if there was a renderer associated with the given contraption. + */ + public static boolean invalidate(Contraption contraption) { + World level = contraption.entity.level; - contraption.kinetics.tick(); - } + return WORLDS.get(level).invalidate(contraption); } - public static void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { - for (RenderedContraption renderer : renderers.values()) { - renderer.beginFrame(info, camX, camY, camZ); - } + public static void tick(World world) { + if (Minecraft.getInstance().isPaused()) return; + + WORLDS.get(world).tick(); } - public static void renderLayer(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { - removeDeadContraptions(); - - if (renderers.isEmpty()) return; - - layer.startDrawing(); - GL11.glEnable(GL13.GL_TEXTURE_3D); - GL13.glActiveTexture(GL40.GL_TEXTURE4); // the shaders expect light volumes to be in texture 4 - - if (Backend.canUseVBOs()) { - ContraptionProgram structureShader = Backend.getProgram(AllProgramSpecs.C_STRUCTURE); - structureShader.bind(viewProjection, camX, camY, camZ, FastRenderDispatcher.getDebugMode()); - for (RenderedContraption renderer : renderers.values()) { - renderer.doRenderLayer(layer, structureShader); - } - } - - if (Backend.canUseInstancing()) { - for (RenderedContraption renderer : renderers.values()) { - renderer.kinetics.render(layer, viewProjection, camX, camY, camZ, renderer::setup); - renderer.teardown(); - } - } - - layer.endDrawing(); - GL11.glDisable(GL13.GL_TEXTURE_3D); - GL13.glActiveTexture(GL40.GL_TEXTURE0); + @SubscribeEvent + public static void beginFrame(BeginFrameEvent event) { + WORLDS.get(event.getWorld()).beginFrame(event); } - private static RenderedContraption getRenderer(World world, Contraption c) { - int entityId = c.entity.getEntityId(); - RenderedContraption contraption = renderers.get(entityId); - - if (contraption == null) { - contraption = new RenderedContraption(world, c); - renderers.put(entityId, contraption); - } - - return contraption; + @SubscribeEvent + public static void renderLayer(RenderLayerEvent event) { + WORLDS.get(event.getWorld()).renderLayer(event); } - 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); - } + @SubscribeEvent + public static void onRendererReload(ReloadRenderersEvent event) { + reset(); } - public static void renderStructure(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - SuperByteBufferCache bufferCache = CreateClient.bufferCache; - List blockLayers = RenderType.getBlockLayers(); - - buffer.getBuffer(RenderType.getSolid()); - for (int i = 0; i < blockLayers.size(); i++) { - RenderType layer = blockLayers.get(i); - Pair key = Pair.of(c, i); - SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(c, layer)); - if (contraptionBuffer.isEmpty()) - continue; - Matrix4f model = msLocal.peek() - .getModel(); - contraptionBuffer.light(model) - .renderInto(ms, buffer.getBuffer(layer)); - } + public static void gatherContext(GatherContextEvent e) { + reset(); } - public static void renderDynamic(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - renderTileEntities(world, c, ms, msLocal, buffer); - if (buffer instanceof IRenderTypeBuffer.Impl) - ((IRenderTypeBuffer.Impl) buffer).draw(); - renderActors(world, c, ms, msLocal, buffer); + public static void renderFromEntity(AbstractContraptionEntity entity, Contraption contraption, IRenderTypeBuffer buffers) { + World world = entity.level; + + ContraptionRenderInfo renderInfo = WORLDS.get(world) + .getRenderInfo(contraption); + ContraptionMatrices matrices = renderInfo.getMatrices(); + + // something went wrong with the other rendering + if (!matrices.isReady()) return; + + PlacementSimulationWorld renderWorld = renderInfo.renderWorld; + + renderTileEntities(world, renderWorld, contraption, matrices, buffers); + + if (buffers instanceof IRenderTypeBuffer.Impl) + ((IRenderTypeBuffer.Impl) buffers).endBatch(); + + renderActors(world, renderWorld, contraption, matrices, buffers); } - 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); + public static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { + PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); - renderWorld = renderer.renderWorld; - } - TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer); + renderWorld.setTileEntities(c.presentTileEntities.values()); + for (Template.BlockInfo info : c.getBlocks() + .values()) + // Skip individual lighting updates to prevent lag with large contraptions + renderWorld.setBlock(info.pos, info.state, 128); + + renderWorld.updateLightSources(); + renderWorld.lighter.runUpdates(Integer.MAX_VALUE, false, false); + + return renderWorld; } - protected static void renderActors(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; + public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, + matrices.getModelViewProjection(), matrices.getLight(), buffer); + } + + 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,128 +130,54 @@ 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.getModel(); + m.pushPose(); + MatrixTransformStack.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.popPose(); } } - private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) { - BufferBuilder builder = buildStructure(c, layer); + public static SuperByteBuffer buildStructureBuffer(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + Collection values = c.getBlocks() + .values(); + BufferBuilder builder = ModelUtil.getBufferBuilderFromTemplate(renderWorld, layer, values); 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 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; - ForgeHooksClient.setRenderLayer(layer); - MatrixStack ms = new MatrixStack(); - BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRendererDispatcher(); - BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); - Random random = new Random(); - BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); - builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - renderWorld.setTileEntities(c.presentTileEntities.values()); + for (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.set(lx + xOffset, ly + yOffset, lz + zOffset); + block += world.getBrightness(LightType.BLOCK, pos) / 8f; + sky += world.getBrightness(LightType.SKY, pos) / 8f; + } - for (Template.BlockInfo info : c.getBlocks() - .values()) - renderWorld.setBlockState(info.pos, info.state); + return LightTexture.pack((int) block, (int) sky); + } - for (Template.BlockInfo info : c.getBlocks() - .values()) { - BlockState state = info.state; + public static int getContraptionWorldLight(MovementContext context, PlacementSimulationWorld renderWorld) { + return WorldRenderer.getLightColor(renderWorld, context.localPos); + } - if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) - continue; - if (!RenderTypeLookup.canRenderInLayer(state, layer)) - continue; + public static void reset() { + WORLDS.empty(ContraptionRenderManager::delete); - 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); + if (Backend.getInstance().available()) { + WORLDS = new WorldAttached<>(FlwContraptionManager::new); } else { - return -1; + WORLDS = new WorldAttached<>(SBBContraptionManager::new); } } - - public static void invalidateAll() { - for (RenderedContraption renderer : renderers.values()) { - renderer.invalidate(); - } - - renderers.clear(); - } - - public static void removeDeadContraptions() { - renderers.values().removeIf(renderer -> { - if (renderer.isDead()) { - renderer.invalidate(); - return true; - } - return false; - }); - } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderInfo.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderInfo.java new file mode 100644 index 000000000..861db5c41 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderInfo.java @@ -0,0 +1,75 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.jozufozu.flywheel.event.BeginFrameEvent; +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.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; + +import net.minecraft.util.math.MathHelper; + +public class ContraptionRenderInfo { + public final Contraption contraption; + public final PlacementSimulationWorld renderWorld; + + private final ContraptionMatrices matrices = new ContraptionMatrices(); + private boolean visible; + + public ContraptionRenderInfo(Contraption contraption, PlacementSimulationWorld renderWorld) { + this.contraption = contraption; + this.renderWorld = renderWorld; + } + + public int getEntityId() { + return contraption.entity.getId(); + } + + public boolean isDead() { + return !contraption.entity.isAlive(); + } + + public void beginFrame(BeginFrameEvent event) { + matrices.clear(); + + AbstractContraptionEntity entity = contraption.entity; + + visible = event.getClippingHelper().isVisible(entity.getBoundingBoxForCulling().inflate(2)); + } + + public boolean isVisible() { + return visible && contraption.entity.isAlive(); + } + + /** + * Need to call this during RenderLayerEvent. + */ + public void setupMatrices(MatrixStack viewProjection, double camX, double camY, double camZ) { + if (!matrices.isReady()) { + AbstractContraptionEntity entity = contraption.entity; + + viewProjection.pushPose(); + + double x = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.xOld, entity.getX()) - camX; + double y = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.yOld, entity.getY()) - camY; + double z = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.zOld, entity.getZ()) - camZ; + + viewProjection.translate(x, y, z); + + matrices.setup(viewProjection, entity); + + viewProjection.popPose(); + } + } + + /** + * If #setupMatrices is called correctly, the returned matrices will be ready + */ + public ContraptionMatrices getMatrices() { + return matrices; + } + + public void invalidate() { + + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderManager.java new file mode 100644 index 000000000..5bc3abed3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderManager.java @@ -0,0 +1,115 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import java.lang.ref.Reference; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import com.jozufozu.flywheel.event.BeginFrameEvent; +import com.jozufozu.flywheel.event.RenderLayerEvent; +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.ContraptionHandler; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; + +public abstract class ContraptionRenderManager { + protected final World world; + + private int removalTimer; + + protected final Int2ObjectMap renderInfos = new Int2ObjectOpenHashMap<>(); + protected final List visible = new ObjectArrayList<>(); + + public ContraptionRenderManager(IWorld world) { + this.world = (World) world; + } + + public boolean invalidate(Contraption contraption) { + int entityId = contraption.entity.getId(); + + C removed = renderInfos.remove(entityId); + + if (removed != null) { + removed.invalidate(); + visible.remove(removed); + return true; + } + + return false; + } + + public void renderLayer(RenderLayerEvent event) { + for (C c : visible) { + c.setupMatrices(event.stack, event.camX, event.camY, event.camZ); + } + } + + protected abstract C create(Contraption c); + + public void tick() { + removalTimer++; + if (removalTimer >= 20) { + removeDeadRenderers(); + removalTimer = 0; + } + + ContraptionHandler.loadedContraptions.get(world) + .values() + .stream() + .map(Reference::get) + .filter(Objects::nonNull) + .map(AbstractContraptionEntity::getContraption) + .forEach(this::getRenderInfo); + } + + public void beginFrame(BeginFrameEvent event) { + + renderInfos.int2ObjectEntrySet() + .stream() + .map(Map.Entry::getValue) + .forEach(renderInfo -> renderInfo.beginFrame(event)); + + collectVisible(); + } + + protected void collectVisible() { + visible.clear(); + renderInfos.int2ObjectEntrySet() + .stream() + .map(Map.Entry::getValue) + .filter(ContraptionRenderInfo::isVisible) + .forEach(visible::add); + } + + public C getRenderInfo(Contraption c) { + int entityId = c.entity.getId(); + C renderInfo = renderInfos.get(entityId); + + if (renderInfo == null) { + renderInfo = create(c); + renderInfos.put(entityId, renderInfo); + } + + return renderInfo; + } + + public void delete() { + for (C renderer : renderInfos.values()) { + renderer.invalidate(); + } + renderInfos.clear(); + } + + /** + * Remove all render infos associated with dead/removed contraptions. + */ + public void removeDeadRenderers() { + renderInfos.values().removeIf(ContraptionRenderInfo::isDead); + } + +} 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/content/contraptions/components/structureMovement/render/FlwContraptionManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/FlwContraptionManager.java new file mode 100644 index 000000000..05485d3ad --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/FlwContraptionManager.java @@ -0,0 +1,97 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import static org.lwjgl.opengl.GL11.glBindTexture; +import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; +import com.jozufozu.flywheel.backend.state.RenderLayer; +import com.jozufozu.flywheel.event.RenderLayerEvent; +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.render.AllProgramSpecs; +import com.simibubi.create.foundation.render.CreateContexts; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.world.IWorld; + +public class FlwContraptionManager extends ContraptionRenderManager { + + public FlwContraptionManager(IWorld world) { + super(world); + } + + @Override + public void tick() { + super.tick(); + + for (RenderedContraption contraption : visible) { + ContraptionLighter lighter = contraption.getLighter(); + if (lighter.getBounds().volume() < AllConfigs.CLIENT.maxContraptionLightVolume.get()) + lighter.tick(contraption); + + contraption.kinetics.tick(); + } + } + + @Override + public void renderLayer(RenderLayerEvent event) { + super.renderLayer(event); + + if (visible.isEmpty()) return; + + RenderType layer = event.getType(); + + layer.setupRenderState(); + GlTextureUnit.T4.makeActive(); // the shaders expect light volumes to be in texture 4 + + ContraptionProgram structureShader = CreateContexts.STRUCTURE.getProgram(AllProgramSpecs.STRUCTURE); + + structureShader.bind(); + structureShader.uploadViewProjection(event.viewProjection); + structureShader.uploadCameraPos(event.camX, event.camY, event.camZ); + + for (RenderedContraption renderedContraption : visible) { + renderedContraption.doRenderLayer(layer, structureShader); + } + + if (Backend.getInstance().canUseInstancing()) { + RenderLayer renderLayer = event.getLayer(); + if (renderLayer != null) { + for (RenderedContraption renderer : visible) { + renderer.materialManager.render(renderLayer, event.viewProjection, event.camX, event.camY, event.camZ); + } + } + } + + // clear the light volume state + GlTextureUnit.T4.makeActive(); + glBindTexture(GL_TEXTURE_3D, 0); + + layer.clearRenderState(); + GlTextureUnit.T0.makeActive(); + } + + @Override + protected RenderedContraption create(Contraption c) { + PlacementSimulationWorld renderWorld = ContraptionRenderDispatcher.setupRenderWorld(world, c); + return new RenderedContraption(c, renderWorld); + } + + @Override + public void removeDeadRenderers() { + boolean removed = renderInfos.values() + .removeIf(renderer -> { + if (renderer.isDead()) { + renderer.invalidate(); + return true; + } + return false; + }); + + // we use visible in #tick() so we have to re-evaluate it if any were removed + if (removed) collectVisible(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java new file mode 100644 index 000000000..b63caab74 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java @@ -0,0 +1,29 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; + +public class LightVolumeDebugger { + public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { +// ContraptionRenderDispatcher.RENDERERS.values() +// .stream() +// .flatMap(r -> { +// GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume(); +// GridAlignedBB sample = r.getLighter().lightVolume.getSampleVolume(); +// +// ArrayList> pairs = new ArrayList<>(2); +// +// pairs.add(Pair.of(texture, 0xFFFFFF)); +// pairs.add(Pair.of(sample, 0xFFFF00)); +// +// return pairs.stream(); +// }) +// .map(pair -> { +// AABBOutline outline = new AABBOutline(GridAlignedBB.toAABB(pair.getFirst())); +// +// outline.getParams().colored(pair.getSecond()); +// return outline; +// }) +// .forEach(outline -> outline.render(ms, buffer, AnimationTickHolder.getPartialTicks())); + } +} 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..e088b3647 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 @@ -3,219 +3,168 @@ package com.simibubi.create.content.contraptions.components.structureMovement.re import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Random; - -import org.lwjgl.opengl.GL11; +import java.util.Map; +import java.util.function.Supplier; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.backend.model.ArrayModelRenderer; +import com.jozufozu.flywheel.backend.model.ModelRenderer; +import com.jozufozu.flywheel.core.model.IModel; +import com.jozufozu.flywheel.core.model.WorldModel; +import com.jozufozu.flywheel.event.BeginFrameEvent; +import com.jozufozu.flywheel.light.GridAlignedBB; 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.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.util.math.vector.Vector3d; 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 ContraptionRenderInfo { - 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 final Matrix4f modelViewPartial = new Matrix4f(); + private boolean modelViewPartialReady; + private AxisAlignedBB lightBox; - private Matrix4f model; - private AxisAlignedBB lightBox; + public RenderedContraption(Contraption contraption, PlacementSimulationWorld renderWorld) { + super(contraption, renderWorld); + this.lighter = contraption.makeLighter(); + this.materialManager = MaterialManager.builder(CreateContexts.CWORLD) + .setGroupFactory(ContraptionGroup.forContraption(this)) + .setIgnoreOriginCoordinate(true) + .build(); + 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(BeginFrameEvent event) { + super.beginFrame(event); - public ContraptionLighter getLighter() { - return lighter; - } + modelViewPartial.setIdentity(); + modelViewPartialReady = false; - public void doRenderLayer(RenderType layer, ContraptionProgram shader) { - ContraptionModel structure = renderLayers.get(layer); - if (structure != null) { - setup(shader); - structure.render(); - teardown(); - } - } + if (!isVisible()) return; - public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { - kinetics.beginFrame(info, camX, camY, camZ); + kinetics.beginFrame(event.getInfo()); - AbstractContraptionEntity entity = contraption.entity; - float pt = AnimationTickHolder.getPartialTicks(); + Vector3d cameraPos = event.getCameraPos(); - MatrixStack stack = new MatrixStack(); + lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume()) + .move(-cameraPos.x, -cameraPos.y, -cameraPos.z); + } - 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); + @Override + public void setupMatrices(MatrixStack viewProjection, double camX, double camY, double camZ) { + super.setupMatrices(viewProjection, camX, camY, camZ); - entity.doLocalTransforms(pt, new MatrixStack[]{ stack }); + if (!modelViewPartialReady) { + setupModelViewPartial(modelViewPartial, getMatrices().getModel().last().pose(), contraption.entity, camX, camY, camZ, AnimationTickHolder.getPartialTicks()); + modelViewPartialReady = true; + } + } - model = stack.peek().getModel(); + void setup(ContraptionProgram shader) { + if (!modelViewPartialReady || lightBox == null) return; + shader.bind(modelViewPartial, lightBox); + lighter.lightVolume.bind(); + } - AxisAlignedBB lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume()); + public 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.chunkBufferLayers(); - kinetics.invalidate(); - } + for (RenderType layer : blockLayers) { + Supplier layerModel = () -> new WorldModel(renderWorld, layer, contraption.getBlocks().values()); - private void buildLayers() { - for (ContraptionModel buffer : renderLayers.values()) { - buffer.delete(); - } + ModelRenderer renderer; + if (Backend.getInstance().compat.vertexArrayObjectsSupported()) + renderer = new ArrayModelRenderer(layerModel); + else + renderer = new ModelRenderer(layerModel); - renderLayers.clear(); + renderLayers.put(layer, renderer); + } + } - List blockLayers = RenderType.getBlockLayers(); + private void buildInstancedTiles() { + Collection tileEntities = contraption.maybeInstancedTileEntities; + if (!tileEntities.isEmpty()) { + for (TileEntity te : tileEntities) { + if (InstancedRenderRegistry.getInstance() + .canInstance(te.getType())) { + World world = te.getLevel(); + BlockPos pos = te.getBlockPos(); + te.setLevelAndPosition(renderWorld, pos); + kinetics.add(te); + te.setLevelAndPosition(world, pos); + } + } + } + } - for (RenderType layer : blockLayers) { - renderLayers.put(layer, buildStructureModel(renderWorld, contraption, layer)); - } - } + private void buildActors() { + contraption.getActors().forEach(kinetics::createActor); + } - 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); - } - } - } - } + public static void setupModelViewPartial(Matrix4f matrix, Matrix4f modelMatrix, AbstractContraptionEntity entity, double camX, double camY, double camZ, float pt) { + float x = (float) (MathHelper.lerp(pt, entity.xOld, entity.getX()) - camX); + float y = (float) (MathHelper.lerp(pt, entity.yOld, entity.getY()) - camY); + float z = (float) (MathHelper.lerp(pt, entity.zOld, entity.getZ()) - camZ); + matrix.setTranslation(x, y, z); + matrix.multiply(modelMatrix); + } - private void buildActors() { - contraption.getActors().forEach(kinetics::createActor); - } - - private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { - BufferBuilder builder = buildStructure(renderWorld, c, layer); - return new ContraptionModel(builder); - } - - private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { - PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); - - renderWorld.setTileEntities(c.presentTileEntities.values()); - - for (Template.BlockInfo info : c.getBlocks() - .values()) - renderWorld.setBlockState(info.pos, info.state); - - WorldLightManager lighter = renderWorld.lighter; - - renderWorld.chunkProvider.getLightSources().forEach((pos) -> lighter.func_215573_a(pos, renderWorld.getLightValue(pos))); - - lighter.tick(Integer.MAX_VALUE, true, false); - - return renderWorld; - } - - private static BufferBuilder buildStructure(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { - - ForgeHooksClient.setRenderLayer(layer); - MatrixStack ms = new MatrixStack(); - BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRendererDispatcher(); - BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); - Random random = new Random(); - BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); - builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - - for (Template.BlockInfo info : c.getBlocks() - .values()) { - BlockState state = info.state; - - if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) - continue; - if (!RenderTypeLookup.canRenderInLayer(state, layer)) - continue; - - IBakedModel originalModel = dispatcher.getModelForState(state); - ms.push(); - ms.translate(info.pos.getX(), info.pos.getY(), info.pos.getZ()); - blockRenderer.renderModel(renderWorld, originalModel, state, info.pos, ms, builder, true, random, 42, - OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); - ms.pop(); - } - - builder.finishDrawing(); - return builder; - } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/SBBContraptionManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/SBBContraptionManager.java new file mode 100644 index 000000000..0fb8e5536 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/SBBContraptionManager.java @@ -0,0 +1,61 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import static com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher.buildStructureBuffer; + +import com.jozufozu.flywheel.event.RenderLayerEvent; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.foundation.render.Compartment; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.world.IWorld; + +public class SBBContraptionManager extends ContraptionRenderManager { + public static final Compartment> CONTRAPTION = new Compartment<>(); + + public SBBContraptionManager(IWorld world) { + super(world); + } + + @Override + public void renderLayer(RenderLayerEvent event) { + super.renderLayer(event); + visible.forEach(info -> renderContraptionLayerSBB(event, info)); + } + + @Override + public boolean invalidate(Contraption contraption) { + for (RenderType chunkBufferLayer : RenderType.chunkBufferLayers()) { + CreateClient.BUFFER_CACHE.invalidate(CONTRAPTION, Pair.of(contraption, chunkBufferLayer)); + } + return super.invalidate(contraption); + } + + @Override + protected ContraptionRenderInfo create(Contraption c) { + PlacementSimulationWorld renderWorld = ContraptionRenderDispatcher.setupRenderWorld(world, c); + return new ContraptionRenderInfo(c, renderWorld); + } + + private void renderContraptionLayerSBB(RenderLayerEvent event, ContraptionRenderInfo renderInfo) { + RenderType layer = event.getType(); + + if (!renderInfo.isVisible()) return; + + SuperByteBuffer contraptionBuffer = CreateClient.BUFFER_CACHE.get(CONTRAPTION, Pair.of(renderInfo.contraption, layer), () -> buildStructureBuffer(renderInfo.renderWorld, renderInfo.contraption, layer)); + + if (!contraptionBuffer.isEmpty()) { + ContraptionMatrices matrices = renderInfo.getMatrices(); + + contraptionBuffer.transform(matrices.getModel()) + .light(matrices.getWorld()) + .hybridLight() + .renderInto(matrices.getViewProjection(), event.buffers.bufferSource() + .getBuffer(layer)); + } + + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/package-info.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/package-info.java new file mode 100644 index 000000000..c6a4ae555 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import javax.annotation.ParametersAreNonnullByDefault; + +import mcp.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ClientMotionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ClientMotionPacket.java index 1a4c7307c..9e2487763 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ClientMotionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ClientMotionPacket.java @@ -46,15 +46,15 @@ public class ClientMotionPacket extends SimplePacketBase { .getSender(); if (sender == null) return; - sender.setMotion(motion); + sender.setDeltaMovement(motion); sender.setOnGround(onGround); if (onGround) { - sender.handleFallDamage(sender.fallDistance, 1); + sender.causeFallDamage(sender.fallDistance, 1); sender.fallDistance = 0; - sender.connection.floatingTickCount = 0; + sender.connection.aboveGroundTickCount = 0; } AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> sender), - new LimbSwingUpdatePacket(sender.getEntityId(), sender.getPositionVec(), limbSwing)); + new LimbSwingUpdatePacket(sender.getId(), sender.position(), limbSwing)); }); context.get() .setPacketHandled(true); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionFluidPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionFluidPacket.java index bc0d308bd..fd648bb5d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionFluidPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionFluidPacket.java @@ -41,7 +41,7 @@ public class ContraptionFluidPacket extends SimplePacketBase { public void handle(Supplier context) { context.get() .enqueueWork(() -> { - Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityId); + Entity entityByID = Minecraft.getInstance().level.getEntity(entityId); if (!(entityByID instanceof AbstractContraptionEntity)) return; AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java index 1120719d6..9d731d735 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java @@ -24,7 +24,7 @@ public class ContraptionInteractionPacket extends SimplePacketBase { public ContraptionInteractionPacket(AbstractContraptionEntity target, Hand hand, BlockPos localPos, Direction side) { this.interactionHand = hand; this.localPos = localPos; - this.target = target.getEntityId(); + this.target = target.getId(); this.face = side; } @@ -33,7 +33,7 @@ public class ContraptionInteractionPacket extends SimplePacketBase { int handId = buffer.readInt(); interactionHand = handId == -1 ? null : Hand.values()[handId]; localPos = buffer.readBlockPos(); - face = Direction.byIndex(buffer.readShort()); + face = Direction.from3DDataValue(buffer.readShort()); } @Override @@ -41,7 +41,7 @@ public class ContraptionInteractionPacket extends SimplePacketBase { buffer.writeInt(target); buffer.writeInt(interactionHand == null ? -1 : interactionHand.ordinal()); buffer.writeBlockPos(localPos); - buffer.writeShort(face.getIndex()); + buffer.writeShort(face.get3DDataValue()); } @Override @@ -50,20 +50,20 @@ public class ContraptionInteractionPacket extends SimplePacketBase { ServerPlayerEntity sender = context.get().getSender(); if (sender == null) return; - Entity entityByID = sender.getServerWorld().getEntityByID(target); + Entity entityByID = sender.getLevel().getEntity(target); if (!(entityByID instanceof AbstractContraptionEntity)) return; AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get()).getValue() + 10; - if (!sender.canEntityBeSeen(entityByID)) + if (!sender.canSee(entityByID)) d -= 3; d *= d; - if (sender.getDistanceSq(entityByID) > d) { + if (sender.distanceToSqr(entityByID) > d) { // TODO log? return; } if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand)) - sender.swingHand(interactionHand, true); + sender.swing(interactionHand, true); }); context.get().setPacketHandled(true); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionSeatMappingPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionSeatMappingPacket.java index 6d6ce8d8f..b05df0f01 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionSeatMappingPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionSeatMappingPacket.java @@ -28,7 +28,7 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase { mapping = new HashMap<>(); short size = buffer.readShort(); for (int i = 0; i < size; i++) - mapping.put(buffer.readUniqueId(), (int) buffer.readShort()); + mapping.put(buffer.readUUID(), (int) buffer.readShort()); } @Override @@ -36,7 +36,7 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase { buffer.writeInt(entityID); buffer.writeShort(mapping.size()); mapping.forEach((k, v) -> { - buffer.writeUniqueId(k); + buffer.writeUUID(k); buffer.writeShort(v); }); } @@ -45,7 +45,7 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase { public void handle(Supplier context) { context.get() .enqueueWork(() -> { - Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityID); + Entity entityByID = Minecraft.getInstance().level.getEntity(entityID); if (!(entityByID instanceof AbstractContraptionEntity)) return; AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/LimbSwingUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/LimbSwingUpdatePacket.java index c4f1f70a8..454ef81d4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/LimbSwingUpdatePacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/LimbSwingUpdatePacket.java @@ -43,17 +43,17 @@ public class LimbSwingUpdatePacket extends SimplePacketBase { public void handle(Supplier context) { context.get() .enqueueWork(() -> { - ClientWorld world = Minecraft.getInstance().world; + ClientWorld world = Minecraft.getInstance().level; if (world == null) return; - Entity entity = world.getEntityByID(entityId); + Entity entity = world.getEntity(entityId); if (entity == null) return; CompoundNBT data = entity.getPersistentData(); data.putInt("LastOverrideLimbSwingUpdate", 0); data.putFloat("OverrideLimbSwing", limbSwing); - entity.setPositionAndRotationDirect(position.x, position.y, position.z, entity.rotationYaw, - entity.rotationPitch, 2, false); + entity.lerpTo(position.x, position.y, position.z, entity.yRot, + entity.xRot, 2, false); }); context.get() .setPacketHandled(true); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingCreationPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingCreationPacket.java index 795a3e89e..c042219d1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingCreationPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingCreationPacket.java @@ -14,8 +14,8 @@ public class CouplingCreationPacket extends SimplePacketBase { int id1, id2; public CouplingCreationPacket(AbstractMinecartEntity cart1, AbstractMinecartEntity cart2) { - id1 = cart1.getEntityId(); - id2 = cart2.getEntityId(); + id1 = cart1.getId(); + id2 = cart2.getId(); } public CouplingCreationPacket(PacketBuffer buffer) { @@ -36,7 +36,7 @@ public class CouplingCreationPacket extends SimplePacketBase { ServerPlayerEntity sender = context.get() .getSender(); if (sender != null) - CouplingHandler.tryToCoupleCarts(sender, sender.world, id1, id2); + CouplingHandler.tryToCoupleCarts(sender, sender.level, id1, id2); }); context.get() .setPacketHandled(true); 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..924bd4d11 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 @@ -67,8 +67,8 @@ public class CouplingHandler { } public static boolean tryToCoupleCarts(@Nullable PlayerEntity player, World world, int cartId1, int cartId2) { - Entity entity1 = world.getEntityByID(cartId1); - Entity entity2 = world.getEntityByID(cartId2); + Entity entity1 = world.getEntity(cartId1); + Entity entity2 = world.getEntity(cartId2); if (!(entity1 instanceof AbstractMinecartEntity)) return false; @@ -80,8 +80,8 @@ public class CouplingHandler { String noLoops = "no_loops"; String tooFar = "too_far"; - int distanceTo = (int) entity1.getPositionVec() - .distanceTo(entity2.getPositionVec()); + int distanceTo = (int) entity1.position() + .distanceTo(entity2.position()); boolean contraptionCoupling = player == null; if (distanceTo < 2) { @@ -97,8 +97,8 @@ public class CouplingHandler { AbstractMinecartEntity cart1 = (AbstractMinecartEntity) entity1; AbstractMinecartEntity cart2 = (AbstractMinecartEntity) entity2; - UUID mainID = cart1.getUniqueID(); - UUID connectedID = cart2.getUniqueID(); + UUID mainID = cart1.getUUID(); + UUID connectedID = cart2.getUUID(); MinecartController mainController = CapabilityMinecartController.getIfPresent(world, mainID); MinecartController connectedController = CapabilityMinecartController.getIfPresent(world, connectedID); @@ -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; } @@ -146,7 +146,7 @@ public class CouplingHandler { for (Hand hand : Hand.values()) { if (player.isCreative()) break; - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getItemInHand(hand); if (!AllItems.MINECART_COUPLING.isIn(heldItem)) continue; heldItem.shrink(1); @@ -177,7 +177,7 @@ public class CouplingHandler { public static void status(PlayerEntity player, String key) { if (player == null) return; - player.sendStatusMessage(Lang.translate("minecart_coupling." + key), true); + player.displayClientMessage(Lang.translate("minecart_coupling." + key), true); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandlerClient.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandlerClient.java index 00fda4789..d4b34b7c0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandlerClient.java @@ -28,8 +28,8 @@ public class CouplingHandlerClient { return; spawnSelectionParticles(selectedCart.getBoundingBox(), false); ClientPlayerEntity player = Minecraft.getInstance().player; - ItemStack heldItemMainhand = player.getHeldItemMainhand(); - ItemStack heldItemOffhand = player.getHeldItemOffhand(); + ItemStack heldItemMainhand = player.getMainHandItem(); + ItemStack heldItemOffhand = player.getOffhandItem(); if (AllItems.MINECART_COUPLING.isIn(heldItemMainhand) || AllItems.MINECART_COUPLING.isIn(heldItemOffhand)) return; selectedCart = null; @@ -53,14 +53,14 @@ public class CouplingHandlerClient { } private static void spawnSelectionParticles(AxisAlignedBB axisAlignedBB, boolean highlight) { - ClientWorld world = Minecraft.getInstance().world; + ClientWorld world = Minecraft.getInstance().level; Vector3d center = axisAlignedBB.getCenter(); int amount = highlight ? 100 : 2; IParticleData particleData = highlight ? ParticleTypes.END_ROD : new RedstoneParticleData(1, 1, 1, 1); for (int i = 0; i < amount; i++) { Vector3d v = VecHelper.offsetRandomly(Vector3d.ZERO, r, 1); double yOffset = v.y; - v = v.mul(1, 0, 1) + v = v.multiply(1, 0, 1) .normalize() .add(0, yOffset / 8f, 0) .add(center); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java index e16ea5263..24c97dc04 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java @@ -28,7 +28,7 @@ public class CouplingPhysics { float couplingLength = c.getFirst() .getCouplingLength(true); softCollisionStep(world, carts, couplingLength); - if (world.isRemote) + if (world.isClientSide) return; hardCollisionStep(world, carts, couplingLength); } @@ -44,15 +44,15 @@ public class CouplingPhysics { AbstractMinecartEntity cart = carts.get(current); AbstractMinecartEntity otherCart = carts.get(!current); - float stress = (float) (couplingLength - cart.getPositionVec() - .distanceTo(otherCart.getPositionVec())); + float stress = (float) (couplingLength - cart.position() + .distanceTo(otherCart.position())); if (Math.abs(stress) < 1 / 8f) continue; RailShape shape = null; BlockPos railPosition = cart.getCurrentRailPosition(); - BlockState railState = world.getBlockState(railPosition.up()); + BlockState railState = world.getBlockState(railPosition.above()); if (railState.getBlock() instanceof AbstractRailBlock) { AbstractRailBlock block = (AbstractRailBlock) railState.getBlock(); @@ -60,8 +60,8 @@ public class CouplingPhysics { } Vector3d correction = Vector3d.ZERO; - Vector3d pos = cart.getPositionVec(); - Vector3d link = otherCart.getPositionVec() + Vector3d pos = cart.position(); + Vector3d link = otherCart.position() .subtract(pos); float correctionMagnitude = firstLoop ? -stress / 2f : -stress; @@ -83,7 +83,7 @@ public class CouplingPhysics { MinecartSim2020.moveCartAlongTrack(cart, correction, railPosition, railState); else { cart.move(MoverType.SELF, correction); - cart.setMotion(cart.getMotion() + cart.setDeltaMovement(cart.getDeltaMovement() .scale(0.95f)); } firstLoop = false; @@ -95,20 +95,20 @@ public class CouplingPhysics { Couple canAddmotion = carts.map(MinecartSim2020::canAddMotion); // Assuming Minecarts will never move faster than 1 block/tick - Couple motions = carts.map(Entity::getMotion); + Couple motions = carts.map(Entity::getDeltaMovement); motions.replaceWithParams(VecHelper::clamp, Couple.create(1f, 1f)); Couple nextPositions = carts.map(MinecartSim2020::predictNextPositionOf); Couple shapes = carts.mapWithContext((cart, current) -> { AbstractMinecartEntity minecart = cart.getMinecart(); Vector3d vec = nextPositions.get(current); - int x = MathHelper.floor(vec.getX()); - int y = MathHelper.floor(vec.getY()); - int z = MathHelper.floor(vec.getZ()); + int x = MathHelper.floor(vec.x()); + int y = MathHelper.floor(vec.y()); + int z = MathHelper.floor(vec.z()); BlockPos pos = new BlockPos(x, y - 1, z); - if (minecart.world.getBlockState(pos).isIn(BlockTags.RAILS)) pos = pos.down(); + if (minecart.level.getBlockState(pos).is(BlockTags.RAILS)) pos = pos.below(); BlockPos railPosition = pos; - BlockState railState = world.getBlockState(railPosition.up()); + BlockState railState = world.getBlockState(railPosition.above()); if (!(railState.getBlock() instanceof AbstractRailBlock)) return null; AbstractRailBlock block = (AbstractRailBlock) railState.getBlock(); @@ -117,7 +117,7 @@ public class CouplingPhysics { float futureStress = (float) (couplingLength - nextPositions.getFirst() .distanceTo(nextPositions.getSecond())); - if (MathHelper.epsilonEquals(futureStress, 0D)) + if (MathHelper.equal(futureStress, 0D)) return; for (boolean current : Iterate.trueAndFalse) { @@ -147,11 +147,11 @@ public class CouplingPhysics { } motions.replaceWithParams(VecHelper::clamp, maxSpeed); - carts.forEachWithParams(Entity::setMotion, motions); + carts.forEachWithParams(Entity::setDeltaMovement, motions); } public static Vector3d followLinkOnRail(Vector3d link, Vector3d cart, float diffToReduce, Vector3d railAxis) { - double dotProduct = railAxis.dotProduct(link); + double dotProduct = railAxis.dot(link); if (Double.isNaN(dotProduct) || dotProduct == 0 || diffToReduce == 0) return cart; 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..1b8cef08a 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 @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.tr import static net.minecraft.util.math.MathHelper.lerp; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -11,9 +12,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -33,7 +33,7 @@ import net.minecraft.util.math.vector.Vector3f; public class CouplingRenderer { public static void renderAll(MatrixStack ms, IRenderTypeBuffer buffer) { - CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().world, + CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().level, c -> { if (c.getFirst().hasContraptionCoupling(true)) return; @@ -43,29 +43,29 @@ public class CouplingRenderer { public static void tickDebugModeRenders() { if (KineticDebugger.isActive()) - CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().world, CouplingRenderer::doDebugRender); + CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().level, CouplingRenderer::doDebugRender); } public static void renderCoupling(MatrixStack ms, IRenderTypeBuffer buffer, Couple carts) { - ClientWorld world = Minecraft.getInstance().world; + ClientWorld world = Minecraft.getInstance().level; if (carts.getFirst() == null || carts.getSecond() == null) return; Couple lightValues = - carts.map(c -> WorldRenderer.getLightmapCoordinates(world, new BlockPos(c.getBoundingBox() + carts.map(c -> WorldRenderer.getLightColor(world, new BlockPos(c.getBoundingBox() .getCenter()))); Vector3d center = carts.getFirst() - .getPositionVec() + .position() .add(carts.getSecond() - .getPositionVec()) + .position()) .scale(.5f); Couple transforms = carts.map(c -> getSuitableCartEndpoint(c, center)); - BlockState renderState = Blocks.AIR.getDefaultState(); - IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid()); + BlockState renderState = Blocks.AIR.defaultBlockState(); + IVertexBuilder builder = buffer.getBuffer(RenderType.solid()); SuperByteBuffer attachment = PartialBufferer.get(AllBlockPartials.COUPLING_ATTACHMENT, renderState); SuperByteBuffer ring = PartialBufferer.get(AllBlockPartials.COUPLING_RING, renderState); SuperByteBuffer connector = PartialBufferer.get(AllBlockPartials.COUPLING_CONNECTOR, renderState); @@ -77,21 +77,21 @@ public class CouplingRenderer { .apply(zero); Vector3d endPointDiff = secondEndpoint.subtract(firstEndpoint); double connectorYaw = -Math.atan2(endPointDiff.z, endPointDiff.x) * 180.0D / Math.PI; - double connectorPitch = Math.atan2(endPointDiff.y, endPointDiff.mul(1, 0, 1) + double connectorPitch = Math.atan2(endPointDiff.y, endPointDiff.multiply(1, 0, 1) .length()) * 180 / Math.PI; - MatrixStacker msr = MatrixStacker.of(ms); + MatrixTransformStack msr = MatrixTransformStack.of(ms); carts.forEachWithContext((cart, isFirst) -> { CartEndpoint cartTransform = transforms.get(isFirst); - ms.push(); + ms.pushPose(); cartTransform.apply(ms); attachment.light(lightValues.get(isFirst)) .renderInto(ms, builder); msr.rotateY(connectorYaw - cartTransform.yaw); ring.light(lightValues.get(isFirst)) .renderInto(ms, builder); - ms.pop(); + ms.popPose(); }); int l1 = lightValues.getFirst(); @@ -99,7 +99,7 @@ public class CouplingRenderer { int meanBlockLight = (((l1 >> 4) & 0xf) + ((l2 >> 4) & 0xf)) / 2; int meanSkyLight = (((l1 >> 20) & 0xf) + ((l2 >> 20) & 0xf)) / 2; - ms.push(); + ms.pushPose(); msr.translate(firstEndpoint) .rotateY(connectorYaw) .rotateZ(connectorPitch); @@ -107,11 +107,11 @@ public class CouplingRenderer { connector.light(meanSkyLight << 20 | meanBlockLight << 4) .renderInto(ms, builder); - ms.pop(); + ms.popPose(); } private static CartEndpoint getSuitableCartEndpoint(AbstractMinecartEntity cart, Vector3d centerOfCoupling) { - long i = cart.getEntityId() * 493286711L; + long i = cart.getId() * 493286711L; i = i * i * 4392167121L + i * 98761L; float x = (((float) (i >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; float y = (((float) (i >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F + 0.375F; @@ -119,18 +119,18 @@ public class CouplingRenderer { float pt = AnimationTickHolder.getPartialTicks(); - double xIn = lerp(pt, cart.lastTickPosX, cart.getX()); - double yIn = lerp(pt, cart.lastTickPosY, cart.getY()); - double zIn = lerp(pt, cart.lastTickPosZ, cart.getZ()); + double xIn = lerp(pt, cart.xOld, cart.getX()); + double yIn = lerp(pt, cart.yOld, cart.getY()); + double zIn = lerp(pt, cart.zOld, cart.getZ()); - float yaw = lerp(pt, cart.prevRotationYaw, cart.rotationYaw); - float pitch = lerp(pt, cart.prevRotationPitch, cart.rotationPitch); - float roll = cart.getRollingAmplitude() - pt; + float yaw = lerp(pt, cart.yRotO, cart.yRot); + float pitch = lerp(pt, cart.xRotO, cart.xRot); + float roll = cart.getHurtTime() - pt; float rollAmplifier = cart.getDamage() - pt; if (rollAmplifier < 0.0F) rollAmplifier = 0.0F; - roll = roll > 0 ? MathHelper.sin(roll) * roll * rollAmplifier / 10.0F * cart.getRollingDirection() : 0; + roll = roll > 0 ? MathHelper.sin(roll) * roll * rollAmplifier / 10.0F * cart.getHurtDir() : 0; Vector3d positionVec = new Vector3d(xIn, yIn, zIn); Vector3d frontVec = positionVec.add(VecHelper.rotate(new Vector3d(.5, 0, 0), 180 - yaw, Axis.Y)); @@ -140,8 +140,8 @@ public class CouplingRenderer { boolean flip = false; if (railVecOfPos != null) { - frontVec = cart.getPosOffset(xIn, yIn, zIn, (double) 0.3F); - backVec = cart.getPosOffset(xIn, yIn, zIn, (double) -0.3F); + frontVec = cart.getPosOffs(xIn, yIn, zIn, (double) 0.3F); + backVec = cart.getPosOffs(xIn, yIn, zIn, (double) -0.3F); if (frontVec == null) frontVec = railVecOfPos; if (backVec == null) @@ -165,7 +165,7 @@ public class CouplingRenderer { final float offsetMagnitude = 13 / 16f; boolean isBackFaceCloser = - frontVec.squareDistanceTo(centerOfCoupling) > backVec.squareDistanceTo(centerOfCoupling); + frontVec.distanceToSqr(centerOfCoupling) > backVec.distanceToSqr(centerOfCoupling); flip = isBackFaceCloser; float offset = isBackFaceCloser ? -offsetMagnitude : offsetMagnitude; @@ -204,12 +204,12 @@ public class CouplingRenderer { public void apply(MatrixStack ms) { ms.translate(x, y, z); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(yaw)); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(pitch)); - ms.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(roll)); + ms.mulPose(Vector3f.YP.rotationDegrees(yaw)); + ms.mulPose(Vector3f.ZP.rotationDegrees(pitch)); + ms.mulPose(Vector3f.XP.rotationDegrees(roll)); ms.translate(offset, 0, 0); if (flip) - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(180)); + ms.mulPose(Vector3f.YP.rotationDegrees(180)); } } @@ -218,25 +218,25 @@ public class CouplingRenderer { int yOffset = 1; MinecartController first = c.getFirst(); AbstractMinecartEntity mainCart = first.cart(); - Vector3d mainCenter = mainCart.getPositionVec() - .add(0, yOffset, 0); + Vector3d mainCenter = mainCart.position() + .add(0, yOffset, 0); Vector3d connectedCenter = c.getSecond() - .cart() - .getPositionVec() - .add(0, yOffset, 0); + .cart() + .position() + .add(0, yOffset, 0); - int color = ColorHelper.mixColors(0xabf0e9, 0xee8572, (float) MathHelper - .clamp(Math.abs(first.getCouplingLength(true) - connectedCenter.distanceTo(mainCenter)) * 8, 0, 1)); + int color = Color.mixColors(0xabf0e9, 0xee8572, (float) MathHelper + .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.getId() + "", 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); + Vector3d point = mainCart.position() + .add(0, yOffset, 0); + CreateClient.OUTLINER.showLine(mainCart.getId() + "_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..737f4a828 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 @@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.tr 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; @@ -43,7 +44,7 @@ public class MinecartCouplingItem extends Item { return; MinecartController controller = capability.orElse(null); - ItemStack heldItem = player.getHeldItem(event.getHand()); + ItemStack heldItem = player.getItemInHand(event.getHand()); if (AllItems.MINECART_COUPLING.isIn(heldItem)) { if (!onCouplingInteractOnMinecart(event, minecart, player, controller)) return; @@ -61,11 +62,11 @@ public class MinecartCouplingItem extends Item { AbstractMinecartEntity minecart, PlayerEntity player, MinecartController controller) { World world = event.getWorld(); if (controller.isFullyCoupled()) { - if (!world.isRemote) + if (!world.isClientSide) CouplingHandler.status(player, "two_couplings_max"); return true; } - if (world != null && world.isRemote) + if (world != null && world.isClientSide) DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> cartClicked(player, minecart)); return true; } @@ -75,9 +76,14 @@ public class MinecartCouplingItem extends Item { int couplings = (controller.isConnectedToCoupling() ? 1 : 0) + (controller.isLeadingCoupling() ? 1 : 0); if (couplings == 0) return false; - if (event.getWorld().isRemote) + if (event.getWorld().isClientSide) 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/MinecartSim2020.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java index 0a8f00f41..0c0f3689b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.contraptions.components.structureMovement.train; -import static net.minecraft.entity.Entity.horizontalMag; +import static net.minecraft.entity.Entity.getHorizontalDistanceSqr; import java.util.Map; @@ -30,32 +30,32 @@ import net.minecraftforge.common.util.LazyOptional; public class MinecartSim2020 { private static final Map> MATRIX = Util.make(Maps.newEnumMap(RailShape.class), (map) -> { - Vector3i west = Direction.WEST.getDirectionVec(); - Vector3i east = Direction.EAST.getDirectionVec(); - Vector3i north = Direction.NORTH.getDirectionVec(); - Vector3i south = Direction.SOUTH.getDirectionVec(); + Vector3i west = Direction.WEST.getNormal(); + Vector3i east = Direction.EAST.getNormal(); + Vector3i north = Direction.NORTH.getNormal(); + Vector3i south = Direction.SOUTH.getNormal(); map.put(RailShape.NORTH_SOUTH, Pair.of(north, south)); map.put(RailShape.EAST_WEST, Pair.of(west, east)); - map.put(RailShape.ASCENDING_EAST, Pair.of(west.down(), east)); - map.put(RailShape.ASCENDING_WEST, Pair.of(west, east.down())); - map.put(RailShape.ASCENDING_NORTH, Pair.of(north, south.down())); - map.put(RailShape.ASCENDING_SOUTH, Pair.of(north.down(), south)); + map.put(RailShape.ASCENDING_EAST, Pair.of(west.below(), east)); + map.put(RailShape.ASCENDING_WEST, Pair.of(west, east.below())); + map.put(RailShape.ASCENDING_NORTH, Pair.of(north, south.below())); + map.put(RailShape.ASCENDING_SOUTH, Pair.of(north.below(), south)); map.put(RailShape.SOUTH_EAST, Pair.of(south, east)); map.put(RailShape.SOUTH_WEST, Pair.of(south, west)); map.put(RailShape.NORTH_WEST, Pair.of(north, west)); map.put(RailShape.NORTH_EAST, Pair.of(north, east)); }); - + public static Vector3d predictNextPositionOf(AbstractMinecartEntity cart) { - Vector3d position = cart.getPositionVec(); - Vector3d motion = VecHelper.clamp(cart.getMotion(), 1f); + Vector3d position = cart.position(); + Vector3d motion = VecHelper.clamp(cart.getDeltaMovement(), 1f); return position.add(motion); } public static boolean canAddMotion(AbstractMinecartEntity c) { if (c instanceof FurnaceMinecartEntity) - return MathHelper.epsilonEquals(((FurnaceMinecartEntity) c).pushX, 0) - && MathHelper.epsilonEquals(((FurnaceMinecartEntity) c).pushZ, 0); + return MathHelper.equal(((FurnaceMinecartEntity) c).xPush, 0) + && MathHelper.equal(((FurnaceMinecartEntity) c).zPush, 0); LazyOptional capability = c.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY); if (capability.isPresent() && capability.orElse(null) @@ -70,7 +70,7 @@ public class MinecartSim2020 { if (forcedMovement.equals(Vector3d.ZERO)) return; - Vector3d previousMotion = cart.getMotion(); + Vector3d previousMotion = cart.getDeltaMovement(); cart.fallDistance = 0.0F; double x = cart.getX(); @@ -85,7 +85,7 @@ public class MinecartSim2020 { actualY = cartPos.getY() + 1; AbstractRailBlock abstractrailblock = (AbstractRailBlock) trackState.getBlock(); - RailShape railshape = abstractrailblock.getRailDirection(trackState, cart.world, cartPos, cart); + RailShape railshape = abstractrailblock.getRailDirection(trackState, cart.level, cartPos, cart); switch (railshape) { case ASCENDING_EAST: forcedMovement = forcedMovement.add(-1 * cart.getSlopeAdjustment(), 0.0D, 0.0D); @@ -138,8 +138,8 @@ public class MinecartSim2020 { actualX = d23 + d4 * d14; actualZ = d10 + d5 * d14; - cart.setPosition(actualX, actualY, actualZ); - cart.setMotion(forcedMovement); + cart.setPos(actualX, actualY, actualZ); + cart.setDeltaMovement(forcedMovement); cart.moveMinecartOnRail(cartPos); x = cart.getX(); @@ -148,10 +148,10 @@ public class MinecartSim2020 { if (Vector3i.getY() != 0 && MathHelper.floor(x) - cartPos.getX() == Vector3i.getX() && MathHelper.floor(z) - cartPos.getZ() == Vector3i.getZ()) { - cart.setPosition(x, y + (double) Vector3i.getY(), z); + cart.setPos(x, y + (double) Vector3i.getY(), z); } else if (Vector3i1.getY() != 0 && MathHelper.floor(x) - cartPos.getX() == Vector3i1.getX() && MathHelper.floor(z) - cartPos.getZ() == Vector3i1.getZ()) { - cart.setPosition(x, y + (double) Vector3i1.getY(), z); + cart.setPos(x, y + (double) Vector3i1.getY(), z); } x = cart.getX(); @@ -161,13 +161,13 @@ public class MinecartSim2020 { Vector3d Vector3d3 = cart.getPos(x, y, z); if (Vector3d3 != null && actualVec != null) { double d17 = (actualVec.y - Vector3d3.y) * 0.05D; - Vector3d Vector3d4 = cart.getMotion(); - double d18 = Math.sqrt(horizontalMag(Vector3d4)); + Vector3d Vector3d4 = cart.getDeltaMovement(); + double d18 = Math.sqrt(getHorizontalDistanceSqr(Vector3d4)); if (d18 > 0.0D) { - cart.setMotion(Vector3d4.mul((d18 + d17) / d18, 1.0D, (d18 + d17) / d18)); + cart.setDeltaMovement(Vector3d4.multiply((d18 + d17) / d18, 1.0D, (d18 + d17) / d18)); } - cart.setPosition(x, Vector3d3.y, z); + cart.setPos(x, Vector3d3.y, z); } x = cart.getX(); @@ -177,12 +177,12 @@ public class MinecartSim2020 { int j = MathHelper.floor(x); int i = MathHelper.floor(z); if (j != cartPos.getX() || i != cartPos.getZ()) { - Vector3d Vector3d5 = cart.getMotion(); - double d26 = Math.sqrt(horizontalMag(Vector3d5)); - cart.setMotion(d26 * (double) (j - cartPos.getX()), Vector3d5.y, d26 * (double) (i - cartPos.getZ())); + Vector3d Vector3d5 = cart.getDeltaMovement(); + double d26 = Math.sqrt(getHorizontalDistanceSqr(Vector3d5)); + cart.setDeltaMovement(d26 * (double) (j - cartPos.getX()), Vector3d5.y, d26 * (double) (i - cartPos.getZ())); } - cart.setMotion(previousMotion); + cart.setDeltaMovement(previousMotion); } public static Vector3d getRailVec(RailShape shape) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/CapabilityMinecartController.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/CapabilityMinecartController.java index fa21259c0..7dcb896ba 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/CapabilityMinecartController.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/CapabilityMinecartController.java @@ -80,10 +80,10 @@ public class CapabilityMinecartController implements ICapabilitySerializable(HashMap::new); - loadedMinecartsWithCoupling = new WorldAttached<>(HashSet::new); - queuedAdditions = new WorldAttached<>(() -> ObjectLists.synchronize(new ObjectArrayList<>())); - queuedUnloads = new WorldAttached<>(() -> ObjectLists.synchronize(new ObjectArrayList<>())); + loadedMinecartsByUUID = new WorldAttached<>($ -> new HashMap<>()); + loadedMinecartsWithCoupling = new WorldAttached<>($ -> new HashSet<>()); + queuedAdditions = new WorldAttached<>($ -> ObjectLists.synchronize(new ObjectArrayList<>())); + queuedUnloads = new WorldAttached<>($ -> ObjectLists.synchronize(new ObjectArrayList<>())); } public static void tick(World world) { @@ -98,17 +98,17 @@ public class CapabilityMinecartController implements ICapabilitySerializable capability = cart.getCapability(MINECART_CONTROLLER_CAPABILITY); @@ -120,7 +120,7 @@ public class CapabilityMinecartController implements ICapabilitySerializable carts = loadedMinecartsByUUID.get(world); List unloads = queuedUnloads.get(world); - UUID uniqueID = entity.getUniqueID(); + UUID uniqueID = entity.getUUID(); if (!carts.containsKey(uniqueID) || unloads.contains(uniqueID)) return; - if (world.isRemote) + if (world.isClientSide) return; - handleKilledMinecart(world, carts.get(uniqueID), entity.getPositionVec()); + handleKilledMinecart(world, carts.get(uniqueID), entity.position()); } protected static void handleKilledMinecart(World world, MinecartController controller, Vector3d removedPos) { @@ -184,13 +184,13 @@ public class CapabilityMinecartController implements ICapabilitySerializable { internalStall.booleanValue() || otherCart == null || !otherCart.isPresent() || otherCart.isStalled(false)); })); - if (!world.isRemote) { + if (!world.isClientSide) { setStalled(internalStall.booleanValue(), true); disassemble(cart); } @@ -99,29 +99,29 @@ public class MinecartController implements INBTSerializable { if (passengers.isEmpty() || !(passengers.get(0) instanceof AbstractContraptionEntity)) { return; } - World world = cart.world; + World world = cart.level; int i = MathHelper.floor(cart.getX()); int j = MathHelper.floor(cart.getY()); int k = MathHelper.floor(cart.getZ()); if (world.getBlockState(new BlockPos(i, j - 1, k)) - .isIn(BlockTags.RAILS)) { + .is(BlockTags.RAILS)) { --j; } BlockPos blockpos = new BlockPos(i, j, k); BlockState blockstate = world.getBlockState(blockpos); - if (cart.canUseRail() && blockstate.isIn(BlockTags.RAILS) + if (cart.canUseRail() && blockstate.is(BlockTags.RAILS) && blockstate.getBlock() instanceof PoweredRailBlock && ((PoweredRailBlock) blockstate.getBlock()) .isActivatorRail()) { - if (cart.isBeingRidden()) { - cart.removePassengers(); + if (cart.isVehicle()) { + cart.ejectPassengers(); } - if (cart.getRollingAmplitude() == 0) { - cart.setRollingDirection(-cart.getRollingDirection()); - cart.setRollingAmplitude(10); + if (cart.getHurtTime() == 0) { + cart.setHurtDir(-cart.getHurtDir()); + cart.setHurtTime(10); cart.setDamage(50.0F); - cart.velocityChanged = true; + cart.hurtMarked = true; } } } @@ -172,7 +172,7 @@ public class MinecartController implements INBTSerializable { } public void removeConnection(boolean main) { - if (hasContraptionCoupling(main) && !getWorld().isRemote) { + if (hasContraptionCoupling(main) && !getWorld().isClientSide) { List passengers = cart().getPassengers(); if (!passengers.isEmpty()) { Entity entity = passengers.get(0); @@ -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); @@ -240,8 +240,8 @@ public class MinecartController implements INBTSerializable { } public void coupleWith(boolean isLeading, UUID coupled, float length, boolean contraption) { - UUID mainID = isLeading ? cart().getUniqueID() : coupled; - UUID connectedID = isLeading ? coupled : cart().getUniqueID(); + UUID mainID = isLeading ? cart().getUUID() : coupled; + UUID connectedID = isLeading ? coupled : cart().getUUID(); couplings.set(isLeading, Optional.of(new CouplingData(mainID, connectedID, length, contraption))); needsEntryRefresh |= isLeading; sendData(); @@ -290,7 +290,7 @@ public class MinecartController implements INBTSerializable { } public void sendData() { - if (getWorld().isRemote) + if (getWorld().isClientSide) return; AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(this::cart), new MinecartControllerUpdatePacket(this)); @@ -342,7 +342,7 @@ public class MinecartController implements INBTSerializable { } private World getWorld() { - return cart().getEntityWorld(); + return cart().getCommandSenderWorld(); } private static class CouplingData { @@ -367,16 +367,16 @@ public class MinecartController implements INBTSerializable { CompoundNBT serialize() { CompoundNBT nbt = new CompoundNBT(); - nbt.put("Main", NBTUtil.fromUuid(mainCartID)); - nbt.put("Connected", NBTUtil.fromUuid(connectedCartID)); + nbt.put("Main", NBTUtil.createUUID(mainCartID)); + nbt.put("Connected", NBTUtil.createUUID(connectedCartID)); nbt.putFloat("Length", length); nbt.putBoolean("Contraption", contraption); return nbt; } static CouplingData read(CompoundNBT nbt) { - UUID mainCartID = NBTUtil.readUniqueId(NBTHelper.getINBT(nbt, "Main")); - UUID connectedCartID = NBTUtil.readUniqueId(NBTHelper.getINBT(nbt, "Connected")); + UUID mainCartID = NBTUtil.loadUUID(NBTHelper.getINBT(nbt, "Main")); + UUID connectedCartID = NBTUtil.loadUUID(NBTHelper.getINBT(nbt, "Connected")); float length = nbt.getFloat("Length"); boolean contraption = nbt.getBoolean("Contraption"); return new CouplingData(mainCartID, connectedCartID, length, contraption); @@ -396,22 +396,22 @@ public class MinecartController implements INBTSerializable { private StallData() {} StallData(AbstractMinecartEntity entity) { - position = entity.getPositionVec(); - motion = entity.getMotion(); - yaw = entity.rotationYaw; - pitch = entity.rotationPitch; + position = entity.position(); + motion = entity.getDeltaMovement(); + yaw = entity.yRot; + pitch = entity.xRot; tick(entity); } void tick(AbstractMinecartEntity entity) { - entity.setPosition(position.x, position.y, position.z); - entity.setMotion(Vector3d.ZERO); - entity.rotationYaw = yaw; - entity.rotationPitch = pitch; + entity.setPos(position.x, position.y, position.z); + entity.setDeltaMovement(Vector3d.ZERO); + entity.yRot = yaw; + entity.xRot = pitch; } void release(AbstractMinecartEntity entity) { - entity.setMotion(motion); + entity.setDeltaMovement(motion); } CompoundNBT serialize() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java index 58008e2c8..2f52fb897 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java @@ -21,19 +21,19 @@ public class MinecartControllerUpdatePacket extends SimplePacketBase { public MinecartControllerUpdatePacket(MinecartController controller) { entityID = controller.cart() - .getEntityId(); + .getId(); nbt = controller.serializeNBT(); } public MinecartControllerUpdatePacket(PacketBuffer buffer) { entityID = buffer.readInt(); - nbt = buffer.readCompoundTag(); + nbt = buffer.readNbt(); } @Override public void write(PacketBuffer buffer) { buffer.writeInt(entityID); - buffer.writeCompoundTag(nbt); + buffer.writeNbt(nbt); } @Override @@ -46,10 +46,10 @@ public class MinecartControllerUpdatePacket extends SimplePacketBase { @OnlyIn(Dist.CLIENT) private void handleCL() { - ClientWorld world = Minecraft.getInstance().world; + ClientWorld world = Minecraft.getInstance().level; if (world == null) return; - Entity entityByID = world.getEntityByID(entityID); + Entity entityByID = world.getEntity(entityID); if (entityByID == null) return; entityByID.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailBlock.java index 95d44b209..2b744df9c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailBlock.java @@ -45,23 +45,23 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl public static final EnumProperty SHAPE = BlockStateProperties.RAIL_SHAPE_STRAIGHT; public static final BooleanProperty BACKWARDS = BooleanProperty.create("backwards"); - public static final IntegerProperty POWER = BlockStateProperties.POWER_0_15; + public static final IntegerProperty POWER = BlockStateProperties.POWER; public ControllerRailBlock(Properties properties) { super(true, properties); - this.setDefaultState(this.stateContainer.getBaseState() - .with(POWER, 0) - .with(BACKWARDS, false) - .with(SHAPE, NORTH_SOUTH)); + this.registerDefaultState(this.stateDefinition.any() + .setValue(POWER, 0) + .setValue(BACKWARDS, false) + .setValue(SHAPE, NORTH_SOUTH)); } public static Vector3i getAccelerationVector(BlockState state) { Direction pointingTo = getPointingTowards(state); - return (isStateBackwards(state) ? pointingTo.getOpposite() : pointingTo).getDirectionVec(); + return (isStateBackwards(state) ? pointingTo.getOpposite() : pointingTo).getNormal(); } private static Direction getPointingTowards(BlockState state) { - switch (state.get(SHAPE)) { + switch (state.getValue(SHAPE)) { case ASCENDING_WEST: case EAST_WEST: return Direction.WEST; @@ -75,9 +75,9 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl } @Override - protected BlockState getUpdatedState(World world, BlockPos pos, BlockState state, boolean p_208489_4_) { - BlockState updatedState = super.getUpdatedState(world, pos, state, p_208489_4_); - if (updatedState.get(SHAPE) == state.get(SHAPE)) + protected BlockState updateDir(World world, BlockPos pos, BlockState state, boolean p_208489_4_) { + BlockState updatedState = super.updateDir(world, pos, state, p_208489_4_); + if (updatedState.getValue(SHAPE) == state.getValue(SHAPE)) return updatedState; BlockState reversedUpdatedState = updatedState; @@ -87,13 +87,13 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl Direction offset = getPointingTowards(updatedState); if (opposite) offset = offset.getOpposite(); - for (BlockPos adjPos : Iterate.hereBelowAndAbove(pos.offset(offset))) { + for (BlockPos adjPos : Iterate.hereBelowAndAbove(pos.relative(offset))) { BlockState adjState = world.getBlockState(adjPos); if (!AllBlocks.CONTROLLER_RAIL.has(adjState)) continue; if (getPointingTowards(adjState).getAxis() != offset.getAxis()) continue; - if (adjState.get(BACKWARDS) != reversedUpdatedState.get(BACKWARDS)) + if (adjState.getValue(BACKWARDS) != reversedUpdatedState.getValue(BACKWARDS)) reversedUpdatedState = reversedUpdatedState.cycle(BACKWARDS); } } @@ -101,31 +101,31 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl // Replace if changed if (reversedUpdatedState != updatedState) - world.setBlockState(pos, reversedUpdatedState); + world.setBlockAndUpdate(pos, reversedUpdatedState); return reversedUpdatedState; } private static void decelerateCart(BlockPos pos, AbstractMinecartEntity cart) { Vector3d diff = VecHelper.getCenterOf(pos) - .subtract(cart.getPositionVec()); - cart.setMotion(diff.x / 16f, 0, diff.z / 16f); + .subtract(cart.position()); + cart.setDeltaMovement(diff.x / 16f, 0, diff.z / 16f); if (cart instanceof FurnaceMinecartEntity) { FurnaceMinecartEntity fme = (FurnaceMinecartEntity) cart; - fme.pushX = fme.pushZ = 0; + fme.xPush = fme.zPush = 0; } } private static boolean isStableWith(BlockState testState, IBlockReader world, BlockPos pos) { - return hasSolidSideOnTop(world, pos.down()) && (!testState.get(SHAPE) - .isAscending() || hasSolidSideOnTop(world, pos.offset(getPointingTowards(testState)))); + return canSupportRigidBlock(world, pos.below()) && (!testState.getValue(SHAPE) + .isAscending() || canSupportRigidBlock(world, pos.relative(getPointingTowards(testState)))); } @Override public BlockState getStateForPlacement(BlockItemUseContext p_196258_1_) { - Direction direction = p_196258_1_.getPlacementHorizontalFacing(); + Direction direction = p_196258_1_.getHorizontalDirection(); BlockState base = super.getStateForPlacement(p_196258_1_); - return (base == null ? getDefaultState() : base).with(BACKWARDS, + return (base == null ? defaultBlockState() : base).setValue(BACKWARDS, direction.getAxisDirection() == AxisDirection.POSITIVE); } @@ -135,26 +135,26 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl } @Override - protected void fillStateContainer(StateContainer.Builder p_206840_1_) { + protected void createBlockStateDefinition(StateContainer.Builder p_206840_1_) { p_206840_1_.add(SHAPE, POWER, BACKWARDS); } @Override public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) { - if (world.isRemote) + if (world.isClientSide) return; - Vector3d accelerationVec = Vector3d.of(getAccelerationVector(state)); - double targetSpeed = cart.getMaxSpeedWithRail() * state.get(POWER) / 15f; + Vector3d accelerationVec = Vector3d.atLowerCornerOf(getAccelerationVector(state)); + double targetSpeed = cart.getMaxSpeedWithRail() * state.getValue(POWER) / 15f; if (cart instanceof FurnaceMinecartEntity) { FurnaceMinecartEntity fme = (FurnaceMinecartEntity) cart; - fme.pushX = accelerationVec.x; - fme.pushZ = accelerationVec.z; + fme.xPush = accelerationVec.x; + fme.zPush = accelerationVec.z; } - Vector3d motion = cart.getMotion(); - if ((motion.dotProduct(accelerationVec) >= 0 || motion.lengthSquared() < 0.0001) && targetSpeed > 0) - cart.setMotion(accelerationVec.scale(targetSpeed)); + Vector3d motion = cart.getDeltaMovement(); + if ((motion.dot(accelerationVec) >= 0 || motion.lengthSqr() < 0.0001) && targetSpeed > 0) + cart.setDeltaMovement(accelerationVec.scale(targetSpeed)); else decelerateCart(pos, cart); } @@ -162,12 +162,12 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl @Override protected void updateState(BlockState state, World world, BlockPos pos, Block block) { int newPower = calculatePower(world, pos); - if (state.get(POWER) != newPower) - placeAndNotify(state.with(POWER, newPower), pos, world); + if (state.getValue(POWER) != newPower) + placeAndNotify(state.setValue(POWER, newPower), pos, world); } private int calculatePower(World world, BlockPos pos) { - int newPower = world.getRedstonePowerFromNeighbors(pos); + int newPower = world.getBestNeighborSignal(pos); if (newPower != 0) return newPower; @@ -184,7 +184,7 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl break; forwardDistance++; lastForwardRail = testPos; - forwardPower = world.getRedstonePowerFromNeighbors(testPos); + forwardPower = world.getBestNeighborSignal(testPos); if (forwardPower != 0) break; } @@ -194,7 +194,7 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl break; backwardsDistance++; lastBackwardsRail = testPos; - backwardsPower = world.getRedstonePowerFromNeighbors(testPos); + backwardsPower = world.getBestNeighborSignal(testPos); if (backwardsPower != 0) break; } @@ -213,37 +213,30 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { - World world = context.getWorld(); - if (world.isRemote) + World world = context.getLevel(); + if (world.isClientSide) return ActionResultType.SUCCESS; - BlockPos pos = context.getPos(); + BlockPos pos = context.getClickedPos(); for (Rotation testRotation : new Rotation[] { Rotation.CLOCKWISE_90, Rotation.CLOCKWISE_180, Rotation.COUNTERCLOCKWISE_90 }) { BlockState testState = rotate(state, testRotation); if (isStableWith(testState, world, pos)) { placeAndNotify(testState, pos, world); - break; + return ActionResultType.SUCCESS; } } - return ActionResultType.SUCCESS; - } - - @Override - public ActionResultType onSneakWrenched(BlockState state, ItemUseContext context) { - World world = context.getWorld(); - BlockPos pos = context.getPos(); - BlockState testState = state.with(BACKWARDS, !state.get(BACKWARDS)); + BlockState testState = state.setValue(BACKWARDS, !state.getValue(BACKWARDS)); if (isStableWith(testState, world, pos)) placeAndNotify(testState, pos, world); return ActionResultType.SUCCESS; } private void placeAndNotify(BlockState state, BlockPos pos, World world) { - world.setBlockState(pos, state, 3); - world.notifyNeighborsOfStateChange(pos.down(), this); - if (state.get(SHAPE) + world.setBlock(pos, state, 3); + world.updateNeighborsAt(pos.below(), this); + if (state.getValue(SHAPE) .isAscending()) - world.notifyNeighborsOfStateChange(pos.up(), this); + world.updateNeighborsAt(pos.above(), this); } @Nullable @@ -252,9 +245,9 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl if (!(current.getBlock() instanceof ControllerRailBlock)) return null; Vector3i accelerationVec = getAccelerationVector(current); - BlockPos baseTestPos = reversed ? from.subtract(accelerationVec) : from.add(accelerationVec); + BlockPos baseTestPos = reversed ? from.subtract(accelerationVec) : from.offset(accelerationVec); for (BlockPos testPos : Iterate.hereBelowAndAbove(baseTestPos)) { - if (testPos.getY() > from.getY() && !current.get(SHAPE) + if (testPos.getY() > from.getY() && !current.getValue(SHAPE) .isAscending()) continue; BlockState testState = world.getBlockState(testPos); @@ -266,13 +259,13 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl } @Override - public boolean hasComparatorInputOverride(BlockState state) { + public boolean hasAnalogOutputSignal(BlockState state) { return true; } @Override - public int getComparatorInputOverride(BlockState state, World world, BlockPos pos) { - return state.get(POWER); + public int getAnalogOutputSignal(BlockState state, World world, BlockPos pos) { + return state.getValue(POWER); } @Override @@ -280,11 +273,11 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl if (rotation == Rotation.NONE) return state; - RailShape railshape = Blocks.POWERED_RAIL.getDefaultState() - .with(SHAPE, state.get(SHAPE)) + RailShape railshape = Blocks.POWERED_RAIL.defaultBlockState() + .setValue(SHAPE, state.getValue(SHAPE)) .rotate(rotation) - .get(SHAPE); - state = state.with(SHAPE, railshape); + .getValue(SHAPE); + state = state.setValue(SHAPE, railshape); if (rotation == Rotation.CLOCKWISE_180 || (getPointingTowards(state).getAxis() == Axis.Z) == (rotation == Rotation.COUNTERCLOCKWISE_90)) @@ -298,11 +291,11 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl if (mirror == Mirror.NONE) return state; - RailShape railshape = Blocks.POWERED_RAIL.getDefaultState() - .with(SHAPE, state.get(SHAPE)) + RailShape railshape = Blocks.POWERED_RAIL.defaultBlockState() + .setValue(SHAPE, state.getValue(SHAPE)) .mirror(mirror) - .get(SHAPE); - state = state.with(SHAPE, railshape); + .getValue(SHAPE); + state = state.setValue(SHAPE, railshape); if ((getPointingTowards(state).getAxis() == Axis.Z) == (mirror == Mirror.LEFT_RIGHT)) return state.cycle(BACKWARDS); @@ -311,10 +304,10 @@ public class ControllerRailBlock extends AbstractRailBlock implements IWrenchabl } public static boolean isStateBackwards(BlockState state) { - return state.get(BACKWARDS) ^ isReversedSlope(state); + return state.getValue(BACKWARDS) ^ isReversedSlope(state); } public static boolean isReversedSlope(BlockState state) { - return state.get(SHAPE) == RailShape.ASCENDING_SOUTH || state.get(SHAPE) == RailShape.ASCENDING_EAST; + return state.getValue(SHAPE) == RailShape.ASCENDING_SOUTH || state.getValue(SHAPE) == RailShape.ASCENDING_EAST; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailGenerator.java index cc961ac13..0cdda2aa0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailGenerator.java @@ -25,7 +25,7 @@ public class ControllerRailGenerator extends SpecialBlockStateGen { @Override protected int getYRotation(BlockState state) { - RailShape shape = state.get(ControllerRailBlock.SHAPE); + RailShape shape = state.getValue(ControllerRailBlock.SHAPE); boolean backwards = ControllerRailBlock.isStateBackwards(state); int rotation = backwards ? 180 : 0; @@ -45,7 +45,7 @@ public class ControllerRailGenerator extends SpecialBlockStateGen { @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - RailShape shape = state.get(ControllerRailBlock.SHAPE); + RailShape shape = state.getValue(ControllerRailBlock.SHAPE); boolean backwards = ControllerRailBlock.isStateBackwards(state); String model = shape.isAscending() ? backwards ? "ascending_south" : "ascending_north" : "north_south"; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ReinforcedRailBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ReinforcedRailBlock.java index cb092ceff..22eb42a2d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ReinforcedRailBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ReinforcedRailBlock.java @@ -38,7 +38,7 @@ public class ReinforcedRailBlock extends AbstractRailBlock { } @Override - public void fillItemGroup(ItemGroup p_149666_1_, NonNullList p_149666_2_) { + public void fillItemCategory(ItemGroup p_149666_1_, NonNullList p_149666_2_) { // TODO re-add when finished } @@ -49,15 +49,15 @@ public class ReinforcedRailBlock extends AbstractRailBlock { } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(RAIL_SHAPE, CONNECTS_N, CONNECTS_S); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - boolean alongX = context.getPlacementHorizontalFacing().getAxis() == Axis.X; - return super.getStateForPlacement(context).with(RAIL_SHAPE, alongX ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH).with(CONNECTS_N, false).with(CONNECTS_S, false); + boolean alongX = context.getHorizontalDirection().getAxis() == Axis.X; + return super.getStateForPlacement(context).setValue(RAIL_SHAPE, alongX ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH).setValue(CONNECTS_N, false).setValue(CONNECTS_S, false); } @Override @@ -68,22 +68,22 @@ public class ReinforcedRailBlock extends AbstractRailBlock { @Override protected void updateState(@Nonnull BlockState state, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Block block) { super.updateState(state, world, pos, block); - world.setBlockState(pos, getUpdatedState(world, pos, state, true)); + world.setBlockAndUpdate(pos, updateDir(world, pos, state, true)); } @Override @Nonnull - protected BlockState getUpdatedState(@Nonnull World world, BlockPos pos, BlockState state, + protected BlockState updateDir(@Nonnull World world, BlockPos pos, BlockState state, boolean p_208489_4_) { - boolean alongX = state.get(RAIL_SHAPE) == RailShape.EAST_WEST; - BlockPos sPos = pos.add(alongX ? -1 : 0, 0, alongX ? 0 : 1); - BlockPos nPos = pos.add(alongX ? 1 : 0, 0, alongX ? 0 : -1); + boolean alongX = state.getValue(RAIL_SHAPE) == RailShape.EAST_WEST; + BlockPos sPos = pos.offset(alongX ? -1 : 0, 0, alongX ? 0 : 1); + BlockPos nPos = pos.offset(alongX ? 1 : 0, 0, alongX ? 0 : -1); - return super.getUpdatedState(world, pos, state, p_208489_4_).with(CONNECTS_S, world.getBlockState(sPos).getBlock() instanceof ReinforcedRailBlock && - (world.getBlockState(sPos).get(RAIL_SHAPE) == state.get(RAIL_SHAPE))) - .with(CONNECTS_N, world.getBlockState(nPos).getBlock() instanceof ReinforcedRailBlock && - (world.getBlockState(nPos).get(RAIL_SHAPE) == state.get(RAIL_SHAPE))); + return super.updateDir(world, pos, state, p_208489_4_).setValue(CONNECTS_S, world.getBlockState(sPos).getBlock() instanceof ReinforcedRailBlock && + (world.getBlockState(sPos).getValue(RAIL_SHAPE) == state.getValue(RAIL_SHAPE))) + .setValue(CONNECTS_N, world.getBlockState(nPos).getBlock() instanceof ReinforcedRailBlock && + (world.getBlockState(nPos).getValue(RAIL_SHAPE) == state.getValue(RAIL_SHAPE))); } @Override @@ -98,13 +98,13 @@ public class ReinforcedRailBlock extends AbstractRailBlock { @Override @Nonnull public VoxelShape getShape(BlockState state, @Nonnull IBlockReader reader, @Nonnull BlockPos pos, ISelectionContext context) { - boolean alongX = state.get(RAIL_SHAPE) == RailShape.EAST_WEST; - return VoxelShapes.or(makeCuboidShape(0, -2, 0, 16, 2, 16), VoxelShapes.or(makeCuboidShape(0, -2, 0, alongX ? 16 : -1, 12, alongX ? -1 : 16), makeCuboidShape(alongX ? 0 : 17, -2, alongX ? 17 : 0, 16, 12, 16))); + boolean alongX = state.getValue(RAIL_SHAPE) == RailShape.EAST_WEST; + return VoxelShapes.or(box(0, -2, 0, 16, 2, 16), VoxelShapes.or(box(0, -2, 0, alongX ? 16 : -1, 12, alongX ? -1 : 16), box(alongX ? 0 : 17, -2, alongX ? 17 : 0, 16, 12, 16))); } @Override @Nonnull - public PushReaction getPushReaction(BlockState state) { + public PushReaction getPistonPushReaction(BlockState state) { return PushReaction.BLOCK; } @@ -115,16 +115,16 @@ public class ReinforcedRailBlock extends AbstractRailBlock { }*/ @Override - public boolean isValidPosition(BlockState state, IWorldReader world, BlockPos pos) { - return !(world.getBlockState(pos.down()).getBlock() instanceof AbstractRailBlock || world.getBlockState(pos.up()).getBlock() instanceof AbstractRailBlock); + public boolean canSurvive(BlockState state, IWorldReader world, BlockPos pos) { + return !(world.getBlockState(pos.below()).getBlock() instanceof AbstractRailBlock || world.getBlockState(pos.above()).getBlock() instanceof AbstractRailBlock); } @Override public void neighborChanged(@Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull Block block, @Nonnull BlockPos pos2, boolean p_220069_6_) { - if (!world.isRemote) { - if ((world.getBlockState(pos.down()).getBlock() instanceof AbstractRailBlock)) { + if (!world.isClientSide) { + if ((world.getBlockState(pos.below()).getBlock() instanceof AbstractRailBlock)) { if (!p_220069_6_) { - spawnDrops(state, world, pos); + dropResources(state, world, pos); } world.removeBlock(pos, false); } else { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableBlock.java index c9763ef7f..f4cbc379f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableBlock.java @@ -37,7 +37,7 @@ public class TurntableBlock extends KineticBlock implements ITE 0) + if (e.getDeltaMovement().y > 0) return; if (e.getY() < pos.getY() + .5f) return; @@ -60,36 +60,36 @@ public class TurntableBlock extends KineticBlock implements ITE 1/4f) speed *= MathHelper.clamp((1/2f - offset.length()) * 2, 0, 1); - mc.player.rotationYaw = mc.player.prevRotationYaw - speed * AnimationTickHolder.getPartialTicks(); - mc.player.renderYawOffset = mc.player.rotationYaw; + mc.player.yRot = mc.player.yRotO - speed * AnimationTickHolder.getPartialTicks(); + mc.player.yBodyRot = mc.player.yRot; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelBlock.java index de25c380c..e801e40c4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelBlock.java @@ -5,7 +5,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllFluids; import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; +import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.config.AllConfigs; @@ -18,6 +18,7 @@ import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.BubbleColumnBlock; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.fluid.FluidState; import net.minecraft.item.BlockItemUseContext; import net.minecraft.tileentity.TileEntity; @@ -33,7 +34,7 @@ import net.minecraft.world.World; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -public class WaterWheelBlock extends HorizontalKineticBlock implements ITE { +public class WaterWheelBlock extends DirectionalKineticBlock implements ITE { public WaterWheelBlock(Properties properties) { super(properties); @@ -45,21 +46,21 @@ public class WaterWheelBlock extends HorizontalKineticBlock implements ITE 0 ^ !clockwise ? -flow.y * clockwiseMultiplier : -flow.y; } - if (te.getSpeed() == 0 && flowStrength != 0 && !world.isRemote()) { + if (wf.getAxis() == Axis.Y) { + if (side.getAxis() == Axis.Z) + flowStrength = flow.x < 0 ^ !clockwise ? flow.x * clockwiseMultiplier : flow.x; + if (side.getAxis() == Axis.X) + flowStrength = flow.z > 0 ^ !clockwise ? -flow.z * clockwiseMultiplier : -flow.z; + } + + if (te.getSpeed() == 0 && flowStrength != 0 && !world.isClientSide()) { AllTriggers.triggerForNearbyPlayers(AllTriggers.WATER_WHEEL, world, pos, 5); - if (FluidHelper.isLava(fluid.getFluid())) + if (FluidHelper.isLava(fluid.getType())) AllTriggers.triggerForNearbyPlayers(AllTriggers.LAVA_WHEEL, world, pos, 5); - if (fluid.getFluid().isEquivalentTo(AllFluids.CHOCOLATE.get())) + if (fluid.getType() + .isSame(AllFluids.CHOCOLATE.get())) AllTriggers.triggerForNearbyPlayers(AllTriggers.CHOCOLATE_WHEEL, world, pos, 5); } @@ -147,28 +157,48 @@ public class WaterWheelBlock extends HorizontalKineticBlock implements ITE tolerance) + facing = Direction.DOWN; + else if (Vector3d.atLowerCornerOf(Direction.UP.getNormal()) + .dot(lookVec.normalize()) > tolerance) + facing = Direction.UP; + else + facing = horizontalFacing; + + } + + return defaultBlockState().setValue(FACING, sneaking ? facing.getOpposite() : facing); } @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return state.get(HORIZONTAL_FACING) + return state.getValue(FACING) .getAxis() == face.getAxis(); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(HORIZONTAL_FACING) + return state.getValue(FACING) .getAxis(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java index 7f89e5c47..6b8b9e9d7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java @@ -32,20 +32,20 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity { if (compound.contains("Flows")) { for (Direction d : Iterate.directions) setFlow(d, compound.getCompound("Flows") - .getFloat(d.getString())); + .getFloat(d.getSerializedName())); } } @Override public AxisAlignedBB makeRenderBoundingBox() { - return new AxisAlignedBB(pos).grow(1); + return new AxisAlignedBB(worldPosition).inflate(1); } @Override public void write(CompoundNBT compound, boolean clientPacket) { CompoundNBT flows = new CompoundNBT(); for (Direction d : Iterate.directions) - flows.putFloat(d.getString(), this.flows.get(d)); + flows.putFloat(d.getSerializedName(), this.flows.get(d)); compound.put("Flows", flows); super.write(compound, clientPacket); @@ -53,7 +53,7 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity { public void setFlow(Direction direction, float speed) { flows.put(direction, speed); - markDirty(); + setChanged(); } @Override @@ -70,7 +70,7 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity { public void lazyTick() { super.lazyTick(); AllBlocks.WATER_WHEEL.get() - .updateAllSides(getBlockState(), world, pos); + .updateAllSides(getBlockState(), level, worldPosition); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FlowSource.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FlowSource.java index e2beb3a37..22aa2cd07 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FlowSource.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FlowSource.java @@ -52,7 +52,7 @@ public abstract class FlowSource { public abstract boolean isEndpoint(); public void manageSource(World world) {} - + public void whileFlowPresent(World world, boolean pulling) {} public LazyOptional provideHandler() { @@ -68,9 +68,9 @@ public abstract class FlowSource { } public void manageSource(World world) { - if (fluidHandler.isPresent()) + if (fluidHandler.isPresent() && world.getGameTime() % 20 != 0) return; - TileEntity tileEntity = world.getTileEntity(location.getConnectedPos()); + TileEntity tileEntity = world.getBlockEntity(location.getConnectedPos()); if (tileEntity != null) fluidHandler = tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, location.getOppositeFace()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidBottleItemHook.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidBottleItemHook.java index 9a2d9f047..211e5964a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidBottleItemHook.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidBottleItemHook.java @@ -35,15 +35,15 @@ public class FluidBottleItemHook extends Item { World world = event.getWorld(); PlayerEntity player = event.getPlayer(); - RayTraceResult raytraceresult = rayTrace(world, player, RayTraceContext.FluidMode.SOURCE_ONLY); + RayTraceResult raytraceresult = getPlayerPOVHitResult(world, player, RayTraceContext.FluidMode.SOURCE_ONLY); if (raytraceresult.getType() != RayTraceResult.Type.BLOCK) return; - BlockPos blockpos = ((BlockRayTraceResult) raytraceresult).getPos(); - if (!world.isBlockModifiable(player, blockpos)) + BlockPos blockpos = ((BlockRayTraceResult) raytraceresult).getBlockPos(); + if (!world.mayInteract(player, blockpos)) return; FluidState fluidState = world.getFluidState(blockpos); - if (fluidState.isTagged(FluidTags.WATER) && fluidState.getFluid() + if (fluidState.is(FluidTags.WATER) && fluidState.getType() .getRegistryName() .getNamespace() .equals(Create.ID)) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidFX.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidFX.java index bd22b97d1..8fb4b209f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidFX.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidFX.java @@ -29,12 +29,12 @@ public class FluidFX { if (fluid == Fluids.EMPTY) return; - FluidState defaultState = fluid.getDefaultState(); + FluidState defaultState = fluid.defaultFluidState(); if (defaultState == null || defaultState.isEmpty()) { return; } - BlockParticleData blockParticleData = new BlockParticleData(ParticleTypes.BLOCK, defaultState.getBlockState()); + BlockParticleData blockParticleData = new BlockParticleData(ParticleTypes.BLOCK, defaultState.createLegacyBlock()); Vector3d center = VecHelper.getCenterOf(pos); for (int i = 0; i < 20; i++) { @@ -61,17 +61,17 @@ public class FluidFX { public static void spawnRimParticles(World world, BlockPos pos, Direction side, int amount, IParticleData particle, float rimRadius) { - Vector3d directionVec = Vector3d.of(side.getDirectionVec()); + Vector3d directionVec = Vector3d.atLowerCornerOf(side.getNormal()); for (int i = 0; i < amount; i++) { Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, 1) .normalize(); vec = VecHelper.clampComponentWise(vec, rimRadius) - .mul(VecHelper.axisAlingedPlaneOf(directionVec)) + .multiply(VecHelper.axisAlingedPlaneOf(directionVec)) .add(directionVec.scale(.45 + r.nextFloat() / 16f)); Vector3d m = vec.scale(.05f); vec = vec.add(VecHelper.getCenterOf(pos)); - world.addOptionalParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z); + world.addAlwaysVisibleParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z); } } @@ -79,7 +79,7 @@ public class FluidFX { float rimRadius, Vector3d directionVec, boolean inbound) { for (int i = 0; i < amount; i++) { Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, rimRadius * .75f); - vec = vec.mul(VecHelper.axisAlingedPlaneOf(directionVec)) + vec = vec.multiply(VecHelper.axisAlingedPlaneOf(directionVec)) .add(directionVec.scale(.5 + r.nextFloat() / 4f)); Vector3d m = vec.scale(1 / 4f); Vector3d centerOf = VecHelper.getCenterOf(pos); @@ -90,7 +90,7 @@ public class FluidFX { .subtract(vec) .scale(1 / 16f); } - world.addOptionalParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z); + world.addAlwaysVisibleParticle(particle, vec.x, vec.y - 1 / 16f, vec.z, m.x, m.y, m.z); } } @@ -99,7 +99,7 @@ public class FluidFX { } private static World world() { - return Minecraft.getInstance().world; + return Minecraft.getInstance().level; } } 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..eedcc0cd9 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; @@ -90,7 +91,7 @@ public class FluidNetwork { if (!pipeConnection.hasFlow()) continue; - + Flow flow = pipeConnection.flow.get(); if (!fluid.isEmpty() && !flow.fluid.isFluidEqual(fluid)) { iterator.remove(); @@ -103,7 +104,7 @@ public class FluidNetwork { } if (!flow.complete) continue; - + if (fluid.isEmpty()) fluid = flow.fluid; @@ -157,11 +158,14 @@ public class FluidNetwork { source = sourceSupplier.get(); if (!source.isPresent()) return; + + keepPortableFluidInterfaceEngaged(); + if (targets.isEmpty()) return; for (Pair> pair : targets) { if (pair.getSecond() - .isPresent()) + .isPresent() && world.getGameTime() % 40 != 0) continue; PipeConnection pipeConnection = get(pair.getFirst()); if (pipeConnection == null) @@ -179,7 +183,7 @@ public class FluidNetwork { IFluidHandler handler = source.orElse(null); if (handler == null) return; - + FluidStack transfer = FluidStack.EMPTY; for (int i = 0; i < handler.getTanks(); i++) { FluidStack contained = handler.getFluidInTank(i); @@ -190,13 +194,13 @@ public class FluidNetwork { FluidStack toExtract = FluidHelper.copyStackWithAmount(contained, flowSpeed); transfer = handler.drain(toExtract, action); } - + if (transfer.isEmpty()) { FluidStack genericExtract = handler.drain(flowSpeed, action); if (!genericExtract.isEmpty() && genericExtract.isFluidEqual(fluid)) transfer = genericExtract; } - + if (transfer.isEmpty()) return; @@ -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/FluidPropagator.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java index 6e49b3c2e..cf4d8f3a7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java @@ -54,14 +54,14 @@ public class FluidPropagator { pipe.wipePressure(); for (Direction direction : getPipeConnections(currentState, pipe)) { - BlockPos target = currentPos.offset(direction); + BlockPos target = currentPos.relative(direction); if (!world.isAreaLoaded(target, 0)) continue; - TileEntity tileEntity = world.getTileEntity(target); + TileEntity tileEntity = world.getBlockEntity(target); BlockState targetState = world.getBlockState(target); if (tileEntity instanceof PumpTileEntity) { - if (!AllBlocks.MECHANICAL_PUMP.has(targetState) || targetState.get(PumpBlock.FACING) + if (!AllBlocks.MECHANICAL_PUMP.has(targetState) || targetState.getValue(PumpBlock.FACING) .getAxis() != direction.getAxis()) continue; discoveredPumps.add(Pair.of((PumpTileEntity) tileEntity, direction.getOpposite())); @@ -101,7 +101,7 @@ public class FluidPropagator { for (Direction d : Iterate.directions) { if (pos.equals(start) && d != side) continue; - BlockPos target = pos.offset(d); + BlockPos target = pos.relative(d); if (visited.contains(target)) continue; @@ -123,7 +123,7 @@ public class FluidPropagator { public static Direction validateNeighbourChange(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos, boolean isMoving) { - if (world.isRemote) + if (world.isClientSide) return null; if (otherBlock instanceof FluidPipeBlock) return null; @@ -136,7 +136,7 @@ public class FluidPropagator { if (getStraightPipeAxis(state) == null) return null; for (Direction d : Iterate.directions) { - if (!pos.offset(d) + if (!pos.relative(d) .equals(neighborPos)) continue; return d; @@ -149,21 +149,23 @@ public class FluidPropagator { } public static boolean isOpenEnd(IBlockReader reader, BlockPos pos, Direction side) { - BlockPos connectedPos = pos.offset(side); + BlockPos connectedPos = pos.relative(side); BlockState connectedState = reader.getBlockState(connectedPos); FluidTransportBehaviour pipe = FluidPropagator.getPipe(reader, connectedPos); if (pipe != null && pipe.canHaveFlowToward(connectedState, side.getOpposite())) return false; - if (PumpBlock.isPump(connectedState) && connectedState.get(PumpBlock.FACING) + if (PumpBlock.isPump(connectedState) && connectedState.getValue(PumpBlock.FACING) .getAxis() == side.getAxis()) return false; - if (connectedState.contains(BlockStateProperties.HONEY_LEVEL)) + if (connectedState.hasProperty(BlockStateProperties.LEVEL_HONEY)) return true; if (BlockHelper.hasBlockSolidSide(connectedState, reader, connectedPos, side.getOpposite())) return false; + if (hasFluidCapability(reader, connectedPos, side.getOpposite())) + return false; if (!(connectedState.getMaterial() - .isReplaceable() && connectedState.getBlockHardness(reader, connectedPos) != -1) - && !connectedState.contains(BlockStateProperties.WATERLOGGED)) + .isReplaceable() && connectedState.getDestroySpeed(reader, connectedPos) != -1) + && !connectedState.hasProperty(BlockStateProperties.WATERLOGGED)) return false; return true; } @@ -202,7 +204,7 @@ public class FluidPropagator { // } public static boolean hasFluidCapability(IBlockReader world, BlockPos pos, Direction side) { - TileEntity tileEntity = world.getTileEntity(pos); + TileEntity tileEntity = world.getBlockEntity(pos); return tileEntity != null && tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side) .isPresent(); } @@ -210,17 +212,17 @@ public class FluidPropagator { @Nullable public static Axis getStraightPipeAxis(BlockState state) { if (state.getBlock() instanceof PumpBlock) - return state.get(PumpBlock.FACING) + return state.getValue(PumpBlock.FACING) .getAxis(); if (state.getBlock() instanceof AxisPipeBlock) - return state.get(AxisPipeBlock.AXIS); + return state.getValue(AxisPipeBlock.AXIS); if (!FluidPipeBlock.isPipe(state)) return null; Axis axisFound = null; int connections = 0; for (Axis axis : Iterate.axes) { - Direction d1 = Direction.getFacingFromAxis(AxisDirection.NEGATIVE, axis); - Direction d2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); + Direction d1 = Direction.get(AxisDirection.NEGATIVE, axis); + Direction d2 = Direction.get(AxisDirection.POSITIVE, axis); boolean openAt1 = FluidPipeBlock.isOpenAt(state, d1); boolean openAt2 = FluidPipeBlock.isOpenAt(state, d2); if (openAt1) diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidReactions.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidReactions.java index aa010ab7b..9c249f8fd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidReactions.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidReactions.java @@ -24,41 +24,41 @@ public class FluidReactions { AllTriggers.triggerForNearbyPlayers(AllTriggers.PIPE_COLLISION, world, pos, 5); if (f1 == Fluids.WATER && f2 == Fluids.LAVA || f2 == Fluids.WATER && f1 == Fluids.LAVA) - world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); + world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState()); else if (f1 == Fluids.LAVA && FluidHelper.hasBlockState(f2)) { BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f2) - .getDefaultState()); + .defaultFluidState()); if (lavaInteraction != null) - world.setBlockState(pos, lavaInteraction); + world.setBlockAndUpdate(pos, lavaInteraction); } else if (f2 == Fluids.LAVA && FluidHelper.hasBlockState(f1)) { BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f1) - .getDefaultState()); + .defaultFluidState()); if (lavaInteraction != null) - world.setBlockState(pos, lavaInteraction); + world.setBlockAndUpdate(pos, lavaInteraction); } } public static void handlePipeSpillCollision(World world, BlockPos pos, Fluid pipeFluid, FluidState worldFluid) { Fluid pf = FluidHelper.convertToStill(pipeFluid); - Fluid wf = worldFluid.getFluid(); - if (pf.isIn(FluidTags.WATER) && wf == Fluids.LAVA) - world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState()); + Fluid wf = worldFluid.getType(); + if (pf.is(FluidTags.WATER) && wf == Fluids.LAVA) + world.setBlockAndUpdate(pos, Blocks.OBSIDIAN.defaultBlockState()); else if (pf == Fluids.WATER && wf == Fluids.FLOWING_LAVA) - world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); + world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState()); else if (pf == Fluids.LAVA && wf == Fluids.WATER) - world.setBlockState(pos, Blocks.STONE.getDefaultState()); + world.setBlockAndUpdate(pos, Blocks.STONE.defaultBlockState()); else if (pf == Fluids.LAVA && wf == Fluids.FLOWING_WATER) - world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); + world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState()); if (pf == Fluids.LAVA) { BlockState lavaInteraction = AllFluids.getLavaInteraction(worldFluid); if (lavaInteraction != null) - world.setBlockState(pos, lavaInteraction); + world.setBlockAndUpdate(pos, lavaInteraction); } else if (wf == Fluids.FLOWING_LAVA && FluidHelper.hasBlockState(pf)) { BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(pf) - .getDefaultState()); + .defaultFluidState()); if (lavaInteraction != null) - world.setBlockState(pos, lavaInteraction); + world.setBlockAndUpdate(pos, lavaInteraction); } } 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..0d7bb5199 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; @@ -26,14 +29,14 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { public static BehaviourType TYPE = new BehaviourType<>(); - enum UpdatePhase { + public enum UpdatePhase { WAIT_FOR_PUMPS, // Do not run Layer II logic while pumps could still be distributing pressure FLIP_FLOWS, // Do not cut any flows until all pipes had a chance to reverse them IDLE; // Operate normally } - Map interfaces; - UpdatePhase phase; + public Map interfaces; + public UpdatePhase phase; public FluidTransportBehaviour(SmartTileEntity te) { super(te); @@ -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.isClientSide || 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; @@ -142,7 +145,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { if (interfaces == null) interfaces = new IdentityHashMap<>(); for (Direction face : Iterate.directions) - if (nbt.contains(face.getName2())) + if (nbt.contains(face.getName())) interfaces.computeIfAbsent(face, d -> new PipeConnection(d)); // Invalid data (missing/outdated). Defer init to runtime @@ -152,7 +155,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { } interfaces.values() - .forEach(connection -> connection.deserializeNBT(nbt, clientPacket)); + .forEach(connection -> connection.deserializeNBT(nbt, tileEntity.getBlockPos(), clientPacket)); } @Override @@ -235,15 +238,15 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { if (!canHaveFlowToward(state, direction)) return AttachmentTypes.NONE; - BlockPos offsetPos = pos.offset(direction); + BlockPos offsetPos = pos.relative(direction); BlockState facingState = world.getBlockState(offsetPos); - if (facingState.getBlock() instanceof PumpBlock && facingState.get(PumpBlock.FACING) + if (facingState.getBlock() instanceof PumpBlock && facingState.getValue(PumpBlock.FACING) .getAxis() == direction.getAxis()) return AttachmentTypes.NONE; if (AllBlocks.ENCASED_FLUID_PIPE.has(facingState) - && facingState.get(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(direction.getOpposite()))) + && facingState.getValue(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(direction.getOpposite()))) return AttachmentTypes.NONE; if (FluidPropagator.hasFluidCapability(world, offsetPos, direction.getOpposite()) @@ -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<>($ -> new HashMap<>()); + + 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..47e344737 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 @@ -1,8 +1,9 @@ package com.simibubi.create.content.contraptions.fluids; -import static net.minecraft.state.properties.BlockStateProperties.HONEY_LEVEL; +import static net.minecraft.state.properties.BlockStateProperties.LEVEL_HONEY; import static net.minecraft.state.properties.BlockStateProperties.WATERLOGGED; +import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; @@ -10,6 +11,7 @@ import javax.annotation.Nullable; import com.simibubi.create.AllFluids; import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; import com.simibubi.create.foundation.advancement.AllTriggers; +import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.utility.BlockFace; @@ -31,6 +33,7 @@ import net.minecraft.util.SoundEvents; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.common.Tags; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -38,9 +41,16 @@ import net.minecraftforge.fluids.capability.templates.FluidTank; public class OpenEndedPipe extends FlowSource { - World world; - BlockPos pos; - AxisAlignedBB aoe; + private static final List EFFECT_HANDLERS = new ArrayList<>(); + + static { + registerEffectHandler(new PotionEffectHandler()); + registerEffectHandler(new MilkEffectHandler()); + } + + private World world; + private BlockPos pos; + private AxisAlignedBB aoe; private OpenEndFluidHandler fluidHandler; private BlockPos outputPos; @@ -54,9 +64,29 @@ public class OpenEndedPipe extends FlowSource { fluidHandler = new OpenEndFluidHandler(); outputPos = face.getConnectedPos(); pos = face.getPos(); - aoe = new AxisAlignedBB(outputPos).expand(0, -1, 0); + aoe = new AxisAlignedBB(outputPos).expandTowards(0, -1, 0); if (face.getFace() == Direction.DOWN) - aoe = aoe.expand(0, -1, 0); + aoe = aoe.expandTowards(0, -1, 0); + } + + public static void registerEffectHandler(IEffectHandler handler) { + EFFECT_HANDLERS.add(handler); + } + + public World getWorld() { + return world; + } + + public BlockPos getPos() { + return pos; + } + + public BlockPos getOutputPos() { + return outputPos; + } + + public AxisAlignedBB getAOE() { + return aoe; } @Override @@ -64,6 +94,32 @@ public class OpenEndedPipe extends FlowSource { this.world = world; } + @Override + public LazyOptional provideHandler() { + return LazyOptional.of(() -> fluidHandler); + } + + @Override + public boolean isEndpoint() { + return true; + } + + public CompoundNBT serializeNBT() { + CompoundNBT compound = new CompoundNBT(); + fluidHandler.writeToNBT(compound); + compound.putBoolean("Pulling", wasPulling); + compound.put("Location", location.serializeNBT()); + return compound; + } + + 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; + } + private FluidStack removeFluidFromSpace(boolean simulate) { FluidStack empty = FluidStack.EMPTY; if (world == null) @@ -73,13 +129,13 @@ public class OpenEndedPipe extends FlowSource { BlockState state = world.getBlockState(outputPos); FluidState fluidState = state.getFluidState(); - boolean waterlog = state.contains(WATERLOGGED); - - if (state.contains(HONEY_LEVEL) && state.get(HONEY_LEVEL) >= 5) { + boolean waterlog = state.hasProperty(WATERLOGGED); + + if (state.hasProperty(LEVEL_HONEY) && state.getValue(LEVEL_HONEY) >= 5) { if (!simulate) - world.setBlockState(outputPos, state.with(HONEY_LEVEL, 0), 3); + world.setBlock(outputPos, state.setValue(LEVEL_HONEY, 0), 3); return new FluidStack(AllFluids.HONEY.get() - .getStillFluid(), 250); + .getSource(), 250); } if (!waterlog && !state.getMaterial() @@ -88,7 +144,7 @@ public class OpenEndedPipe extends FlowSource { if (fluidState.isEmpty() || !fluidState.isSource()) return empty; - FluidStack stack = new FluidStack(fluidState.getFluid(), 1000); + FluidStack stack = new FluidStack(fluidState.getType(), 1000); if (simulate) return stack; @@ -96,13 +152,13 @@ public class OpenEndedPipe extends FlowSource { AllTriggers.triggerForNearbyPlayers(AllTriggers.PIPE_SPILL, world, pos, 5); if (waterlog) { - world.setBlockState(outputPos, state.with(WATERLOGGED, false), 3); - world.getPendingFluidTicks() + world.setBlock(outputPos, state.setValue(WATERLOGGED, false), 3); + world.getLiquidTicks() .scheduleTick(outputPos, Fluids.WATER, 1); return stack; } - world.setBlockState(outputPos, fluidState.getBlockState() - .with(FlowingFluidBlock.LEVEL, 14), 3); + world.setBlock(outputPos, fluidState.createLegacyBlock() + .setValue(FlowingFluidBlock.LEVEL, 14), 3); return stack; } @@ -114,7 +170,7 @@ public class OpenEndedPipe extends FlowSource { BlockState state = world.getBlockState(outputPos); FluidState fluidState = state.getFluidState(); - boolean waterlog = state.contains(WATERLOGGED); + boolean waterlog = state.hasProperty(WATERLOGGED); if (!waterlog && !state.getMaterial() .isReplaceable()) @@ -123,11 +179,11 @@ public class OpenEndedPipe extends FlowSource { return false; if (!FluidHelper.hasBlockState(fluid.getFluid())) { if (!simulate) - applyEffects(world, fluid); + applyEffects(fluid); return true; } - if (!fluidState.isEmpty() && fluidState.getFluid() != fluid.getFluid()) { + if (!fluidState.isEmpty() && fluidState.getType() != fluid.getFluid()) { FluidReactions.handlePipeSpillCollision(world, outputPos, fluid.getFluid(), fluidState); return false; } @@ -139,80 +195,51 @@ public class OpenEndedPipe extends FlowSource { if (simulate) return true; - if (world.getDimension().isUltrawarm() && fluid.getFluid() - .isIn(FluidTags.WATER)) { + if (world.dimensionType() + .ultraWarm() + && fluid.getFluid() + .is(FluidTags.WATER)) { int i = outputPos.getX(); int j = outputPos.getY(); int k = outputPos.getZ(); - world.playSound(null, i, j, k, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, - 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F); + world.playSound(null, i, j, k, SoundEvents.FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, + 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F); return true; } AllTriggers.triggerForNearbyPlayers(AllTriggers.PIPE_SPILL, world, pos, 5); if (waterlog) { - world.setBlockState(outputPos, state.with(WATERLOGGED, true), 3); - world.getPendingFluidTicks() + world.setBlock(outputPos, state.setValue(WATERLOGGED, true), 3); + world.getLiquidTicks() .scheduleTick(outputPos, Fluids.WATER, 1); return true; } - world.setBlockState(outputPos, fluid.getFluid() - .getDefaultState() - .getBlockState(), 3); + + if (!AllConfigs.SERVER.fluids.placeFluidSourceBlocks.get()) + return true; + + world.setBlock(outputPos, fluid.getFluid() + .defaultFluidState() + .createLegacyBlock(), 3); return true; } - private void applyEffects(World world, FluidStack fluid) { - if (!fluid.getFluid() - .isEquivalentTo(AllFluids.POTION.get())) { - // other fx - return; - } - - if (cachedFluid == null || cachedEffects == null || !fluid.isFluidEqual(cachedFluid)) { - FluidStack copy = fluid.copy(); - copy.setAmount(250); - ItemStack bottle = PotionFluidHandler.fillBottle(new ItemStack(Items.GLASS_BOTTLE), fluid); - cachedEffects = PotionUtils.getEffectsFromStack(bottle); - } - - if (cachedEffects.isEmpty()) - return; - - List list = - this.world.getEntitiesWithinAABB(LivingEntity.class, aoe, LivingEntity::canBeHitWithPotion); - for (LivingEntity livingentity : list) { - for (EffectInstance effectinstance : cachedEffects) { - Effect effect = effectinstance.getPotion(); - if (effect.isInstant()) { - effect.affectEntity(null, null, livingentity, effectinstance.getAmplifier(), 0.5D); - continue; - } - livingentity.addPotionEffect(new EffectInstance(effectinstance)); + private boolean canApplyEffects(FluidStack fluid) { + for (IEffectHandler handler : EFFECT_HANDLERS) { + if (handler.canApplyEffects(this, fluid)) { + return true; } } - + return false; } - @Override - public LazyOptional provideHandler() { - return LazyOptional.of(() -> fluidHandler); - } - - public CompoundNBT serializeNBT() { - CompoundNBT compound = new CompoundNBT(); - fluidHandler.writeToNBT(compound); - compound.putBoolean("Pulling", wasPulling); - compound.put("Location", location.serializeNBT()); - return compound; - } - - public static OpenEndedPipe fromNBT(CompoundNBT compound) { - OpenEndedPipe oep = new OpenEndedPipe(BlockFace.fromNBT(compound.getCompound("Location"))); - oep.fluidHandler.readFromNBT(compound); - oep.wasPulling = compound.getBoolean("Pulling"); - return oep; + private void applyEffects(FluidStack fluid) { + for (IEffectHandler handler : EFFECT_HANDLERS) { + if (handler.canApplyEffects(this, fluid)) { + handler.applyEffects(this, fluid); + } + } } private class OpenEndFluidHandler extends FluidTank { @@ -233,15 +260,20 @@ public class OpenEndedPipe extends FlowSource { if (!provideFluidToSpace(resource, true)) return 0; - if (!getFluid().isEmpty() && !getFluid().isFluidEqual(resource)) + FluidStack containedFluidStack = getFluid(); + if (!containedFluidStack.isEmpty() && !containedFluidStack.isFluidEqual(resource)) setFluid(FluidStack.EMPTY); if (wasPulling) wasPulling = false; + if (canApplyEffects(resource)) + resource = FluidHelper.copyStackWithAmount(resource, 1); int fill = super.fill(resource, action); - if (action.execute() && (getFluidAmount() == 1000 || !FluidHelper.hasBlockState(getFluid().getFluid())) - && provideFluidToSpace(getFluid(), false)) - setFluid(FluidStack.EMPTY); + if (action.simulate()) + return fill; + if (getFluidAmount() == 1000 || !FluidHelper.hasBlockState(containedFluidStack.getFluid())) + if (provideFluidToSpace(containedFluidStack, false)) + setFluid(FluidStack.EMPTY); return fill; } @@ -297,9 +329,62 @@ public class OpenEndedPipe extends FlowSource { } - @Override - public boolean isEndpoint() { - return true; + public interface IEffectHandler { + boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid); + + void applyEffects(OpenEndedPipe pipe, FluidStack fluid); + } + + public static class PotionEffectHandler implements IEffectHandler { + @Override + public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) { + return fluid.getFluid().isSame(AllFluids.POTION.get()); + } + + @Override + public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) { + if (pipe.cachedFluid == null || pipe.cachedEffects == null || !fluid.isFluidEqual(pipe.cachedFluid)) { + FluidStack copy = fluid.copy(); + copy.setAmount(250); + ItemStack bottle = PotionFluidHandler.fillBottle(new ItemStack(Items.GLASS_BOTTLE), fluid); + pipe.cachedEffects = PotionUtils.getMobEffects(bottle); + } + + if (pipe.cachedEffects.isEmpty()) + return; + + List list = + pipe.getWorld().getEntitiesOfClass(LivingEntity.class, pipe.getAOE(), LivingEntity::isAffectedByPotions); + for (LivingEntity livingentity : list) { + for (EffectInstance effectinstance : pipe.cachedEffects) { + Effect effect = effectinstance.getEffect(); + if (effect.isInstantenous()) { + effect.applyInstantenousEffect(null, null, livingentity, effectinstance.getAmplifier(), 0.5D); + } else { + livingentity.addEffect(new EffectInstance(effectinstance)); + } + } + } + } + } + + public static class MilkEffectHandler implements IEffectHandler { + @Override + public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) { + return Tags.Fluids.MILK.contains(fluid.getFluid()); + } + + @Override + public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) { + World world = pipe.getWorld(); + if (world.getGameTime() % 5 != 0) + return; + List list = + world.getEntitiesOfClass(LivingEntity.class, pipe.getAOE(), LivingEntity::isAffectedByPotions); + ItemStack curativeItem = new ItemStack(Items.MILK_BUCKET); + for (LivingEntity livingentity : list) + livingentity.curePotionEffects(curativeItem); + } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeAttachmentModel.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeAttachmentModel.java index cda095609..686d00915 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeAttachmentModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeAttachmentModel.java @@ -90,8 +90,8 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData { public void putBracket(BlockState state) { this.bracket = Minecraft.getInstance() - .getBlockRendererDispatcher() - .getModelForState(state); + .getBlockRenderer() + .getBlockModel(state); } public IBakedModel getBracket() { @@ -99,7 +99,7 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData { } public void putRim(Direction face, AttachmentTypes rim) { - rims[face.getIndex()] = rim; + rims[face.get3DDataValue()] = rim; } public void setEncased(boolean encased) { @@ -107,11 +107,11 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData { } public boolean hasRim(Direction face) { - return rims[face.getIndex()] != AttachmentTypes.NONE; + return rims[face.get3DDataValue()] != AttachmentTypes.NONE; } public AttachmentTypes getRim(Direction face) { - return rims[face.getIndex()]; + return rims[face.get3DDataValue()]; } public boolean isEncased() { 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..3ef881ba0 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 @@ -32,7 +32,7 @@ import net.minecraftforge.fml.DistExecutor; public class PipeConnection { - Direction side; + public Direction side; // Layer I Couple pressure; // [inbound, outward] @@ -87,7 +87,7 @@ public class PipeConnection { FlowSource flowSource = source.get(); flowSource.manageSource(world); } - + public boolean manageFlows(World world, BlockPos pos, FluidStack internalFluid, Predicate extractionPredicate) { @@ -178,7 +178,7 @@ public class PipeConnection { } FluidTransportBehaviour behaviour = - TileEntityBehaviour.get(world, pos.offset(side), FluidTransportBehaviour.TYPE); + TileEntityBehaviour.get(world, pos.relative(side), FluidTransportBehaviour.TYPE); source = Optional.of(behaviour == null ? new FlowSource.Blocked(location) : new FlowSource.OtherPipe(location)); return true; } @@ -190,10 +190,10 @@ public class PipeConnection { if (flow.fluid.isEmpty()) return; - if (world.isRemote) { + if (world.isClientSide) { if (!source.isPresent()) determineSource(world, pos); - + spawnParticles(world, pos, flow.fluid); if (particleSplashNextTick) spawnSplashOnRim(world, pos, flow.fluid); @@ -211,12 +211,12 @@ public class PipeConnection { public void serializeNBT(CompoundNBT tag, boolean clientPacket) { CompoundNBT connectionData = new CompoundNBT(); - tag.put(side.getName2(), connectionData); + tag.put(side.getName(), connectionData); if (hasPressure()) { ListNBT pressureData = new ListNBT(); - pressureData.add(FloatNBT.of(getInboundPressure())); - pressureData.add(FloatNBT.of(getOutwardPressure())); + pressureData.add(FloatNBT.valueOf(getInboundPressure())); + pressureData.add(FloatNBT.valueOf(getOutwardPressure())); connectionData.put("Pressure", pressureData); } @@ -239,8 +239,8 @@ public class PipeConnection { return source.orElse(null) instanceof OpenEndedPipe; } - public void deserializeNBT(CompoundNBT tag, boolean clientPacket) { - CompoundNBT connectionData = tag.getCompound(side.getName2()); + public void deserializeNBT(CompoundNBT tag, BlockPos tilePos, boolean clientPacket) { + CompoundNBT connectionData = tag.getCompound(side.getName()); if (connectionData.contains("Pressure")) { ListNBT pressureData = connectionData.getList("Pressure", NBT.TAG_FLOAT); @@ -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"); @@ -282,8 +282,8 @@ public class PipeConnection { /** * @return zero if outward == inbound
- * positive if outward > inbound
- * negative if outward < inbound + * positive if outward {@literal >} inbound
+ * negative if outward {@literal <} inbound */ public float comparePressure() { return getOutwardPressure() - getInboundPressure(); @@ -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().level) + 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().level) + if (!isRenderEntityWithinDistance(pos)) + return; spawnRimParticles(world, pos, fluid, SPLASH_PARTICLE_AMOUNT); } @@ -396,7 +398,7 @@ public class PipeConnection { @OnlyIn(Dist.CLIENT) private void spawnPouringLiquid(World world, BlockPos pos, FluidStack fluid, int amount) { IParticleData particle = FluidFX.getFluidParticle(fluid); - Vector3d directionVec = Vector3d.of(side.getDirectionVec()); + Vector3d directionVec = Vector3d.atLowerCornerOf(side.getNormal()); if (!hasFlow()) return; Flow flow = this.flow.get(); @@ -406,11 +408,11 @@ public class PipeConnection { @OnlyIn(Dist.CLIENT) public static boolean isRenderEntityWithinDistance(BlockPos pos) { Entity renderViewEntity = Minecraft.getInstance() - .getRenderViewEntity(); + .getCameraEntity(); if (renderViewEntity == null) return false; Vector3d center = VecHelper.getCenterOf(pos); - if (renderViewEntity.getPositionVec() + if (renderViewEntity.position() .distanceTo(center) > MAX_PARTICLE_RENDER_DISTANCE) return false; return true; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java index 6dd88516a..1caa73897 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java @@ -2,8 +2,6 @@ package com.simibubi.create.content.contraptions.fluids; import java.util.Random; -import org.apache.commons.lang3.mutable.MutableBoolean; - import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; @@ -36,7 +34,7 @@ public class PumpBlock extends DirectionalKineticBlock implements IWaterLoggable public PumpBlock(Properties p_i48415_1_) { super(p_i48415_1_); - setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); + registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); } @Override @@ -51,95 +49,68 @@ public class PumpBlock extends DirectionalKineticBlock implements IWaterLoggable @Override public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { - return originalState.with(FACING, originalState.get(FACING) + return originalState.setValue(FACING, originalState.getValue(FACING) .getOpposite()); } @Override public BlockState updateAfterWrenched(BlockState newState, ItemUseContext context) { - BlockState state = super.updateAfterWrenched(newState, context); - World world = context.getWorld(); - BlockPos pos = context.getPos(); - if (world.isRemote) - return state; - TileEntity tileEntity = world.getTileEntity(pos); - if (!(tileEntity instanceof PumpTileEntity)) - return state; - PumpTileEntity pump = (PumpTileEntity) tileEntity; - pump.sidesToUpdate.forEach(MutableBoolean::setTrue); - pump.reversed = !pump.reversed; - return state; + return super.updateAfterWrenched(newState, context); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(FACING) + return state.getValue(FACING) .getAxis(); } @Override public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, ISelectionContext p_220053_4_) { - return AllShapes.PUMP.get(state.get(FACING)); + return AllShapes.PUMP.get(state.getValue(FACING)); } @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos, boolean isMoving) { - DebugPacketSender.func_218806_a(world, pos); + DebugPacketSender.sendNeighborsUpdatePacket(world, pos); Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving); if (d == null) return; if (!isOpenAt(state, d)) return; - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); -// if (world.isRemote) -// return; -// if (otherBlock instanceof FluidPipeBlock) -// return; -// TileEntity tileEntity = world.getTileEntity(pos); -// if (!(tileEntity instanceof PumpTileEntity)) -// return; -// PumpTileEntity pump = (PumpTileEntity) tileEntity; -// Direction facing = state.get(FACING); -// for (boolean front : Iterate.trueAndFalse) { -// Direction side = front ? facing : facing.getOpposite(); -// if (!pos.offset(side) -// .equals(neighborPos)) -// continue; -// pump.updatePipesOnSide(side); -// } } @Override public FluidState getFluidState(BlockState state) { - return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) - : Fluids.EMPTY.getDefaultState(); + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) + : Fluids.EMPTY.defaultFluidState(); } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(BlockStateProperties.WATERLOGGED); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, - IWorld world, BlockPos pos, BlockPos neighbourPos) { - if (state.get(BlockStateProperties.WATERLOGGED)) { - world.getPendingFluidTicks() - .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world, + BlockPos pos, BlockPos neighbourPos) { + if (state.getValue(BlockStateProperties.WATERLOGGED)) { + world.getLiquidTicks() + .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } return state; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - FluidState FluidState = context.getWorld() - .getFluidState(context.getPos()); - return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, - Boolean.valueOf(FluidState.getFluid() == Fluids.WATER)); + FluidState FluidState = context.getLevel() + .getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, + Boolean.valueOf(FluidState.getType() == Fluids.WATER)); } public static boolean isPump(BlockState state) { @@ -147,36 +118,46 @@ public class PumpBlock extends DirectionalKineticBlock implements IWaterLoggable } @Override - public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { - if (world.isRemote) + public void onPlace(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, world, pos, oldState, isMoving); + if (world.isClientSide) return; if (state != oldState) - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); + + if (isPump(state) && isPump(oldState) && state.getValue(FACING) == oldState.getValue(FACING) + .getOpposite()) { + TileEntity tileEntity = world.getBlockEntity(pos); + if (!(tileEntity instanceof PumpTileEntity)) + return; + PumpTileEntity pump = (PumpTileEntity) tileEntity; + pump.pressureUpdate = true; + } } public static boolean isOpenAt(BlockState state, Direction d) { - return d.getAxis() == state.get(FACING) + return d.getAxis() == state.getValue(FACING) .getAxis(); } @Override - public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random r) { + public void tick(BlockState state, ServerWorld world, BlockPos pos, Random r) { FluidPropagator.propagateChangedPipe(world, pos, state); } @Override - public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { boolean blockTypeChanged = state.getBlock() != newState.getBlock(); - if (blockTypeChanged && !world.isRemote) + if (blockTypeChanged && !world.isClientSide) FluidPropagator.propagateChangedPipe(world, pos, state); if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity())) - world.removeTileEntity(pos); + world.removeBlockEntity(pos); } - + @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } - + } 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..5c6886304 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,26 +2,26 @@ 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.material.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); + Direction facing = referenceState.getValue(FACING); return getRotatingMaterial().getModel(AllBlockPartials.MECHANICAL_PUMP_COG, referenceState, facing); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java index 8ecc077a4..9c92d47d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.fluids; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; @@ -7,7 +8,6 @@ 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.utility.AngleHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -34,10 +34,10 @@ public class PumpRenderer extends KineticTileEntityRenderer { BlockState blockState = te.getBlockState(); float angle = MathHelper.lerp(pump.arrowDirection.getValue(partialTicks), 0, 90) - 90; for (float yRot : new float[] { 0, 90 }) { - ms.push(); + ms.pushPose(); SuperByteBuffer arrow = PartialBufferer.get(AllBlockPartials.MECHANICAL_PUMP_ARROW, blockState); - Direction direction = blockState.get(PumpBlock.FACING); - MatrixStacker.of(ms) + Direction direction = blockState.getValue(PumpBlock.FACING); + MatrixTransformStack.of(ms) .centre() .rotateY(AngleHelper.horizontalAngle(direction) + 180) .rotateX(-AngleHelper.verticalAngle(direction) - 90) @@ -46,8 +46,8 @@ public class PumpRenderer extends KineticTileEntityRenderer { .rotateY(yRot) .rotateZ(angle) .translateBack(rotationOffset); - arrow.light(light).renderInto(ms, buffer.getBuffer(RenderType.getSolid())); - ms.pop(); + arrow.light(light).renderInto(ms, buffer.getBuffer(RenderType.solid())); + ms.popPose(); } } 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..9428867f0 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 @@ -39,6 +39,7 @@ public class PumpTileEntity extends KineticTileEntity { LerpedFloat arrowDirection; Couple sidesToUpdate; + boolean pressureUpdate; boolean reversed; public PumpTileEntity(TileEntityType typeIn) { @@ -65,13 +66,17 @@ public class PumpTileEntity extends KineticTileEntity { super.tick(); float speed = getSpeed(); - if (world.isRemote) { + if (level.isClientSide) { if (speed == 0) return; arrowDirection.chase(speed >= 0 ? 1 : -1, .5f, Chaser.EXP); arrowDirection.tickChaser(); - return; + if (!isVirtual()) + return; } + +// if (pressureUpdate) +// updatePressureChange(); sidesToUpdate.forEachWithContext((update, isFront) -> { if (update.isFalse()) @@ -84,6 +89,7 @@ public class PumpTileEntity extends KineticTileEntity { return; if (speed < 0 != reversed) { reversed = speed < 0; + updatePressureChange(); return; } } @@ -96,14 +102,19 @@ public class PumpTileEntity extends KineticTileEntity { return; if (speed != 0) reversed = speed < 0; - if (world.isRemote) + if (level.isClientSide && !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)); - + updatePressureChange(); + } + + public void updatePressureChange() { + pressureUpdate = false; + BlockPos frontPos = worldPosition.relative(getFront()); + BlockPos backPos = worldPosition.relative(getFront().getOpposite()); + FluidPropagator.propagateChangedPipe(level, frontPos, level.getBlockState(frontPos)); + FluidPropagator.propagateChangedPipe(level, backPos, level.getBlockState(backPos)); + FluidTransportBehaviour behaviour = getBehaviour(FluidTransportBehaviour.TYPE); if (behaviour != null) behaviour.wipePressure(); @@ -114,17 +125,17 @@ public class PumpTileEntity extends KineticTileEntity { if (getSpeed() == 0) return; - BlockFace start = new BlockFace(pos, side); + BlockFace start = new BlockFace(worldPosition, side); boolean pull = isPullingOnSide(isFront(side)); Set targets = new HashSet<>(); Map>> pipeGraph = new HashMap<>(); if (!pull) - FluidPropagator.resetAffectedFluidNetworks(world, pos, side.getOpposite()); + FluidPropagator.resetAffectedFluidNetworks(level, worldPosition, side.getOpposite()); - if (!hasReachedValidEndpoint(world, start, pull)) { + if (!hasReachedValidEndpoint(level, start, pull)) { - pipeGraph.computeIfAbsent(pos, $ -> Pair.of(0, new IdentityHashMap<>())) + pipeGraph.computeIfAbsent(worldPosition, $ -> Pair.of(0, new IdentityHashMap<>())) .getSecond() .put(side, pull); pipeGraph.computeIfAbsent(start.getConnectedPos(), $ -> Pair.of(1, new IdentityHashMap<>())) @@ -141,13 +152,13 @@ public class PumpTileEntity extends KineticTileEntity { int distance = entry.getFirst(); BlockPos currentPos = entry.getSecond(); - if (!world.isAreaLoaded(currentPos, 0)) + if (!level.isAreaLoaded(currentPos, 0)) continue; if (visited.contains(currentPos)) continue; visited.add(currentPos); - BlockState currentState = world.getBlockState(currentPos); - FluidTransportBehaviour pipe = FluidPropagator.getPipe(world, currentPos); + BlockState currentState = level.getBlockState(currentPos); + FluidTransportBehaviour pipe = FluidPropagator.getPipe(level, currentPos); if (pipe == null) continue; @@ -155,11 +166,11 @@ public class PumpTileEntity extends KineticTileEntity { BlockFace blockFace = new BlockFace(currentPos, face); BlockPos connectedPos = blockFace.getConnectedPos(); - if (!world.isAreaLoaded(connectedPos, 0)) + if (!level.isAreaLoaded(connectedPos, 0)) continue; if (blockFace.isEquivalent(start)) continue; - if (hasReachedValidEndpoint(world, blockFace, pull)) { + if (hasReachedValidEndpoint(level, blockFace, pull)) { pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())) .getSecond() .put(face, pull); @@ -167,7 +178,7 @@ public class PumpTileEntity extends KineticTileEntity { continue; } - FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(world, connectedPos); + FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(level, connectedPos); if (pipeBehaviour == null) continue; if (pipeBehaviour instanceof PumpFluidTransferBehaviour) @@ -205,13 +216,13 @@ public class PumpTileEntity extends KineticTileEntity { BlockPos pipePos = face.getPos(); Direction pipeSide = face.getFace(); - if (pipePos.equals(pos)) + if (pipePos.equals(worldPosition)) continue; boolean inbound = pipeGraph.get(pipePos) .getSecond() .get(pipeSide); - FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(world, pipePos); + FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(level, pipePos); if (pipeBehaviour == null) continue; @@ -248,7 +259,7 @@ public class PumpTileEntity extends KineticTileEntity { if (map.get(nextFacing) != pull) continue; if (!searchForEndpointRecursively(pipeGraph, targets, validFaces, - new BlockFace(currentPos.offset(nextFacing), nextFacing.getOpposite()), pull)) + new BlockFace(currentPos.relative(nextFacing), nextFacing.getOpposite()), pull)) continue; validFaces.computeIfAbsent(distance, $ -> new HashSet<>()) @@ -266,11 +277,11 @@ public class PumpTileEntity extends KineticTileEntity { private boolean hasReachedValidEndpoint(IWorld world, BlockFace blockFace, boolean pull) { BlockPos connectedPos = blockFace.getConnectedPos(); BlockState connectedState = world.getBlockState(connectedPos); - TileEntity tileEntity = world.getTileEntity(connectedPos); + TileEntity tileEntity = world.getBlockEntity(connectedPos); Direction face = blockFace.getFace(); // facing a pump - if (PumpBlock.isPump(connectedState) && connectedState.get(PumpBlock.FACING) + if (PumpBlock.isPump(connectedState) && connectedState.getValue(PumpBlock.FACING) .getAxis() == face.getAxis() && tileEntity instanceof PumpTileEntity) { PumpTileEntity pumpTE = (PumpTileEntity) tileEntity; return pumpTE.isPullingOnSide(pumpTE.isFront(blockFace.getOppositeFace())) != pull; @@ -316,7 +327,7 @@ public class PumpTileEntity extends KineticTileEntity { BlockState blockState = getBlockState(); if (!(blockState.getBlock() instanceof PumpBlock)) return false; - Direction front = blockState.get(PumpBlock.FACING); + Direction front = blockState.getValue(PumpBlock.FACING); boolean isFront = side == front; return isFront; } @@ -326,7 +337,7 @@ public class PumpTileEntity extends KineticTileEntity { BlockState blockState = getBlockState(); if (!(blockState.getBlock() instanceof PumpBlock)) return null; - return blockState.get(PumpBlock.FACING); + return blockState.getValue(PumpBlock.FACING); } protected void updatePipeNetwork(boolean front) { @@ -338,7 +349,7 @@ public class PumpTileEntity extends KineticTileEntity { BlockState blockState = getBlockState(); if (!(blockState.getBlock() instanceof PumpBlock)) return false; - return blockState.get(PumpBlock.FACING) + return blockState.getValue(PumpBlock.FACING) .getAxis() == side.getAxis(); } @@ -380,7 +391,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/VirtualFluid.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/VirtualFluid.java index 9ab196582..c7b5c930c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/VirtualFluid.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/VirtualFluid.java @@ -15,23 +15,23 @@ public class VirtualFluid extends ForgeFlowingFluid { } @Override - public Fluid getStillFluid() { - return super.getStillFluid(); + public Fluid getSource() { + return super.getSource(); } @Override - public Fluid getFlowingFluid() { + public Fluid getFlowing() { return this; } @Override - public Item getFilledBucket() { + public Item getBucket() { return Items.AIR; } @Override - protected BlockState getBlockState(FluidState state) { - return Blocks.AIR.getDefaultState(); + protected BlockState createLegacyBlock(FluidState state) { + return Blocks.AIR.defaultBlockState(); } @Override @@ -40,7 +40,7 @@ public class VirtualFluid extends ForgeFlowingFluid { } @Override - public int getLevel(FluidState p_207192_1_) { + public int getAmount(FluidState p_207192_1_) { return 0; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingBySpout.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingBySpout.java index fc012e730..314a02e88 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingBySpout.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingBySpout.java @@ -1,8 +1,10 @@ package com.simibubi.create.content.contraptions.fluids.actors; import java.util.List; +import java.util.Optional; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; import com.simibubi.create.foundation.fluid.FluidIngredient; import net.minecraft.item.ItemStack; @@ -17,7 +19,13 @@ public class FillingBySpout { static RecipeWrapper wrapper = new RecipeWrapper(new ItemStackHandler(1)); public static boolean canItemBeFilled(World world, ItemStack stack) { - wrapper.setInventorySlotContents(0, stack); + wrapper.setItem(0, stack); + + Optional assemblyRecipe = + SequencedAssemblyRecipe.getRecipe(world, wrapper, AllRecipeTypes.FILLING.getType(), FillingRecipe.class); + if (assemblyRecipe.isPresent()) + return true; + if (AllRecipeTypes.FILLING.find(wrapper, world) .isPresent()) return true; @@ -25,9 +33,19 @@ public class FillingBySpout { } public static int getRequiredAmountForItem(World world, ItemStack stack, FluidStack availableFluid) { - wrapper.setInventorySlotContents(0, stack); + wrapper.setItem(0, stack); + + Optional assemblyRecipe = + SequencedAssemblyRecipe.getRecipe(world, wrapper, AllRecipeTypes.FILLING.getType(), FillingRecipe.class); + if (assemblyRecipe.isPresent()) { + FluidIngredient requiredFluid = assemblyRecipe.get() + .getRequiredFluid(); + if (requiredFluid.test(availableFluid)) + return requiredFluid.getRequiredAmount(); + } + for (IRecipe recipe : world.getRecipeManager() - .getRecipes(AllRecipeTypes.FILLING.getType(), wrapper, world)) { + .getRecipesFor(AllRecipeTypes.FILLING.getType(), wrapper, world)) { FillingRecipe fillingRecipe = (FillingRecipe) recipe; FluidIngredient requiredFluid = fillingRecipe.getRequiredFluid(); if (requiredFluid.test(availableFluid)) @@ -40,19 +58,30 @@ public class FillingBySpout { FluidStack toFill = availableFluid.copy(); toFill.setAmount(requiredAmount); - wrapper.setInventorySlotContents(0, stack); - for (IRecipe recipe : world.getRecipeManager() - .getRecipes(AllRecipeTypes.FILLING.getType(), wrapper, world)) { - FillingRecipe fillingRecipe = (FillingRecipe) recipe; - FluidIngredient requiredFluid = fillingRecipe.getRequiredFluid(); - if (requiredFluid.test(toFill)) { - List results = fillingRecipe.rollResults(); - availableFluid.shrink(requiredAmount); - stack.shrink(1); - return results.isEmpty() ? ItemStack.EMPTY : results.get(0); - } + wrapper.setItem(0, stack); + + FillingRecipe fillingRecipe = + SequencedAssemblyRecipe.getRecipe(world, wrapper, AllRecipeTypes.FILLING.getType(), FillingRecipe.class) + .filter(fr -> fr.getRequiredFluid() + .test(toFill)) + .orElseGet(() -> { + for (IRecipe recipe : world.getRecipeManager() + .getRecipesFor(AllRecipeTypes.FILLING.getType(), wrapper, world)) { + FillingRecipe fr = (FillingRecipe) recipe; + FluidIngredient requiredFluid = fr.getRequiredFluid(); + if (requiredFluid.test(toFill)) + return fr; + } + return null; + }); + + if (fillingRecipe != null) { + List results = fillingRecipe.rollResults(); + availableFluid.shrink(requiredAmount); + stack.shrink(1); + return results.isEmpty() ? ItemStack.EMPTY : results.get(0); } - + return GenericItemFilling.fillItem(world, requiredAmount, stack, availableFluid); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingRecipe.java index 7a085f03a..21e3d3499 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingRecipe.java @@ -1,14 +1,30 @@ package com.simibubi.create.content.contraptions.fluids.actors; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; +import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; import com.simibubi.create.foundation.fluid.FluidIngredient; +import com.simibubi.create.foundation.utility.Lang; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +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.fluids.FluidStack; import net.minecraftforge.items.wrapper.RecipeWrapper; -public class FillingRecipe extends ProcessingRecipe { +public class FillingRecipe extends ProcessingRecipe implements IAssemblyRecipe { public FillingRecipe(ProcessingRecipeParams params) { super(AllRecipeTypes.FILLING, params); @@ -16,7 +32,8 @@ public class FillingRecipe extends ProcessingRecipe { @Override public boolean matches(RecipeWrapper inv, World p_77569_2_) { - return ingredients.get(0).test(inv.getStackInSlot(0)); + return ingredients.get(0) + .test(inv.getItem(0)); } @Override @@ -28,16 +45,46 @@ public class FillingRecipe extends ProcessingRecipe { protected int getMaxOutputCount() { return 1; } - + @Override protected int getMaxFluidInputCount() { return 1; } - + public FluidIngredient getRequiredFluid() { if (fluidIngredients.isEmpty()) throw new IllegalStateException("Filling Recipe: " + id.toString() + " has no fluid ingredient!"); return fluidIngredients.get(0); } + @Override + public void addAssemblyIngredients(List list) {} + + @Override + public void addAssemblyFluidIngredients(List list) { + list.add(getRequiredFluid()); + } + + @Override + @OnlyIn(Dist.CLIENT) + public ITextComponent getDescriptionForAssembly() { + List matchingFluidStacks = fluidIngredients.get(0) + .getMatchingFluidStacks(); + if (matchingFluidStacks.size() == 0) + return new StringTextComponent("Invalid"); + return Lang.translate("recipe.assembly.spout_filling_fluid", + new TranslationTextComponent(matchingFluidStacks.get(0) + .getTranslationKey()).getString()); + } + + @Override + public void addRequiredMachines(Set list) { + list.add(AllBlocks.SPOUT.get()); + } + + @Override + public Supplier> getJEISubCategory() { + return () -> SequencedAssemblySubCategory.AssemblySpouting::new; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java index 7d49cd826..73d864880 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java @@ -86,17 +86,18 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { BlockState emptied = blockState; Fluid fluid = Fluids.EMPTY; - if (blockState.contains(BlockStateProperties.WATERLOGGED) && blockState.get(BlockStateProperties.WATERLOGGED)) { - emptied = blockState.with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(false)); + if (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED)) { + emptied = blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(false)); fluid = Fluids.WATER; } else if (blockState.getBlock() instanceof FlowingFluidBlock) { FlowingFluidBlock flowingFluid = (FlowingFluidBlock) blockState.getBlock(); - emptied = Blocks.AIR.getDefaultState(); - if (blockState.get(FlowingFluidBlock.LEVEL) == 0) + emptied = Blocks.AIR.defaultBlockState(); + if (blockState.getValue(FlowingFluidBlock.LEVEL) == 0) fluid = flowingFluid.getFluid(); else { - affectedArea.expandTo(new MutableBoundingBox(currentPos, currentPos)); - world.setBlockState(currentPos, emptied, 2 | 16); + affectedArea.expand(new MutableBoundingBox(currentPos, currentPos)); + if (!tileEntity.isVirtual()) + world.setBlock(currentPos, emptied, 2 | 16); queue.dequeue(); if (queue.isEmpty()) { isValid = checkValid(world, rootPos); @@ -105,18 +106,18 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { continue; } } else if (blockState.getFluidState() - .getFluid() != Fluids.EMPTY - && blockState.getCollisionShape(world, currentPos, ISelectionContext.dummy()) + .getType() != Fluids.EMPTY + && blockState.getCollisionShape(world, currentPos, ISelectionContext.empty()) .isEmpty()) { fluid = blockState.getFluidState() - .getFluid(); - emptied = Blocks.AIR.getDefaultState(); + .getType(); + emptied = Blocks.AIR.defaultBlockState(); } if (this.fluid == null) this.fluid = fluid; - if (!this.fluid.isEquivalentTo(fluid)) { + if (!this.fluid.isSame(fluid)) { queue.dequeue(); if (queue.isEmpty()) { isValid = checkValid(world, rootPos); @@ -129,15 +130,16 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { return true; playEffect(world, currentPos, fluid, true); - AllTriggers.triggerForNearbyPlayers(AllTriggers.HOSE_PULLEY, world, tileEntity.getPos(), 8); + AllTriggers.triggerForNearbyPlayers(AllTriggers.HOSE_PULLEY, world, tileEntity.getBlockPos(), 8); if (infinite) { - AllTriggers.triggerForNearbyPlayers(AllTriggers.INFINITE_FLUID.constructTriggerFor(FluidHelper.convertToStill(fluid)), world, tileEntity.getPos(), 8); + AllTriggers.triggerForNearbyPlayers(AllTriggers.INFINITE_FLUID.constructTriggerFor(FluidHelper.convertToStill(fluid)), world, tileEntity.getBlockPos(), 8); return true; } - world.setBlockState(currentPos, emptied, 2 | 16); - affectedArea.expandTo(new MutableBoundingBox(currentPos, currentPos)); + if (!tileEntity.isVirtual()) + world.setBlock(currentPos, emptied, 2 | 16); + affectedArea.expand(new MutableBoundingBox(currentPos, currentPos)); queue.dequeue(); if (queue.isEmpty()) { @@ -173,10 +175,10 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { protected boolean checkValid(World world, BlockPos root) { BlockPos currentPos = root; - for (int timeout = 1000; timeout > 0 && !root.equals(tileEntity.getPos()); timeout--) { + for (int timeout = 1000; timeout > 0 && !root.equals(tileEntity.getBlockPos()); timeout--) { FluidBlockType canPullFluidsFrom = canPullFluidsFrom(world.getBlockState(currentPos), currentPos); if (canPullFluidsFrom == FluidBlockType.FLOWING) { - currentPos = currentPos.up(); + currentPos = currentPos.above(); continue; } if (canPullFluidsFrom == FluidBlockType.SOURCE) @@ -198,12 +200,12 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { } protected FluidBlockType canPullFluidsFrom(BlockState blockState, BlockPos pos) { - if (blockState.contains(BlockStateProperties.WATERLOGGED) && blockState.get(BlockStateProperties.WATERLOGGED)) + if (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED)) return FluidBlockType.SOURCE; if (blockState.getBlock() instanceof FlowingFluidBlock) - return blockState.get(FlowingFluidBlock.LEVEL) == 0 ? FluidBlockType.SOURCE : FluidBlockType.FLOWING; + return blockState.getValue(FlowingFluidBlock.LEVEL) == 0 ? FluidBlockType.SOURCE : FluidBlockType.FLOWING; if (blockState.getFluidState() - .getFluid() != Fluids.EMPTY && blockState.getCollisionShape(getWorld(), pos, ISelectionContext.dummy()) + .getType() != Fluids.EMPTY && blockState.getCollisionShape(getWorld(), pos, ISelectionContext.empty()) .isEmpty()) return FluidBlockType.SOURCE; return FluidBlockType.NONE; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java index a4b6fe0cd..814651f9d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java @@ -7,6 +7,7 @@ import java.util.Objects; import java.util.Set; import com.simibubi.create.foundation.advancement.AllTriggers; +import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; @@ -59,7 +60,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { super.tick(); if (!infinityCheckFrontier.isEmpty() && rootPos != null) { Fluid fluid = getWorld().getFluidState(rootPos) - .getFluid(); + .getType(); if (fluid != Fluids.EMPTY) continueValidation(fluid); } @@ -124,25 +125,27 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { int maxRange = maxRange(); int maxRangeSq = maxRange * maxRange; int maxBlocks = maxBlocks(); - boolean evaporate = world.getDimension() - .isUltrawarm() && fluid.isIn(FluidTags.WATER); + boolean evaporate = world.dimensionType() + .ultraWarm() && fluid.is(FluidTags.WATER); + boolean canPlaceSources = AllConfigs.SERVER.fluids.placeFluidSourceBlocks.get(); - if (infinite || evaporate) { + if ((!fillInfinite() && infinite) || evaporate || !canPlaceSources) { FluidState fluidState = world.getFluidState(rootPos); - boolean equivalentTo = fluidState.getFluid() - .isEquivalentTo(fluid); - if (!equivalentTo && !evaporate) + boolean equivalentTo = fluidState.getType() + .isSame(fluid); + if (!equivalentTo && !evaporate && canPlaceSources) return false; if (simulate) return true; - playEffect(world, null, fluid, false); + playEffect(world, root, fluid, false); if (evaporate) { int i = root.getX(); int j = root.getY(); int k = root.getZ(); - world.playSound(null, i, j, k, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, - 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F); - } + world.playSound(null, i, j, k, SoundEvents.FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, + 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F); + } else if (!canPlaceSources) + AllTriggers.triggerForNearbyPlayers(AllTriggers.HOSE_PULLEY, world, tileEntity.getBlockPos(), 8); return true; } @@ -175,33 +178,36 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { playEffect(world, currentPos, fluid, false); BlockState blockState = world.getBlockState(currentPos); - if (blockState.contains(BlockStateProperties.WATERLOGGED) && fluid.isEquivalentTo(Fluids.WATER)) { - world.setBlockState(currentPos, - updatePostWaterlogging(blockState.with(BlockStateProperties.WATERLOGGED, true)), 2 | 16); + if (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && fluid.isSame(Fluids.WATER)) { + if (!tileEntity.isVirtual()) + world.setBlock(currentPos, + updatePostWaterlogging(blockState.setValue(BlockStateProperties.WATERLOGGED, true)), + 2 | 16); } else { replaceBlock(world, currentPos, blockState); - world.setBlockState(currentPos, FluidHelper.convertToStill(fluid) - .getDefaultState() - .getBlockState(), 2 | 16); + if (!tileEntity.isVirtual()) + world.setBlock(currentPos, FluidHelper.convertToStill(fluid) + .defaultFluidState() + .createLegacyBlock(), 2 | 16); } - ITickList pendingFluidTicks = world.getPendingFluidTicks(); + ITickList pendingFluidTicks = world.getLiquidTicks(); if (pendingFluidTicks instanceof ServerTickList) { ServerTickList serverTickList = (ServerTickList) pendingFluidTicks; NextTickListEntry removedEntry = null; - for (NextTickListEntry nextTickListEntry : serverTickList.pendingTickListEntriesHashSet) { - if (nextTickListEntry.position.equals(currentPos)) { + for (NextTickListEntry nextTickListEntry : serverTickList.tickNextTickSet) { + if (nextTickListEntry.pos.equals(currentPos)) { removedEntry = nextTickListEntry; break; } } if (removedEntry != null) { - serverTickList.pendingTickListEntriesHashSet.remove(removedEntry); - serverTickList.pendingTickListEntriesTreeSet.remove(removedEntry); + serverTickList.tickNextTickSet.remove(removedEntry); + serverTickList.tickNextTickList.remove(removedEntry); } } - affectedArea.expandTo(new MutableBoundingBox(currentPos, currentPos)); + affectedArea.expand(new MutableBoundingBox(currentPos, currentPos)); } } @@ -215,10 +221,10 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { if (side == Direction.UP) continue; - BlockPos offsetPos = currentPos.offset(side); + BlockPos offsetPos = currentPos.relative(side); if (visited.contains(offsetPos)) continue; - if (offsetPos.distanceSq(rootPos) > maxRangeSq) + if (offsetPos.distSqr(rootPos) > maxRangeSq) continue; SpaceType nextSpaceType = getAtPos(world, offsetPos, fluid); @@ -228,7 +234,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { } if (!simulate && success) - AllTriggers.triggerForNearbyPlayers(AllTriggers.HOSE_PULLEY, world, tileEntity.getPos(), 8); + AllTriggers.triggerForNearbyPlayers(AllTriggers.HOSE_PULLEY, world, tileEntity.getBlockPos(), 8); return success; } @@ -249,39 +255,39 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { BlockState blockState = world.getBlockState(pos); FluidState fluidState = blockState.getFluidState(); - if (blockState.contains(BlockStateProperties.WATERLOGGED)) - return toFill.isEquivalentTo(Fluids.WATER) - ? blockState.get(BlockStateProperties.WATERLOGGED) ? SpaceType.FILLED : SpaceType.FILLABLE + if (blockState.hasProperty(BlockStateProperties.WATERLOGGED)) + return toFill.isSame(Fluids.WATER) + ? blockState.getValue(BlockStateProperties.WATERLOGGED) ? SpaceType.FILLED : SpaceType.FILLABLE : SpaceType.BLOCKING; if (blockState.getBlock() instanceof FlowingFluidBlock) - return blockState.get(FlowingFluidBlock.LEVEL) == 0 - ? toFill.isEquivalentTo(fluidState.getFluid()) ? SpaceType.FILLED : SpaceType.BLOCKING + return blockState.getValue(FlowingFluidBlock.LEVEL) == 0 + ? toFill.isSame(fluidState.getType()) ? SpaceType.FILLED : SpaceType.BLOCKING : SpaceType.FILLABLE; - if (fluidState.getFluid() != Fluids.EMPTY - && blockState.getCollisionShape(getWorld(), pos, ISelectionContext.dummy()) + if (fluidState.getType() != Fluids.EMPTY + && blockState.getCollisionShape(getWorld(), pos, ISelectionContext.empty()) .isEmpty()) - return toFill.isEquivalentTo(fluidState.getFluid()) ? SpaceType.FILLED : SpaceType.BLOCKING; + return toFill.isSame(fluidState.getType()) ? SpaceType.FILLED : SpaceType.BLOCKING; return canBeReplacedByFluid(world, pos, blockState) ? SpaceType.FILLABLE : SpaceType.BLOCKING; } protected void replaceBlock(World world, BlockPos pos, BlockState state) { TileEntity tileentity = state.getBlock() - .hasTileEntity(state) ? world.getTileEntity(pos) : null; - Block.spawnDrops(state, world, pos, tileentity); + .hasTileEntity(state) ? world.getBlockEntity(pos) : null; + Block.dropResources(state, world, pos, tileentity); } // From FlowingFluidBlock#isBlocked protected boolean canBeReplacedByFluid(IBlockReader world, BlockPos pos, BlockState state) { Block block = state.getBlock(); - if (!(block instanceof DoorBlock) && !block.isIn(BlockTags.SIGNS) && block != Blocks.LADDER + if (!(block instanceof DoorBlock) && !block.is(BlockTags.SIGNS) && block != Blocks.LADDER && block != Blocks.SUGAR_CANE && block != Blocks.BUBBLE_COLUMN) { Material material = state.getMaterial(); - if (material != Material.PORTAL && material != Material.STRUCTURE_VOID && material != Material.OCEAN_PLANT - && material != Material.SEA_GRASS) { - return !material.blocksMovement(); + if (material != Material.PORTAL && material != Material.STRUCTURAL_AIR && material != Material.WATER_PLANT + && material != Material.REPLACEABLE_WATER_PLANT) { + return !material.blocksMotion(); } else { return false; } @@ -291,8 +297,8 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { } protected BlockState updatePostWaterlogging(BlockState state) { - if (state.contains(BlockStateProperties.LIT)) - state = state.with(BlockStateProperties.LIT, false); + if (state.hasProperty(BlockStateProperties.LIT)) + state = state.setValue(BlockStateProperties.LIT, false); return state; } 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..186aa9589 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 @@ -6,6 +6,7 @@ import java.util.List; import java.util.Set; import java.util.function.BiConsumer; +import com.simibubi.create.AllTags; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.networking.AllPackets; @@ -50,10 +51,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 +69,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() { @@ -84,6 +91,10 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { return AllConfigs.SERVER.fluids.hosePulleyBlockThreshold.get(); } + protected boolean fillInfinite() { + return AllConfigs.SERVER.fluids.fillInfinite.get(); + } + public void reset() { if (affectedArea != null) scheduleUpdatesInAffectedArea(); @@ -102,13 +113,15 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { protected void scheduleUpdatesInAffectedArea() { World world = getWorld(); - BlockPos.getAllInBox(new BlockPos(affectedArea.minX - 1, affectedArea.minY - 1, affectedArea.minZ - 1), new BlockPos(affectedArea.maxX + 1, affectedArea.maxY + 1, affectedArea.maxZ + 1)) + BlockPos + .betweenClosedStream(new BlockPos(affectedArea.x0 - 1, affectedArea.y0 - 1, affectedArea.z0 - 1), + new BlockPos(affectedArea.x1 + 1, affectedArea.y1 + 1, affectedArea.z1 + 1)) .forEach(pos -> { FluidState nextFluidState = world.getFluidState(pos); if (nextFluidState.isEmpty()) return; - world.getPendingFluidTicks() - .scheduleTick(pos, nextFluidState.getFluid(), world.getRandom() + world.getLiquidTicks() + .scheduleTick(pos, nextFluidState.getType(), world.getRandom() .nextInt(5)); }); } @@ -123,9 +136,9 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { if (compareDistance != 0) return compareDistance; return Double.compare(VecHelper.getCenterOf(pos2) - .squareDistanceTo(centerOfRoot), + .distanceToSqr(centerOfRoot), VecHelper.getCenterOf(pos1) - .squareDistanceTo(centerOfRoot)); + .distanceToSqr(centerOfRoot)); } protected Fluid search(Fluid fluid, List frontier, Set visited, @@ -148,10 +161,10 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { if (fluidState.isEmpty()) continue; - Fluid currentFluid = FluidHelper.convertToStill(fluidState.getFluid()); + Fluid currentFluid = FluidHelper.convertToStill(fluidState.getType()); if (fluid == null) fluid = currentFluid; - if (!currentFluid.isEquivalentTo(fluid)) + if (!currentFluid.isSame(fluid)) continue; add.accept(currentPos, entry.distance); @@ -160,16 +173,16 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { if (!searchDownward && side == Direction.DOWN) continue; - BlockPos offsetPos = currentPos.offset(side); + BlockPos offsetPos = currentPos.relative(side); if (visited.contains(offsetPos)) continue; - if (offsetPos.distanceSq(rootPos) > maxRangeSq) + if (offsetPos.distSqr(rootPos) > maxRangeSq) continue; FluidState nextFluidState = world.getFluidState(offsetPos); if (nextFluidState.isEmpty()) continue; - Fluid nextFluid = nextFluidState.getFluid(); + Fluid nextFluid = nextFluidState.getType(); if (nextFluid == FluidHelper.convertToFlowing(nextFluid) && side == Direction.UP && !VecHelper.onSameAxis(rootPos, offsetPos, Axis.Y)) continue; @@ -177,29 +190,29 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { frontier.add(new BlockPosEntry(offsetPos, entry.distance + 1)); } } - + return fluid; } protected void playEffect(World world, BlockPos pos, Fluid fluid, boolean fillSound) { - BlockPos splooshPos = pos == null ? tileEntity.getPos() : pos; + BlockPos splooshPos = pos == null ? tileEntity.getBlockPos() : pos; SoundEvent soundevent = fillSound ? fluid.getAttributes() .getFillSound() : fluid.getAttributes() .getEmptySound(); if (soundevent == null) - soundevent = fluid.isIn(FluidTags.LAVA) - ? fillSound ? SoundEvents.ITEM_BUCKET_FILL_LAVA : SoundEvents.ITEM_BUCKET_EMPTY_LAVA - : fillSound ? SoundEvents.ITEM_BUCKET_FILL : SoundEvents.ITEM_BUCKET_EMPTY; + soundevent = + fluid.is(FluidTags.LAVA) ? fillSound ? SoundEvents.BUCKET_FILL_LAVA : SoundEvents.BUCKET_EMPTY_LAVA + : fillSound ? SoundEvents.BUCKET_FILL : SoundEvents.BUCKET_EMPTY; world.playSound(null, splooshPos, soundevent, SoundCategory.BLOCKS, 0.3F, 1.0F); 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); + return maxBlocks() != -1 && !AllTags.AllFluidTags.NO_INFINITE_DRAINING.matches(fluid); } @Override @@ -208,9 +221,9 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { nbt.put("LastPos", NBTUtil.writeBlockPos(rootPos)); if (affectedArea != null) { nbt.put("AffectedAreaFrom", - NBTUtil.writeBlockPos(new BlockPos(affectedArea.minX, affectedArea.minY, affectedArea.minZ))); + NBTUtil.writeBlockPos(new BlockPos(affectedArea.x0, affectedArea.y0, affectedArea.z0))); nbt.put("AffectedAreaTo", - NBTUtil.writeBlockPos(new BlockPos(affectedArea.maxX, affectedArea.maxY, affectedArea.maxZ))); + NBTUtil.writeBlockPos(new BlockPos(affectedArea.x1, affectedArea.y1, affectedArea.z1))); } super.write(nbt, clientPacket); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java index 0b523ffcc..8704f92a7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java @@ -37,7 +37,7 @@ public class FluidSplashPacket extends SimplePacketBase { public void handle(Supplier ctx) { ctx.get() .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - if (Minecraft.getInstance().player.getPositionVec() + if (Minecraft.getInstance().player.position() .distanceTo(new Vector3d(pos.getX(), pos.getY(), pos.getZ())) > 100) return; FluidFX.splash(pos, 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..e8aeb3a9c 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)) @@ -52,7 +83,7 @@ public class GenericItemFilling { return -1; if (tank instanceof FluidBucketWrapper) { Item filledBucket = availableFluid.getFluid() - .getFilledBucket(); + .getBucket(); if (filledBucket == null || filledBucket == Items.AIR) return -1; if (!((FluidBucketWrapper) tank).getFluid() @@ -67,14 +98,13 @@ public class GenericItemFilling { private static boolean canFillGlassBottleInternally(FluidStack availableFluid) { return availableFluid.getFluid() - .isEquivalentTo(Fluids.WATER) + .isSame(Fluids.WATER) || availableFluid.getFluid() - .isEquivalentTo(AllFluids.POTION.get()); + .isSame(AllFluids.POTION.get()); } private static boolean canFillBucketInternally(FluidStack availableFluid) { - return availableFluid.getFluid() - .isEquivalentTo(AllFluids.MILK.get().getFlowingFluid()); + return false; } public static ItemStack fillItem(World world, int requiredAmount, ItemStack stack, FluidStack availableFluid) { @@ -85,19 +115,13 @@ public class GenericItemFilling { if (stack.getItem() == Items.GLASS_BOTTLE && canFillGlassBottleInternally(toFill)) { ItemStack fillBottle = ItemStack.EMPTY; if (FluidHelper.isWater(toFill.getFluid())) - fillBottle = PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), Potions.WATER); + fillBottle = PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER); else fillBottle = PotionFluidHandler.fillBottle(stack, toFill); stack.shrink(1); return fillBottle; } - if (stack.getItem() == Items.BUCKET && canFillBucketInternally(toFill)) { - ItemStack filledBucket = new ItemStack(Items.MILK_BUCKET); - stack.shrink(1); - return filledBucket; - } - ItemStack split = stack.copy(); split.setCount(1); LazyOptional capability = diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyBlock.java index 7ec814a63..b79cfc316 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyBlock.java @@ -28,30 +28,30 @@ public class HosePulleyBlock extends HorizontalKineticBlock implements ITE pos.down((int) Math.ceil(offset.getValue())), () -> !this.isMoving); + () -> worldPosition.below((int) Math.ceil(offset.getValue())), () -> !this.isMoving); capability = LazyOptional.of(() -> handler); } @@ -83,7 +83,7 @@ public class HosePulleyTileEntity extends KineticTileEntity { float newOffset = offset.getValue() + getMovementSpeed(); if (newOffset < 0) isMoving = false; - if (!world.getBlockState(pos.down((int) Math.ceil(newOffset))) + if (!level.getBlockState(worldPosition.below((int) Math.ceil(newOffset))) .getMaterial() .isReplaceable()) { isMoving = false; @@ -100,13 +100,13 @@ public class HosePulleyTileEntity extends KineticTileEntity { @Override @OnlyIn(Dist.CLIENT) public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().expand(0, -offset.getValue(), 0); + return super.getRenderBoundingBox().expandTowards(0, -offset.getValue(), 0); } @Override @OnlyIn(Dist.CLIENT) - public double getMaxRenderDistanceSquared() { - return super.getMaxRenderDistanceSquared() + offset.getValue() * offset.getValue(); + public double getViewDistance() { + return super.getViewDistance() + offset.getValue() * offset.getValue(); } @Override @@ -117,7 +117,7 @@ public class HosePulleyTileEntity extends KineticTileEntity { newOffset = 0; isMoving = false; } - if (!world.getBlockState(pos.down((int) Math.ceil(newOffset))) + if (!level.getBlockState(worldPosition.below((int) Math.ceil(newOffset))) .getMaterial() .isReplaceable()) { newOffset = (int) newOffset; @@ -132,13 +132,13 @@ public class HosePulleyTileEntity extends KineticTileEntity { @Override public void lazyTick() { super.lazyTick(); - if (world.isRemote) + if (level.isClientSide) return; if (isMoving) return; int ceil = (int) Math.ceil(offset.getValue() + getMovementSpeed()); - if (getMovementSpeed() > 0 && world.getBlockState(pos.down(ceil)) + if (getMovementSpeed() > 0 && level.getBlockState(worldPosition.below(ceil)) .getMaterial() .isReplaceable()) { isMoving = true; @@ -169,14 +169,14 @@ public class HosePulleyTileEntity extends KineticTileEntity { } @Override - public void remove() { - super.remove(); + public void setRemoved() { + super.setRemoved(); capability.invalidate(); } public float getMovementSpeed() { - float movementSpeed = getSpeed() / 512f; - if (world.isRemote) + float movementSpeed = convertToLinear(getSpeed()); + if (level.isClientSide) movementSpeed *= ServerSpeedProvider.get(); return movementSpeed; } @@ -188,13 +188,13 @@ public class HosePulleyTileEntity extends KineticTileEntity { @Override public LazyOptional getCapability(Capability cap, Direction side) { if (isFluidHandlerCap(cap) - && (side == null || HosePulleyBlock.hasPipeTowards(world, pos, getBlockState(), side))) + && (side == null || HosePulleyBlock.hasPipeTowards(level, worldPosition, getBlockState(), side))) return this.capability.cast(); return super.getCapability(cap, side); } @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..4a31fd084 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 @@ -12,6 +12,7 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.InventoryHelper; +import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; import net.minecraft.pathfinding.PathType; import net.minecraft.tileentity.TileEntity; @@ -24,6 +25,7 @@ import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; public class ItemDrainBlock extends Block implements IWrenchable, ITE { @@ -32,31 +34,32 @@ public class ItemDrainBlock extends Block implements IWrenchable, ITE { if (!heldItem.isEmpty()) { te.internalTank.allowInsertion(); ActionResultType tryExchange = tryExchange(worldIn, player, handIn, heldItem, te); te.internalTank.forbidInsertion(); - if (tryExchange.isAccepted()) + if (tryExchange.consumesAction()) return tryExchange; } - + ItemStack heldItemStack = te.getHeldItemStack(); - if (!worldIn.isRemote && !heldItemStack.isEmpty()) { + if (!worldIn.isClientSide && !heldItemStack.isEmpty()) { player.inventory.placeItemBackInInventory(worldIn, heldItemStack); te.heldItem = null; te.notifyUpdate(); } return ActionResultType.SUCCESS; - } catch (TileEntityException e) { - } - - return ActionResultType.PASS; + }); } protected ActionResultType tryExchange(World worldIn, PlayerEntity player, Hand handIn, ItemStack heldItem, @@ -75,15 +78,15 @@ public class ItemDrainBlock extends Block implements IWrenchable, ITE { ItemStack heldItemStack = te.getHeldItemStack(); if (!heldItemStack.isEmpty()) - InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), heldItemStack); + InventoryHelper.dropItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), heldItemStack); }); - worldIn.removeTileEntity(pos); + worldIn.removeBlockEntity(pos); } @Override @@ -102,17 +105,17 @@ public class ItemDrainBlock extends Block implements IWrenchable, ITE 1 && EmptyingByBasin.canItemBeEmptied(te.getWorld(), stack)) { + if (stack.getCount() > 1 && EmptyingByBasin.canItemBeEmptied(te.getLevel(), stack)) { returned = ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - 1); stack = ItemHandlerHelper.copyStackWithSize(stack, 1); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainRenderer.java index 8b7ac12f4..83953bdc1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainRenderer.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.fluids.actors; import java.util.Random; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; @@ -10,7 +11,6 @@ import com.simibubi.create.foundation.fluid.FluidRenderer; 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.renderer.SmartTileEntityRenderer; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; @@ -48,25 +48,25 @@ public class ItemDrainRenderer extends SmartTileEntityRenderer 1 && EmptyingByBasin.canItemBeEmptied(world, inserted)) { + if (inserted.getCount() > 1 && EmptyingByBasin.canItemBeEmptied(level, inserted)) { returned = ItemHandlerHelper.copyStackWithSize(inserted, inserted.getCount() - 1); inserted = ItemHandlerHelper.copyStackWithSize(inserted, 1); } @@ -81,7 +81,7 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI transportedStack.prevSideOffset = transportedStack.sideOffset; transportedStack.prevBeltPosition = transportedStack.beltPosition; setHeldItem(transportedStack, side); - markDirty(); + setChanged(); sendData(); return returned; @@ -100,7 +100,7 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI return; } - boolean onClient = world.isRemote && !isVirtual(); + boolean onClient = level.isClientSide && !isVirtual(); if (processingTicks > 0) { heldItem.prevBeltPosition = .5f; @@ -144,26 +144,26 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI return; } - BlockPos nextPosition = pos.offset(side); + BlockPos nextPosition = worldPosition.relative(side); DirectBeltInputBehaviour directBeltInputBehaviour = - TileEntityBehaviour.get(world, nextPosition, DirectBeltInputBehaviour.TYPE); + TileEntityBehaviour.get(level, nextPosition, DirectBeltInputBehaviour.TYPE); if (directBeltInputBehaviour == null) { - if (!BlockHelper.hasBlockSolidSide(world.getBlockState(nextPosition), world, nextPosition, + if (!BlockHelper.hasBlockSolidSide(level.getBlockState(nextPosition), level, nextPosition, side.getOpposite())) { ItemStack ejected = heldItem.stack; - Vector3d outPos = VecHelper.getCenterOf(pos) - .add(Vector3d.of(side.getDirectionVec()) + Vector3d outPos = VecHelper.getCenterOf(worldPosition) + .add(Vector3d.atLowerCornerOf(side.getNormal()) .scale(.75)); float movementSpeed = itemMovementPerTick(); - Vector3d outMotion = Vector3d.of(side.getDirectionVec()) + Vector3d outMotion = Vector3d.atLowerCornerOf(side.getNormal()) .scale(movementSpeed) .add(0, 1 / 8f, 0); outPos.add(outMotion.normalize()); - ItemEntity entity = new ItemEntity(world, outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); - entity.setMotion(outMotion); - entity.setDefaultPickupDelay(); - entity.velocityChanged = true; - world.addEntity(entity); + ItemEntity entity = new ItemEntity(level, outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); + entity.setDeltaMovement(outMotion); + entity.setDefaultPickUpDelay(); + entity.hurtMarked = true; + level.addFreshEntity(entity); heldItem = null; notifyUpdate(); @@ -177,8 +177,8 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI ItemStack returned = directBeltInputBehaviour.handleInsertion(heldItem.copy(), side, false); if (returned.isEmpty()) { - if (world.getTileEntity(nextPosition) instanceof ItemDrainTileEntity) - AllTriggers.triggerForNearbyPlayers(AllTriggers.CHAINED_ITEM_DRAIN, world, pos, 5); + if (level.getBlockEntity(nextPosition) instanceof ItemDrainTileEntity) + AllTriggers.triggerForNearbyPlayers(AllTriggers.CHAINED_ITEM_DRAIN, level, worldPosition, 5); heldItem = null; notifyUpdate(); return; @@ -194,7 +194,7 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI } if (heldItem.prevBeltPosition < .5f && heldItem.beltPosition >= .5f) { - if (!EmptyingByBasin.canItemBeEmptied(world, heldItem.stack)) + if (!EmptyingByBasin.canItemBeEmptied(level, heldItem.stack)) return; heldItem.beltPosition = .5f; if (onClient) @@ -206,14 +206,14 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI } protected boolean continueProcessing() { - if (world.isRemote && !isVirtual()) + if (level.isClientSide && !isVirtual()) return true; if (processingTicks < 5) return true; - if (!EmptyingByBasin.canItemBeEmptied(world, heldItem.stack)) + if (!EmptyingByBasin.canItemBeEmptied(level, heldItem.stack)) return false; - Pair emptyItem = EmptyingByBasin.emptyItem(world, heldItem.stack, true); + Pair emptyItem = EmptyingByBasin.emptyItem(level, heldItem.stack, true); FluidStack fluidFromItem = emptyItem.getFirst(); if (processingTicks > 5) { @@ -228,8 +228,8 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI return true; } - emptyItem = EmptyingByBasin.emptyItem(world, heldItem.stack.copy(), false); - AllTriggers.triggerForNearbyPlayers(AllTriggers.ITEM_DRAIN, world, pos, 5); + emptyItem = EmptyingByBasin.emptyItem(level, heldItem.stack.copy(), false); + AllTriggers.triggerForNearbyPlayers(AllTriggers.ITEM_DRAIN, level, worldPosition, 5); // Process finished ItemStack out = emptyItem.getSecond(); @@ -250,8 +250,8 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI } @Override - public void remove() { - super.remove(); + public void setRemoved() { + super.setRemoved(); for (LazyOptional lazyOptional : itemHandlers.values()) lazyOptional.invalidate(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutBlock.java index be3a9dcd2..30ea3345e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutBlock.java @@ -38,17 +38,17 @@ public class SpoutBlock extends Block implements IWrenchable { } @Override - public boolean hasComparatorInputOverride(BlockState state) { + public boolean hasAnalogOutputSignal(BlockState state) { return true; } @Override - public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) { + public int getAnalogOutputSignal(BlockState blockState, World worldIn, BlockPos pos) { return ComparatorUtil.levelOfSmartFluidTank(worldIn, pos); } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutRenderer.java index 2cbacbd36..2136e2b4c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutRenderer.java @@ -1,10 +1,10 @@ package com.simibubi.create.content.contraptions.fluids.actors; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.fluid.FluidRenderer; import com.simibubi.create.foundation.render.PartialBufferer; -import com.simibubi.create.foundation.render.backend.core.PartialModel; 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.renderer.SafeTileEntityRenderer; @@ -39,25 +39,26 @@ public class SpoutRenderer extends SafeTileEntityRenderer { .getValue(partialTicks); if (!fluidStack.isEmpty() && level != 0) { + level = Math.max(level, 0.175f); float min = 2.5f / 16f; float max = min + (11 / 16f); float yOffset = (11 / 16f) * level; - ms.push(); + ms.pushPose(); ms.translate(0, yOffset, 0); FluidRenderer.renderTiledFluidBB(fluidStack, min, min - yOffset, min, max, min, max, buffer, ms, light, false); - ms.pop(); + ms.popPose(); } - int processingTicks = te.getCorrectedProcessingTicks(); - float processingPT = te.getCorrectedProcessingTicks() - partialTicks; + int processingTicks = te.processingTicks; + float processingPT = processingTicks - partialTicks; float processingProgress = 1 - (processingPT - 5) / 10; processingProgress = MathHelper.clamp(processingProgress, 0, 1); float radius = 0; if (processingTicks != -1) { radius = (float) (Math.pow(((2 * processingProgress) - 1), 2) - 1); - AxisAlignedBB bb = new AxisAlignedBB(0.5, .5, 0.5, 0.5, -1.2, 0.5).grow(radius / 32f); + AxisAlignedBB bb = new AxisAlignedBB(0.5, .5, 0.5, 0.5, -1.2, 0.5).inflate(radius / 32f); FluidRenderer.renderTiledFluidBB(fluidStack, (float) bb.minX, (float) bb.minY, (float) bb.minZ, (float) bb.maxX, (float) bb.maxY, (float) bb.maxZ, buffer, ms, light, true); } @@ -70,14 +71,14 @@ public class SpoutRenderer extends SafeTileEntityRenderer { else if (processingPT < 10) squeeze = -1; - ms.push(); + ms.pushPose(); for (PartialModel bit : BITS) { PartialBufferer.get(bit, te.getBlockState()) .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .renderInto(ms, buffer.getBuffer(RenderType.solid())); ms.translate(0, -3 * squeeze / 32f, 0); } - ms.pop(); + ms.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java index 02c0e05a2..8d3c6515a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java @@ -6,12 +6,12 @@ import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProce import java.util.ArrayList; import java.util.List; -import javax.annotation.Nullable; - +import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; import com.simibubi.create.content.contraptions.fluids.FluidFX; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.advancement.AllTriggers; +import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour; @@ -27,11 +27,9 @@ import net.minecraft.item.PotionItem; import net.minecraft.nbt.CompoundNBT; import net.minecraft.particles.IParticleData; import net.minecraft.potion.PotionUtils; -import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.text.ITextComponent; import net.minecraftforge.api.distmarker.Dist; @@ -40,28 +38,15 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fml.ModList; public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInformation { - private static final boolean IS_TIC_LOADED = ModList.get().isLoaded("tconstruct"); - private static final Class CASTING_FLUID_HANDLER_CLASS; - static { - Class testClass; - try { - testClass = Class.forName("slimeknights.tconstruct.library.smeltery.CastingFluidHandler"); - } catch (ClassNotFoundException e) { - testClass = null; - } - CASTING_FLUID_HANDLER_CLASS = testClass; - } public static final int FILLING_TIME = 20; - protected BeltProcessingBehaviour beltProcessing; - protected int processingTicks; - protected boolean sendSplash; - private boolean shouldAnimate = true; + + public int processingTicks; + public boolean sendSplash; + public BlockSpoutingBehaviour customProcess; SmartFluidTankBehaviour tank; @@ -76,7 +61,7 @@ public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInfor @OnlyIn(Dist.CLIENT) public AxisAlignedBB getRenderBoundingBox() { if (cachedBoundingBox == null) - cachedBoundingBox = super.getRenderBoundingBox().expand(0, -2, 0); + cachedBoundingBox = super.getRenderBoundingBox().expandTowards(0, -2, 0); return cachedBoundingBox; } @@ -93,26 +78,25 @@ public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInfor protected ProcessingResult onItemReceived(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler) { - if (!FillingBySpout.canItemBeFilled(world, transported.stack)) + if (!FillingBySpout.canItemBeFilled(level, transported.stack)) return PASS; if (tank.isEmpty()) return HOLD; - if (FillingBySpout.getRequiredAmountForItem(world, transported.stack, getCurrentFluidInTank()) == -1) + if (FillingBySpout.getRequiredAmountForItem(level, transported.stack, getCurrentFluidInTank()) == -1) return PASS; return HOLD; } protected ProcessingResult whenItemHeld(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler) { - shouldAnimate = true; if (processingTicks != -1 && processingTicks != 5) return HOLD; - if (!FillingBySpout.canItemBeFilled(world, transported.stack)) + if (!FillingBySpout.canItemBeFilled(level, transported.stack)) return PASS; if (tank.isEmpty()) return HOLD; FluidStack fluid = getCurrentFluidInTank(); - int requiredAmountForItem = FillingBySpout.getRequiredAmountForItem(world, transported.stack, fluid.copy()); + int requiredAmountForItem = FillingBySpout.getRequiredAmountForItem(level, transported.stack, fluid.copy()); if (requiredAmountForItem == -1) return PASS; if (requiredAmountForItem > fluid.getAmount()) @@ -125,7 +109,7 @@ public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInfor } // Process finished - ItemStack out = FillingBySpout.fillItem(world, requiredAmountForItem, transported.stack, fluid); + ItemStack out = FillingBySpout.fillItem(level, requiredAmountForItem, transported.stack, fluid); if (!out.isEmpty()) { List outList = new ArrayList<>(); TransportedItemStack held = null; @@ -137,10 +121,10 @@ public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInfor handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(outList, held)); } - AllTriggers.triggerForNearbyPlayers(AllTriggers.SPOUT, world, pos, 5); - if (out.getItem() instanceof PotionItem && !PotionUtils.getEffectsFromStack(out) + AllTriggers.triggerForNearbyPlayers(AllTriggers.SPOUT, level, worldPosition, 5); + if (out.getItem() instanceof PotionItem && !PotionUtils.getMobEffects(out) .isEmpty()) - AllTriggers.triggerForNearbyPlayers(AllTriggers.SPOUT_POTION, world, pos, 5); + AllTriggers.triggerForNearbyPlayers(AllTriggers.SPOUT_POTION, level, worldPosition, 5); tank.getPrimaryHandler() .setFluid(fluid); @@ -149,59 +133,6 @@ public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInfor return HOLD; } - private void processTicCastBlock() { - if (!IS_TIC_LOADED || CASTING_FLUID_HANDLER_CLASS == null) - return; - if (world == null) - return; - IFluidHandler localTank = this.tank.getCapability() - .orElse(null); - if (localTank == null) - return; - FluidStack fluid = getCurrentFluidInTank(); - if (fluid.getAmount() == 0) - return; - TileEntity te = world.getTileEntity(pos.down(2)); - if (te == null) - return; - IFluidHandler handler = getFluidHandler(pos.down(2), Direction.UP); - if (!CASTING_FLUID_HANDLER_CLASS.isInstance(handler)) - return; - if (handler.getTanks() != 1) - return; - if (!handler.isFluidValid(0, this.getCurrentFluidInTank())) - return; - FluidStack containedFluid = handler.getFluidInTank(0); - if (!(containedFluid.isEmpty() || containedFluid.isFluidEqual(fluid))) - return; - if (processingTicks == -1) { - processingTicks = FILLING_TIME; - notifyUpdate(); - return; - } - FluidStack drained = localTank.drain(144, IFluidHandler.FluidAction.SIMULATE); - if (!drained.isEmpty()) { - int filled = handler.fill(drained, IFluidHandler.FluidAction.SIMULATE); - shouldAnimate = filled > 0; - sendSplash = shouldAnimate; - if (processingTicks == 5) { - if (filled > 0) { - drained = localTank.drain(filled, IFluidHandler.FluidAction.EXECUTE); - if (!drained.isEmpty()) { - FluidStack fillStack = drained.copy(); - fillStack.setAmount(Math.min(drained.getAmount(), 6)); - drained.shrink(filled); - fillStack.setAmount(filled); - handler.fill(fillStack, IFluidHandler.FluidAction.EXECUTE); - } - } - tank.getPrimaryHandler() - .setFluid(fluid); - this.notifyUpdate(); - } - } - } - private FluidStack getCurrentFluidInTank() { return tank.getPrimaryHandler() .getFluid(); @@ -239,53 +170,67 @@ public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInfor public void tick() { super.tick(); - processTicCastBlock(); - if (processingTicks >= 0) + + FluidStack currentFluidInTank = getCurrentFluidInTank(); + if (processingTicks == -1 && (isVirtual() || !level.isClientSide()) && !currentFluidInTank.isEmpty()) { + BlockSpoutingBehaviour.forEach(behaviour -> { + if (customProcess != null) + return; + if (behaviour.fillBlock(level, worldPosition.below(2), this, currentFluidInTank, true) > 0) { + processingTicks = FILLING_TIME; + customProcess = behaviour; + notifyUpdate(); + } + }); + } + + if (processingTicks >= 0) { processingTicks--; - if (processingTicks >= 8 && world.isRemote && shouldAnimate) + if (processingTicks == 5 && customProcess != null) { + int fillBlock = customProcess.fillBlock(level, worldPosition.below(2), this, currentFluidInTank, false); + customProcess = null; + if (fillBlock > 0) { + tank.getPrimaryHandler() + .setFluid(FluidHelper.copyStackWithAmount(currentFluidInTank, + currentFluidInTank.getAmount() - fillBlock)); + sendSplash = true; + notifyUpdate(); + } + } + } + + if (processingTicks >= 8 && level.isClientSide) spawnProcessingParticles(tank.getPrimaryTank() .getRenderedFluid()); } protected void spawnProcessingParticles(FluidStack fluid) { - Vector3d vec = VecHelper.getCenterOf(pos); + if (isVirtual()) + return; + Vector3d vec = VecHelper.getCenterOf(worldPosition); vec = vec.subtract(0, 8 / 16f, 0); IParticleData particle = FluidFX.getFluidParticle(fluid); - world.addOptionalParticle(particle, vec.x, vec.y, vec.z, 0, -.1f, 0); + level.addAlwaysVisibleParticle(particle, vec.x, vec.y, vec.z, 0, -.1f, 0); } protected static int SPLASH_PARTICLE_COUNT = 20; protected void spawnSplash(FluidStack fluid) { - Vector3d vec = VecHelper.getCenterOf(pos); + if (isVirtual()) + return; + Vector3d vec = VecHelper.getCenterOf(worldPosition); vec = vec.subtract(0, 2 - 5 / 16f, 0); IParticleData particle = FluidFX.getFluidParticle(fluid); for (int i = 0; i < SPLASH_PARTICLE_COUNT; i++) { - Vector3d m = VecHelper.offsetRandomly(Vector3d.ZERO, world.rand, 0.125f); + Vector3d m = VecHelper.offsetRandomly(Vector3d.ZERO, level.random, 0.125f); m = new Vector3d(m.x, Math.abs(m.y), m.z); - world.addOptionalParticle(particle, vec.x, vec.y, vec.z, m.x, m.y, m.z); + level.addAlwaysVisibleParticle(particle, vec.x, vec.y, vec.z, m.x, m.y, m.z); } } - @Nullable - private IFluidHandler getFluidHandler(BlockPos pos, Direction direction) { - if (this.world == null) { - return null; - } else { - TileEntity te = this.world.getTileEntity(pos); - return te != null ? te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction) - .orElse(null) : null; - } - } - - public int getCorrectedProcessingTicks() { - if (shouldAnimate) - return processingTicks; - return -1; - } - @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - return containedFluidTooltip(tooltip, isPlayerSneaking, getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); + return containedFluidTooltip(tooltip, isPlayerSneaking, + getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/BasinFluidParticle.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/BasinFluidParticle.java index 64f392743..05fa110d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/BasinFluidParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/BasinFluidParticle.java @@ -24,72 +24,72 @@ public class BasinFluidParticle extends FluidStackParticle { public BasinFluidParticle(ClientWorld world, FluidStack fluid, double x, double y, double z, double vx, double vy, double vz) { super(world, fluid, x, y, z, vx, vy, vz); - particleGravity = 0; - motionX = 0; - motionY = 0; - motionZ = 0; - yOffset = world.rand.nextFloat() * 1 / 32f; - posY += yOffset; - particleScale = 0; - maxAge = 60; - Vector3d currentPos = new Vector3d(posX, posY, posZ); + gravity = 0; + xd = 0; + yd = 0; + zd = 0; + yOffset = world.random.nextFloat() * 1 / 32f; + y += yOffset; + quadSize = 0; + lifetime = 60; + Vector3d currentPos = new Vector3d(x, y, z); basinPos = new BlockPos(currentPos); centerOfBasin = VecHelper.getCenterOf(basinPos); if (vx != 0) { - maxAge = 20; + lifetime = 20; Vector3d centerOf = VecHelper.getCenterOf(basinPos); Vector3d diff = currentPos.subtract(centerOf) - .mul(1, 0, 1) + .multiply(1, 0, 1) .normalize() .scale(.375); targetPos = centerOf.add(diff); - prevPosX = posX = centerOfBasin.x; - prevPosZ = posZ = centerOfBasin.z; + xo = x = centerOfBasin.x; + zo = z = centerOfBasin.z; } } @Override public void tick() { super.tick(); - particleScale = targetPos != null ? Math.max(1 / 32f, ((1f * age) / maxAge) / 8) - : 1 / 8f * (1 - ((Math.abs(age - (maxAge / 2)) / (1f * maxAge)))); + quadSize = targetPos != null ? Math.max(1 / 32f, ((1f * age) / lifetime) / 8) + : 1 / 8f * (1 - ((Math.abs(age - (lifetime / 2)) / (1f * lifetime)))); if (age % 2 == 0) { - if (!AllBlocks.BASIN.has(world.getBlockState(basinPos))) { - setExpired(); + if (!AllBlocks.BASIN.has(level.getBlockState(basinPos))) { + remove(); return; } - TileEntity tileEntity = world.getTileEntity(basinPos); + TileEntity tileEntity = level.getBlockEntity(basinPos); if (tileEntity instanceof BasinTileEntity) { float totalUnits = ((BasinTileEntity) tileEntity).getTotalFluidUnits(0); if (totalUnits < 1) totalUnits = 0; float fluidLevel = MathHelper.clamp(totalUnits / 2000, 0, 1); - posY = 2 / 16f + basinPos.getY() + 12 / 16f * fluidLevel + yOffset; + y = 2 / 16f + basinPos.getY() + 12 / 16f * fluidLevel + yOffset; } } if (targetPos != null) { - float progess = (1f * age) / maxAge; + float progess = (1f * age) / lifetime; Vector3d currentPos = centerOfBasin.add(targetPos.subtract(centerOfBasin) .scale(progess)); - posX = currentPos.x; - posZ = currentPos.z; + x = currentPos.x; + z = currentPos.z; } } @Override - public void buildGeometry(IVertexBuilder vb, ActiveRenderInfo info, float pt) { - Quaternion rotation = info.getRotation(); + public void render(IVertexBuilder vb, ActiveRenderInfo info, float pt) { + Quaternion rotation = info.rotation(); Quaternion prevRotation = new Quaternion(rotation); rotation.set(1, 0, 0, 1); rotation.normalize(); - super.buildGeometry(vb, info, pt); + super.render(vb, info, pt); rotation.set(0, 0, 0, 1); - rotation.multiply(prevRotation); + rotation.mul(prevRotation); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidParticleData.java index 14c324e72..b1ee8f926 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidParticleData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidParticleData.java @@ -47,12 +47,12 @@ public class FluidParticleData implements IParticleData, ICustomParticleData() { // TODO Fluid particles on command - public FluidParticleData deserialize(ParticleType particleTypeIn, StringReader reader) + public FluidParticleData fromCommand(ParticleType particleTypeIn, StringReader reader) throws CommandSyntaxException { return new FluidParticleData(particleTypeIn, new FluidStack(Fluids.WATER, 1)); } - public FluidParticleData read(ParticleType particleTypeIn, PacketBuffer buffer) { + public FluidParticleData fromNetwork(ParticleType particleTypeIn, PacketBuffer buffer) { return new FluidParticleData(particleTypeIn, buffer.readFluidStack()); } }; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidStackParticle.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidStackParticle.java index 1119601b4..08927cb60 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidStackParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidStackParticle.java @@ -2,7 +2,7 @@ package com.simibubi.create.content.contraptions.fluids.particle; import com.simibubi.create.AllParticleTypes; import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.particle.IParticleRenderType; @@ -15,8 +15,8 @@ import net.minecraft.util.math.vector.Vector3d; import net.minecraftforge.fluids.FluidStack; public class FluidStackParticle extends SpriteTexturedParticle { - private final float field_217587_G; - private final float field_217588_H; + private final float uo; + private final float vo; private FluidStack fluid; public static FluidStackParticle create(ParticleType type, ClientWorld world, FluidStack fluid, double x, @@ -31,31 +31,31 @@ public class FluidStackParticle extends SpriteTexturedParticle { super(world, x, y, z, vx, vy, vz); this.fluid = fluid; this.setSprite(Minecraft.getInstance() - .getSpriteAtlas(PlayerContainer.BLOCK_ATLAS_TEXTURE) + .getTextureAtlas(PlayerContainer.BLOCK_ATLAS) .apply(fluid.getFluid() .getAttributes() .getStillTexture())); - this.particleGravity = 1.0F; - this.particleRed = 0.8F; - this.particleGreen = 0.8F; - this.particleBlue = 0.8F; + this.gravity = 1.0F; + this.rCol = 0.8F; + this.gCol = 0.8F; + this.bCol = 0.8F; this.multiplyColor(fluid.getFluid() .getAttributes() .getColor(fluid)); - - this.motionX = vx; - this.motionY = vy; - this.motionZ = vz; - this.particleScale /= 2.0F; - this.field_217587_G = this.rand.nextFloat() * 3.0F; - this.field_217588_H = this.rand.nextFloat() * 3.0F; + this.xd = vx; + this.yd = vy; + this.zd = vz; + + this.quadSize /= 2.0F; + this.uo = this.random.nextFloat() * 3.0F; + this.vo = this.random.nextFloat() * 3.0F; } @Override - protected int getBrightnessForRender(float p_189214_1_) { - int brightnessForRender = super.getBrightnessForRender(p_189214_1_); + protected int getLightColor(float p_189214_1_) { + int brightnessForRender = super.getLightColor(p_189214_1_); int skyLight = brightnessForRender >> 20; int blockLight = (brightnessForRender >> 4) & 0xf; blockLight = Math.max(blockLight, fluid.getFluid() @@ -65,25 +65,25 @@ public class FluidStackParticle extends SpriteTexturedParticle { } protected void multiplyColor(int color) { - this.particleRed *= (float) (color >> 16 & 255) / 255.0F; - this.particleGreen *= (float) (color >> 8 & 255) / 255.0F; - this.particleBlue *= (float) (color & 255) / 255.0F; + this.rCol *= (float) (color >> 16 & 255) / 255.0F; + this.gCol *= (float) (color >> 8 & 255) / 255.0F; + this.bCol *= (float) (color & 255) / 255.0F; } - protected float getMinU() { - return this.sprite.getInterpolatedU((double) ((this.field_217587_G + 1.0F) / 4.0F * 16.0F)); + protected float getU0() { + return this.sprite.getU((double) ((this.uo + 1.0F) / 4.0F * 16.0F)); } - protected float getMaxU() { - return this.sprite.getInterpolatedU((double) (this.field_217587_G / 4.0F * 16.0F)); + protected float getU1() { + return this.sprite.getU((double) (this.uo / 4.0F * 16.0F)); } - protected float getMinV() { - return this.sprite.getInterpolatedV((double) (this.field_217588_H / 4.0F * 16.0F)); + protected float getV0() { + return this.sprite.getV((double) (this.vo / 4.0F * 16.0F)); } - protected float getMaxV() { - return this.sprite.getInterpolatedV((double) ((this.field_217588_H + 1.0F) / 4.0F * 16.0F)); + protected float getV1() { + return this.sprite.getV((double) ((this.vo + 1.0F) / 4.0F * 16.0F)); } @Override @@ -92,18 +92,18 @@ public class FluidStackParticle extends SpriteTexturedParticle { if (!canEvaporate()) return; if (onGround) - setExpired(); - if (!isExpired) + remove(); + if (!removed) return; - if (!onGround && world.rand.nextFloat() < 1 / 8f) + if (!onGround && level.random.nextFloat() < 1 / 8f) return; - Vector3d rgb = ColorHelper.getRGB(fluid.getFluid() + Vector3d rgb = Color.vectorFromRGB(fluid.getFluid() .getAttributes() .getColor(fluid)); - world.addParticle(ParticleTypes.ENTITY_EFFECT, posX, posY, posZ, rgb.x, rgb.y, rgb.z); + level.addParticle(ParticleTypes.ENTITY_EFFECT, x, y, z, rgb.x, rgb.y, rgb.z); } - + protected boolean canEvaporate() { return fluid.getFluid() instanceof PotionFluid; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java index dde62b1ff..76ec1811d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java @@ -7,6 +7,7 @@ import java.util.Random; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.fluids.FluidPropagator; +import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; import com.simibubi.create.content.contraptions.wrench.IWrenchableWithBracket; import com.simibubi.create.foundation.advancement.AllTriggers; @@ -44,37 +45,39 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchableWith } @Override - public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { boolean blockTypeChanged = state.getBlock() != newState.getBlock(); - if (blockTypeChanged && !world.isRemote) + if (blockTypeChanged && !world.isClientSide) FluidPropagator.propagateChangedPipe(world, pos, state); if (state != newState && !isMoving) - removeBracket(world, pos, true).ifPresent(stack -> Block.spawnAsEntity(world, pos, stack)); + removeBracket(world, pos, true).ifPresent(stack -> Block.popResource(world, pos, stack)); if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity())) - world.removeTileEntity(pos); + world.removeBlockEntity(pos); } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult hit) { - if (!AllBlocks.COPPER_CASING.isIn(player.getHeldItem(hand))) + if (!AllBlocks.COPPER_CASING.isIn(player.getItemInHand(hand))) return ActionResultType.PASS; - if (!world.isRemote) { + if (!world.isClientSide) { BlockState newState = AllBlocks.ENCASED_FLUID_PIPE.getDefaultState(); for (Direction d : Iterate.directionsInAxis(getAxis(state))) - newState = newState.with(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(d), true); - world.setBlockState(pos, newState); + newState = newState.setValue(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(d), true); + FluidTransportBehaviour.cacheFlows(world, pos); + world.setBlockAndUpdate(pos, newState); + FluidTransportBehaviour.loadFlows(world, pos); } AllTriggers.triggerFor(AllTriggers.CASING_PIPE, player); return ActionResultType.SUCCESS; } @Override - public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { - if (world.isRemote) + public void onPlace(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { + if (world.isClientSide) return; if (state != oldState) - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @@ -87,43 +90,43 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchableWith @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos, boolean isMoving) { - DebugPacketSender.func_218806_a(world, pos); + DebugPacketSender.sendNeighborsUpdatePacket(world, pos); Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving); if (d == null) return; if (!isOpenAt(state, d)) return; - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } public static boolean isOpenAt(BlockState state, Direction d) { - return d.getAxis() == state.get(AXIS); + return d.getAxis() == state.getValue(AXIS); } @Override - public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random r) { + public void tick(BlockState state, ServerWorld world, BlockPos pos, Random r) { FluidPropagator.propagateChangedPipe(world, pos, state); } @Override public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, ISelectionContext p_220053_4_) { - return AllShapes.EIGHT_VOXEL_POLE.get(state.get(AXIS)); + return AllShapes.EIGHT_VOXEL_POLE.get(state.getValue(AXIS)); } public BlockState toRegularPipe(IWorld world, BlockPos pos, BlockState state) { - Direction side = Direction.getFacingFromAxis(AxisDirection.POSITIVE, state.get(AXIS)); - Map facingToPropertyMap = FluidPipeBlock.FACING_TO_PROPERTY_MAP; + Direction side = Direction.get(AxisDirection.POSITIVE, state.getValue(AXIS)); + Map facingToPropertyMap = FluidPipeBlock.PROPERTY_BY_DIRECTION; return AllBlocks.FLUID_PIPE.get() .updateBlockState(AllBlocks.FLUID_PIPE.getDefaultState() - .with(facingToPropertyMap.get(side), true) - .with(facingToPropertyMap.get(side.getOpposite()), true), side, null, world, pos); + .setValue(facingToPropertyMap.get(side), true) + .setValue(facingToPropertyMap.get(side.getOpposite()), true), side, null, world, pos); } @Override public Axis getAxis(BlockState state) { - return state.get(AXIS); + return state.getValue(AXIS); } @Override @@ -133,7 +136,7 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchableWith return Optional.empty(); BlockState bracket = behaviour.getBracket(); behaviour.removeBracket(inOnReplacedContext); - if (bracket == Blocks.AIR.getDefaultState()) + if (bracket == Blocks.AIR.defaultBlockState()) return Optional.empty(); return Optional.of(new ItemStack(bracket.getBlock())); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java index 6932c02fb..588f3f620 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java @@ -7,7 +7,7 @@ import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; import com.simibubi.create.content.contraptions.fluids.FluidPropagator; import com.simibubi.create.content.contraptions.relays.elementary.AbstractShaftBlock; import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; -import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.block.Block; @@ -19,7 +19,7 @@ import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.IStringSerializable; -public class BracketBlock extends ProperDirectionalBlock { +public class BracketBlock extends WrenchableDirectionalBlock { public static final BooleanProperty AXIS_ALONG_FIRST_COORDINATE = DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; @@ -29,15 +29,15 @@ public class BracketBlock extends ProperDirectionalBlock { PIPE, COG, SHAFT; @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(AXIS_ALONG_FIRST_COORDINATE) + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(AXIS_ALONG_FIRST_COORDINATE) .add(TYPE)); } @@ -47,7 +47,7 @@ public class BracketBlock extends ProperDirectionalBlock { public Optional getSuitableBracket(BlockState blockState, Direction direction) { if (blockState.getBlock() instanceof AbstractShaftBlock) - return getSuitableBracket(blockState.get(RotatedPillarKineticBlock.AXIS), direction, + return getSuitableBracket(blockState.getValue(RotatedPillarKineticBlock.AXIS), direction, blockState.getBlock() instanceof CogWheelBlock ? BracketType.COG : BracketType.SHAFT); return getSuitableBracket(FluidPropagator.getStraightPipeAxis(blockState), direction, BracketType.PIPE); } @@ -58,9 +58,9 @@ public class BracketBlock extends ProperDirectionalBlock { return Optional.empty(); boolean alongFirst = axis != Axis.Z ? targetBlockAxis == Axis.Z : targetBlockAxis == Axis.Y; - return Optional.of(getDefaultState().with(TYPE, type) - .with(FACING, direction) - .with(AXIS_ALONG_FIRST_COORDINATE, !alongFirst)); + return Optional.of(defaultBlockState().setValue(TYPE, type) + .setValue(FACING, direction) + .setValue(AXIS_ALONG_FIRST_COORDINATE, !alongFirst)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlockItem.java index d7aaf70b8..b636ce1f6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlockItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlockItem.java @@ -24,9 +24,9 @@ public class BracketBlockItem extends BlockItem { } @Override - public ActionResultType onItemUse(ItemUseContext context) { - World world = context.getWorld(); - BlockPos pos = context.getPos(); + public ActionResultType useOn(ItemUseContext context) { + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); BlockState state = world.getBlockState(pos); BracketBlock bracketBlock = getBracketBlock(); PlayerEntity player = context.getPlayer(); @@ -37,29 +37,29 @@ public class BracketBlockItem extends BlockItem { return ActionResultType.FAIL; if (!behaviour.canHaveBracket()) return ActionResultType.FAIL; - if (world.isRemote) + if (world.isClientSide) return ActionResultType.SUCCESS; - Optional suitableBracket = bracketBlock.getSuitableBracket(state, context.getFace()); + Optional suitableBracket = bracketBlock.getSuitableBracket(state, context.getClickedFace()); if (!suitableBracket.isPresent() && player != null) suitableBracket = - bracketBlock.getSuitableBracket(state, Direction.getFacingDirections(player)[0].getOpposite()); + bracketBlock.getSuitableBracket(state, Direction.orderedByNearest(player)[0].getOpposite()); if (!suitableBracket.isPresent()) return ActionResultType.SUCCESS; BlockState bracket = behaviour.getBracket(); behaviour.applyBracket(suitableBracket.get()); - if (!world.isRemote && player != null) + if (!world.isClientSide && player != null) behaviour.triggerAdvancements(world, player, state); if (player == null || !player.isCreative()) { - context.getItem() + context.getItemInHand() .shrink(1); - if (bracket != Blocks.AIR.getDefaultState()) { + if (bracket != Blocks.AIR.defaultBlockState()) { ItemStack returnedStack = new ItemStack(bracket.getBlock()); if (player == null) - Block.spawnAsEntity(world, pos, returnedStack); + Block.popResource(world, pos, returnedStack); else player.inventory.placeItemBackInInventory(world, returnedStack); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketGenerator.java index 456ee4766..e31ac7a86 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketGenerator.java @@ -28,9 +28,9 @@ public class BracketGenerator extends DirectionalAxisBlockStateGen { @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - String type = state.get(BracketBlock.TYPE) - .getString(); - boolean vertical = state.get(BracketBlock.FACING) + String type = state.getValue(BracketBlock.TYPE) + .getSerializedName(); + boolean vertical = state.getValue(BracketBlock.FACING) .getAxis() .isVertical(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java index 3a6ff0f7a..e668ab22c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java @@ -13,6 +13,7 @@ import java.util.Random; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.fluids.FluidPropagator; +import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement; @@ -39,22 +40,22 @@ import net.minecraft.world.server.ServerWorld; public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBlockItemRequirement { - public static final Map FACING_TO_PROPERTY_MAP = SixWayBlock.FACING_TO_PROPERTY_MAP; + public static final Map FACING_TO_PROPERTY_MAP = SixWayBlock.PROPERTY_BY_DIRECTION; public EncasedPipeBlock(Properties p_i48339_1_) { super(p_i48339_1_); - setDefaultState(getDefaultState().with(NORTH, false) - .with(SOUTH, false) - .with(DOWN, false) - .with(UP, false) - .with(WEST, false) - .with(EAST, false)); + registerDefaultState(defaultBlockState().setValue(NORTH, false) + .setValue(SOUTH, false) + .setValue(DOWN, false) + .setValue(UP, false) + .setValue(WEST, false) + .setValue(EAST, false)); } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override @@ -63,18 +64,18 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc } @Override - public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { boolean blockTypeChanged = state.getBlock() != newState.getBlock(); - if (blockTypeChanged && !world.isRemote) + if (blockTypeChanged && !world.isClientSide) FluidPropagator.propagateChangedPipe(world, pos, state); if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity())) - world.removeTileEntity(pos); + world.removeBlockEntity(pos); } @Override - public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { - if (!world.isRemote && state != oldState) - world.getPendingBlockTicks() + public void onPlace(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { + if (!world.isClientSide && state != oldState) + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @@ -87,18 +88,18 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos, boolean isMoving) { - DebugPacketSender.func_218806_a(world, pos); + DebugPacketSender.sendNeighborsUpdatePacket(world, pos); Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving); if (d == null) return; - if (!state.get(FACING_TO_PROPERTY_MAP.get(d))) + if (!state.getValue(FACING_TO_PROPERTY_MAP.get(d))) return; - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @Override - public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random r) { + public void tick(BlockState state, ServerWorld world, BlockPos pos, Random r) { FluidPropagator.propagateChangedPipe(world, pos, state); } @@ -109,39 +110,41 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { - World world = context.getWorld(); - BlockPos pos = context.getPos(); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); - if (world.isRemote) + if (world.isClientSide) return ActionResultType.SUCCESS; - context.getWorld() - .playEvent(2001, context.getPos(), Block.getStateId(state)); + context.getLevel() + .levelEvent(2001, context.getClickedPos(), Block.getId(state)); BlockState equivalentPipe = transferSixWayProperties(state, AllBlocks.FLUID_PIPE.getDefaultState()); Direction firstFound = Direction.UP; for (Direction d : Iterate.directions) - if (state.get(FACING_TO_PROPERTY_MAP.get(d))) { + if (state.getValue(FACING_TO_PROPERTY_MAP.get(d))) { firstFound = d; break; } - world.setBlockState(pos, AllBlocks.FLUID_PIPE.get() + FluidTransportBehaviour.cacheFlows(world, pos); + world.setBlockAndUpdate(pos, AllBlocks.FLUID_PIPE.get() .updateBlockState(equivalentPipe, firstFound, null, world, pos)); + FluidTransportBehaviour.loadFlows(world, pos); return ActionResultType.SUCCESS; } public static BlockState transferSixWayProperties(BlockState from, BlockState to) { for (Direction d : Iterate.directions) { BooleanProperty property = FACING_TO_PROPERTY_MAP.get(d); - to = to.with(property, from.get(property)); + to = to.setValue(property, from.getValue(property)); } return to; } - + @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); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java index ec2cc1b2d..dbf49a8f3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.fluids.pipes; +import java.util.Arrays; import java.util.Optional; import java.util.Random; @@ -38,6 +39,7 @@ import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.IBlockDisplayReader; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; @@ -49,7 +51,7 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren public FluidPipeBlock(Properties properties) { super(4 / 16f, properties); - this.setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); + this.registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); } @Override @@ -57,32 +59,63 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren if (tryRemoveBracket(context)) return ActionResultType.SUCCESS; - World world = context.getWorld(); - BlockPos pos = context.getPos(); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); + Direction clickedFace = context.getClickedFace(); + Axis axis = getAxis(world, pos, state); - if (axis == null) + if (axis == null) { + Vector3d clickLocation = context.getClickLocation() + .subtract(pos.getX(), pos.getY(), pos.getZ()); + double closest = Float.MAX_VALUE; + Direction argClosest = Direction.UP; + for (Direction direction : Iterate.directions) { + if (clickedFace.getAxis() == direction.getAxis()) + continue; + Vector3d centerOf = Vector3d.atCenterOf(direction.getNormal()); + double distance = centerOf.distanceToSqr(clickLocation); + if (distance < closest) { + closest = distance; + argClosest = direction; + } + } + axis = argClosest.getAxis(); + } + + if (clickedFace.getAxis() == axis) return ActionResultType.PASS; - if (context.getFace() - .getAxis() == axis) - return ActionResultType.PASS; - if (!world.isRemote) - world.setBlockState(pos, AllBlocks.GLASS_FLUID_PIPE.getDefaultState() - .with(GlassFluidPipeBlock.AXIS, axis).with(BlockStateProperties.WATERLOGGED, state.get(BlockStateProperties.WATERLOGGED))); + if (!world.isClientSide) { + FluidTransportBehaviour.cacheFlows(world, pos); + world.setBlockAndUpdate(pos, AllBlocks.GLASS_FLUID_PIPE.getDefaultState() + .setValue(GlassFluidPipeBlock.AXIS, axis) + .setValue(BlockStateProperties.WATERLOGGED, state.getValue(BlockStateProperties.WATERLOGGED))); + FluidTransportBehaviour.loadFlows(world, pos); + } return ActionResultType.SUCCESS; } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult hit) { - if (!AllBlocks.COPPER_CASING.isIn(player.getHeldItem(hand))) + if (!AllBlocks.COPPER_CASING.isIn(player.getItemInHand(hand))) return ActionResultType.PASS; AllTriggers.triggerFor(AllTriggers.CASING_PIPE, player); - if (!world.isRemote) - world.setBlockState(pos, + if (!world.isClientSide) { + FluidTransportBehaviour.cacheFlows(world, pos); + world.setBlockAndUpdate(pos, EncasedPipeBlock.transferSixWayProperties(state, AllBlocks.ENCASED_FLUID_PIPE.getDefaultState())); + FluidTransportBehaviour.loadFlows(world, pos); + } return ActionResultType.SUCCESS; } + public BlockState getAxisState(Axis axis) { + BlockState defaultState = defaultBlockState(); + for (Direction d : Iterate.directions) + defaultState = defaultState.setValue(PROPERTY_BY_DIRECTION.get(d), d.getAxis() == axis); + return defaultState; + } + @Nullable private Axis getAxis(IBlockReader world, BlockPos pos, BlockState state) { return FluidPropagator.getStraightPipeAxis(state); @@ -99,40 +132,40 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren } @Override - public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { boolean blockTypeChanged = state.getBlock() != newState.getBlock(); - if (blockTypeChanged && !world.isRemote) + if (blockTypeChanged && !world.isClientSide) FluidPropagator.propagateChangedPipe(world, pos, state); if (state != newState && !isMoving) - removeBracket(world, pos, true).ifPresent(stack -> Block.spawnAsEntity(world, pos, stack)); + removeBracket(world, pos, true).ifPresent(stack -> Block.popResource(world, pos, stack)); if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity())) - world.removeTileEntity(pos); + world.removeBlockEntity(pos); } @Override - public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { - if (world.isRemote) + public void onPlace(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { + if (world.isClientSide) return; if (state != oldState) - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos, boolean isMoving) { - DebugPacketSender.func_218806_a(world, pos); + DebugPacketSender.sendNeighborsUpdatePacket(world, pos); Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving); if (d == null) return; if (!isOpenAt(state, d)) return; - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @Override - public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random r) { + public void tick(BlockState state, ServerWorld world, BlockPos pos, Random r) { FluidPropagator.propagateChangedPipe(world, pos, state); } @@ -140,15 +173,17 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren return state.getBlock() instanceof FluidPipeBlock; } - public static boolean canConnectTo(IBlockDisplayReader world, BlockPos neighbourPos, BlockState neighbour, Direction direction) { + public static boolean canConnectTo(IBlockDisplayReader world, BlockPos neighbourPos, BlockState neighbour, + Direction direction) { if (FluidPropagator.hasFluidCapability(world, neighbourPos, direction.getOpposite())) return true; - if (neighbour.contains(BlockStateProperties.HONEY_LEVEL)) + if (neighbour.hasProperty(BlockStateProperties.LEVEL_HONEY)) return true; FluidTransportBehaviour transport = TileEntityBehaviour.get(world, neighbourPos, FluidTransportBehaviour.TYPE); - BracketedTileEntityBehaviour bracket = TileEntityBehaviour.get(world, neighbourPos, BracketedTileEntityBehaviour.TYPE); + BracketedTileEntityBehaviour bracket = + TileEntityBehaviour.get(world, neighbourPos, BracketedTileEntityBehaviour.TYPE); if (isPipe(neighbour)) - return bracket == null || !bracket.isBacketPresent() + return bracket == null || !bracket.isBracketPresent() || FluidPropagator.getStraightPipeAxis(neighbour) == direction.getAxis(); if (transport == null) return false; @@ -157,7 +192,7 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren public static boolean shouldDrawRim(IBlockDisplayReader world, BlockPos pos, BlockState state, Direction direction) { - BlockPos offsetPos = pos.offset(direction); + BlockPos offsetPos = pos.relative(direction); BlockState facingState = world.getBlockState(offsetPos); if (!isPipe(facingState)) return true; @@ -175,7 +210,7 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren } public static boolean isOpenAt(BlockState state, Direction direction) { - return state.get(FACING_TO_PROPERTY_MAP.get(direction)); + return state.getValue(PROPERTY_BY_DIRECTION.get(direction)); } public static boolean isCornerOrEndPipe(IBlockDisplayReader world, BlockPos pos, BlockState state) { @@ -198,28 +233,28 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN, BlockStateProperties.WATERLOGGED); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - FluidState FluidState = context.getWorld() - .getFluidState(context.getPos()); - return updateBlockState(getDefaultState(), context.getNearestLookingDirection(), null, context.getWorld(), - context.getPos()).with(BlockStateProperties.WATERLOGGED, - Boolean.valueOf(FluidState.getFluid() == Fluids.WATER)); + FluidState FluidState = context.getLevel() + .getFluidState(context.getClickedPos()); + return updateBlockState(defaultBlockState(), context.getNearestLookingDirection(), null, context.getLevel(), + context.getClickedPos()).setValue(BlockStateProperties.WATERLOGGED, + Boolean.valueOf(FluidState.getType() == Fluids.WATER)); } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, - IWorld world, BlockPos pos, BlockPos neighbourPos) { - if (state.get(BlockStateProperties.WATERLOGGED)) - world.getPendingFluidTicks() - .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); - if (isOpenAt(state, direction) && neighbourState.contains(BlockStateProperties.WATERLOGGED)) - world.getPendingBlockTicks() + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world, + BlockPos pos, BlockPos neighbourPos) { + if (state.getValue(BlockStateProperties.WATERLOGGED)) + world.getLiquidTicks() + .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + if (isOpenAt(state, direction) && neighbourState.hasProperty(BlockStateProperties.WATERLOGGED)) + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); return updateBlockState(state, direction, direction.getOpposite(), world, pos); } @@ -228,14 +263,20 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren IBlockDisplayReader world, BlockPos pos) { BracketedTileEntityBehaviour bracket = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE); - if (bracket != null && bracket.isBacketPresent()) + if (bracket != null && bracket.isBracketPresent()) return state; + BlockState prevState = state; + int prevStateSides = (int) Arrays.stream(Iterate.directions) + .map(PROPERTY_BY_DIRECTION::get) + .filter(prevState::getValue) + .count(); + // Update sides that are not ignored for (Direction d : Iterate.directions) if (d != ignore) { - boolean shouldConnect = canConnectTo(world, pos.offset(d), world.getBlockState(pos.offset(d)), d); - state = state.with(FACING_TO_PROPERTY_MAP.get(d), shouldConnect); + boolean shouldConnect = canConnectTo(world, pos.relative(d), world.getBlockState(pos.relative(d)), d); + state = state.setValue(PROPERTY_BY_DIRECTION.get(d), shouldConnect); } // See if it has enough connections @@ -250,17 +291,21 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren // Add opposite end if only one connection if (connectedDirection != null) - return state.with(FACING_TO_PROPERTY_MAP.get(connectedDirection.getOpposite()), true); + return state.setValue(PROPERTY_BY_DIRECTION.get(connectedDirection.getOpposite()), true); + + // If we can't connect to anything and weren't connected before, do nothing + if (prevStateSides == 2) + return prevState; // Use preferred - return state.with(FACING_TO_PROPERTY_MAP.get(preferredDirection), true) - .with(FACING_TO_PROPERTY_MAP.get(preferredDirection.getOpposite()), true); + return state.setValue(PROPERTY_BY_DIRECTION.get(preferredDirection), true) + .setValue(PROPERTY_BY_DIRECTION.get(preferredDirection.getOpposite()), true); } @Override public FluidState getFluidState(BlockState state) { - return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) - : Fluids.EMPTY.getDefaultState(); + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) + : Fluids.EMPTY.defaultFluidState(); } @Override @@ -271,14 +316,14 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren return Optional.empty(); BlockState bracket = behaviour.getBracket(); behaviour.removeBracket(inOnReplacedContext); - if (bracket == Blocks.AIR.getDefaultState()) + if (bracket == Blocks.AIR.defaultBlockState()) return Optional.empty(); return Optional.of(new ItemStack(bracket.getBlock())); } - + @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } - + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java index dbcbb66f1..0b34ef02e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java @@ -41,7 +41,7 @@ public class FluidPipeTileEntity extends SmartTileEntity { @Override public boolean canHaveFlowToward(BlockState state, Direction direction) { return (FluidPipeBlock.isPipe(state) || state.getBlock() instanceof EncasedPipeBlock) - && state.get(FluidPipeBlock.FACING_TO_PROPERTY_MAP.get(direction)); + && state.getValue(FluidPipeBlock.PROPERTY_BY_DIRECTION.get(direction)); } @Override @@ -52,7 +52,7 @@ public class FluidPipeTileEntity extends SmartTileEntity { if (attachment == AttachmentTypes.RIM && AllBlocks.ENCASED_FLUID_PIPE.has(state)) return AttachmentTypes.RIM; - BlockPos offsetPos = pos.offset(direction); + BlockPos offsetPos = pos.relative(direction); if (!FluidPipeBlock.isPipe(world.getBlockState(offsetPos))) { FluidTransportBehaviour pipeBehaviour = TileEntityBehaviour.get(world, offsetPos, FluidTransportBehaviour.TYPE); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java index 051093f80..b4f03bf4e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java @@ -34,7 +34,7 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi public FluidValveBlock(Properties properties) { super(properties); - setDefaultState(getDefaultState().with(ENABLED, false)); + registerDefaultState(defaultBlockState().setValue(ENABLED, false)); } @Override @@ -44,14 +44,14 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(ENABLED)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(ENABLED)); } @Override protected boolean prefersConnectionTo(IWorldReader reader, BlockPos pos, Direction facing, boolean shaftAxis) { if (!shaftAxis) { - BlockPos offset = pos.offset(facing); + BlockPos offset = pos.relative(facing); BlockState blockState = reader.getBlockState(offset); return FluidPipeBlock.canConnectTo(reader, offset, blockState, facing); } @@ -67,8 +67,8 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi public static Axis getPipeAxis(BlockState state) { if (!(state.getBlock() instanceof FluidValveBlock)) throw new IllegalStateException("Provided BlockState is for a different block."); - Direction facing = state.get(FACING); - boolean alongFirst = !state.get(AXIS_ALONG_FIRST_COORDINATE); + Direction facing = state.getValue(FACING); + boolean alongFirst = !state.getValue(AXIS_ALONG_FIRST_COORDINATE); for (Axis axis : Iterate.axes) { if (axis == facing.getAxis()) continue; @@ -87,38 +87,39 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi } @Override - public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { boolean blockTypeChanged = state.getBlock() != newState.getBlock(); - if (blockTypeChanged && !world.isRemote) + if (blockTypeChanged && !world.isClientSide) FluidPropagator.propagateChangedPipe(world, pos, state); if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity())) - world.removeTileEntity(pos); + world.removeBlockEntity(pos); } @Override - public boolean isValidPosition(BlockState p_196260_1_, IWorldReader p_196260_2_, BlockPos p_196260_3_) { + public boolean canSurvive(BlockState p_196260_1_, IWorldReader p_196260_2_, BlockPos p_196260_3_) { return true; } @Override - public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { - if (world.isRemote) + public void onPlace(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, world, pos, oldState, isMoving); + if (world.isClientSide) return; if (state != oldState) - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos, boolean isMoving) { - DebugPacketSender.func_218806_a(world, pos); + DebugPacketSender.sendNeighborsUpdatePacket(world, pos); Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving); if (d == null) return; if (!isOpenAt(state, d)) return; - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @@ -127,12 +128,12 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi } @Override - public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random r) { + public void tick(BlockState state, ServerWorld world, BlockPos pos, Random r) { FluidPropagator.propagateChangedPipe(world, pos, state); } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java index 2e041cc60..82ed9782e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java @@ -1,16 +1,17 @@ package com.simibubi.create.content.contraptions.fluids.pipes; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.material.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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.AnimationTickHolder; -import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.util.Direction; import net.minecraft.util.math.MathHelper; @@ -23,10 +24,10 @@ public class FluidValveInstance extends ShaftInstance implements IDynamicInstanc protected final double yRot; protected final int pointerRotationOffset; - public FluidValveInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + public FluidValveInstance(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); - Direction facing = blockState.get(FluidValveBlock.FACING); + Direction facing = blockState.getValue(FluidValveBlock.FACING); yRot = AngleHelper.horizontalAngle(facing); xRot = facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90; @@ -37,7 +38,9 @@ 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.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(AllBlockPartials.FLUID_VALVE_POINTER, blockState).createInstance(); transformPointer((FluidValveTileEntity) tile); } @@ -56,7 +59,7 @@ public class FluidValveInstance extends ShaftInstance implements IDynamicInstanc float pointerRotation = MathHelper.lerp(valve.pointer.getValue(AnimationTickHolder.getPartialTicks()), 0, -90); MatrixStack ms = new MatrixStack(); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .translate(getInstancePosition()) .centre() .rotateY(yRot) 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..495c13858 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,14 +1,14 @@ package com.simibubi.create.content.contraptions.fluids.pipes; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -28,12 +28,12 @@ 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.getLevel())) return; super.renderSafe(te, partialTicks, ms, buffer, light, overlay); BlockState blockState = te.getBlockState(); SuperByteBuffer pointer = PartialBufferer.get(AllBlockPartials.FLUID_VALVE_POINTER, blockState); - Direction facing = blockState.get(FluidValveBlock.FACING); + Direction facing = blockState.getValue(FluidValveBlock.FACING); if (!(te instanceof FluidValveTileEntity)) return; @@ -46,7 +46,7 @@ public class FluidValveRenderer extends KineticTileEntityRenderer { if (pipeAxis.isHorizontal() && shaftAxis == Axis.Z || pipeAxis.isVertical()) pointerRotationOffset = 90; - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .centre() .rotateY(AngleHelper.horizontalAngle(facing)) .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) @@ -54,7 +54,7 @@ public class FluidValveRenderer extends KineticTileEntityRenderer { .unCentre(); pointer.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .renderInto(ms, buffer.getBuffer(RenderType.solid())); } @Override 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..524a02405 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 @@ -40,20 +40,20 @@ public class FluidValveTileEntity extends KineticTileEntity { super.tick(); pointer.tickChaser(); - if (world.isRemote) + if (level.isClientSide) return; BlockState blockState = getBlockState(); if (!(blockState.getBlock() instanceof FluidValveBlock)) return; - boolean stateOpen = blockState.get(FluidValveBlock.ENABLED); + boolean stateOpen = blockState.getValue(FluidValveBlock.ENABLED); if (stateOpen && pointer.getValue() == 0) { - switchToBlockState(world, pos, blockState.with(FluidValveBlock.ENABLED, false)); + switchToBlockState(level, worldPosition, blockState.setValue(FluidValveBlock.ENABLED, false)); return; } if (!stateOpen && pointer.getValue() == 1) { - switchToBlockState(world, pos, blockState.with(FluidValveBlock.ENABLED, true)); + switchToBlockState(level, worldPosition, blockState.setValue(FluidValveBlock.ENABLED, true)); return; } } @@ -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; } @@ -97,7 +97,7 @@ public class FluidValveTileEntity extends KineticTileEntity { @Override public boolean canPullFluidFrom(FluidStack fluid, BlockState state, Direction direction) { - if (state.contains(FluidValveBlock.ENABLED) && state.get(FluidValveBlock.ENABLED)) + if (state.hasProperty(FluidValveBlock.ENABLED) && state.getValue(FluidValveBlock.ENABLED)) return super.canPullFluidFrom(fluid, state, direction); return false; } 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..b1a4729f2 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; @@ -25,7 +26,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; - @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public class GlassFluidPipeBlock extends AxisPipeBlock implements IWaterLoggable, ISpecialBlockItemRequirement { @@ -34,12 +34,12 @@ public class GlassFluidPipeBlock extends AxisPipeBlock implements IWaterLoggable public GlassFluidPipeBlock(Properties p_i48339_1_) { super(p_i48339_1_); - setDefaultState(getDefaultState().with(ALT, false).with(BlockStateProperties.WATERLOGGED, false)); + registerDefaultState(defaultBlockState().setValue(ALT, false).setValue(BlockStateProperties.WATERLOGGED, false)); } @Override - protected void fillStateContainer(Builder p_206840_1_) { - super.fillStateContainer(p_206840_1_.add(ALT, BlockStateProperties.WATERLOGGED)); + protected void createBlockStateDefinition(Builder p_206840_1_) { + super.createBlockStateDefinition(p_206840_1_.add(ALT, BlockStateProperties.WATERLOGGED)); } @Override @@ -57,36 +57,38 @@ public class GlassFluidPipeBlock extends AxisPipeBlock implements IWaterLoggable if (tryRemoveBracket(context)) return ActionResultType.SUCCESS; BlockState newState; - World world = context.getWorld(); - BlockPos pos = context.getPos(); - newState = toRegularPipe(world, pos, state).with(BlockStateProperties.WATERLOGGED, state.get(BlockStateProperties.WATERLOGGED)); - world.setBlockState(pos, newState, 3); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); + FluidTransportBehaviour.cacheFlows(world, pos); + newState = toRegularPipe(world, pos, state).setValue(BlockStateProperties.WATERLOGGED, state.getValue(BlockStateProperties.WATERLOGGED)); + world.setBlock(pos, newState, 3); + FluidTransportBehaviour.loadFlows(world, pos); return ActionResultType.SUCCESS; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - FluidState ifluidstate = context.getWorld() - .getFluidState(context.getPos()); + FluidState ifluidstate = context.getLevel() + .getFluidState(context.getClickedPos()); BlockState state = super.getStateForPlacement(context); - return state == null ? null : state.with(BlockStateProperties.WATERLOGGED, - ifluidstate.getFluid() == Fluids.WATER); + return state == null ? null : state.setValue(BlockStateProperties.WATERLOGGED, + ifluidstate.getType() == Fluids.WATER); } @Override public FluidState getFluidState(BlockState state) { - return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) - : Fluids.EMPTY.getDefaultState(); + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) + : Fluids.EMPTY.defaultFluidState(); } - + @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) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } - + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java index 2fcd7aa9a..0a1637e17 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java @@ -5,6 +5,7 @@ import java.util.Random; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.fluids.FluidPropagator; +import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VoxelShaper; @@ -28,24 +29,24 @@ import net.minecraft.world.TickPriority; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; -public class SmartFluidPipeBlock extends HorizontalFaceBlock implements IAxisPipe { +public class SmartFluidPipeBlock extends HorizontalFaceBlock implements IAxisPipe, IWrenchable { public SmartFluidPipeBlock(Properties p_i48339_1_) { super(p_i48339_1_); } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(FACE) - .add(HORIZONTAL_FACING); + .add(FACING); } @Override public BlockState getStateForPlacement(BlockItemUseContext ctx) { BlockState stateForPlacement = super.getStateForPlacement(ctx); Axis prefferedAxis = null; - BlockPos pos = ctx.getPos(); - World world = ctx.getWorld(); + BlockPos pos = ctx.getClickedPos(); + World world = ctx.getLevel(); for (Direction side : Iterate.directions) { if (!prefersConnectionTo(world, pos, side)) continue; @@ -57,16 +58,16 @@ public class SmartFluidPipeBlock extends HorizontalFaceBlock implements IAxisPip } if (prefferedAxis == Axis.Y) - stateForPlacement = stateForPlacement.with(FACE, AttachFace.WALL) - .with(HORIZONTAL_FACING, stateForPlacement.get(HORIZONTAL_FACING) + stateForPlacement = stateForPlacement.setValue(FACE, AttachFace.WALL) + .setValue(FACING, stateForPlacement.getValue(FACING) .getOpposite()); else if (prefferedAxis != null) { - if (stateForPlacement.get(FACE) == AttachFace.WALL) - stateForPlacement = stateForPlacement.with(FACE, AttachFace.FLOOR); + if (stateForPlacement.getValue(FACE) == AttachFace.WALL) + stateForPlacement = stateForPlacement.setValue(FACE, AttachFace.FLOOR); for (Direction direction : ctx.getNearestLookingDirections()) { if (direction.getAxis() != prefferedAxis) continue; - stateForPlacement = stateForPlacement.with(HORIZONTAL_FACING, direction.getOpposite()); + stateForPlacement = stateForPlacement.setValue(FACING, direction.getOpposite()); } } @@ -74,44 +75,44 @@ public class SmartFluidPipeBlock extends HorizontalFaceBlock implements IAxisPip } protected boolean prefersConnectionTo(IWorldReader reader, BlockPos pos, Direction facing) { - BlockPos offset = pos.offset(facing); + BlockPos offset = pos.relative(facing); BlockState blockState = reader.getBlockState(offset); return FluidPipeBlock.canConnectTo(reader, offset, blockState, facing); } @Override - public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { boolean blockTypeChanged = state.getBlock() != newState.getBlock(); - if (blockTypeChanged && !world.isRemote) + if (blockTypeChanged && !world.isClientSide) FluidPropagator.propagateChangedPipe(world, pos, state); if (state.hasTileEntity() && (blockTypeChanged || !newState.hasTileEntity())) - world.removeTileEntity(pos); + world.removeBlockEntity(pos); } @Override - public boolean isValidPosition(BlockState p_196260_1_, IWorldReader p_196260_2_, BlockPos p_196260_3_) { + public boolean canSurvive(BlockState p_196260_1_, IWorldReader p_196260_2_, BlockPos p_196260_3_) { return true; } @Override - public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { - if (world.isRemote) + public void onPlace(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { + if (world.isClientSide) return; if (state != oldState) - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block otherBlock, BlockPos neighborPos, boolean isMoving) { - DebugPacketSender.func_218806_a(world, pos); + DebugPacketSender.sendNeighborsUpdatePacket(world, pos); Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving); if (d == null) return; if (!isOpenAt(state, d)) return; - world.getPendingBlockTicks() + world.getBlockTicks() .scheduleTick(pos, this, 1, TickPriority.HIGH); } @@ -120,13 +121,13 @@ public class SmartFluidPipeBlock extends HorizontalFaceBlock implements IAxisPip } @Override - public void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random r) { + public void tick(BlockState state, ServerWorld world, BlockPos pos, Random r) { FluidPropagator.propagateChangedPipe(world, pos, state); } protected static Axis getPipeAxis(BlockState state) { - return state.get(FACE) == AttachFace.WALL ? Axis.Y - : state.get(HORIZONTAL_FACING) + return state.getValue(FACE) == AttachFace.WALL ? Axis.Y + : state.getValue(FACING) .getAxis(); } @@ -143,10 +144,10 @@ public class SmartFluidPipeBlock extends HorizontalFaceBlock implements IAxisPip @Override public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, ISelectionContext p_220053_4_) { - AttachFace face = state.get(FACE); + AttachFace face = state.getValue(FACE); VoxelShaper shape = face == AttachFace.FLOOR ? AllShapes.SMART_FLUID_PIPE_FLOOR : face == AttachFace.CEILING ? AllShapes.SMART_FLUID_PIPE_CEILING : AllShapes.SMART_FLUID_PIPE_WALL; - return shape.get(state.get(HORIZONTAL_FACING)); + return shape.get(state.getValue(FACING)); } @Override @@ -155,7 +156,7 @@ public class SmartFluidPipeBlock extends HorizontalFaceBlock implements IAxisPip } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeGenerator.java index 0b2467ab0..aff0ac8f5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeGenerator.java @@ -14,14 +14,14 @@ public class SmartFluidPipeGenerator extends SpecialBlockStateGen { @Override protected int getXRotation(BlockState state) { - AttachFace attachFace = state.get(SmartFluidPipeBlock.FACE); + AttachFace attachFace = state.getValue(SmartFluidPipeBlock.FACE); return attachFace == AttachFace.CEILING ? 180 : attachFace == AttachFace.FLOOR ? 0 : 270; } @Override protected int getYRotation(BlockState state) { - AttachFace attachFace = state.get(SmartFluidPipeBlock.FACE); - int angle = horizontalAngle(state.get(SmartFluidPipeBlock.HORIZONTAL_FACING)); + AttachFace attachFace = state.getValue(SmartFluidPipeBlock.FACE); + int angle = horizontalAngle(state.getValue(SmartFluidPipeBlock.FACING)); return angle + (attachFace == AttachFace.CEILING ? 180 : 0); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeTileEntity.java index 8b9544464..31c88e29f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeTileEntity.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.fluids.pipes; import java.util.List; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.fluids.FluidPropagator; import com.simibubi.create.content.contraptions.fluids.pipes.StraightPipeTileEntity.StraightPipeFluidTransportBehaviour; @@ -10,7 +11,6 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -38,9 +38,9 @@ public class SmartFluidPipeTileEntity extends SmartTileEntity { } private void onFilterChanged(ItemStack newFilter) { - if (world.isRemote) + if (level.isClientSide) return; - FluidPropagator.propagateChangedPipe(world, pos, getBlockState()); + FluidPropagator.propagateChangedPipe(level, worldPosition, getBlockState()); } class SmartPipeBehaviour extends StraightPipeFluidTransportBehaviour { @@ -68,7 +68,7 @@ public class SmartFluidPipeTileEntity extends SmartTileEntity { @Override protected Vector3d getLocalOffset(BlockState state) { - AttachFace face = state.get(SmartFluidPipeBlock.FACE); + AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); float y = face == AttachFace.CEILING ? 0.3f : face == AttachFace.WALL ? 11.3f : 15.3f; float z = face == AttachFace.CEILING ? 4.6f : face == AttachFace.WALL ? 0.6f : 4.6f; return VecHelper.rotateCentered(VecHelper.voxelSpace(8, y, z), angleY(state), Axis.Y); @@ -76,15 +76,15 @@ public class SmartFluidPipeTileEntity extends SmartTileEntity { @Override protected void rotate(BlockState state, MatrixStack ms) { - AttachFace face = state.get(SmartFluidPipeBlock.FACE); - MatrixStacker.of(ms) + AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); + MatrixTransformStack.of(ms) .rotateY(angleY(state)) .rotateX(face == AttachFace.CEILING ? -45 : 45); } protected float angleY(BlockState state) { - AttachFace face = state.get(SmartFluidPipeBlock.FACE); - float horizontalAngle = AngleHelper.horizontalAngle(state.get(SmartFluidPipeBlock.HORIZONTAL_FACING)); + AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); + float horizontalAngle = AngleHelper.horizontalAngle(state.getValue(SmartFluidPipeBlock.FACING)); if (face == AttachFace.WALL) horizontalAngle += 180; return horizontalAngle; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/StraightPipeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/StraightPipeTileEntity.java index 6b886ede3..c8d365642 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/StraightPipeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/StraightPipeTileEntity.java @@ -35,14 +35,14 @@ public class StraightPipeTileEntity extends SmartTileEntity { @Override public boolean canHaveFlowToward(BlockState state, Direction direction) { - return state.contains(AxisPipeBlock.AXIS) && state.get(AxisPipeBlock.AXIS) == direction.getAxis(); + return state.hasProperty(AxisPipeBlock.AXIS) && state.getValue(AxisPipeBlock.AXIS) == direction.getAxis(); } @Override public AttachmentTypes getRenderedRimAttachment(IBlockDisplayReader world, BlockPos pos, BlockState state, Direction direction) { AttachmentTypes attachment = super.getRenderedRimAttachment(world, pos, state, direction); - BlockState otherState = world.getBlockState(pos.offset(direction)); + BlockState otherState = world.getBlockState(pos.relative(direction)); Axis axis = IAxisPipe.getAxisOf(state); Axis otherAxis = IAxisPipe.getAxisOf(otherState); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/TransparentStraightPipeRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/TransparentStraightPipeRenderer.java index 5fc575317..2b65b410d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/TransparentStraightPipeRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/TransparentStraightPipeRenderer.java @@ -47,8 +47,8 @@ public class TransparentStraightPipeRenderer extends SafeTileEntityRenderer customEffects) { FluidStack fluidStack = new FluidStack(AllFluids.POTION.get() - .getStillFluid(), amount); + .getSource(), amount); addPotionToFluidStack(fluidStack, potion); appendEffects(fluidStack, customEffects); return fluidStack; @@ -47,7 +47,7 @@ public class PotionFluid extends VirtualFluid { @Override public int getColor(FluidStack stack) { CompoundNBT tag = stack.getOrCreateTag(); - int color = PotionUtils.getPotionColorFromEffectList(PotionUtils.getEffectsFromTag(tag)) | 0xff000000; + int color = PotionUtils.getColor(PotionUtils.getAllEffects(tag)) | 0xff000000; return color; } @@ -56,9 +56,9 @@ public class PotionFluid extends VirtualFluid { CompoundNBT tag = stack.getOrCreateTag(); IItemProvider itemFromBottleType = PotionFluidHandler.itemFromBottleType(NBTHelper.readEnum(tag, "Bottle", BottleType.class)); - return PotionUtils.getPotionTypeFromNBT(tag) - .getNamePrefixed(itemFromBottleType.asItem() - .getTranslationKey() + ".effect."); + return PotionUtils.getPotion(tag) + .getName(itemFromBottleType.asItem() + .getDescriptionId() + ".effect."); } } @@ -80,7 +80,7 @@ public class PotionFluid extends VirtualFluid { CompoundNBT compoundnbt = fs.getOrCreateTag(); ListNBT listnbt = compoundnbt.getList("CustomPotionEffects", 9); for (EffectInstance effectinstance : customEffects) - listnbt.add(effectinstance.write(new CompoundNBT())); + listnbt.add(effectinstance.save(new CompoundNBT())); compoundnbt.put("CustomPotionEffects", listnbt); return fs; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluidHandler.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluidHandler.java index f577c249c..e53d83064 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluidHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluidHandler.java @@ -45,12 +45,12 @@ public class PotionFluidHandler { public static FluidIngredient potionIngredient(Potion potion, int amount) { return FluidIngredient.fromFluidStack(FluidHelper.copyStackWithAmount(PotionFluidHandler - .getFluidFromPotionItem(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTION), potion)), amount)); + .getFluidFromPotionItem(PotionUtils.setPotion(new ItemStack(Items.POTION), potion)), amount)); } public static FluidStack getFluidFromPotionItem(ItemStack stack) { - Potion potion = PotionUtils.getPotionFromItem(stack); - List list = PotionUtils.getFullEffectsFromItem(stack); + Potion potion = PotionUtils.getPotion(stack); + List list = PotionUtils.getCustomEffects(stack); FluidStack fluid = PotionFluid.withEffects(250, potion, list); BottleType bottleTypeFromItem = bottleTypeFromItem(stack); if (potion == Potions.WATER && list.isEmpty() && bottleTypeFromItem == BottleType.REGULAR) @@ -87,31 +87,31 @@ public class PotionFluidHandler { public static ItemStack fillBottle(ItemStack stack, FluidStack availableFluid) { CompoundNBT tag = availableFluid.getOrCreateTag(); ItemStack potionStack = new ItemStack(itemFromBottleType(NBTHelper.readEnum(tag, "Bottle", BottleType.class))); - PotionUtils.addPotionToItemStack(potionStack, PotionUtils.getPotionTypeFromNBT(tag)); - PotionUtils.appendEffects(potionStack, PotionUtils.getFullEffectsFromTag(tag)); + PotionUtils.setPotion(potionStack, PotionUtils.getPotion(tag)); + PotionUtils.setCustomEffects(potionStack, PotionUtils.getCustomEffects(tag)); return potionStack; } // Modified version of PotionUtils#addPotionTooltip @OnlyIn(Dist.CLIENT) public static void addPotionTooltip(FluidStack fs, List tooltip, float p_185182_2_) { - List list = PotionUtils.getEffectsFromTag(fs.getOrCreateTag()); + List list = PotionUtils.getAllEffects(fs.getOrCreateTag()); List> list1 = Lists.newArrayList(); if (list.isEmpty()) { - tooltip.add((new TranslationTextComponent("effect.none")).formatted(TextFormatting.GRAY)); + tooltip.add((new TranslationTextComponent("effect.none")).withStyle(TextFormatting.GRAY)); } else { for (EffectInstance effectinstance : list) { - TranslationTextComponent textcomponent = new TranslationTextComponent(effectinstance.getEffectName()); - Effect effect = effectinstance.getPotion(); - Map map = effect.getAttributeModifierMap(); + TranslationTextComponent textcomponent = new TranslationTextComponent(effectinstance.getDescriptionId()); + Effect effect = effectinstance.getEffect(); + Map map = effect.getAttributeModifiers(); if (!map.isEmpty()) { for (Entry entry : map.entrySet()) { AttributeModifier attributemodifier = entry.getValue(); AttributeModifier attributemodifier1 = new AttributeModifier(attributemodifier.getName(), - effect.getAttributeModifierAmount(effectinstance.getAmplifier(), attributemodifier), + effect.getAttributeModifierValue(effectinstance.getAmplifier(), attributemodifier), attributemodifier.getOperation()); list1.add(new Tuple<>( - entry.getKey().getTranslationKey(), + entry.getKey().getDescriptionId(), attributemodifier1)); } } @@ -123,18 +123,18 @@ public class PotionFluidHandler { if (effectinstance.getDuration() > 20) { textcomponent.append(" (") - .append(EffectUtils.getPotionDurationString(effectinstance, p_185182_2_)) + .append(EffectUtils.formatDuration(effectinstance, p_185182_2_)) .append(")"); } - tooltip.add(textcomponent.formatted(effect.getEffectType() - .getColor())); + tooltip.add(textcomponent.withStyle(effect.getCategory() + .getTooltipFormatting())); } } if (!list1.isEmpty()) { tooltip.add(new StringTextComponent("")); - tooltip.add((new TranslationTextComponent("potion.whenDrank")).formatted(TextFormatting.DARK_PURPLE)); + tooltip.add((new TranslationTextComponent("potion.whenDrank")).withStyle(TextFormatting.DARK_PURPLE)); for (Tuple tuple : list1) { AttributeModifier attributemodifier2 = tuple.getB(); @@ -150,18 +150,18 @@ public class PotionFluidHandler { if (d0 > 0.0D) { tooltip.add((new TranslationTextComponent( "attribute.modifier.plus." + attributemodifier2.getOperation() - .getId(), - ItemStack.DECIMALFORMAT.format(d1), + .toValue(), + ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), new TranslationTextComponent(tuple.getA()))) - .formatted(TextFormatting.BLUE)); + .withStyle(TextFormatting.BLUE)); } else if (d0 < 0.0D) { d1 = d1 * -1.0D; tooltip.add((new TranslationTextComponent( "attribute.modifier.take." + attributemodifier2.getOperation() - .getId(), - ItemStack.DECIMALFORMAT.format(d1), + .toValue(), + ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), new TranslationTextComponent(tuple.getA()))) - .formatted(TextFormatting.RED)); + .withStyle(TextFormatting.RED)); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/recipe/PotionMixingRecipeManager.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/recipe/PotionMixingRecipeManager.java index 1219f058a..52e356dd0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/recipe/PotionMixingRecipeManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/recipe/PotionMixingRecipeManager.java @@ -43,8 +43,8 @@ public class PotionMixingRecipeManager { continue; List bottles = new ArrayList<>(); - PotionBrewing.POTION_ITEMS.forEach(i -> { - for (ItemStack itemStack : i.getMatchingStacks()) + PotionBrewing.ALLOWED_CONTAINERS.forEach(i -> { + for (ItemStack itemStack : i.getItems()) bottles.add(itemStack); }); @@ -55,7 +55,7 @@ public class PotionMixingRecipeManager { if (potion == Potions.EMPTY) continue; for (ItemStack stack : bottles) - basicPotions.add(PotionUtils.addPotionToItemStack(stack.copy(), potion)); + basicPotions.add(PotionUtils.setPotion(stack.copy(), potion)); } Set uniqueKeys = new HashSet<>(); @@ -69,7 +69,7 @@ public class PotionMixingRecipeManager { newPotions.clear(); for (ItemStack inputPotionStack : potionFrontier) { - Potion inputPotion = PotionUtils.getPotionFromItem(inputPotionStack); + Potion inputPotion = PotionUtils.getPotion(inputPotionStack); for (ItemStack potionReagent : reagents) { ItemStack outputPotionStack = iBrewingRecipe.getOutput(inputPotionStack.copy(), potionReagent); @@ -89,7 +89,7 @@ public class PotionMixingRecipeManager { continue; if (inputPotionStack.getItem() == outputPotionStack.getItem()) { - Potion outputPotion = PotionUtils.getPotionFromItem(outputPotionStack); + Potion outputPotion = PotionUtils.getPotion(outputPotionStack); if (outputPotion == Potions.WATER) continue; } @@ -100,7 +100,7 @@ public class PotionMixingRecipeManager { fluidFromPotionItem2.setAmount(1000); MixingRecipe mixingRecipe = new ProcessingRecipeBuilder<>(MixingRecipe::new, - Create.asResource("potion_" + recipeIndex++)).require(Ingredient.fromStacks(potionReagent)) + Create.asResource("potion_" + recipeIndex++)).require(Ingredient.of(potionReagent)) .require(FluidIngredient.fromFluidStack(fluidFromPotionItem)) .output(fluidFromPotionItem2) .requiresHeat(HeatCondition.HEATED) @@ -135,7 +135,7 @@ public class PotionMixingRecipeManager { ALL.clear(); getAllBrewingRecipes().forEach(recipe -> { for (Ingredient ingredient : recipe.getIngredients()) { - for (ItemStack itemStack : ingredient.getMatchingStacks()) { + for (ItemStack itemStack : ingredient.getItems()) { ALL.computeIfAbsent(itemStack.getItem(), t -> new ArrayList<>()) .add(recipe); return; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java index 2b7426d6a..0ad417194 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java @@ -66,9 +66,9 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE p_206840_1_) { + protected void createBlockStateDefinition(Builder p_206840_1_) { p_206840_1_.add(TOP, BOTTOM, SHAPE); } @@ -102,19 +102,19 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE ComparatorUtil.fractionToRedstoneLevel(te.getFillState())) .orElse(0); 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..02f1d3116 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 @@ -39,7 +39,7 @@ public class FluidTankConnectivityHandler { TankSearchCache cache = new TankSearchCache(); List frontier = new ArrayList<>(); frontier.add(te); - formTanks(te.getType(), te.getWorld(), cache, frontier); + formTanks(te.getType(), te.getLevel(), cache, frontier); } private static void formTanks(TileEntityType type, IBlockReader world, TankSearchCache cache, @@ -50,7 +50,7 @@ public class FluidTankConnectivityHandler { int minX = Integer.MAX_VALUE; int minZ = Integer.MAX_VALUE; for (FluidTankTileEntity fluidTankTileEntity : frontier) { - BlockPos pos = fluidTankTileEntity.getPos(); + BlockPos pos = fluidTankTileEntity.getBlockPos(); minX = Math.min(pos.getX(), minX); minZ = Math.min(pos.getZ(), minZ); } @@ -59,7 +59,7 @@ public class FluidTankConnectivityHandler { while (!frontier.isEmpty()) { FluidTankTileEntity tank = frontier.remove(0); - BlockPos tankPos = tank.getPos(); + BlockPos tankPos = tank.getBlockPos(); if (visited.contains(tankPos)) continue; @@ -70,8 +70,8 @@ public class FluidTankConnectivityHandler { creationQueue.add(Pair.of(amount, tank)); for (Axis axis : Iterate.axes) { - Direction d = Direction.getFacingFromAxis(AxisDirection.NEGATIVE, axis); - BlockPos next = tankPos.offset(d); + Direction d = Direction.get(AxisDirection.NEGATIVE, axis); + BlockPos next = tankPos.relative(d); if (next.getX() <= minX || next.getZ() <= minZ) continue; @@ -91,9 +91,9 @@ public class FluidTankConnectivityHandler { while (!creationQueue.isEmpty()) { Pair next = creationQueue.poll(); FluidTankTileEntity toCreate = next.getValue(); - if (visited.contains(toCreate.getPos())) + if (visited.contains(toCreate.getBlockPos())) continue; - visited.add(toCreate.getPos()); + visited.add(toCreate.getBlockPos()); tryToFormNewTank(toCreate, cache, false); } @@ -131,15 +131,15 @@ public class FluidTankConnectivityHandler { BlockState state = te.getBlockState(); if (FluidTankBlock.isTank(state)) { - state = state.with(FluidTankBlock.BOTTOM, true); - state = state.with(FluidTankBlock.TOP, te.height == 1); - te.getWorld() - .setBlockState(te.getPos(), state, 22); + state = state.setValue(FluidTankBlock.BOTTOM, true); + state = state.setValue(FluidTankBlock.TOP, te.height == 1); + te.getLevel() + .setBlock(te.getBlockPos(), state, 22); } te.setWindows(te.window); te.onFluidStackChanged(te.tankInventory.getFluid()); - te.markDirty(); + te.setChanged(); } return bestAmount; @@ -150,8 +150,8 @@ public class FluidTankConnectivityHandler { int amount = 0; int height = 0; TileEntityType type = te.getType(); - World world = te.getWorld(); - BlockPos origin = te.getPos(); + World world = te.getLevel(); + BlockPos origin = te.getBlockPos(); LazyOptional capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); FluidTank teTank = (FluidTank) capability.orElse(null); FluidStack fluid = capability.map(ifh -> ifh.getFluidInTank(0)) @@ -163,7 +163,7 @@ public class FluidTankConnectivityHandler { for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos pos = origin.add(xOffset, yOffset, zOffset); + BlockPos pos = origin.offset(xOffset, yOffset, zOffset); Optional tank = cache.getOrCache(type, world, pos); if (!tank.isPresent()) break Search; @@ -173,7 +173,7 @@ public class FluidTankConnectivityHandler { if (otherWidth > width) break Search; - BlockPos controllerPos = controller.getPos(); + BlockPos controllerPos = controller.getBlockPos(); if (!controllerPos.equals(origin)) { if (controllerPos.getX() < origin.getX()) break Search; @@ -199,13 +199,13 @@ public class FluidTankConnectivityHandler { if (simulate) return amount; - + boolean opaque = false; for (int yOffset = 0; yOffset < height; yOffset++) { for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos pos = origin.add(xOffset, yOffset, zOffset); + BlockPos pos = origin.offset(xOffset, yOffset, zOffset); FluidTankTileEntity tank = tankAt(type, world, pos); if (tank == te) continue; @@ -228,13 +228,13 @@ public class FluidTankConnectivityHandler { BlockState state = world.getBlockState(pos); if (!FluidTankBlock.isTank(state)) continue; - state = state.with(FluidTankBlock.BOTTOM, yOffset == 0); - state = state.with(FluidTankBlock.TOP, yOffset == height - 1); - world.setBlockState(pos, state, 22); + state = state.setValue(FluidTankBlock.BOTTOM, yOffset == 0); + state = state.setValue(FluidTankBlock.TOP, yOffset == height - 1); + world.setBlock(pos, state, 22); } } } - + te.setWindows(!opaque); return amount; @@ -253,8 +253,8 @@ public class FluidTankConnectivityHandler { if (width == 1 && height == 1) return; - World world = te.getWorld(); - BlockPos origin = te.getPos(); + World world = te.getLevel(); + BlockPos origin = te.getBlockPos(); List frontier = new ArrayList<>(); FluidStack toDistribute = te.tankInventory.getFluid() .copy(); @@ -267,7 +267,7 @@ public class FluidTankConnectivityHandler { for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos pos = origin.add(xOffset, yOffset, zOffset); + BlockPos pos = origin.offset(xOffset, yOffset, zOffset); FluidTankTileEntity tankAt = tankAt(te.getType(), world, pos); if (tankAt == null) continue; @@ -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()); @@ -317,7 +317,7 @@ public class FluidTankConnectivityHandler { @Nullable public static FluidTankTileEntity tankAt(TileEntityType type, IBlockReader world, BlockPos pos) { - TileEntity te = world.getTileEntity(pos); + TileEntity te = world.getBlockEntity(pos); if (te instanceof FluidTankTileEntity && te.getType() == type) return (FluidTankTileEntity) te; return null; @@ -325,7 +325,7 @@ public class FluidTankConnectivityHandler { @Nullable public static FluidTankTileEntity anyTankAt(IBlockReader world, BlockPos pos) { - TileEntity te = world.getTileEntity(pos); + TileEntity te = world.getBlockEntity(pos); if (te instanceof FluidTankTileEntity) return (FluidTankTileEntity) te; return null; @@ -370,8 +370,8 @@ public class FluidTankConnectivityHandler { } public static boolean isConnected(IBlockReader world, BlockPos tankPos, BlockPos otherTankPos) { - TileEntity te1 = world.getTileEntity(tankPos); - TileEntity te2 = world.getTileEntity(otherTankPos); + TileEntity te1 = world.getBlockEntity(tankPos); + TileEntity te2 = world.getBlockEntity(otherTankPos); if (!(te1 instanceof FluidTankTileEntity) || !(te2 instanceof FluidTankTileEntity)) return false; return ((FluidTankTileEntity) te1).getController() diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankGenerator.java index 1a64dbeae..71fdd634b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankGenerator.java @@ -35,9 +35,9 @@ public class FluidTankGenerator extends SpecialBlockStateGen { @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - Boolean top = state.get(FluidTankBlock.TOP); - Boolean bottom = state.get(FluidTankBlock.BOTTOM); - Shape shape = state.get(FluidTankBlock.SHAPE); + Boolean top = state.getValue(FluidTankBlock.TOP); + Boolean bottom = state.getValue(FluidTankBlock.BOTTOM); + Shape shape = state.getValue(FluidTankBlock.SHAPE); String shapeName = "middle"; if (top && bottom) @@ -47,7 +47,7 @@ public class FluidTankGenerator extends SpecialBlockStateGen { else if (bottom) shapeName = "bottom"; - String modelName = shapeName + (shape == Shape.PLAIN ? "" : "_" + shape.getString()); + String modelName = shapeName + (shape == Shape.PLAIN ? "" : "_" + shape.getSerializedName()); if (!prefix.isEmpty()) return prov.models() diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java index cec618615..348fbcb45 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java @@ -21,21 +21,21 @@ public class FluidTankItem extends BlockItem { } @Override - public ActionResultType tryPlace(BlockItemUseContext ctx) { - ActionResultType initialResult = super.tryPlace(ctx); - if (!initialResult.isAccepted()) + public ActionResultType place(BlockItemUseContext ctx) { + ActionResultType initialResult = super.place(ctx); + if (!initialResult.consumesAction()) return initialResult; tryMultiPlace(ctx); return initialResult; } @Override - protected boolean onBlockPlaced(BlockPos p_195943_1_, World p_195943_2_, PlayerEntity p_195943_3_, + protected boolean updateCustomBlockEntityTag(BlockPos p_195943_1_, World p_195943_2_, PlayerEntity p_195943_3_, ItemStack p_195943_4_, BlockState p_195943_5_) { MinecraftServer minecraftserver = p_195943_2_.getServer(); if (minecraftserver == null) return false; - CompoundNBT nbt = p_195943_4_.getChildTag("BlockEntityTag"); + CompoundNBT nbt = p_195943_4_.getTagElement("BlockEntityTag"); if (nbt != null) { nbt.remove("Luminosity"); nbt.remove("Size"); @@ -50,23 +50,23 @@ public class FluidTankItem extends BlockItem { } } } - return super.onBlockPlaced(p_195943_1_, p_195943_2_, p_195943_3_, p_195943_4_, p_195943_5_); + return super.updateCustomBlockEntityTag(p_195943_1_, p_195943_2_, p_195943_3_, p_195943_4_, p_195943_5_); } private void tryMultiPlace(BlockItemUseContext ctx) { PlayerEntity player = ctx.getPlayer(); if (player == null) return; - if (player.isSneaking()) + if (player.isShiftKeyDown()) return; - Direction face = ctx.getFace(); + Direction face = ctx.getClickedFace(); if (!face.getAxis() .isVertical()) return; - ItemStack stack = ctx.getItem(); - World world = ctx.getWorld(); - BlockPos pos = ctx.getPos(); - BlockPos placedOnPos = pos.offset(face.getOpposite()); + ItemStack stack = ctx.getItemInHand(); + World world = ctx.getLevel(); + BlockPos pos = ctx.getClickedPos(); + BlockPos placedOnPos = pos.relative(face.getOpposite()); BlockState placedOnState = world.getBlockState(placedOnPos); if (!FluidTankBlock.isTank(placedOnState)) @@ -83,17 +83,17 @@ public class FluidTankItem extends BlockItem { return; int tanksToPlace = 0; - BlockPos startPos = face == Direction.DOWN ? controllerTE.getPos() - .down() - : controllerTE.getPos() - .up(controllerTE.height); + BlockPos startPos = face == Direction.DOWN ? controllerTE.getBlockPos() + .below() + : controllerTE.getBlockPos() + .above(controllerTE.height); if (startPos.getY() != pos.getY()) return; for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos offsetPos = startPos.add(xOffset, 0, zOffset); + BlockPos offsetPos = startPos.offset(xOffset, 0, zOffset); BlockState blockState = world.getBlockState(offsetPos); if (FluidTankBlock.isTank(blockState)) continue; @@ -109,14 +109,14 @@ public class FluidTankItem extends BlockItem { for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos offsetPos = startPos.add(xOffset, 0, zOffset); + BlockPos offsetPos = startPos.offset(xOffset, 0, zOffset); BlockState blockState = world.getBlockState(offsetPos); if (FluidTankBlock.isTank(blockState)) continue; - BlockItemUseContext context = BlockItemUseContext.func_221536_a(ctx, offsetPos, face); + BlockItemUseContext context = BlockItemUseContext.at(ctx, offsetPos, face); player.getPersistentData() .putBoolean("SilenceTankSound", true); - super.tryPlace(context); + super.place(context); player.getPersistentData() .remove("SilenceTankSound"); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java index b182b7be1..08019b105 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java @@ -41,7 +41,7 @@ public class FluidTankModel extends CTModel { protected Builder gatherModelData(Builder builder, IBlockDisplayReader world, BlockPos pos, BlockState state) { CullData cullData = new CullData(); for (Direction d : Iterate.horizontalDirections) - cullData.setCulled(d, FluidTankConnectivityHandler.isConnected(world, pos, pos.offset(d))); + cullData.setCulled(d, FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(d))); return super.gatherModelData(builder, world, pos, state).withInitial(CULL_PROPERTY, cullData); } @@ -73,14 +73,14 @@ public class FluidTankModel extends CTModel { if (face.getAxis() .isVertical()) return; - culledFaces[face.getHorizontalIndex()] = cull; + culledFaces[face.get2DDataValue()] = cull; } boolean isCulled(Direction face) { if (face.getAxis() .isVertical()) return false; - return culledFaces[face.getHorizontalIndex()]; + return culledFaces[face.get2DDataValue()]; } } 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..fc46d3386 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); @@ -76,7 +77,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI protected void updateConnectivity() { updateConnectivity = false; - if (world.isRemote) + if (level.isClientSide) return; if (!isController()) return; @@ -93,8 +94,8 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI } if (lastKnownPos == null) - lastKnownPos = getPos(); - else if (!lastKnownPos.equals(pos) && pos != null) { + lastKnownPos = getBlockPos(); + else if (!lastKnownPos.equals(worldPosition) && worldPosition != null) { onPositionChanged(); return; } @@ -104,25 +105,31 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI if (fluidLevel != null) fluidLevel.tick(); } + + public BlockPos getLastKnownPos() { + return lastKnownPos; + } public boolean isController() { return controller == null - || pos.getX() == controller.getX() && pos.getY() == controller.getY() && pos.getZ() == controller.getZ(); + || worldPosition.getX() == controller.getX() && worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ(); } @Override public void initialize() { super.initialize(); sendData(); + if (level.isClientSide) + updateRenderBoundingBox(); } private void onPositionChanged() { removeController(true); - lastKnownPos = pos; + lastKnownPos = worldPosition; } protected void onFluidStackChanged(FluidStack newFluidStack) { - if (!hasWorld()) + if (!hasLevel()) return; FluidAttributes attributes = newFluidStack.getFluid() @@ -137,11 +144,11 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos pos = this.pos.add(xOffset, yOffset, zOffset); - FluidTankTileEntity tankAt = FluidTankConnectivityHandler.anyTankAt(world, pos); + BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset); + FluidTankTileEntity tankAt = FluidTankConnectivityHandler.anyTankAt(level, pos); if (tankAt == null) continue; - world.updateComparatorOutputLevel(pos, tankAt.getBlockState() + level.updateNeighbourForOutputSignal(pos, tankAt.getBlockState() .getBlock()); if (tankAt.luminosity == actualLuminosity) continue; @@ -150,14 +157,20 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI } } - if (!world.isRemote) { - markDirty(); + if (!level.isClientSide) { + setChanged(); sendData(); } + + if (isVirtual()) { + if (fluidLevel == null) + fluidLevel = new InterpolatedChasingValue().start(getFillState()); + fluidLevel.target(getFillState()); + } } protected void setLuminosity(int luminosity) { - if (world.isRemote) + if (level.isClientSide) return; if (this.luminosity == luminosity) return; @@ -168,7 +181,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI public FluidTankTileEntity getControllerTE() { if (isController()) return this; - TileEntity tileEntity = world.getTileEntity(controller); + TileEntity tileEntity = level.getBlockEntity(controller); if (tileEntity instanceof FluidTankTileEntity) return (FluidTankTileEntity) tileEntity; return null; @@ -183,7 +196,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI } public void removeController(boolean keepFluids) { - if (world.isRemote) + if (level.isClientSide) return; updateConnectivity = true; if (!keepFluids) @@ -195,14 +208,14 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI BlockState state = getBlockState(); if (FluidTankBlock.isTank(state)) { - state = state.with(FluidTankBlock.BOTTOM, true); - state = state.with(FluidTankBlock.TOP, true); - state = state.with(FluidTankBlock.SHAPE, window ? Shape.WINDOW : Shape.PLAIN); - getWorld().setBlockState(pos, state, 22); + state = state.setValue(FluidTankBlock.BOTTOM, true); + state = state.setValue(FluidTankBlock.TOP, true); + state = state.setValue(FluidTankBlock.SHAPE, window ? Shape.WINDOW : Shape.PLAIN); + getLevel().setBlock(worldPosition, state, 22); } refreshCapability(); - markDirty(); + setChanged(); sendData(); } @@ -236,8 +249,8 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos pos = this.pos.add(xOffset, yOffset, zOffset); - BlockState blockState = world.getBlockState(pos); + BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset); + BlockState blockState = level.getBlockState(pos); if (!FluidTankBlock.isTank(blockState)) continue; @@ -255,9 +268,9 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI shape = Shape.WINDOW; } - world.setBlockState(pos, blockState.with(FluidTankBlock.SHAPE, shape), 22); - world.getChunkProvider() - .getLightManager() + level.setBlock(pos, blockState.setValue(FluidTankBlock.SHAPE, shape), 22); + level.getChunkSource() + .getLightEngine() .checkBlock(pos); } } @@ -265,13 +278,13 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI } public void setController(BlockPos controller) { - if (world.isRemote) + if (level.isClientSide && !isVirtual()) return; if (controller.equals(this.controller)) return; this.controller = controller; refreshCapability(); - markDirty(); + setChanged(); sendData(); } @@ -283,33 +296,35 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI } public BlockPos getController() { - return isController() ? pos : controller; + return isController() ? worldPosition : controller; } - private AxisAlignedBB cachedBoundingBox; + public void updateRenderBoundingBox() { + if (isController()) + renderBoundingBox = super.getRenderBoundingBox().expandTowards(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 @OnlyIn(Dist.CLIENT) - public double getMaxRenderDistanceSquared() { + public double getViewDistance() { int dist = 64 + getMaxHeight() * 2; return dist * dist; } @Nullable public FluidTankTileEntity getOtherFluidTankTileEntity(Direction direction) { - TileEntity otherTE = world.getTileEntity(pos.offset(direction)); + TileEntity otherTE = level.getBlockEntity(worldPosition.relative(direction)); if (otherTE instanceof FluidTankTileEntity) return (FluidTankTileEntity) otherTE; return null; @@ -363,10 +378,11 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI boolean changeOfController = controllerBefore == null ? controller != null : !controllerBefore.equals(controller); if (changeOfController || prevSize != width || prevHeight != height) { - if (hasWorld()) - world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 16); + if (hasLevel()) + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); if (isController()) tankInventory.setCapacity(getCapacityMultiplier() * getTotalTankSize()); + updateRenderBoundingBox(); } if (isController()) { float fillState = getFillState(); @@ -374,10 +390,10 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI fluidLevel = new InterpolatedChasingValue().start(fillState); fluidLevel.target(fillState); } - if (luminosity != prevLum && hasWorld()) - world.getChunkProvider() - .getLightManager() - .checkBlock(pos); + if (luminosity != prevLum && hasLevel()) + level.getChunkSource() + .getLightEngine() + .checkBlock(worldPosition); if (compound.contains("LazySync")) fluidLevel.withSpeed(compound.contains("LazySync") ? 1 / 8f : 1 / 2f); @@ -424,8 +440,8 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI } @Override - public void remove() { - super.remove(); + public void setRemoved() { + super.setRemoved(); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleConfigScreen.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleConfigScreen.java index 63166fd4e..18e4088bb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleConfigScreen.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleConfigScreen.java @@ -10,7 +10,6 @@ import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.utility.Lang; -import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; @@ -27,37 +26,36 @@ public class GoggleConfigScreen extends AbstractSimiScreen { public GoggleConfigScreen() { ITextComponent componentSpacing = new StringTextComponent(" "); tooltip = new ArrayList<>(); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.config.overlay1"))); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.config.overlay2") - .formatted(TextFormatting.GRAY))); + .withStyle(TextFormatting.GRAY))); tooltip.add(StringTextComponent.EMPTY); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.config.overlay3"))); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.config.overlay4"))); tooltip.add(StringTextComponent.EMPTY); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.config.overlay5") - .formatted(TextFormatting.GRAY))); - tooltip.add(componentSpacing.copy() + .withStyle(TextFormatting.GRAY))); + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.config.overlay6") - .formatted(TextFormatting.GRAY))); + .withStyle(TextFormatting.GRAY))); tooltip.add(StringTextComponent.EMPTY); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.config.overlay7"))); - tooltip.add(componentSpacing.copy() + tooltip.add(componentSpacing.plainCopy() .append(Lang.translate("gui.config.overlay8"))); } @Override protected void init() { - Minecraft mc = Minecraft.getInstance(); - this.width = mc.getWindow() - .getScaledWidth(); - this.height = mc.getWindow() - .getScaledHeight(); + this.width = minecraft.getWindow() + .getGuiScaledWidth(); + this.height = minecraft.getWindow() + .getGuiScaledHeight(); offsetX = AllConfigs.CLIENT.overlayOffsetX.get(); offsetY = AllConfigs.CLIENT.overlayOffsetY.get(); @@ -91,7 +89,7 @@ public class GoggleConfigScreen extends AbstractSimiScreen { int titleLinesCount = 1; int tooltipTextWidth = 0; for (ITextProperties textLine : tooltip) { - int textLineWidth = getMinecraft().fontRenderer.getWidth(textLine); + int textLineWidth = minecraft.font.width(textLine); if (textLineWidth > tooltipTextWidth) tooltipTextWidth = textLineWidth; } @@ -110,7 +108,7 @@ public class GoggleConfigScreen extends AbstractSimiScreen { protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { int posX = this.width / 2 + offsetX; int posY = this.height / 2 + offsetY; - renderTooltip(ms, tooltip, posX, posY); + renderComponentTooltip(ms, tooltip, posX, posY); // UIRenderHelper.breadcrumbArrow(ms, 50, 50, 100, 50, 20, 10, 0x80aa9999, 0x10aa9999); // UIRenderHelper.breadcrumbArrow(ms, 100, 80, 0, -50, 20, -10, 0x80aa9999, 0x10aa9999); 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..51a5575b1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java @@ -1,8 +1,10 @@ package com.simibubi.create.content.contraptions.goggles; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; @@ -12,8 +14,11 @@ import com.simibubi.create.content.contraptions.components.structureMovement.IDi import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock; import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.config.CClient; import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.outliner.Outline; @@ -22,6 +27,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; @@ -29,48 +35,55 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.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; +import net.minecraftforge.fml.client.gui.GuiUtils; -@EventBusSubscriber(value = Dist.CLIENT) public class GoggleOverlayRenderer { - private static final Map outlines = CreateClient.outliner.getOutlines(); + private static final List> customGogglePredicates = new LinkedList<>(); + 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; + public static int hoverTicks = 0; + public static BlockPos lastHovered = null; - RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver; - if (!(objectMouseOver instanceof BlockRayTraceResult)) + public static void renderOverlay(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, + float partialTicks) { + RayTraceResult objectMouseOver = Minecraft.getInstance().hitResult; + + if (!(objectMouseOver instanceof BlockRayTraceResult)) { + lastHovered = null; + hoverTicks = 0; return; + } for (OutlineEntry entry : outlines.values()) { 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; Minecraft mc = Minecraft.getInstance(); - ClientWorld world = mc.world; - BlockPos pos = result.getPos(); - ItemStack headSlot = mc.player.getItemStackFromSlot(EquipmentSlotType.HEAD); - TileEntity te = world.getTileEntity(pos); + ClientWorld world = mc.level; + BlockPos pos = result.getBlockPos(); + ItemStack headSlot = mc.player.getItemBySlot(EquipmentSlotType.HEAD); + TileEntity te = world.getBlockEntity(pos); + + if (lastHovered == null || lastHovered.equals(pos)) + hoverTicks++; + else + hoverTicks = 0; + lastHovered = pos; boolean wearingGoggles = AllItems.GOGGLES.isIn(headSlot); + for (Supplier supplier : customGogglePredicates) + wearingGoggles |= supplier.get(); boolean hasGoggleInformation = te instanceof IHaveGoggleInformation; boolean hasHoveringInformation = te instanceof IHaveHoveringInformation; @@ -82,14 +95,14 @@ public class GoggleOverlayRenderer { if (hasGoggleInformation && wearingGoggles) { IHaveGoggleInformation gte = (IHaveGoggleInformation) te; - goggleAddedInformation = gte.addToGoggleTooltip(tooltip, mc.player.isSneaking()); + goggleAddedInformation = gte.addToGoggleTooltip(tooltip, mc.player.isShiftKeyDown()); } if (hasHoveringInformation) { if (!tooltip.isEmpty()) tooltip.add(StringTextComponent.EMPTY); IHaveHoveringInformation hte = (IHaveHoveringInformation) te; - hoverAddedInformation = hte.addToTooltip(tooltip, mc.player.isSneaking()); + hoverAddedInformation = hte.addToTooltip(tooltip, mc.player.isShiftKeyDown()); if (goggleAddedInformation && !hoverAddedInformation) tooltip.remove(tooltip.size() - 1); @@ -110,7 +123,7 @@ public class GoggleOverlayRenderer { // check for piston poles if goggles are worn BlockState state = world.getBlockState(pos); if (wearingGoggles && AllBlocks.PISTON_EXTENSION_POLE.has(state)) { - Direction[] directions = Iterate.directionsInAxis(state.get(PistonExtensionPoleBlock.FACING) + Direction[] directions = Iterate.directionsInAxis(state.getValue(PistonExtensionPoleBlock.FACING) .getAxis()); int poles = 1; boolean pistonFound = false; @@ -118,7 +131,7 @@ public class GoggleOverlayRenderer { int attachedPoles = PistonExtensionPoleBlock.PlacementHelper.get() .attachedPoles(world, pos, dir); poles += attachedPoles; - pistonFound |= world.getBlockState(pos.offset(dir, attachedPoles + 1)) + pistonFound |= world.getBlockState(pos.relative(dir, attachedPoles + 1)) .getBlock() instanceof MechanicalPistonBlock; } @@ -127,7 +140,7 @@ public class GoggleOverlayRenderer { if (!tooltip.isEmpty()) tooltip.add(StringTextComponent.EMPTY); - tooltip.add(IHaveGoggleInformation.componentSpacing.copy() + tooltip.add(IHaveGoggleInformation.componentSpacing.plainCopy() .append(Lang.translate("gui.goggles.pole_length")) .append(new StringTextComponent(" " + poles))); } @@ -135,17 +148,17 @@ public class GoggleOverlayRenderer { if (tooltip.isEmpty()) return; - ms.push(); + ms.pushPose(); Screen tooltipScreen = new TooltipScreen(null); tooltipScreen.init(mc, mc.getWindow() - .getScaledWidth(), + .getGuiScaledWidth(), mc.getWindow() - .getScaledHeight()); + .getGuiScaledHeight()); int titleLinesCount = 1; int tooltipTextWidth = 0; for (ITextProperties textLine : tooltip) { - int textLineWidth = mc.fontRenderer.getWidth(textLine); + int textLineWidth = mc.font.width(textLine); if (textLineWidth > tooltipTextWidth) tooltipTextWidth = textLineWidth; } @@ -157,31 +170,60 @@ public class GoggleOverlayRenderer { tooltipHeight += 2; // gap between title lines and next lines } - int posX = tooltipScreen.width / 2 + AllConfigs.CLIENT.overlayOffsetX.get(); - int posY = tooltipScreen.height / 2 + AllConfigs.CLIENT.overlayOffsetY.get(); - + CClient cfg = AllConfigs.CLIENT; + int posX = tooltipScreen.width / 2 + cfg.overlayOffsetX.get(); + int posY = tooltipScreen.height / 2 + cfg.overlayOffsetY.get(); + posX = Math.min(posX, tooltipScreen.width - tooltipTextWidth - 20); posY = Math.min(posY, tooltipScreen.height - tooltipHeight - 20); - - tooltipScreen.renderTooltip(ms, tooltip, posX, posY); + + float fade = MathHelper.clamp((hoverTicks + partialTicks) / 12f, 0, 1); + Boolean useCustom = cfg.overlayCustomColor.get(); + Color colorBackground = useCustom ? + new Color(cfg.overlayBackgroundColor.get()) : + Theme.c(Theme.Key.VANILLA_TOOLTIP_BACKGROUND).scaleAlpha(.75f); + Color colorBorderTop = useCustom ? + new Color(cfg.overlayBorderColorTop.get()) : + Theme.c(Theme.Key.VANILLA_TOOLTIP_BORDER, true).copy(); + Color colorBorderBot = useCustom ? + new Color(cfg.overlayBorderColorBot.get()) : + Theme.c(Theme.Key.VANILLA_TOOLTIP_BORDER, false).copy(); + + if (fade < 1) { + ms.translate((1 - fade) * Math.signum(cfg.overlayOffsetX.get() + .5f) * 4, 0, 0); + colorBackground.scaleAlpha(fade); + colorBorderTop.scaleAlpha(fade); + colorBorderBot.scaleAlpha(fade); + } + + GuiUtils.drawHoveringText(ms, tooltip, posX, posY, tooltipScreen.width, tooltipScreen.height, -1, + colorBackground.getRGB(), colorBorderTop.getRGB(), colorBorderBot.getRGB(), mc.font); ItemStack item = AllItems.GOGGLES.asStack(); GuiGameElement.of(item) .at(posX + 10, posY - 16, 450) .render(ms); - ms.pop(); + ms.popPose(); } - private static final class TooltipScreen extends Screen { - private TooltipScreen(ITextComponent p_i51108_1_) { + /** + * Use this method to add custom entry points to the goggle overay, e.g. custom + * armor, handheld alternatives, etc. + */ + public static void registerCustomGoggleCondition(Supplier condition) { + customGogglePredicates.add(condition); + } + + public static final class TooltipScreen extends Screen { + public TooltipScreen(ITextComponent p_i51108_1_) { super(p_i51108_1_); } @Override public void init(Minecraft mc, int width, int height) { - this.client = mc; + this.minecraft = mc; this.itemRenderer = mc.getItemRenderer(); - this.textRenderer = mc.fontRenderer; + this.font = mc.font; this.width = width; this.height = height; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesItem.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesItem.java index 3f917e6be..f85c88d8a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesItem.java @@ -18,7 +18,7 @@ public class GogglesItem extends Item { public GogglesItem(Properties properties) { super(properties); - DispenserBlock.registerDispenseBehavior(this, ArmorItem.DISPENSER_BEHAVIOR); + DispenserBlock.registerBehavior(this, ArmorItem.DISPENSE_ITEM_BEHAVIOR); } @Override @@ -26,12 +26,12 @@ public class GogglesItem extends Item { return EquipmentSlotType.HEAD; } - public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { - ItemStack itemstack = playerIn.getHeldItem(handIn); - EquipmentSlotType equipmentslottype = MobEntity.getSlotForItemStack(itemstack); - ItemStack itemstack1 = playerIn.getItemStackFromSlot(equipmentslottype); + public ActionResult use(World worldIn, PlayerEntity playerIn, Hand handIn) { + ItemStack itemstack = playerIn.getItemInHand(handIn); + EquipmentSlotType equipmentslottype = MobEntity.getEquipmentSlotForItem(itemstack); + ItemStack itemstack1 = playerIn.getItemBySlot(equipmentslottype); if (itemstack1.isEmpty()) { - playerIn.setItemStackToSlot(equipmentslottype, itemstack.copy()); + playerIn.setItemSlot(equipmentslottype, itemstack.copy()); itemstack.setCount(0); return new ActionResult<>(ActionResultType.SUCCESS, itemstack); } else { @@ -40,7 +40,7 @@ public class GogglesItem extends Item { } public static boolean canSeeParticles(PlayerEntity player) { - for (ItemStack itemStack : player.getArmorInventoryList()) + for (ItemStack itemStack : player.getArmorSlots()) if (AllItems.GOGGLES.isIn(itemStack)) return true; return false; diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java index af546a856..f9a34b0eb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java @@ -42,7 +42,7 @@ public interface IHaveGoggleInformation { } default boolean containedFluidTooltip(List tooltip, boolean isPlayerSneaking, LazyOptional handler) { - tooltip.add(componentSpacing.copy().append(Lang.translate("gui.goggles.fluid_container"))); + tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.goggles.fluid_container"))); TranslationTextComponent mb = Lang.translate("generic.unit.millibuckets"); Optional resolve = handler.resolve(); if (!resolve.isPresent()) @@ -60,14 +60,14 @@ public interface IHaveGoggleInformation { if (fluidStack.isEmpty()) continue; - ITextComponent fluidName = new TranslationTextComponent(fluidStack.getTranslationKey()).formatted(TextFormatting.GRAY); - ITextComponent contained = new StringTextComponent(format(fluidStack.getAmount())).append(mb).formatted(TextFormatting.GOLD); - ITextComponent slash = new StringTextComponent(" / ").formatted(TextFormatting.GRAY); - ITextComponent capacity = new StringTextComponent(format(tank.getTankCapacity(i))).append(mb).formatted(TextFormatting.DARK_GRAY); + ITextComponent fluidName = new TranslationTextComponent(fluidStack.getTranslationKey()).withStyle(TextFormatting.GRAY); + ITextComponent contained = new StringTextComponent(format(fluidStack.getAmount())).append(mb).withStyle(TextFormatting.GOLD); + ITextComponent slash = new StringTextComponent(" / ").withStyle(TextFormatting.GRAY); + ITextComponent capacity = new StringTextComponent(format(tank.getTankCapacity(i))).append(mb).withStyle(TextFormatting.DARK_GRAY); - tooltip.add(indent.copy() + tooltip.add(indent.plainCopy() .append(fluidName)); - tooltip.add(indent.copy() + tooltip.add(indent.plainCopy() .append(contained) .append(slash) .append(capacity)); @@ -84,10 +84,10 @@ public interface IHaveGoggleInformation { if (!isEmpty) return true; - ITextComponent capacity = Lang.translate("gui.goggles.fluid_container.capacity").formatted(TextFormatting.GRAY); - ITextComponent amount = new StringTextComponent(format(tank.getTankCapacity(0))).append(mb).formatted(TextFormatting.GOLD); + ITextComponent capacity = Lang.translate("gui.goggles.fluid_container.capacity").withStyle(TextFormatting.GRAY); + ITextComponent amount = new StringTextComponent(format(tank.getTankCapacity(0))).append(mb).withStyle(TextFormatting.GOLD); - tooltip.add(indent.copy() + tooltip.add(indent.plainCopy() .append(capacity) .append(amount)); return true; @@ -95,7 +95,7 @@ public interface IHaveGoggleInformation { class Format { - private NumberFormat format = NumberFormat.getNumberInstance(Locale.ROOT);; + private NumberFormat format = NumberFormat.getNumberInstance(Locale.ROOT); private Format() {} @@ -106,7 +106,7 @@ public interface IHaveGoggleInformation { public void update() { format = NumberFormat.getInstance(Minecraft.getInstance() .getLanguageManager() - .getCurrentLanguage() + .getSelected() .getJavaLocale()); format.setMaximumFractionDigits(2); format.setMinimumFractionDigits(0); diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/IAssemblyRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/IAssemblyRecipe.java new file mode 100644 index 000000000..9958cf457 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/IAssemblyRecipe.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.contraptions.itemAssembly; + +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + +import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; +import com.simibubi.create.foundation.fluid.FluidIngredient; + +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public interface IAssemblyRecipe { + + default boolean supportsAssembly() { + return true; + } + + @OnlyIn(Dist.CLIENT) + public ITextComponent getDescriptionForAssembly(); + + public void addRequiredMachines(Set list); + + public void addAssemblyIngredients(List list); + + default void addAssemblyFluidIngredients(List list) {} + + public Supplier> getJEISubCategory(); + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyItem.java b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyItem.java new file mode 100644 index 000000000..36eead8d9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyItem.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.contraptions.itemAssembly; + +import com.simibubi.create.foundation.utility.Color; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.MathHelper; + +public class SequencedAssemblyItem extends Item { + + public SequencedAssemblyItem(Properties p_i48487_1_) { + super(p_i48487_1_.stacksTo(1)); + } + + @Override + public void fillItemCategory(ItemGroup p_150895_1_, NonNullList p_150895_2_) {} + + @Override + public double getDurabilityForDisplay(ItemStack stack) { + if (!stack.hasTag()) + return 1; + CompoundNBT tag = stack.getTag(); + if (!tag.contains("SequencedAssembly")) + return 1; + return MathHelper.lerp(tag.getCompound("SequencedAssembly") + .getFloat("Progress"), 1, 0); + } + + @Override + public boolean showDurabilityBar(ItemStack stack) { + return true; + } + + @Override + public int getRGBDurabilityForDisplay(ItemStack stack) { + return Color.mixColors(0xFF_46FFE0, 0xFF_FFC074, (float) getDurabilityForDisplay(stack)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipe.java new file mode 100644 index 000000000..92f4f70a7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipe.java @@ -0,0 +1,277 @@ +package com.simibubi.create.content.contraptions.itemAssembly; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; +import com.simibubi.create.foundation.fluid.FluidIngredient; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.client.Minecraft; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.IRecipeSerializer; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class SequencedAssemblyRecipe implements IRecipe { + + protected ResourceLocation id; + protected SequencedAssemblyRecipeSerializer serializer; + + protected Ingredient ingredient; + protected List> sequence; + protected int loops; + protected ProcessingOutput transitionalItem; + protected List resultPool; + + public SequencedAssemblyRecipe(ResourceLocation recipeId, SequencedAssemblyRecipeSerializer serializer) { + this.id = recipeId; + this.serializer = serializer; + sequence = new ArrayList<>(); + resultPool = new ArrayList<>(); + loops = 5; + } + + public static > Optional getRecipe(World world, C inv, + IRecipeType type, Class recipeClass) { + //return getRecipe(world, inv.getStackInSlot(0), type, recipeClass).filter(r -> r.matches(inv, world)); + return getRecipes(world, inv.getItem(0), type, recipeClass).filter(r -> r.matches(inv, world)) + .findFirst(); + } + + public static > Optional getRecipe(World world, ItemStack item, + IRecipeType type, Class recipeClass) { + List all = world.getRecipeManager() + .getAllRecipesFor(AllRecipeTypes.SEQUENCED_ASSEMBLY.getType()); + for (SequencedAssemblyRecipe sequencedAssemblyRecipe : all) { + if (!sequencedAssemblyRecipe.appliesTo(item)) + continue; + SequencedRecipe nextRecipe = sequencedAssemblyRecipe.getNextRecipe(item); + ProcessingRecipe recipe = nextRecipe.getRecipe(); + if (recipe.getType() != type || !recipeClass.isInstance(recipe)) + continue; + recipe.enforceNextResult(() -> sequencedAssemblyRecipe.advance(item)); + return Optional.of(recipeClass.cast(recipe)); + } + return Optional.empty(); + } + + public static > Stream getRecipes(World world, ItemStack item, + IRecipeType type, Class recipeClass) { + List all = world.getRecipeManager() + .getAllRecipesFor(AllRecipeTypes.SEQUENCED_ASSEMBLY.getType()); + + return all.stream() + .filter(it -> it.appliesTo(item)) + .map(it -> Pair.of(it, it.getNextRecipe(item).getRecipe())) + .filter(it -> it.getSecond() + .getType() == type && recipeClass.isInstance(it.getSecond())) + .map(it -> { + it.getSecond() + .enforceNextResult(() -> it.getFirst().advance(item)); + return it.getSecond(); + }) + .map(recipeClass::cast); + } + + private ItemStack advance(ItemStack input) { + int step = getStep(input); + if ((step + 1) / sequence.size() >= loops) + return rollResult(); + + ItemStack advancedItem = ItemHandlerHelper.copyStackWithSize(getTransitionalItem(), 1); + CompoundNBT itemTag = advancedItem.getOrCreateTag(); + CompoundNBT tag = new CompoundNBT(); + tag.putString("id", id.toString()); + tag.putInt("Step", step + 1); + tag.putFloat("Progress", (step + 1f) / (sequence.size() * loops)); + itemTag.put("SequencedAssembly", tag); + advancedItem.setTag(itemTag); + return advancedItem; + } + + public int getLoops() { + return loops; + } + + public void addAdditionalIngredientsAndMachines(List list) { + sequence.forEach(sr -> sr.getAsAssemblyRecipe() + .addAssemblyIngredients(list)); + Set machines = new HashSet<>(); + sequence.forEach(sr -> sr.getAsAssemblyRecipe() + .addRequiredMachines(machines)); + machines.stream() + .map(Ingredient::of) + .forEach(list::add); + } + + public void addAdditionalFluidIngredients(List list) { + sequence.forEach(sr -> sr.getAsAssemblyRecipe() + .addAssemblyFluidIngredients(list)); + } + + private ItemStack rollResult() { + float totalWeight = 0; + for (ProcessingOutput entry : resultPool) + totalWeight += entry.getChance(); + float number = Create.RANDOM.nextFloat() * totalWeight; + for (ProcessingOutput entry : resultPool) { + number -= entry.getChance(); + if (number < 0) + return entry.getStack() + .copy(); + } + return ItemStack.EMPTY; + } + + private boolean appliesTo(ItemStack input) { + if (ingredient.test(input)) + return true; + return input.hasTag() && getTransitionalItem().getItem() == input.getItem() && input.getTag() + .contains("SequencedAssembly") && input.getTag() + .getCompound("SequencedAssembly") + .getString("id") + .equals(id.toString()); + } + + private SequencedRecipe getNextRecipe(ItemStack input) { + return sequence.get(getStep(input) % sequence.size()); + } + + private int getStep(ItemStack input) { + if (!input.hasTag()) + return 0; + CompoundNBT tag = input.getTag(); + if (!tag.contains("SequencedAssembly")) + return 0; + int step = tag.getCompound("SequencedAssembly") + .getInt("Step"); + return step; + } + + @Override + public boolean matches(RecipeWrapper inv, World p_77569_2_) { + return false; + } + + @Override + public ItemStack assemble(RecipeWrapper p_77572_1_) { + return ItemStack.EMPTY; + } + + @Override + public boolean canCraftInDimensions(int p_194133_1_, int p_194133_2_) { + return false; + } + + @Override + public ItemStack getResultItem() { + return resultPool.get(0) + .getStack(); + } + + public float getOutputChance() { + float totalWeight = 0; + for (ProcessingOutput entry : resultPool) + totalWeight += entry.getChance(); + return resultPool.get(0) + .getChance() / totalWeight; + } + + @Override + public ResourceLocation getId() { + return id; + } + + @Override + public IRecipeSerializer getSerializer() { + return serializer; + } + + @Override + public boolean isSpecial() { + return true; + } + + @Override + public IRecipeType getType() { + return AllRecipeTypes.SEQUENCED_ASSEMBLY.getType(); + } + + @OnlyIn(Dist.CLIENT) + public static void addToTooltip(List toolTip, ItemStack stack) { + if (!stack.hasTag() || !stack.getTag() + .contains("SequencedAssembly")) + return; + CompoundNBT compound = stack.getTag() + .getCompound("SequencedAssembly"); + ResourceLocation resourceLocation = new ResourceLocation(compound.getString("id")); + Optional> recipe = Minecraft.getInstance().level.getRecipeManager() + .byKey(resourceLocation); + if (!recipe.isPresent()) + return; + IRecipe iRecipe = recipe.get(); + if (!(iRecipe instanceof SequencedAssemblyRecipe)) + return; + + SequencedAssemblyRecipe sequencedAssemblyRecipe = (SequencedAssemblyRecipe) iRecipe; + int length = sequencedAssemblyRecipe.sequence.size(); + int step = sequencedAssemblyRecipe.getStep(stack); + int total = length * sequencedAssemblyRecipe.loops; + toolTip.add(new StringTextComponent("")); + toolTip.add(Lang.translate("recipe.sequenced_assembly") + .withStyle(TextFormatting.GRAY)); + toolTip.add(Lang.translate("recipe.assembly.progress", step, total) + .withStyle(TextFormatting.DARK_GRAY)); + + int remaining = total - step; + for (int i = 0; i < length; i++) { + if (i >= remaining) + break; + SequencedRecipe sequencedRecipe = sequencedAssemblyRecipe.sequence.get((i + step) % length); + ITextComponent textComponent = sequencedRecipe.getAsAssemblyRecipe() + .getDescriptionForAssembly(); + if (i == 0) + toolTip.add(Lang.translate("recipe.assembly.next", textComponent) + .withStyle(TextFormatting.AQUA)); + else + toolTip.add(new StringTextComponent("-> ").append(textComponent) + .withStyle(TextFormatting.DARK_AQUA)); + } + + } + + public Ingredient getIngredient() { + return ingredient; + } + + public List> getSequence() { + return sequence; + } + + public ItemStack getTransitionalItem() { + return transitionalItem.getStack(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeBuilder.java b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeBuilder.java new file mode 100644 index 000000000..c1095a0b4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeBuilder.java @@ -0,0 +1,139 @@ +package com.simibubi.create.content.contraptions.itemAssembly; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.UnaryOperator; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeFactory; + +import net.minecraft.data.IFinishedRecipe; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipeSerializer; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.tags.ITag; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraftforge.common.crafting.conditions.ICondition; + +public class SequencedAssemblyRecipeBuilder { + + private SequencedAssemblyRecipe recipe; + protected List recipeConditions; + + public SequencedAssemblyRecipeBuilder(ResourceLocation id) { + recipeConditions = new ArrayList<>(); + this.recipe = new SequencedAssemblyRecipe(id, + AllRecipeTypes.SEQUENCED_ASSEMBLY.getSerializer()); + } + + public > SequencedAssemblyRecipeBuilder addStep(ProcessingRecipeFactory factory, + UnaryOperator> builder) { + ProcessingRecipeBuilder recipeBuilder = + new ProcessingRecipeBuilder<>(factory, new ResourceLocation("dummy")); + Item placeHolder = recipe.getTransitionalItem() + .getItem(); + recipe.getSequence() + .add(new SequencedRecipe<>(builder.apply(recipeBuilder.require(placeHolder) + .output(placeHolder)) + .build())); + return this; + } + + public SequencedAssemblyRecipeBuilder require(IItemProvider ingredient) { + return require(Ingredient.of(ingredient)); + } + + public SequencedAssemblyRecipeBuilder require(ITag.INamedTag tag) { + return require(Ingredient.of(tag)); + } + + public SequencedAssemblyRecipeBuilder require(Ingredient ingredient) { + recipe.ingredient = ingredient; + return this; + } + + public SequencedAssemblyRecipeBuilder transitionTo(IItemProvider item) { + recipe.transitionalItem = new ProcessingOutput(new ItemStack(item), 1); + return this; + } + + public SequencedAssemblyRecipeBuilder loops(int loops) { + recipe.loops = loops; + return this; + } + + public SequencedAssemblyRecipeBuilder addOutput(IItemProvider item, float weight) { + return addOutput(new ItemStack(item), weight); + } + + public SequencedAssemblyRecipeBuilder addOutput(ItemStack item, float weight) { + recipe.resultPool.add(new ProcessingOutput(item, weight)); + return this; + } + + public SequencedAssemblyRecipe build() { + return recipe; + } + + public void build(Consumer consumer) { + consumer.accept(new DataGenResult(build(), recipeConditions)); + } + + public static class DataGenResult implements IFinishedRecipe { + + private SequencedAssemblyRecipe recipe; + private List recipeConditions; + private ResourceLocation id; + private SequencedAssemblyRecipeSerializer serializer; + + public DataGenResult(SequencedAssemblyRecipe recipe, List recipeConditions) { + this.recipeConditions = recipeConditions; + this.recipe = recipe; + this.id = new ResourceLocation(recipe.getId().getNamespace(), + AllRecipeTypes.SEQUENCED_ASSEMBLY.getId().getPath() + "/" + recipe.getId().getPath()); + this.serializer = (SequencedAssemblyRecipeSerializer) recipe.getSerializer(); + } + + @Override + public void serializeRecipeData(JsonObject json) { + serializer.write(json, recipe); + if (recipeConditions.isEmpty()) + return; + + JsonArray conds = new JsonArray(); + recipeConditions.forEach(c -> conds.add(CraftingHelper.serialize(c))); + json.add("conditions", conds); + } + + @Override + public ResourceLocation getId() { + return id; + } + + @Override + public IRecipeSerializer getType() { + return serializer; + } + + @Override + public JsonObject serializeAdvancement() { + return null; + } + + @Override + public ResourceLocation getAdvancementId() { + return null; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeSerializer.java b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeSerializer.java new file mode 100644 index 000000000..91d54fd21 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeSerializer.java @@ -0,0 +1,89 @@ +package com.simibubi.create.content.contraptions.itemAssembly; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.simibubi.create.content.contraptions.processing.ProcessingOutput; + +import net.minecraft.item.crafting.IRecipeSerializer; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.JSONUtils; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.ForgeRegistryEntry; + +public class SequencedAssemblyRecipeSerializer extends ForgeRegistryEntry> + implements IRecipeSerializer { + + public SequencedAssemblyRecipeSerializer() {} + + protected void writeToJson(JsonObject json, SequencedAssemblyRecipe recipe) { + JsonArray nestedRecipes = new JsonArray(); + JsonArray results = new JsonArray(); + json.add("ingredient", recipe.getIngredient().toJson()); + recipe.getSequence().forEach(i -> nestedRecipes.add(i.toJson())); + recipe.resultPool.forEach(p -> results.add(p.serialize())); + json.add("transitionalItem", recipe.transitionalItem.serialize()); + json.add("sequence", nestedRecipes); + json.add("results", results); + json.addProperty("loops", recipe.loops); + } + + protected SequencedAssemblyRecipe readFromJson(ResourceLocation recipeId, JsonObject json) { + SequencedAssemblyRecipe recipe = new SequencedAssemblyRecipe(recipeId, this); + recipe.ingredient = Ingredient.fromJson(json.get("ingredient")); + recipe.transitionalItem = ProcessingOutput.deserialize(JSONUtils.getAsJsonObject(json, "transitionalItem")); + int i = 0; + for (JsonElement je : JSONUtils.getAsJsonArray(json, "sequence")) + recipe.getSequence().add(SequencedRecipe.fromJson(je.getAsJsonObject(), recipe, i++)); + for (JsonElement je : JSONUtils.getAsJsonArray(json, "results")) + recipe.resultPool.add(ProcessingOutput.deserialize(je)); + if (JSONUtils.isValidNode(json, "loops")) + recipe.loops = JSONUtils.getAsInt(json, "loops"); + return recipe; + } + + protected void writeToBuffer(PacketBuffer buffer, SequencedAssemblyRecipe recipe) { + recipe.getIngredient().toNetwork(buffer); + buffer.writeVarInt(recipe.getSequence().size()); + recipe.getSequence().forEach(sr -> sr.writeToBuffer(buffer)); + buffer.writeVarInt(recipe.resultPool.size()); + recipe.resultPool.forEach(sr -> sr.write(buffer)); + recipe.transitionalItem.write(buffer); + buffer.writeInt(recipe.loops); + } + + protected SequencedAssemblyRecipe readFromBuffer(ResourceLocation recipeId, PacketBuffer buffer) { + SequencedAssemblyRecipe recipe = new SequencedAssemblyRecipe(recipeId, this); + recipe.ingredient = Ingredient.fromNetwork(buffer); + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) + recipe.getSequence().add(SequencedRecipe.readFromBuffer(buffer)); + size = buffer.readVarInt(); + for (int i = 0; i < size; i++) + recipe.resultPool.add(ProcessingOutput.read(buffer)); + recipe.transitionalItem = ProcessingOutput.read(buffer); + recipe.loops = buffer.readInt(); + return recipe; + } + + public final void write(JsonObject json, SequencedAssemblyRecipe recipe) { + writeToJson(json, recipe); + } + + @Override + public final SequencedAssemblyRecipe fromJson(ResourceLocation id, JsonObject json) { + return readFromJson(id, json); + } + + @Override + public final void toNetwork(PacketBuffer buffer, SequencedAssemblyRecipe recipe) { + writeToBuffer(buffer, recipe); + } + + @Override + public final SequencedAssemblyRecipe fromNetwork(ResourceLocation id, PacketBuffer buffer) { + return readFromBuffer(id, buffer); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedRecipe.java new file mode 100644 index 000000000..b545d363d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedRecipe.java @@ -0,0 +1,80 @@ +package com.simibubi.create.content.contraptions.itemAssembly; + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; +import com.simibubi.create.content.contraptions.processing.ProcessingRecipeSerializer; + +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.IRecipeSerializer; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.item.crafting.RecipeManager; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.ForgeRegistries; + +public class SequencedRecipe> { + + private T wrapped; + + public SequencedRecipe(T wrapped) { + this.wrapped = wrapped; + } + + public IAssemblyRecipe getAsAssemblyRecipe() { + return (IAssemblyRecipe) wrapped; + } + + public ProcessingRecipe getRecipe() { + return wrapped; + } + + public JsonObject toJson() { + @SuppressWarnings("unchecked") + ProcessingRecipeSerializer serializer = (ProcessingRecipeSerializer) wrapped.getSerializer(); + JsonObject json = new JsonObject(); + json.addProperty("type", ForgeRegistries.RECIPE_SERIALIZERS.getKey(serializer) + .toString()); + serializer.write(json, wrapped); + return json; + } + + public static SequencedRecipe fromJson(JsonObject json, SequencedAssemblyRecipe parent, int index) { + ResourceLocation parentId = parent.getId(); + IRecipe recipe = RecipeManager.fromJson( + new ResourceLocation(parentId.getNamespace(), parentId.getPath() + "_step_" + index), json); + if (recipe instanceof ProcessingRecipe && recipe instanceof IAssemblyRecipe) { + ProcessingRecipe processingRecipe = (ProcessingRecipe) recipe; + IAssemblyRecipe assemblyRecipe = (IAssemblyRecipe) recipe; + if (assemblyRecipe.supportsAssembly()) { + Ingredient transit = Ingredient.of(parent.getTransitionalItem()); + processingRecipe.getIngredients() + .set(0, index == 0 ? Ingredient.merge(ImmutableList.of(transit, parent.getIngredient())) : transit); + SequencedRecipe sequencedRecipe = new SequencedRecipe<>(processingRecipe); + return sequencedRecipe; + } + } + throw new JsonParseException("Not a supported recipe type"); + } + + public void writeToBuffer(PacketBuffer buffer) { + @SuppressWarnings("unchecked") + ProcessingRecipeSerializer serializer = (ProcessingRecipeSerializer) wrapped.getSerializer(); + buffer.writeResourceLocation(ForgeRegistries.RECIPE_SERIALIZERS.getKey(serializer)); + buffer.writeResourceLocation(wrapped.getId()); + serializer.toNetwork(buffer, wrapped); + } + + public static SequencedRecipe readFromBuffer(PacketBuffer buffer) { + ResourceLocation resourcelocation = buffer.readResourceLocation(); + ResourceLocation resourcelocation1 = buffer.readResourceLocation(); + IRecipeSerializer serializer = ForgeRegistries.RECIPE_SERIALIZERS.getValue(resourcelocation); + if (!(serializer instanceof ProcessingRecipeSerializer)) + throw new JsonParseException("Not a supported recipe type"); + @SuppressWarnings("rawtypes") + ProcessingRecipe recipe = (ProcessingRecipe) serializer.fromNetwork(resourcelocation1, buffer); + return new SequencedRecipe<>(recipe); + } + +} 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..62c88b26f 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,8 +4,8 @@ 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.foundation.utility.ColorHelper; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.Blocks; @@ -29,18 +29,18 @@ public class AirFlowParticle extends SimpleAnimatedParticle { protected AirFlowParticle(ClientWorld world, IAirCurrentSource source, double x, double y, double z, IAnimatedSprite sprite) { - super(world, x, y, z, sprite, world.rand.nextFloat() * .5f); + super(world, x, y, z, sprite, world.random.nextFloat() * .5f); this.source = source; - this.particleScale *= 0.75F; - this.maxAge = 40; - canCollide = false; + this.quadSize *= 0.75F; + this.lifetime = 40; + hasPhysics = false; selectSprite(7); - 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; - this.prevPosZ = posZ; - setAlphaF(.25f); + Vector3d offset = VecHelper.offsetRandomly(Vector3d.ZERO, Create.RANDOM, .25f); + this.setPos(x + offset.x, y + offset.y, z + offset.z); + this.xo = x; + this.yo = y; + this.zo = z; + setAlpha(.25f); } @Nonnull @@ -54,43 +54,43 @@ public class AirFlowParticle extends SimpleAnimatedParticle { dissipate(); return; } - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; - if (this.age++ >= this.maxAge) { - this.setExpired(); + this.xo = this.x; + this.yo = this.y; + this.zo = this.z; + if (this.age++ >= this.lifetime) { + this.remove(); } else { - if (source.getAirCurrent() == null || !source.getAirCurrent().bounds.grow(.25f).contains(posX, posY, posZ)) { + if (source.getAirCurrent() == null || !source.getAirCurrent().bounds.inflate(.25f).contains(x, y, z)) { dissipate(); return; } - Vector3d directionVec = Vector3d.of(source.getAirCurrent().direction.getDirectionVec()); + Vector3d directionVec = Vector3d.atLowerCornerOf(source.getAirCurrent().direction.getNormal()); Vector3d motion = directionVec.scale(1 / 8f); if (!source.getAirCurrent().pushing) motion = motion.scale(-1); - double distance = new Vector3d(posX, posY, posZ).subtract(VecHelper.getCenterOf(source.getAirCurrentPos())) - .mul(directionVec).length() - .5f; + double distance = new Vector3d(x, y, z).subtract(VecHelper.getCenterOf(source.getAirCurrentPos())) + .multiply(directionVec).length() - .5f; if (distance > source.getAirCurrent().maxDistance + 1 || distance < -.25f) { dissipate(); return; } motion = motion.scale(source.getAirCurrent().maxDistance - (distance - 1f)).scale(.5f); - selectSprite((int) MathHelper.clamp((distance / source.getAirCurrent().maxDistance) * 8 + world.rand.nextInt(4), + selectSprite((int) MathHelper.clamp((distance / source.getAirCurrent().maxDistance) * 8 + level.random.nextInt(4), 0, 7)); morphType(distance); - motionX = motion.x; - motionY = motion.y; - motionZ = motion.z; + xd = motion.x; + yd = motion.y; + zd = motion.z; if (this.onGround) { - this.motionX *= 0.7; - this.motionZ *= 0.7; + this.xd *= 0.7; + this.zd *= 0.7; } - this.move(this.motionX, this.motionY, this.motionZ); + this.move(this.xd, this.yd, this.zd); } @@ -102,59 +102,59 @@ public class AirFlowParticle extends SimpleAnimatedParticle { InWorldProcessing.Type type = source.getAirCurrent().getSegmentAt((float) distance); if (type == InWorldProcessing.Type.SPLASHING) { - setColor(ColorHelper.mixColors(0x4499FF, 0x2277FF, world.rand.nextFloat())); - setAlphaF(1f); - selectSprite(world.rand.nextInt(3)); - if (world.rand.nextFloat() < 1 / 32f) - world.addParticle(ParticleTypes.BUBBLE, posX, posY, posZ, motionX * .125f, motionY * .125f, - motionZ * .125f); - if (world.rand.nextFloat() < 1 / 32f) - world.addParticle(ParticleTypes.BUBBLE_POP, posX, posY, posZ, motionX * .125f, motionY * .125f, - motionZ * .125f); + setColor(Color.mixColors(0x4499FF, 0x2277FF, level.random.nextFloat())); + setAlpha(1f); + selectSprite(level.random.nextInt(3)); + if (level.random.nextFloat() < 1 / 32f) + level.addParticle(ParticleTypes.BUBBLE, x, y, z, xd * .125f, yd * .125f, + zd * .125f); + if (level.random.nextFloat() < 1 / 32f) + level.addParticle(ParticleTypes.BUBBLE_POP, x, y, z, xd * .125f, yd * .125f, + zd * .125f); } if (type == InWorldProcessing.Type.SMOKING) { - setColor(ColorHelper.mixColors(0x0, 0x555555, world.rand.nextFloat())); - setAlphaF(1f); - selectSprite(world.rand.nextInt(3)); - if (world.rand.nextFloat() < 1 / 32f) - world.addParticle(ParticleTypes.SMOKE, posX, posY, posZ, motionX * .125f, motionY * .125f, - motionZ * .125f); - if (world.rand.nextFloat() < 1 / 32f) - world.addParticle(ParticleTypes.LARGE_SMOKE, posX, posY, posZ, motionX * .125f, motionY * .125f, - motionZ * .125f); + setColor(Color.mixColors(0x0, 0x555555, level.random.nextFloat())); + setAlpha(1f); + selectSprite(level.random.nextInt(3)); + if (level.random.nextFloat() < 1 / 32f) + level.addParticle(ParticleTypes.SMOKE, x, y, z, xd * .125f, yd * .125f, + zd * .125f); + if (level.random.nextFloat() < 1 / 32f) + level.addParticle(ParticleTypes.LARGE_SMOKE, x, y, z, xd * .125f, yd * .125f, + zd * .125f); } if (type == InWorldProcessing.Type.BLASTING) { - setColor(ColorHelper.mixColors(0xFF4400, 0xFF8855, world.rand.nextFloat())); - setAlphaF(.5f); - selectSprite(world.rand.nextInt(3)); - if (world.rand.nextFloat() < 1 / 32f) - world.addParticle(ParticleTypes.FLAME, posX, posY, posZ, motionX * .25f, motionY * .25f, - motionZ * .25f); - if (world.rand.nextFloat() < 1 / 16f) - world.addParticle(new BlockParticleData(ParticleTypes.BLOCK, Blocks.LAVA.getDefaultState()), posX, posY, - posZ, motionX * .25f, motionY * .25f, motionZ * .25f); + setColor(Color.mixColors(0xFF4400, 0xFF8855, level.random.nextFloat())); + setAlpha(.5f); + selectSprite(level.random.nextInt(3)); + if (level.random.nextFloat() < 1 / 32f) + level.addParticle(ParticleTypes.FLAME, x, y, z, xd * .25f, yd * .25f, + zd * .25f); + if (level.random.nextFloat() < 1 / 16f) + level.addParticle(new BlockParticleData(ParticleTypes.BLOCK, Blocks.LAVA.defaultBlockState()), x, y, + z, xd * .25f, yd * .25f, zd * .25f); } if (type == null) { setColor(0xEEEEEE); - setAlphaF(.25f); + setAlpha(.25f); setSize(.2f, .2f); } } private void dissipate() { - setExpired(); + remove(); } - public int getBrightnessForRender(float partialTick) { - BlockPos blockpos = new BlockPos(this.posX, this.posY, this.posZ); - return this.world.isBlockPresent(blockpos) ? WorldRenderer.getLightmapCoordinates(world, blockpos) : 0; + public int getLightColor(float partialTick) { + BlockPos blockpos = new BlockPos(this.x, this.y, this.z); + return this.level.isLoaded(blockpos) ? WorldRenderer.getLightColor(level, blockpos) : 0; } private void selectSprite(int index) { - setSprite(field_217584_C.get(index, 8)); + setSprite(sprites.get(index, 8)); } public static class Factory implements IParticleFactory { @@ -164,9 +164,9 @@ public class AirFlowParticle extends SimpleAnimatedParticle { this.spriteSet = animatedSprite; } - public Particle makeParticle(AirFlowParticleData data, ClientWorld worldIn, double x, double y, double z, + public Particle createParticle(AirFlowParticleData data, ClientWorld worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { - TileEntity te = worldIn.getTileEntity(new BlockPos(data.posX, data.posY, data.posZ)); + TileEntity te = worldIn.getBlockEntity(new BlockPos(data.posX, data.posY, data.posZ)); if (!(te instanceof IAirCurrentSource)) te = null; return new AirFlowParticle(worldIn, (IAirCurrentSource) te, x, y, z, this.spriteSet); diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticleData.java index 74f6d9a32..bff77492d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticleData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticleData.java @@ -26,7 +26,7 @@ public class AirFlowParticleData implements IParticleData, ICustomParticleDataWi .apply(i, AirFlowParticleData::new)); public static final IParticleData.IDeserializer DESERIALIZER = new IParticleData.IDeserializer() { - public AirFlowParticleData deserialize(ParticleType particleTypeIn, StringReader reader) + public AirFlowParticleData fromCommand(ParticleType particleTypeIn, StringReader reader) throws CommandSyntaxException { reader.expect(' '); int x = reader.readInt(); @@ -37,7 +37,7 @@ public class AirFlowParticleData implements IParticleData, ICustomParticleDataWi return new AirFlowParticleData(x, y, z); } - public AirFlowParticleData read(ParticleType particleTypeIn, PacketBuffer buffer) { + public AirFlowParticleData fromNetwork(ParticleType particleTypeIn, PacketBuffer buffer) { return new AirFlowParticleData(buffer.readInt(), buffer.readInt(), buffer.readInt()); } }; @@ -66,14 +66,14 @@ public class AirFlowParticleData implements IParticleData, ICustomParticleDataWi } @Override - public void write(PacketBuffer buffer) { + public void writeToNetwork(PacketBuffer buffer) { buffer.writeInt(posX); buffer.writeInt(posY); buffer.writeInt(posZ); } @Override - public String getParameters() { + public String writeToString() { return String.format(Locale.ROOT, "%s %d %d %d", AllParticleTypes.AIR_FLOW.parameter(), posX, posY, posZ); } 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..1951cdedb 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 @@ -26,27 +26,33 @@ public class AirParticle extends SimpleAnimatedParticle { protected AirParticle(ClientWorld world, AirParticleData data, double x, double y, double z, double dx, double dy, double dz, IAnimatedSprite sprite) { - super(world, x, y, z, sprite, world.rand.nextFloat() * .5f); - particleScale *= 0.75F; - canCollide = false; + super(world, x, y, z, sprite, world.random.nextFloat() * .5f); + quadSize *= 0.75F; + hasPhysics = false; - setPosition(posX, posY, posZ); - originX = (float) (prevPosX = posX); - originY = (float) (prevPosY = posY); - originZ = (float) (prevPosZ = posZ); + setPos(x, y, z); + originX = (float) (xo = x); + originY = (float) (yo = y); + originZ = (float) (zo = z); targetX = (float) (x + dx); targetY = (float) (y + dy); 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); + double length = new Vector3d(dx, dy, dz).length(); + lifetime = Math.min((int) (length / data.speed), 60); selectSprite(7); - setAlphaF(.25f); + setAlpha(.25f); + + if (length == 0) { + remove(); + setAlpha(0); + } } public IParticleRenderType getRenderType() { @@ -55,15 +61,15 @@ public class AirParticle extends SimpleAnimatedParticle { @Override public void tick() { - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; - if (this.age++ >= this.maxAge) { - this.setExpired(); + this.xo = this.x; + this.yo = this.y; + this.zo = this.z; + if (this.age++ >= this.lifetime) { + this.remove(); return; } - float progress = (float) Math.pow(((float) age) / maxAge, drag); + float progress = (float) Math.pow(((float) age) / lifetime, drag); float angle = (progress * 2 * 360 + twirlAngleOffset) % 360; Vector3d twirl = VecHelper.rotate(new Vector3d(0, twirlRadius, 0), angle, twirlAxis); @@ -71,21 +77,21 @@ public class AirParticle extends SimpleAnimatedParticle { float y = (float) (MathHelper.lerp(progress, originY, targetY) + twirl.y); float z = (float) (MathHelper.lerp(progress, originZ, targetZ) + twirl.z); - motionX = x - posX; - motionY = y - posY; - motionZ = z - posZ; + xd = x - this.x; + yd = y - this.y; + zd = z - this.z; - selectSpriteWithAge(field_217584_C); - this.move(this.motionX, this.motionY, this.motionZ); + setSpriteFromAge(sprites); + this.move(this.xd, this.yd, this.zd); } - public int getBrightnessForRender(float partialTick) { - BlockPos blockpos = new BlockPos(this.posX, this.posY, this.posZ); - return this.world.isBlockPresent(blockpos) ? WorldRenderer.getLightmapCoordinates(world, blockpos) : 0; + public int getLightColor(float partialTick) { + BlockPos blockpos = new BlockPos(this.x, this.y, this.z); + return this.level.isLoaded(blockpos) ? WorldRenderer.getLightColor(level, blockpos) : 0; } private void selectSprite(int index) { - setSprite(field_217584_C.get(index, 8)); + setSprite(sprites.get(index, 8)); } public static class Factory implements IParticleFactory { @@ -95,7 +101,7 @@ public class AirParticle extends SimpleAnimatedParticle { this.spriteSet = animatedSprite; } - public Particle makeParticle(AirParticleData data, ClientWorld worldIn, double x, double y, double z, double xSpeed, + public Particle createParticle(AirParticleData data, ClientWorld worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { return new AirParticle(worldIn, data, x, y, z, xSpeed, ySpeed, zSpeed, this.spriteSet); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/AirParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/particle/AirParticleData.java index 7159756f8..133dc3180 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/AirParticleData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/AirParticleData.java @@ -25,7 +25,7 @@ public class AirParticleData implements IParticleData, ICustomParticleDataWithSp public static final IParticleData.IDeserializer DESERIALIZER = new IParticleData.IDeserializer() { - public AirParticleData deserialize(ParticleType particleTypeIn, StringReader reader) + public AirParticleData fromCommand(ParticleType particleTypeIn, StringReader reader) throws CommandSyntaxException { reader.expect(' '); float drag = reader.readFloat(); @@ -34,7 +34,7 @@ public class AirParticleData implements IParticleData, ICustomParticleDataWithSp return new AirParticleData(drag, speed); } - public AirParticleData read(ParticleType particleTypeIn, PacketBuffer buffer) { + public AirParticleData fromNetwork(ParticleType particleTypeIn, PacketBuffer buffer) { return new AirParticleData(buffer.readFloat(), buffer.readFloat()); } }; @@ -57,13 +57,13 @@ public class AirParticleData implements IParticleData, ICustomParticleDataWithSp } @Override - public void write(PacketBuffer buffer) { + public void writeToNetwork(PacketBuffer buffer) { buffer.writeFloat(drag); buffer.writeFloat(speed); } @Override - public String getParameters() { + public String writeToString() { return String.format(Locale.ROOT, "%s %f %f", AllParticleTypes.AIR.parameter(), drag, speed); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java index f50fdf30d..bc68081d2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java @@ -53,7 +53,7 @@ public class CubeParticle extends Particle { private static final IParticleRenderType renderType = new IParticleRenderType() { @Override - public void beginRender(BufferBuilder builder, TextureManager textureManager) { + public void begin(BufferBuilder builder, TextureManager textureManager) { RenderSystem.disableTexture(); // transparent, additive blending @@ -72,8 +72,8 @@ public class CubeParticle extends Particle { } @Override - public void finishRender(Tessellator tessellator) { - tessellator.draw(); + public void end(Tessellator tessellator) { + tessellator.end(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); RenderSystem.disableLighting(); @@ -86,9 +86,9 @@ public class CubeParticle extends Particle { public CubeParticle(ClientWorld world, double x, double y, double z, double motionX, double motionY, double motionZ) { super(world, x, y, z); - this.motionX = motionX; - this.motionY = motionY; - this.motionZ = motionZ; + this.xd = motionX; + this.yd = motionY; + this.zd = motionZ; setScale(0.2F); } @@ -99,7 +99,7 @@ public class CubeParticle extends Particle { } public void averageAge(int age) { - this.maxAge = (int) (age + (rand.nextDouble() * 2D - 1D) * 8); + this.lifetime = (int) (age + (random.nextDouble() * 2D - 1D) * 8); } public void setHot(boolean hot) { @@ -111,34 +111,34 @@ public class CubeParticle extends Particle { @Override public void tick() { if (this.hot && this.age > 0) { - if (this.prevPosY == this.posY) { + if (this.yo == this.y) { billowing = true; - field_21507 = false; // Prevent motion being ignored due to vertical collision - if (this.motionX == 0 && this.motionZ == 0) { - Vector3d diff = Vector3d.of(new BlockPos(posX, posY, posZ)).add(0.5, 0.5, 0.5).subtract(posX, posY, posZ); - this.motionX = -diff.x * 0.1; - this.motionZ = -diff.z * 0.1; + stoppedByCollision = false; // Prevent motion being ignored due to vertical collision + if (this.xd == 0 && this.zd == 0) { + Vector3d diff = Vector3d.atLowerCornerOf(new BlockPos(x, y, z)).add(0.5, 0.5, 0.5).subtract(x, y, z); + this.xd = -diff.x * 0.1; + this.zd = -diff.z * 0.1; } - this.motionX *= 1.1; - this.motionY *= 0.9; - this.motionZ *= 1.1; + this.xd *= 1.1; + this.yd *= 0.9; + this.zd *= 1.1; } else if (billowing) { - this.motionY *= 1.2; + this.yd *= 1.2; } } super.tick(); } @Override - public void buildGeometry(IVertexBuilder builder, ActiveRenderInfo renderInfo, float p_225606_3_) { - Vector3d projectedView = renderInfo.getProjectedView(); - float lerpedX = (float) (MathHelper.lerp(p_225606_3_, this.prevPosX, this.posX) - projectedView.getX()); - float lerpedY = (float) (MathHelper.lerp(p_225606_3_, this.prevPosY, this.posY) - projectedView.getY()); - float lerpedZ = (float) (MathHelper.lerp(p_225606_3_, this.prevPosZ, this.posZ) - projectedView.getZ()); + public void render(IVertexBuilder builder, ActiveRenderInfo renderInfo, float p_225606_3_) { + Vector3d projectedView = renderInfo.getPosition(); + float lerpedX = (float) (MathHelper.lerp(p_225606_3_, this.xo, this.x) - projectedView.x()); + float lerpedY = (float) (MathHelper.lerp(p_225606_3_, this.yo, this.y) - projectedView.y()); + float lerpedZ = (float) (MathHelper.lerp(p_225606_3_, this.zo, this.z) - projectedView.z()); // int light = getBrightnessForRender(p_225606_3_); int light = 15728880;// 15<<20 && 15<<4 - double ageMultiplier = 1 - Math.pow(age, 3) / Math.pow(maxAge, 3); + double ageMultiplier = 1 - Math.pow(age, 3) / Math.pow(lifetime, 3); for (int i = 0; i < 6; i++) { // 6 faces to a cube @@ -151,9 +151,9 @@ public class CubeParticle extends Particle { Vector3d normal = CUBE_NORMALS[i]; builder.vertex(vec.x, vec.y, vec.z) - .color(particleRed, particleGreen, particleBlue, particleAlpha) - .texture(0, 0) - .light(light) + .color(rCol, gCol, bCol, alpha) + .uv(0, 0) + .uv2(light) .normal((float) normal.x, (float) normal.y, (float) normal.z) .endVertex(); } @@ -170,7 +170,7 @@ public class CubeParticle extends Particle { public Factory() {} @Override - public Particle makeParticle(CubeParticleData data, ClientWorld world, double x, double y, double z, double motionX, + public Particle createParticle(CubeParticleData data, ClientWorld world, double x, double y, double z, double motionX, double motionY, double motionZ) { CubeParticle particle = new CubeParticle(world, x, y, z, motionX, motionY, motionZ); particle.setColor(data.r, data.g, data.b); diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java index 442a68b49..7bf66ce3c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java @@ -29,7 +29,7 @@ public class CubeParticleData implements IParticleData, ICustomParticleData DESERIALIZER = new IParticleData.IDeserializer() { @Override - public CubeParticleData deserialize(ParticleType type, StringReader reader) throws CommandSyntaxException { + public CubeParticleData fromCommand(ParticleType type, StringReader reader) throws CommandSyntaxException { reader.expect(' '); float r = reader.readFloat(); reader.expect(' '); @@ -46,7 +46,7 @@ public class CubeParticleData implements IParticleData, ICustomParticleData type, PacketBuffer buffer) { + public CubeParticleData fromNetwork(ParticleType type, PacketBuffer buffer) { return new CubeParticleData(buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readInt(), buffer.readBoolean()); } }; @@ -93,7 +93,7 @@ public class CubeParticleData implements IParticleData, ICustomParticleData> 16 & 255; j = j + (int) (f * 15.0F * 16.0F); @@ -76,20 +76,20 @@ public class HeaterParticle extends SimpleAnimatedParticle { @Override public void tick() { - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; - if (this.age++ >= this.maxAge) { - this.setExpired(); + this.xo = this.x; + this.yo = this.y; + this.zo = this.z; + if (this.age++ >= this.lifetime) { + this.remove(); } else { - this.selectSpriteWithAge(animatedSprite); - this.move(this.motionX, this.motionY, this.motionZ); - this.motionX *= (double) 0.96F; - this.motionY *= (double) 0.96F; - this.motionZ *= (double) 0.96F; + this.setSpriteFromAge(animatedSprite); + this.move(this.xd, this.yd, this.zd); + this.xd *= (double) 0.96F; + this.yd *= (double) 0.96F; + this.zd *= (double) 0.96F; if (this.onGround) { - this.motionX *= (double) 0.7F; - this.motionZ *= (double) 0.7F; + this.xd *= (double) 0.7F; + this.zd *= (double) 0.7F; } } } @@ -102,7 +102,7 @@ public class HeaterParticle extends SimpleAnimatedParticle { } @Override - public Particle makeParticle(HeaterParticleData data, ClientWorld worldIn, double x, double y, double z, double vx, + public Particle createParticle(HeaterParticleData data, ClientWorld worldIn, double x, double y, double z, double vx, double vy, double vz) { return new HeaterParticle(worldIn, data.r, data.g, data.b, x, y, z, vx, vy, vz, this.spriteSet); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticleData.java index a547ba995..c2cf4c37e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticleData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticleData.java @@ -32,7 +32,7 @@ public class HeaterParticleData implements IParticleData, ICustomParticleDataWit public static final IParticleData.IDeserializer DESERIALIZER = new IParticleData.IDeserializer() { @Override - public HeaterParticleData deserialize(ParticleType arg0, StringReader reader) + public HeaterParticleData fromCommand(ParticleType arg0, StringReader reader) throws CommandSyntaxException { reader.expect(' '); float r = reader.readFloat(); @@ -44,7 +44,7 @@ public class HeaterParticleData implements IParticleData, ICustomParticleDataWit } @Override - public HeaterParticleData read(ParticleType type, PacketBuffer buffer) { + public HeaterParticleData fromNetwork(ParticleType type, PacketBuffer buffer) { return new HeaterParticleData(buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); } }; @@ -80,7 +80,7 @@ public class HeaterParticleData implements IParticleData, ICustomParticleDataWit } @Override - public String getParameters() { + public String writeToString() { return String.format(Locale.ROOT, "%s %f %f %f", AllParticleTypes.HEATER_PARTICLE.parameter(), r, g, b); } @@ -90,7 +90,7 @@ public class HeaterParticleData implements IParticleData, ICustomParticleDataWit } @Override - public void write(PacketBuffer buffer) { + public void writeToNetwork(PacketBuffer buffer) { buffer.writeFloat(r); buffer.writeFloat(g); buffer.writeFloat(b); diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/ICustomParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/particle/ICustomParticleData.java index 8e067799c..8d76c0788 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/ICustomParticleData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/ICustomParticleData.java @@ -20,7 +20,7 @@ public interface ICustomParticleData { return new ParticleType(false, getDeserializer()) { @Override - public Codec getCodec() { + public Codec codec() { return ICustomParticleData.this.getCodec(this); } }; @@ -31,7 +31,7 @@ public interface ICustomParticleData { @OnlyIn(Dist.CLIENT) public default void register(ParticleType type, ParticleManager particles) { - particles.registerFactory(type, getFactory()); + particles.register(type, getFactory()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/ICustomParticleDataWithSprite.java b/src/main/java/com/simibubi/create/content/contraptions/particle/ICustomParticleDataWithSprite.java index 65dd04908..30c554549 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/ICustomParticleDataWithSprite.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/ICustomParticleDataWithSprite.java @@ -19,7 +19,7 @@ public interface ICustomParticleDataWithSprite extends return new ParticleType(false, getDeserializer()) { @Override - public Codec getCodec() { + public Codec codec() { return ICustomParticleDataWithSprite.this.getCodec(this); } }; @@ -37,7 +37,7 @@ public interface ICustomParticleDataWithSprite extends @Override @OnlyIn(Dist.CLIENT) public default void register(ParticleType type, ParticleManager particles) { - particles.registerFactory(type, getMetaFactory()); + particles.register(type, getMetaFactory()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java index ffb2f1996..17480d203 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.particle; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.content.contraptions.goggles.GogglesItem; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; @@ -31,15 +31,15 @@ public class RotationIndicatorParticle extends SimpleAnimatedParticle { private RotationIndicatorParticle(ClientWorld world, double x, double y, double z, int color, float radius1, float radius2, float speed, Axis axis, int lifeSpan, boolean isVisible, IAnimatedSprite sprite) { super(world, x, y, z, sprite, 0); - this.motionX = 0; - this.motionY = 0; - this.motionZ = 0; + this.xd = 0; + this.yd = 0; + this.zd = 0; this.origin = new Vector3d(x, y, z); - this.particleScale *= 0.75F; - this.maxAge = lifeSpan + this.rand.nextInt(32); - this.setColorFade(color); - this.setColor(ColorHelper.mixColors(color, 0xFFFFFF, .5f)); - this.selectSpriteWithAge(sprite); + this.quadSize *= 0.75F; + this.lifetime = lifeSpan + this.random.nextInt(32); + this.setFadeColor(color); + this.setColor(Color.mixColors(color, 0xFFFFFF, .5f)); + this.setSpriteFromAge(sprite); this.radius1 = radius1; this.radius = radius1; this.radius2 = radius2; @@ -48,9 +48,9 @@ public class RotationIndicatorParticle extends SimpleAnimatedParticle { this.isVisible = isVisible; this.offset = axis.isHorizontal() ? new Vector3d(0, 1, 0) : new Vector3d(1, 0, 0); move(0, 0, 0); - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; + this.xo = this.x; + this.yo = this.y; + this.zo = this.z; } @Override @@ -60,21 +60,21 @@ public class RotationIndicatorParticle extends SimpleAnimatedParticle { } @Override - public void buildGeometry(IVertexBuilder buffer, ActiveRenderInfo renderInfo, float partialTicks) { + public void render(IVertexBuilder buffer, ActiveRenderInfo renderInfo, float partialTicks) { if (!isVisible) return; - super.buildGeometry(buffer, renderInfo, partialTicks); + super.render(buffer, renderInfo, partialTicks); } public void move(double x, double y, double z) { - float time = AnimationTickHolder.getTicks(world); - float angle = (float) ((time * speed) % 360) - (speed / 2 * age * (((float) age) / maxAge)); + float time = AnimationTickHolder.getTicks(level); + float angle = (float) ((time * speed) % 360) - (speed / 2 * age * (((float) age) / lifetime)); if (speed < 0 && axis.isVertical()) angle += 180; Vector3d position = VecHelper.rotate(this.offset.scale(radius), angle, axis).add(origin); - posX = position.x; - posY = position.y; - posZ = position.z; + x = position.x; + y = position.y; + z = position.z; } public static class Factory implements IParticleFactory { @@ -84,11 +84,11 @@ public class RotationIndicatorParticle extends SimpleAnimatedParticle { this.spriteSet = animatedSprite; } - public Particle makeParticle(RotationIndicatorParticleData data, ClientWorld worldIn, double x, double y, double z, + public Particle createParticle(RotationIndicatorParticleData data, ClientWorld worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { Minecraft mc = Minecraft.getInstance(); ClientPlayerEntity player = mc.player; - boolean visible = worldIn != mc.world || player != null && GogglesItem.canSeeParticles(player); + boolean visible = worldIn != mc.level || player != null && GogglesItem.canSeeParticles(player); return new RotationIndicatorParticle(worldIn, x, y, z, data.color, data.radius1, data.radius2, data.speed, data.getAxis(), data.lifeSpan, visible, this.spriteSet); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticleData.java index 23fb007e9..2827b49a8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticleData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticleData.java @@ -58,7 +58,7 @@ public class RotationIndicatorParticleData public static final IParticleData.IDeserializer DESERIALIZER = new IParticleData.IDeserializer() { - public RotationIndicatorParticleData deserialize(ParticleType particleTypeIn, + public RotationIndicatorParticleData fromCommand(ParticleType particleTypeIn, StringReader reader) throws CommandSyntaxException { reader.expect(' '); int color = reader.readInt(); @@ -75,7 +75,7 @@ public class RotationIndicatorParticleData return new RotationIndicatorParticleData(color, speed, rad1, rad2, lifeSpan, axis); } - public RotationIndicatorParticleData read(ParticleType particleTypeIn, + public RotationIndicatorParticleData fromNetwork(ParticleType particleTypeIn, PacketBuffer buffer) { return new RotationIndicatorParticleData(buffer.readInt(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readInt(), buffer.readChar()); @@ -113,7 +113,7 @@ public class RotationIndicatorParticleData } @Override - public void write(PacketBuffer buffer) { + public void writeToNetwork(PacketBuffer buffer) { buffer.writeInt(color); buffer.writeFloat(speed); buffer.writeFloat(radius1); @@ -123,7 +123,7 @@ public class RotationIndicatorParticleData } @Override - public String getParameters() { + public String writeToString() { return String.format(Locale.ROOT, "%s %d %.2f %.2f %.2f %d %c", AllParticleTypes.ROTATION_INDICATOR.parameter(), color, speed, radius1, radius2, lifeSpan, axis); } 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..673115935 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 @@ -50,11 +50,11 @@ import net.minecraftforge.items.ItemStackHandler; public class BasinBlock extends Block implements ITE, IWrenchable { - public static final DirectionProperty FACING = BlockStateProperties.FACING_EXCEPT_UP; + public static final DirectionProperty FACING = BlockStateProperties.FACING_HOPPER; public BasinBlock(Properties p_i48440_1_) { super(p_i48440_1_); - setDefaultState(getDefaultState().with(FACING, Direction.DOWN)); + registerDefaultState(defaultBlockState().setValue(FACING, Direction.DOWN)); } @Override @@ -63,13 +63,13 @@ public class BasinBlock extends Block implements ITE, IWrenchab } @Override - protected void fillStateContainer(Builder p_206840_1_) { - super.fillStateContainer(p_206840_1_.add(FACING)); + protected void createBlockStateDefinition(Builder p_206840_1_) { + super.createBlockStateDefinition(p_206840_1_.add(FACING)); } @Override - public boolean isValidPosition(BlockState state, IWorldReader world, BlockPos pos) { - TileEntity tileEntity = world.getTileEntity(pos.up()); + public boolean canSurvive(BlockState state, IWorldReader world, BlockPos pos) { + TileEntity tileEntity = world.getBlockEntity(pos.above()); if (tileEntity instanceof BasinOperatingTileEntity) return false; return true; @@ -82,18 +82,17 @@ public class BasinBlock extends Block implements ITE, IWrenchab @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { - if (!context.getWorld().isRemote) - withTileEntityDo(context.getWorld(), context.getPos(), bte -> bte.onWrenched(context.getFace())); + if (!context.getLevel().isClientSide) + withTileEntityDo(context.getLevel(), context.getClickedPos(), bte -> bte.onWrenched(context.getClickedFace())); return ActionResultType.SUCCESS; } @Override - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - ItemStack heldItem = player.getHeldItem(handIn); + ItemStack heldItem = player.getItemInHand(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) @@ -125,26 +124,24 @@ public class BasinBlock extends Block implements ITE, IWrenchab success = true; } if (success) - worldIn.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, .2f, - 1f + Create.random.nextFloat()); + worldIn.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundCategory.PLAYERS, .2f, + 1f + Create.RANDOM.nextFloat()); te.onEmptied(); - } catch (TileEntityException e) { - } - - return ActionResultType.SUCCESS; + return ActionResultType.SUCCESS; + }); } @Override - public void onLanded(IBlockReader worldIn, Entity entityIn) { - super.onLanded(worldIn, entityIn); - if (!AllBlocks.BASIN.has(worldIn.getBlockState(entityIn.getBlockPos()))) + public void updateEntityAfterFallOn(IBlockReader worldIn, Entity entityIn) { + super.updateEntityAfterFallOn(worldIn, entityIn); + if (!AllBlocks.BASIN.has(worldIn.getBlockState(entityIn.blockPosition()))) return; if (!(entityIn instanceof ItemEntity)) return; if (!entityIn.isAlive()) return; ItemEntity itemEntity = (ItemEntity) entityIn; - withTileEntityDo(worldIn, entityIn.getBlockPos(), te -> { + withTileEntityDo(worldIn, entityIn.blockPosition(), te -> { // Tossed items bypass the quarter-stack limit te.inputInventory.withMaxStackSize(64); @@ -154,9 +151,9 @@ public class BasinBlock extends Block implements ITE, IWrenchab if (insertItem.isEmpty()) { itemEntity.remove(); - if (!itemEntity.world.isRemote) - AllTriggers.triggerForNearbyPlayers(AllTriggers.BASIN_THROW, itemEntity.world, - itemEntity.getBlockPos(), 3); + if (!itemEntity.level.isClientSide) + AllTriggers.triggerForNearbyPlayers(AllTriggers.BASIN_THROW, itemEntity.level, + itemEntity.blockPosition(), 3); return; } @@ -165,7 +162,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab } @Override - public VoxelShape getRaytraceShape(BlockState p_199600_1_, IBlockReader p_199600_2_, BlockPos p_199600_3_) { + public VoxelShape getInteractionShape(BlockState p_199600_1_, IBlockReader p_199600_2_, BlockPos p_199600_3_) { return AllShapes.BASIN_RAYTRACE_SHAPE; } @@ -182,25 +179,25 @@ public class BasinBlock extends Block implements ITE, IWrenchab } @Override - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { if (!state.hasTileEntity() || state.getBlock() == newState.getBlock()) return; TileEntityBehaviour.destroy(worldIn, pos, FilteringBehaviour.TYPE); withTileEntityDo(worldIn, pos, te -> { ItemHelper.dropContents(worldIn, pos, te.inputInventory); ItemHelper.dropContents(worldIn, pos, te.outputInventory); - te.spoutputBuffer.forEach(is -> Block.spawnAsEntity(worldIn, pos, is)); + te.spoutputBuffer.forEach(is -> Block.popResource(worldIn, pos, is)); }); - worldIn.removeTileEntity(pos); + worldIn.removeBlockEntity(pos); } @Override - public boolean hasComparatorInputOverride(BlockState state) { + public boolean hasAnalogOutputSignal(BlockState state) { return true; } @Override - public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) { + public int getAnalogOutputSignal(BlockState blockState, World worldIn, BlockPos pos) { return getTileEntityOptional(worldIn, pos).map(BasinTileEntity::getInputInventory) .map(ItemHelper::calcRedstoneFromInventory) .orElse(0); @@ -212,8 +209,8 @@ public class BasinBlock extends Block implements ITE, IWrenchab } public static boolean canOutputTo(IBlockReader world, BlockPos basinPos, Direction direction) { - BlockPos neighbour = basinPos.offset(direction); - BlockPos output = neighbour.down(); + BlockPos neighbour = basinPos.relative(direction); + BlockPos output = neighbour.below(); BlockState blockState = world.getBlockState(neighbour); if (FunnelBlock.isFunnel(blockState)) { @@ -223,7 +220,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab .isEmpty()) { return false; } else { - TileEntity tileEntity = world.getTileEntity(output); + TileEntity tileEntity = world.getBlockEntity(output); if (tileEntity instanceof BeltTileEntity) { BeltTileEntity belt = (BeltTileEntity) tileEntity; return belt.getSpeed() == 0 || belt.getMovementFacing() != direction.getOpposite(); @@ -238,7 +235,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinGenerator.java index fe96055ac..5df06ac99 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinGenerator.java @@ -18,13 +18,13 @@ public class BasinGenerator extends SpecialBlockStateGen { @Override protected int getYRotation(BlockState state) { - return horizontalAngle(state.get(BasinBlock.FACING)); + return horizontalAngle(state.getValue(BasinBlock.FACING)); } @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - if (state.get(BasinBlock.FACING).getAxis().isVertical()) + if (state.getValue(BasinBlock.FACING).getAxis().isVertical()) return AssetLookup.partialBaseModel(ctx, prov); return AssetLookup.partialBaseModel(ctx, prov, "directional"); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java index 8c51a8fa8..1bf64f5ae 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java @@ -31,9 +31,9 @@ public class BasinMovementBehaviour extends MovementBehaviour { public void tick(MovementContext context) { super.tick(context); if (context.temporaryData == null || (boolean) context.temporaryData) { - Vector3d facingVec = context.rotation.apply(Vector3d.of(Direction.UP.getDirectionVec())); + Vector3d facingVec = context.rotation.apply(Vector3d.atLowerCornerOf(Direction.UP.getNormal())); facingVec.normalize(); - if (Direction.getFacingFromVector(facingVec.x, facingVec.y, facingVec.z) == Direction.DOWN) + if (Direction.getNearest(facingVec.x, facingVec.y, facingVec.z) == Direction.DOWN) dump(context, facingVec); } } @@ -46,8 +46,8 @@ public class BasinMovementBehaviour extends MovementBehaviour { continue; ItemEntity itemEntity = new ItemEntity(context.world, context.position.x, context.position.y, context.position.z, itemStackHandler.getStackInSlot(i)); - itemEntity.setMotion(facingVec.scale(.05)); - context.world.addEntity(itemEntity); + itemEntity.setDeltaMovement(facingVec.scale(.05)); + context.world.addFreshEntity(itemEntity); itemStackHandler.setStackInSlot(i, ItemStack.EMPTY); } context.tileData.put(key, itemStackHandler.serializeNBT()); 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..9eae5b034 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 @@ -60,8 +60,11 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity { if (getSpeed() == 0) return true; if (isRunning()) - return false; - if (world == null || world.isRemote) + return true; + if (level == null || level.isClientSide) + return true; + if (!getBasin().filter(BasinTileEntity::canContinueProcessing) + .isPresent()) return true; List> recipes = getMatchingRecipes(); @@ -89,24 +92,25 @@ 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; BasinTileEntity basin = optionalBasin.get(); + boolean wasEmpty = basin.canContinueProcessing(); if (!BasinRecipe.apply(basin, currentRecipe)) return; Optional processedRecipeTrigger = getProcessedRecipeTrigger(); - if (world != null && !world.isRemote && processedRecipeTrigger.isPresent()) - AllTriggers.triggerForNearbyPlayers(processedRecipeTrigger.get(), world, pos, 4); + if (level != null && !level.isClientSide && processedRecipeTrigger.isPresent()) + AllTriggers.triggerForNearbyPlayers(processedRecipeTrigger.get(), level, worldPosition, 4); basin.inputTank.sendDataImmediately(); - + // Continue mixing - if (matchBasinRecipe(currentRecipe)) { + if (wasEmpty && matchBasinRecipe(currentRecipe)) { continueWithPreviousRecipe(); sendData(); } @@ -115,7 +119,7 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity { } protected List> getMatchingRecipes() { - List> list = RecipeFinder.get(getRecipeCacheKey(), world, this::matchStaticFilters); + List> list = RecipeFinder.get(getRecipeCacheKey(), level, this::matchStaticFilters); return list.stream() .filter(this::matchBasinRecipe) .sorted((r1, r2) -> r2.getIngredients() @@ -128,14 +132,14 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity { protected abstract void onBasinRemoved(); protected Optional getBasin() { - if (world == null) + if (level == null) return Optional.empty(); - TileEntity basinTE = world.getTileEntity(pos.down(2)); + TileEntity basinTE = level.getBlockEntity(worldPosition.below(2)); if (!(basinTE instanceof BasinTileEntity)) return Optional.empty(); return Optional.of((BasinTileEntity) basinTE); } - + protected Optional getProcessedRecipeTrigger() { return Optional.empty(); } @@ -145,7 +149,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/BasinRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRecipe.java index 80e7a6349..b7e57b5bd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRecipe.java @@ -35,7 +35,7 @@ public class BasinRecipe extends ProcessingRecipe { if (filter == null) return false; - boolean filterTest = filter.test(recipe.getRecipeOutput()); + boolean filterTest = filter.test(recipe.getResultItem()); if (recipe instanceof BasinRecipe) { BasinRecipe basinRecipe = (BasinRecipe) recipe; if (basinRecipe.getRollableResults() @@ -66,9 +66,9 @@ public class BasinRecipe extends ProcessingRecipe { if (availableItems == null || availableFluids == null) return false; - HeatLevel heat = BasinTileEntity.getHeatLevelOf(basin.getWorld() - .getBlockState(basin.getPos() - .down(1))); + HeatLevel heat = BasinTileEntity.getHeatLevelOf(basin.getLevel() + .getBlockState(basin.getBlockPos() + .below(1))); if (isBasinRecipe && !((BasinRecipe) recipe).getRequiredHeat() .testBlazeBurner(heat)) return false; @@ -77,7 +77,7 @@ public class BasinRecipe extends ProcessingRecipe { List recipeOutputFluids = new ArrayList<>(); List ingredients = new LinkedList<>(recipe.getIngredients()); - ingredients.sort(Comparator.comparingInt(i -> i.getMatchingStacks().length)); + ingredients.sort(Comparator.comparingInt(i -> i.getItems().length)); List fluidIngredients = isBasinRecipe ? ((BasinRecipe) recipe).getFluidIngredients() : Collections.emptyList(); @@ -101,7 +101,7 @@ public class BasinRecipe extends ProcessingRecipe { continue; // Catalyst items are never consumed if (extracted.hasContainerItem() && extracted.getContainerItem() - .isItemEqual(extracted)) + .sameItem(extracted)) continue Ingredients; if (!simulate) availableItems.extractItem(slot, 1, false); @@ -145,9 +145,9 @@ public class BasinRecipe extends ProcessingRecipe { if (fluidsAffected) { basin.getBehaviour(SmartFluidTankBehaviour.INPUT) - .foreach(TankSegment::onFluidStackChanged); + .forEach(TankSegment::onFluidStackChanged); basin.getBehaviour(SmartFluidTankBehaviour.OUTPUT) - .foreach(TankSegment::onFluidStackChanged); + .forEach(TankSegment::onFluidStackChanged); } if (simulate) { @@ -155,7 +155,7 @@ public class BasinRecipe extends ProcessingRecipe { recipeOutputItems.addAll(((BasinRecipe) recipe).rollResults()); recipeOutputFluids.addAll(((BasinRecipe) recipe).getFluidResults()); } else - recipeOutputItems.add(recipe.getRecipeOutput()); + recipeOutputItems.add(recipe.getResultItem()); } if (!basin.acceptOutputs(recipeOutputItems, recipeOutputFluids, simulate)) @@ -168,7 +168,7 @@ public class BasinRecipe extends ProcessingRecipe { public static BasinRecipe convertShapeless(IRecipe recipe) { BasinRecipe basinRecipe = new ProcessingRecipeBuilder<>(BasinRecipe::new, recipe.getId()).withItemIngredients(recipe.getIngredients()) - .withSingleItemOutput(recipe.getRecipeOutput()) + .withSingleItemOutput(recipe.getResultItem()) .build(); return basinRecipe; } 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..d8249efa3 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 @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.processing; import java.util.Random; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.fluid.FluidRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; @@ -10,7 +11,6 @@ import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRendere import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -42,11 +42,11 @@ public class BasinRenderer extends SmartTileEntityRenderer { float fluidLevel = renderFluids(basin, partialTicks, ms, buffer, light, overlay); float level = MathHelper.clamp(fluidLevel - .3f, .125f, .6f); - ms.push(); + ms.pushPose(); - BlockPos pos = basin.getPos(); + BlockPos pos = basin.getBlockPos(); ms.translate(.5, .2f, .5); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .rotateY(basin.ingredientRotation.getValue(partialTicks)); Random r = new Random(pos.hashCode()); @@ -68,75 +68,75 @@ public class BasinRenderer extends SmartTileEntityRenderer { if (stack.isEmpty()) continue; - ms.push(); + ms.pushPose(); if (fluidLevel > 0) { ms.translate(0, (MathHelper.sin( - AnimationTickHolder.getRenderTime(basin.getWorld()) / 12f + anglePartition * itemCount) + 1.5f) + AnimationTickHolder.getRenderTime(basin.getLevel()) / 12f + anglePartition * itemCount) + 1.5f) * 1 / 32f, 0); } Vector3d itemPosition = VecHelper.rotate(baseVector, anglePartition * itemCount, Axis.Y); ms.translate(itemPosition.x, itemPosition.y, itemPosition.z); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .rotateY(anglePartition * itemCount + 35) .rotateX(65); for (int i = 0; i <= stack.getCount() / 8; i++) { - ms.push(); - + ms.pushPose(); + 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(); + ms.popPose(); } - ms.pop(); + ms.popPose(); itemCount--; } - ms.pop(); + ms.popPose(); BlockState blockState = basin.getBlockState(); if (!(blockState.getBlock() instanceof BasinBlock)) return; - Direction direction = blockState.get(BasinBlock.FACING); + Direction direction = blockState.getValue(BasinBlock.FACING); if (direction == Direction.DOWN) return; - Vector3d directionVec = Vector3d.of(direction.getDirectionVec()); + Vector3d directionVec = Vector3d.atLowerCornerOf(direction.getNormal()); Vector3d outVec = VecHelper.getCenterOf(BlockPos.ZERO) .add(directionVec.scale(.55) .subtract(0, 1 / 2f, 0)); - boolean outToBasin = basin.getWorld() - .getBlockState(basin.getPos() - .offset(direction)) + boolean outToBasin = basin.getLevel() + .getBlockState(basin.getBlockPos() + .relative(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) + + ms.pushPose(); + MatrixTransformStack.of(ms) .translate(outVec) .translate(new Vector3d(0, Math.max(-.55f, -(progress * progress * 2)), 0)) .translate(directionVec.scale(progress * .5f)) .rotateY(AngleHelper.horizontalAngle(direction)) .rotateX(progress * 180); renderItem(ms, buffer, light, overlay, intAttached.getValue()); - ms.pop(); + ms.popPose(); } } protected void renderItem(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, ItemStack stack) { Minecraft.getInstance() .getItemRenderer() - .renderItem(stack, TransformType.GROUND, light, overlay, ms, buffer); + .renderStatic(stack, TransformType.GROUND, light, overlay, ms, buffer); } protected float renderFluids(BasinTileEntity basin, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, 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..e71fa7d2b 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 @@ -26,6 +26,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; @@ -87,6 +88,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor List disabledSpoutputs; Direction preferredSpoutput; protected List spoutputBuffer; + protected List spoutputFluidBuffer; public static final int OUTPUT_ANIMATION_TIME = 10; List> visualizedOutputItems; @@ -113,6 +115,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor disabledSpoutputs = new ArrayList<>(); preferredSpoutput = null; spoutputBuffer = new ArrayList<>(); + spoutputFluidBuffer = new ArrayList<>(); } @Override @@ -149,14 +152,16 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor preferredSpoutput = NBTHelper.readEnum(compound, "PreferredSpoutput", Direction.class); disabledSpoutputs.clear(); ListNBT disabledList = compound.getList("DisabledSpoutput", NBT.TAG_STRING); - disabledList.forEach(d -> disabledSpoutputs.add(Direction.valueOf(((StringNBT) d).getString()))); + disabledList.forEach(d -> disabledSpoutputs.add(Direction.valueOf(((StringNBT) d).getAsString()))); spoutputBuffer = NBTHelper.readItemList(compound.getList("Overflow", NBT.TAG_COMPOUND)); + spoutputFluidBuffer = NBTHelper.readCompoundList(compound.getList("FluidOverflow", NBT.TAG_COMPOUND), + FluidStack::loadFluidStackFromNBT); if (!clientPacket) return; NBTHelper.iterateCompoundList(compound.getList("VisualizedItems", NBT.TAG_COMPOUND), - c -> visualizedOutputItems.add(IntAttached.with(OUTPUT_ANIMATION_TIME, ItemStack.read(c)))); + c -> visualizedOutputItems.add(IntAttached.with(OUTPUT_ANIMATION_TIME, ItemStack.of(c)))); NBTHelper.iterateCompoundList(compound.getList("VisualizedFluids", NBT.TAG_COMPOUND), c -> visualizedOutputFluids .add(IntAttached.with(OUTPUT_ANIMATION_TIME, FluidStack.loadFluidStackFromNBT(c)))); @@ -171,9 +176,11 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor if (preferredSpoutput != null) NBTHelper.writeEnum(compound, "PreferredSpoutput", preferredSpoutput); ListNBT disabledList = new ListNBT(); - disabledSpoutputs.forEach(d -> disabledList.add(StringNBT.of(d.name()))); + disabledSpoutputs.forEach(d -> disabledList.add(StringNBT.valueOf(d.name()))); compound.put("DisabledSpoutput", disabledList); compound.put("Overflow", NBTHelper.writeItemList(spoutputBuffer)); + compound.put("FluidOverflow", + NBTHelper.writeCompoundList(spoutputFluidBuffer, fs -> fs.writeToNBT(new CompoundNBT()))); if (!clientPacket) return; @@ -191,11 +198,11 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor } @Override - public void remove() { + public void setRemoved() { onEmptied(); itemCapability.invalidate(); fluidCapability.invalidate(); - super.remove(); + super.setRemoved(); } @Nonnull @@ -217,10 +224,10 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor public void lazyTick() { super.lazyTick(); updateSpoutput(); - if (!world.isRemote) + if (!level.isClientSide) return; - TileEntity tileEntity = world.getTileEntity(pos.up(2)); + TileEntity tileEntity = level.getBlockEntity(worldPosition.above(2)); if (!(tileEntity instanceof MechanicalMixerTileEntity)) { setAreFluidsMoving(false); return; @@ -231,7 +238,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor public void onWrenched(Direction face) { BlockState blockState = getBlockState(); - Direction currentFacing = blockState.get(BasinBlock.FACING); + Direction currentFacing = blockState.getValue(BasinBlock.FACING); disabledSpoutputs.remove(face); if (currentFacing == face) { @@ -245,55 +252,55 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor } private void updateSpoutput() { - if (world.isRemote) + if (level.isClientSide) return; BlockState blockState = getBlockState(); - Direction currentFacing = blockState.get(BasinBlock.FACING); + Direction currentFacing = blockState.getValue(BasinBlock.FACING); if (currentFacing != Direction.DOWN) notifyChangeOfContents(); Direction newFacing = Direction.DOWN; for (Direction test : Iterate.horizontalDirections) { - boolean canOutputTo = BasinBlock.canOutputTo(world, pos, test); + boolean canOutputTo = BasinBlock.canOutputTo(level, worldPosition, test); if (canOutputTo && !disabledSpoutputs.contains(test)) newFacing = test; } - if (preferredSpoutput != null && BasinBlock.canOutputTo(world, pos, preferredSpoutput) + if (preferredSpoutput != null && BasinBlock.canOutputTo(level, worldPosition, preferredSpoutput) && preferredSpoutput != Direction.UP) newFacing = preferredSpoutput; if (newFacing != currentFacing) - world.setBlockState(pos, blockState.with(BasinBlock.FACING, newFacing)); + level.setBlockAndUpdate(worldPosition, blockState.setValue(BasinBlock.FACING, newFacing)); } @Override public void tick() { super.tick(); - if (world.isRemote) { + if (level.isClientSide) { createFluidParticles(); tickVisualizedOutputs(); ingredientRotationSpeed.tickChaser(); ingredientRotation.setValue(ingredientRotation.getValue() + ingredientRotationSpeed.getValue()); } - if (!spoutputBuffer.isEmpty() && !world.isRemote) + if ((!spoutputBuffer.isEmpty() || !spoutputFluidBuffer.isEmpty()) && !level.isClientSide) tryClearingSpoutputOverflow(); - if (!contentsChanged) return; + contentsChanged = false; getOperator().ifPresent(te -> te.basinChecker.scheduleUpdate()); for (Direction offset : Iterate.horizontalDirections) { - BlockPos toUpdate = pos.up() - .offset(offset); - BlockState stateToUpdate = world.getBlockState(toUpdate); + BlockPos toUpdate = worldPosition.above() + .relative(offset); + BlockState stateToUpdate = level.getBlockState(toUpdate); if (stateToUpdate.getBlock() instanceof BasinBlock - && stateToUpdate.get(BasinBlock.FACING) == offset.getOpposite()) { - TileEntity te = world.getTileEntity(toUpdate); + && stateToUpdate.getValue(BasinBlock.FACING) == offset.getOpposite()) { + TileEntity te = level.getBlockEntity(toUpdate); if (te instanceof BasinTileEntity) ((BasinTileEntity) te).contentsChanged = true; } @@ -304,29 +311,44 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor BlockState blockState = getBlockState(); if (!(blockState.getBlock() instanceof BasinBlock)) return; - Direction direction = blockState.get(BasinBlock.FACING); - TileEntity te = world.getTileEntity(pos.down() - .offset(direction)); + Direction direction = blockState.getValue(BasinBlock.FACING); + TileEntity te = level.getBlockEntity(worldPosition.below() + .relative(direction)); + + FilteringBehaviour filter = null; + InvManipulationBehaviour inserter = null; + if (te != null) { + filter = TileEntityBehaviour.get(level, te.getBlockPos(), FilteringBehaviour.TYPE); + inserter = TileEntityBehaviour.get(level, te.getBlockPos(), InvManipulationBehaviour.TYPE); + } + IItemHandler targetInv = te == null ? null : te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) + .orElse(inserter == null ? null : inserter.getInventory()); + + IFluidHandler targetTank = te == null ? null + : te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()) .orElse(null); + boolean update = false; for (Iterator iterator = spoutputBuffer.iterator(); iterator.hasNext();) { ItemStack itemStack = iterator.next(); if (direction == Direction.DOWN) { - Block.spawnAsEntity(world, pos, itemStack); + Block.popResource(level, worldPosition, itemStack); iterator.remove(); update = true; continue; } if (targetInv == null) - return; + break; if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack, true) .isEmpty()) continue; + if (filter != null && !filter.test(itemStack)) + continue; update = true; ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), false); @@ -334,6 +356,34 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor visualizedOutputItems.add(IntAttached.withZero(itemStack)); } + for (Iterator iterator = spoutputFluidBuffer.iterator(); iterator.hasNext();) { + FluidStack fluidStack = iterator.next(); + + if (direction == Direction.DOWN) { + iterator.remove(); + update = true; + continue; + } + + if (targetTank == null) + break; + + for (boolean simulate : Iterate.trueAndFalse) { + FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE; + int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler + ? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action) + : targetTank.fill(fluidStack.copy(), action); + if (fill != fluidStack.getAmount()) + break; + if (simulate) + continue; + + update = true; + iterator.remove(); + visualizedOutputFluids.add(IntAttached.withZero(fluidStack)); + } + } + if (update) { notifyChangeOfContents(); sendData(); @@ -367,9 +417,9 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor } private Optional getOperator() { - if (world == null) + if (level == null) return Optional.empty(); - TileEntity te = world.getTileEntity(pos.up(2)); + TileEntity te = level.getBlockEntity(worldPosition.above(2)); if (te instanceof BasinOperatingTileEntity) return Optional.of((BasinOperatingTileEntity) te); return Optional.empty(); @@ -393,10 +443,14 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor @Override @OnlyIn(Dist.CLIENT) - public double getMaxRenderDistanceSquared() { + public double getViewDistance() { return 256; } + public boolean canContinueProcessing() { + return spoutputBuffer.isEmpty() && spoutputFluidBuffer.isEmpty(); + } + public boolean acceptOutputs(List outputItems, List outputFluids, boolean simulate) { outputInventory.allowInsertion(); outputTank.allowInsertion(); @@ -410,45 +464,54 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor BlockState blockState = getBlockState(); if (!(blockState.getBlock() instanceof BasinBlock)) return false; - Direction direction = blockState.get(BasinBlock.FACING); - IItemHandler targetInv = null; - IFluidHandler targetTank = null; + Direction direction = blockState.getValue(BasinBlock.FACING); + if (direction != Direction.DOWN) { + + TileEntity te = level.getBlockEntity(worldPosition.below() + .relative(direction)); - if (direction == Direction.DOWN) { - // No output basin, gather locally - targetInv = outputInventory; - targetTank = outputTank.getCapability() - .orElse(null); - - } else { - // Output basin, try moving items to it - if (!spoutputBuffer.isEmpty()) + InvManipulationBehaviour inserter = + te == null ? null : TileEntityBehaviour.get(level, te.getBlockPos(), InvManipulationBehaviour.TYPE); + IItemHandler targetInv = te == null ? null + : te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) + .orElse(inserter == null ? null : inserter.getInventory()); + IFluidHandler targetTank = te == null ? null + : te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()) + .orElse(null); + if (!outputItems.isEmpty() && targetInv == null) return false; - TileEntity te = world.getTileEntity(pos.down() - .offset(direction)); - if (te == null) + if (!outputFluids.isEmpty() && targetTank == null) return false; - targetInv = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(null); - targetTank = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(null); + + if (simulate) + return true; + for (ItemStack itemStack : outputItems) { + if (itemStack.hasContainerItem() && itemStack.getContainerItem() + .sameItem(itemStack)) + continue; + spoutputBuffer.add(itemStack.copy()); + } + for (FluidStack fluidStack : outputFluids) + spoutputFluidBuffer.add(fluidStack.copy()); + return true; } + IItemHandler targetInv = outputInventory; + IFluidHandler targetTank = outputTank.getCapability() + .orElse(null); + if (targetInv == null && !outputItems.isEmpty()) return false; + for (ItemStack itemStack : outputItems) { // Catalyst items are never consumed if (itemStack.hasContainerItem() && itemStack.getContainerItem() - .isItemEqual(itemStack)) + .sameItem(itemStack)) continue; - - if (simulate || direction == Direction.DOWN) { - if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate) - .isEmpty()) - return false; - } else - spoutputBuffer.add(itemStack.copy()); + if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate) + .isEmpty()) + return false; } if (outputFluids.isEmpty()) @@ -463,8 +526,6 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor : targetTank.fill(fluidStack.copy(), action); if (fill != fluidStack.getAmount()) return false; - else if (!simulate) - visualizedOutputFluids.add(IntAttached.withZero(fluidStack)); } return true; @@ -476,8 +537,8 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor } public static HeatLevel getHeatLevelOf(BlockState state) { - if (state.contains(BlazeBurnerBlock.HEAT_LEVEL)) - return state.get(BlazeBurnerBlock.HEAT_LEVEL); + if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL)) + return state.getValue(BlazeBurnerBlock.HEAT_LEVEL); return AllTags.AllBlockTags.FAN_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE; } @@ -499,7 +560,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor } private void createFluidParticles() { - Random r = world.rand; + Random r = level.random; if (!visualizedOutputFluids.isEmpty()) createOutputFluidParticles(r); @@ -524,7 +585,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor float fluidLevel = MathHelper.clamp(totalUnits / 2000, 0, 1); float rim = 2 / 16f; float space = 12 / 16f; - float surface = pos.getY() + rim + space * fluidLevel + 1 / 32f; + float surface = worldPosition.getY() + rim + space * fluidLevel + 1 / 32f; if (areFluidsMoving) { createMovingFluidParticles(surface, segments); @@ -537,9 +598,9 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor for (TankSegment tankSegment : behaviour.getTanks()) { if (tankSegment.isEmpty(0)) continue; - float x = pos.getX() + rim + space * r.nextFloat(); - float z = pos.getZ() + rim + space * r.nextFloat(); - world.addOptionalParticle( + float x = worldPosition.getX() + rim + space * r.nextFloat(); + float z = worldPosition.getZ() + rim + space * r.nextFloat(); + level.addAlwaysVisibleParticle( new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()), x, surface, z, 0, 0, 0); } @@ -550,11 +611,11 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor BlockState blockState = getBlockState(); if (!(blockState.getBlock() instanceof BasinBlock)) return; - Direction direction = blockState.get(BasinBlock.FACING); + Direction direction = blockState.getValue(BasinBlock.FACING); if (direction == Direction.DOWN) return; - Vector3d directionVec = Vector3d.of(direction.getDirectionVec()); - Vector3d outVec = VecHelper.getCenterOf(pos) + Vector3d directionVec = Vector3d.atLowerCornerOf(direction.getNormal()); + Vector3d outVec = VecHelper.getCenterOf(worldPosition) .add(directionVec.scale(.65) .subtract(0, 1 / 4f, 0)); Vector3d outMotion = directionVec.scale(1 / 16f) @@ -565,7 +626,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor FluidStack fluidStack = ia.getValue(); IParticleData fluidParticle = FluidFX.getFluidParticle(fluidStack); Vector3d m = VecHelper.offsetRandomly(outMotion, r, 1 / 16f); - world.addOptionalParticle(fluidParticle, outVec.x, outVec.y, outVec.z, m.x, m.y, m.z); + level.addAlwaysVisibleParticle(fluidParticle, outVec.x, outVec.y, outVec.z, m.x, m.y, m.z); }); } } @@ -573,7 +634,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor private void createMovingFluidParticles(float surface, int segments) { Vector3d pointer = new Vector3d(1, 0, 0).scale(1 / 16f); float interval = 360f / segments; - Vector3d centerOf = VecHelper.getCenterOf(pos); + Vector3d centerOf = VecHelper.getCenterOf(worldPosition); float intervalOffset = (AnimationTickHolder.getTicks() * 18) % 360; int currentSegment = 0; @@ -585,9 +646,9 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor continue; float angle = interval * (1 + currentSegment) + intervalOffset; Vector3d vec = centerOf.add(VecHelper.rotate(pointer, angle, Axis.Y)); - world.addOptionalParticle( + level.addAlwaysVisibleParticle( new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()), - vec.getX(), surface, vec.getZ(), 1, 0, 0); + vec.x(), surface, vec.z(), 1, 0, 0); currentSegment++; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingByBasin.java b/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingByBasin.java index 8545a81d1..cddadc1cf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingByBasin.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingByBasin.java @@ -27,7 +27,7 @@ public class EmptyingByBasin { if (stack.getItem() instanceof PotionItem) return true; - wrapper.setInventorySlotContents(0, stack); + wrapper.setItem(0, stack); if (AllRecipeTypes.EMPTYING.find(wrapper, world) .isPresent()) return true; @@ -52,7 +52,7 @@ public class EmptyingByBasin { if (stack.getItem() instanceof PotionItem) return PotionFluidHandler.emptyPotion(stack, simulate); - wrapper.setInventorySlotContents(0, stack); + wrapper.setItem(0, stack); Optional> recipe = AllRecipeTypes.EMPTYING.find(wrapper, world); if (recipe.isPresent()) { EmptyingRecipe emptyingRecipe = (EmptyingRecipe) recipe.get(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingRecipe.java index fbed9d886..8c7cebfab 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingRecipe.java @@ -15,7 +15,7 @@ public class EmptyingRecipe extends ProcessingRecipe { @Override public boolean matches(RecipeWrapper inv, World p_77569_2_) { - return ingredients.get(0).test(inv.getStackInSlot(0)); + return ingredients.get(0).test(inv.getItem(0)); } @Override 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 77% 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..1269ff7fc 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,13 +12,12 @@ 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; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -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 @@ -66,11 +57,11 @@ public class InWorldProcessing { public static Type byBlock(IBlockReader reader, BlockPos pos) { BlockState blockState = reader.getBlockState(pos); FluidState fluidState = reader.getFluidState(pos); - if (fluidState.getFluid() == Fluids.WATER || fluidState.getFluid() == Fluids.FLOWING_WATER) + if (fluidState.getType() == Fluids.WATER || fluidState.getType() == Fluids.FLOWING_WATER) return Type.SPLASHING; Block block = blockState.getBlock(); if (block == Blocks.FIRE || AllBlocks.LIT_BLAZE_BURNER.has(blockState) - || (BlockTags.CAMPFIRES.contains(block) && blockState.method_28500(CampfireBlock.LIT).orElse(false)) + || (BlockTags.CAMPFIRES.contains(block) && blockState.getOptionalValue(CampfireBlock.LIT).orElse(false)) || getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING) return Type.SMOKING; if (block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) @@ -88,7 +79,7 @@ public class InWorldProcessing { CompoundNBT processing = compound.getCompound("Processing"); if (Type.valueOf(processing.getString("Type")) != type) { - boolean canProcess = canProcess(entity.getItem(), type, entity.world); + boolean canProcess = canProcess(entity.getItem(), type, entity.level); processing.putString("Type", type.name()); if (!canProcess) processing.putInt("Time", -1); @@ -99,21 +90,32 @@ public class InWorldProcessing { return false; } } - return canProcess(entity.getItem(), type, entity.world); + return canProcess(entity.getItem(), type, entity.level); } private static boolean canProcess(ItemStack stack, Type type, World world) { if (type == Type.BLASTING) { - return true; + WRAPPER.setItem(0, stack); + Optional smeltingRecipe = world.getRecipeManager() + .getRecipeFor(IRecipeType.SMELTING, WRAPPER, world); + + if (smeltingRecipe.isPresent()) + return true; + + WRAPPER.setItem(0, stack); + Optional blastingRecipe = world.getRecipeManager() + .getRecipeFor(IRecipeType.BLASTING, WRAPPER, world); + + if (blastingRecipe.isPresent()) + return true; + + return !stack.getItem().isFireResistant(); } 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.setItem(0, stack); Optional recipe = world.getRecipeManager() - .getRecipe(IRecipeType.SMOKING, smoker, world); + .getRecipeFor(IRecipeType.SMOKING, WRAPPER, world); return recipe.isPresent(); } @@ -124,15 +126,15 @@ public class InWorldProcessing { } public static boolean isWashable(ItemStack stack, World world) { - splashingInv.setInventorySlotContents(0, stack); - Optional recipe = AllRecipeTypes.SPLASHING.find(splashingInv, world); + SPLASHING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world); return recipe.isPresent(); } public static void applyProcessing(ItemEntity entity, Type type) { if (decrementProcessingTime(entity, type) != 0) return; - List stacks = process(entity.getItem(), type, entity.world); + List stacks = process(entity.getItem(), type, entity.level); if (stacks == null) return; if (stacks.isEmpty()) { @@ -141,9 +143,9 @@ public class InWorldProcessing { } entity.setItem(stacks.remove(0)); for (ItemStack additional : stacks) { - ItemEntity entityIn = new ItemEntity(entity.world, entity.getX(), entity.getY(), entity.getZ(), additional); - entityIn.setMotion(entity.getMotion()); - entity.world.addEntity(entityIn); + ItemEntity entityIn = new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), additional); + entityIn.setDeltaMovement(entity.getDeltaMovement()); + entity.level.addFreshEntity(entityIn); } } @@ -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.setItem(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.setItem(0, stack); Optional smokingRecipe = world.getRecipeManager() - .getRecipe(IRecipeType.SMOKING, smoker, world); + .getRecipeFor(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.setItem(0, stack); + Optional smeltingRecipe = world.getRecipeManager() + .getRecipeFor(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.setItem(0, stack); Optional blastingRecipe = world.getRecipeManager() - .getRecipe(IRecipeType.BLASTING, blastFurnace, world); + .getRecipeFor(IRecipeType.BLASTING, WRAPPER, world); if (blastingRecipe.isPresent()) return applyRecipeOn(stack, blastingRecipe.get()); @@ -260,9 +253,9 @@ public class InWorldProcessing { } entity.setItem(stacks.remove(0)); for (ItemStack additional : stacks) { - ItemEntity entityIn = new ItemEntity(entity.world, entity.getX(), entity.getY(), entity.getZ(), additional); - entityIn.setMotion(entity.getMotion()); - entity.world.addEntity(entityIn); + ItemEntity entityIn = new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), additional); + entityIn.setDeltaMovement(entity.getDeltaMovement()); + entity.level.addFreshEntity(entityIn); } } @@ -292,17 +285,18 @@ public class InWorldProcessing { } } } else { - ItemStack out = recipe.getRecipeOutput() + ItemStack out = recipe.getResultItem() .copy(); stacks = ItemHelper.multipliedOutput(stackIn, out); } return stacks; } + public static void spawnParticlesForProcessing(@Nullable World world, Vector3d vec, Type type) { - if (world == null || !world.isRemote) + if (world == null || !world.isClientSide) return; - if (world.rand.nextInt(8) != 0) + if (world.random.nextInt(8) != 0) return; switch (type) { @@ -313,16 +307,22 @@ public class InWorldProcessing { world.addParticle(ParticleTypes.POOF, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0); break; case SPLASHING: - Vector3d color = ColorHelper.getRGB(0x0055FF); + Vector3d color = Color.vectorFromRGB(0x0055FF); world.addParticle(new RedstoneParticleData((float) color.x, (float) color.y, (float) color.z, 1), - vec.x + (world.rand.nextFloat() - .5f) * .5f, vec.y + .5f, vec.z + (world.rand.nextFloat() - .5f) * .5f, + vec.x + (world.random.nextFloat() - .5f) * .5f, vec.y + .5f, vec.z + (world.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); - world.addParticle(ParticleTypes.SPIT, vec.x + (world.rand.nextFloat() - .5f) * .5f, vec.y + .5f, - vec.z + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); + world.addParticle(ParticleTypes.SPIT, vec.x + (world.random.nextFloat() - .5f) * .5f, vec.y + .5f, + vec.z + (world.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); break; default: break; } } + public static class SplashingWrapper extends RecipeWrapper { + public SplashingWrapper() { + super(new ItemStackHandler(1)); + } + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingInventory.java b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingInventory.java index 45cb0927b..21fb2f34c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingInventory.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingInventory.java @@ -11,11 +11,22 @@ public class ProcessingInventory extends ItemStackHandler { public float recipeDuration; public boolean appliedRecipe; public Consumer callback; + private boolean limit; public ProcessingInventory(Consumer callback) { - super(10); + super(16); this.callback = callback; } + + public ProcessingInventory withSlotLimit(boolean limit) { + this.limit = limit; + return this; + } + + @Override + public int getSlotLimit(int slot) { + return !limit ? super.getSlotLimit(slot) : 1; + } public void clear() { for (int i = 0; i < getSlots(); i++) @@ -36,7 +47,7 @@ public class ProcessingInventory extends ItemStackHandler { public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { ItemStack insertItem = super.insertItem(slot, stack, simulate); if (slot == 0 && !insertItem.equals(stack, true)) - callback.accept(insertItem.copy()); + callback.accept(getStackInSlot(slot)); return insertItem; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingOutput.java b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingOutput.java index 8303e0686..c83f362e8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingOutput.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingOutput.java @@ -79,16 +79,16 @@ public class ProcessingOutput { throw new JsonSyntaxException("ProcessingOutput must be a json object"); JsonObject json = je.getAsJsonObject(); - String itemId = JSONUtils.getString(json, "item"); - int count = JSONUtils.getInt(json, "count", 1); - float chance = JSONUtils.hasField(json, "chance") ? JSONUtils.getFloat(json, "chance") : 1; + String itemId = JSONUtils.getAsString(json, "item"); + int count = JSONUtils.getAsInt(json, "count", 1); + float chance = JSONUtils.isValidNode(json, "chance") ? JSONUtils.getAsFloat(json, "chance") : 1; ItemStack itemstack = new ItemStack(ForgeRegistries.ITEMS.getValue(new ResourceLocation(itemId)), count); - if (JSONUtils.hasField(json, "nbt")) { + if (JSONUtils.isValidNode(json, "nbt")) { try { JsonElement element = json.get("nbt"); - itemstack.setTag(JsonToNBT.getTagFromJson( - element.isJsonObject() ? Create.GSON.toJson(element) : JSONUtils.getString(element, "nbt"))); + itemstack.setTag(JsonToNBT.parseTag( + element.isJsonObject() ? Create.GSON.toJson(element) : JSONUtils.convertToString(element, "nbt"))); } catch (CommandSyntaxException e) { e.printStackTrace(); } @@ -98,12 +98,12 @@ public class ProcessingOutput { } public void write(PacketBuffer buf) { - buf.writeItemStack(getStack()); + buf.writeItem(getStack()); buf.writeFloat(getChance()); } public static ProcessingOutput read(PacketBuffer buf) { - return new ProcessingOutput(buf.readItemStack(), buf.readFloat()); + return new ProcessingOutput(buf.readItem(), buf.readFloat()); } } 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..b5eb01f6f 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 @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.processing; import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; import java.util.stream.Collectors; import javax.annotation.ParametersAreNonnullByDefault; @@ -9,11 +10,10 @@ import javax.annotation.ParametersAreNonnullByDefault; import org.apache.logging.log4j.Logger; import com.google.gson.JsonObject; -import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; import com.simibubi.create.foundation.fluid.FluidIngredient; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import mcp.MethodsReturnNonnullByDefault; import net.minecraft.inventory.IInventory; @@ -41,22 +41,23 @@ public abstract class ProcessingRecipe implements IRecipe< private IRecipeType type; private IRecipeSerializer serializer; - private AllRecipeTypes enumType; + private IRecipeTypeInfo typeInfo; + private Supplier forcedResult; - public ProcessingRecipe(AllRecipeTypes recipeType, ProcessingRecipeParams params) { - - this.enumType = recipeType; + public ProcessingRecipe(IRecipeTypeInfo typeInfo, ProcessingRecipeParams params) { + this.forcedResult = null; + this.typeInfo = typeInfo; this.processingDuration = params.processingDuration; this.fluidIngredients = params.fluidIngredients; this.fluidResults = params.fluidResults; - this.serializer = recipeType.serializer; + this.serializer = typeInfo.getSerializer(); this.requiredHeat = params.requiredHeat; this.ingredients = params.ingredients; - this.type = recipeType.type; + this.type = typeInfo.getType(); this.results = params.results; this.id = params.id; - validate(Lang.asId(recipeType.name())); + validate(typeInfo.getId()); } // Recipe type options: @@ -83,9 +84,9 @@ public abstract class ProcessingRecipe implements IRecipe< // - private void validate(String recipeTypeName) { - String messageHeader = "Your custom " + recipeTypeName + " recipe (" + id.toString() + ")"; - Logger logger = Create.logger; + private void validate(ResourceLocation recipeTypeId) { + String messageHeader = "Your custom " + recipeTypeId + " recipe (" + id.toString() + ")"; + Logger logger = Create.LOGGER; int ingredientCount = ingredients.size(); int outputCount = results.size(); @@ -120,15 +121,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; } @@ -139,10 +140,16 @@ public abstract class ProcessingRecipe implements IRecipe< .collect(Collectors.toList()); } + public void enforceNextResult(Supplier stack) { + forcedResult = stack; + } + public List rollResults() { List results = new ArrayList<>(); - for (ProcessingOutput output : getRollableResults()) { - ItemStack stack = output.rollOutput(); + NonNullList rollableResults = getRollableResults(); + for (int i = 0; i < rollableResults.size(); i++) { + ProcessingOutput output = rollableResults.get(i); + ItemStack stack = i == 0 && forcedResult != null ? forcedResult.get() : output.rollOutput(); if (!stack.isEmpty()) results.add(stack); } @@ -156,52 +163,56 @@ public abstract class ProcessingRecipe implements IRecipe< public HeatCondition getRequiredHeat() { return requiredHeat; } - + // IRecipe<> paperwork - + @Override - public ItemStack getCraftingResult(T inv) { - return getRecipeOutput(); + public ItemStack assemble(T inv) { + return getResultItem(); } @Override - public boolean canFit(int width, int height) { + public boolean canCraftInDimensions(int width, int height) { return true; } @Override - public ItemStack getRecipeOutput() { + public ItemStack getResultItem() { return getRollableResults().isEmpty() ? ItemStack.EMPTY : getRollableResults().get(0) .getStack(); } @Override - public ResourceLocation getId() { - return id; - } - - @Override - public boolean isDynamic() { + public boolean isSpecial() { return true; } - @Override - public IRecipeSerializer getSerializer() { - return serializer; - } - // Processing recipes do not show up in the recipe book @Override public String getGroup() { return "processing"; } + @Override + public ResourceLocation getId() { + return id; + } + + @Override + public IRecipeSerializer getSerializer() { + return serializer; + } + @Override public IRecipeType getType() { return type; } + public IRecipeTypeInfo getTypeInfo() { + return typeInfo; + } + // Additional Data added by subtypes public void readAdditional(JsonObject json) {} @@ -212,8 +223,4 @@ public abstract class ProcessingRecipe implements IRecipe< public void writeAdditional(PacketBuffer buffer) {} - public AllRecipeTypes getEnumType() { - return enumType; - } - } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeBuilder.java b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeBuilder.java index be0045bae..19c839295 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeBuilder.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeBuilder.java @@ -6,12 +6,10 @@ import java.util.function.Consumer; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.Create; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.fluid.FluidIngredient; -import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import net.minecraft.data.IFinishedRecipe; import net.minecraft.fluid.Fluid; @@ -42,7 +40,7 @@ public class ProcessingRecipeBuilder> { } public ProcessingRecipeBuilder withItemIngredients(Ingredient... ingredients) { - return withItemIngredients(NonNullList.from(Ingredient.EMPTY, ingredients)); + return withItemIngredients(NonNullList.of(Ingredient.EMPTY, ingredients)); } public ProcessingRecipeBuilder withItemIngredients(NonNullList ingredients) { @@ -55,7 +53,7 @@ public class ProcessingRecipeBuilder> { } public ProcessingRecipeBuilder withItemOutputs(ProcessingOutput... outputs) { - return withItemOutputs(NonNullList.from(ProcessingOutput.EMPTY, outputs)); + return withItemOutputs(NonNullList.of(ProcessingOutput.EMPTY, outputs)); } public ProcessingRecipeBuilder withItemOutputs(NonNullList outputs) { @@ -64,7 +62,7 @@ public class ProcessingRecipeBuilder> { } public ProcessingRecipeBuilder withFluidIngredients(FluidIngredient... ingredients) { - return withFluidIngredients(NonNullList.from(FluidIngredient.EMPTY, ingredients)); + return withFluidIngredients(NonNullList.of(FluidIngredient.EMPTY, ingredients)); } public ProcessingRecipeBuilder withFluidIngredients(NonNullList ingredients) { @@ -73,7 +71,7 @@ public class ProcessingRecipeBuilder> { } public ProcessingRecipeBuilder withFluidOutputs(FluidStack... outputs) { - return withFluidOutputs(NonNullList.from(FluidStack.EMPTY, outputs)); + return withFluidOutputs(NonNullList.of(FluidStack.EMPTY, outputs)); } public ProcessingRecipeBuilder withFluidOutputs(NonNullList outputs) { @@ -106,11 +104,11 @@ public class ProcessingRecipeBuilder> { // Datagen shortcuts public ProcessingRecipeBuilder require(ITag.INamedTag tag) { - return require(Ingredient.fromTag(tag)); + return require(Ingredient.of(tag)); } public ProcessingRecipeBuilder require(IItemProvider item) { - return require(Ingredient.fromItems(item)); + return require(Ingredient.of(item)); } public ProcessingRecipeBuilder require(Ingredient ingredient) { @@ -193,15 +191,15 @@ public class ProcessingRecipeBuilder> { public static class ProcessingRecipeParams { - ResourceLocation id; - NonNullList ingredients; - NonNullList results; - NonNullList fluidIngredients; - NonNullList fluidResults; - int processingDuration; - HeatCondition requiredHeat; + protected ResourceLocation id; + protected NonNullList ingredients; + protected NonNullList results; + protected NonNullList fluidIngredients; + protected NonNullList fluidResults; + protected int processingDuration; + protected HeatCondition requiredHeat; - ProcessingRecipeParams(ResourceLocation id) { + protected ProcessingRecipeParams(ResourceLocation id) { this.id = id; ingredients = NonNullList.create(); results = NonNullList.create(); @@ -222,21 +220,21 @@ public class ProcessingRecipeBuilder> { @SuppressWarnings("unchecked") public DataGenResult(S recipe, List recipeConditions) { - this.recipeConditions = recipeConditions; - AllRecipeTypes recipeType = recipe.getEnumType(); - String typeName = Lang.asId(recipeType.name()); this.recipe = recipe; + this.recipeConditions = recipeConditions; + IRecipeTypeInfo recipeType = this.recipe.getTypeInfo(); + ResourceLocation typeId = recipeType.getId(); - if (!(recipeType.serializer instanceof ProcessingRecipeSerializer)) - throw new IllegalStateException("Cannot datagen ProcessingRecipe of type: " + typeName); + if (!(recipeType.getSerializer() instanceof ProcessingRecipeSerializer)) + throw new IllegalStateException("Cannot datagen ProcessingRecipe of type: " + typeId); - this.id = Create.asResource(typeName + "/" + recipe.getId() - .getPath()); + this.id = new ResourceLocation(recipe.getId().getNamespace(), + typeId.getPath() + "/" + recipe.getId().getPath()); this.serializer = (ProcessingRecipeSerializer) recipe.getSerializer(); } @Override - public void serialize(JsonObject json) { + public void serializeRecipeData(JsonObject json) { serializer.write(json, recipe); if (recipeConditions.isEmpty()) return; @@ -247,22 +245,22 @@ public class ProcessingRecipeBuilder> { } @Override - public ResourceLocation getID() { + public ResourceLocation getId() { return id; } @Override - public IRecipeSerializer getSerializer() { + public IRecipeSerializer getType() { return serializer; } @Override - public JsonObject getAdvancementJson() { + public JsonObject serializeAdvancement() { return null; } @Override - public ResourceLocation getAdvancementID() { + public ResourceLocation getAdvancementId() { return null; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeSerializer.java b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeSerializer.java index 031a7f973..38404346b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeSerializer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipeSerializer.java @@ -35,7 +35,7 @@ public class ProcessingRecipeSerializer> extends F JsonArray jsonOutputs = new JsonArray(); recipe.getIngredients() - .forEach(i -> jsonIngredients.add(i.serialize())); + .forEach(i -> jsonIngredients.add(i.toJson())); recipe.getFluidIngredients() .forEach(i -> jsonIngredients.add(i.serialize())); @@ -65,16 +65,16 @@ public class ProcessingRecipeSerializer> extends F NonNullList results = NonNullList.create(); NonNullList fluidResults = NonNullList.create(); - for (JsonElement je : JSONUtils.getJsonArray(json, "ingredients")) { + for (JsonElement je : JSONUtils.getAsJsonArray(json, "ingredients")) { if (FluidIngredient.isFluidIngredient(je)) fluidIngredients.add(FluidIngredient.deserialize(je)); else - ingredients.add(Ingredient.deserialize(je)); + ingredients.add(Ingredient.fromJson(je)); } - for (JsonElement je : JSONUtils.getJsonArray(json, "results")) { + for (JsonElement je : JSONUtils.getAsJsonArray(json, "results")) { JsonObject jsonObject = je.getAsJsonObject(); - if (JSONUtils.hasField(jsonObject, "fluid")) + if (JSONUtils.isValidNode(jsonObject, "fluid")) fluidResults.add(FluidHelper.deserializeFluidStack(jsonObject)); else results.add(ProcessingOutput.deserialize(je)); @@ -85,12 +85,14 @@ public class ProcessingRecipeSerializer> extends F .withFluidIngredients(fluidIngredients) .withFluidOutputs(fluidResults); - if (JSONUtils.hasField(json, "processingTime")) - builder.duration(JSONUtils.getInt(json, "processingTime")); - if (JSONUtils.hasField(json, "heatRequirement")) - builder.requiresHeat(HeatCondition.deserialize(JSONUtils.getString(json, "heatRequirement"))); + if (JSONUtils.isValidNode(json, "processingTime")) + builder.duration(JSONUtils.getAsInt(json, "processingTime")); + if (JSONUtils.isValidNode(json, "heatRequirement")) + builder.requiresHeat(HeatCondition.deserialize(JSONUtils.getAsString(json, "heatRequirement"))); - return builder.build(); + T recipe = builder.build(); + recipe.readAdditional(json); + return recipe; } protected void writeToBuffer(PacketBuffer buffer, T recipe) { @@ -100,7 +102,7 @@ public class ProcessingRecipeSerializer> extends F NonNullList fluidOutputs = recipe.getFluidResults(); buffer.writeVarInt(ingredients.size()); - ingredients.forEach(i -> i.write(buffer)); + ingredients.forEach(i -> i.toNetwork(buffer)); buffer.writeVarInt(fluidIngredients.size()); fluidIngredients.forEach(i -> i.write(buffer)); @@ -112,6 +114,8 @@ public class ProcessingRecipeSerializer> extends F buffer.writeVarInt(recipe.getProcessingDuration()); buffer.writeVarInt(recipe.getRequiredHeat() .ordinal()); + + recipe.writeAdditional(buffer); } protected T readFromBuffer(ResourceLocation recipeId, PacketBuffer buffer) { @@ -122,27 +126,29 @@ public class ProcessingRecipeSerializer> extends F int size = buffer.readVarInt(); for (int i = 0; i < size; i++) - ingredients.add(Ingredient.read(buffer)); - + ingredients.add(Ingredient.fromNetwork(buffer)); + size = buffer.readVarInt(); for (int i = 0; i < size; i++) fluidIngredients.add(FluidIngredient.read(buffer)); - + size = buffer.readVarInt(); for (int i = 0; i < size; i++) results.add(ProcessingOutput.read(buffer)); - + size = buffer.readVarInt(); for (int i = 0; i < size; i++) fluidResults.add(FluidStack.readFromPacket(buffer)); - return new ProcessingRecipeBuilder<>(factory, recipeId).withItemIngredients(ingredients) + T recipe = new ProcessingRecipeBuilder<>(factory, recipeId).withItemIngredients(ingredients) .withItemOutputs(results) .withFluidIngredients(fluidIngredients) .withFluidOutputs(fluidResults) .duration(buffer.readVarInt()) .requiresHeat(HeatCondition.values()[buffer.readVarInt()]) .build(); + recipe.readAdditional(buffer); + return recipe; } public final void write(JsonObject json, T recipe) { @@ -150,17 +156,17 @@ public class ProcessingRecipeSerializer> extends F } @Override - public final T read(ResourceLocation id, JsonObject json) { + public final T fromJson(ResourceLocation id, JsonObject json) { return readFromJson(id, json); } @Override - public final void write(PacketBuffer buffer, T recipe) { + public final void toNetwork(PacketBuffer buffer, T recipe) { writeToBuffer(buffer, recipe); } @Override - public final T read(ResourceLocation id, PacketBuffer buffer) { + public final T fromNetwork(ResourceLocation id, PacketBuffer buffer) { return readFromBuffer(id, buffer); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java index ddd630313..077da0232 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java @@ -29,10 +29,9 @@ import net.minecraft.loot.LootPool; import net.minecraft.loot.LootTable; import net.minecraft.loot.conditions.BlockStateProperty; import net.minecraft.loot.conditions.ILootCondition.IBuilder; -import net.minecraft.pathfinding.PathType; import net.minecraft.loot.conditions.SurvivesExplosion; +import net.minecraft.pathfinding.PathType; import net.minecraft.state.EnumProperty; -import net.minecraft.state.Property; import net.minecraft.state.StateContainer.Builder; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResult; @@ -58,24 +57,24 @@ import net.minecraftforge.common.util.FakePlayer; @ParametersAreNonnullByDefault public class BlazeBurnerBlock extends Block implements ITE { - public static final Property HEAT_LEVEL = EnumProperty.create("blaze", HeatLevel.class); + public static final EnumProperty HEAT_LEVEL = EnumProperty.create("blaze", HeatLevel.class); public BlazeBurnerBlock(Properties properties) { super(properties); - setDefaultState(super.getDefaultState().with(HEAT_LEVEL, HeatLevel.NONE)); + registerDefaultState(defaultBlockState().setValue(HEAT_LEVEL, HeatLevel.NONE)); } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder); builder.add(HEAT_LEVEL); } @Override - public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState p_220082_4_, boolean p_220082_5_) { - if (world.isRemote) + public void onPlace(BlockState state, World world, BlockPos pos, BlockState p_220082_4_, boolean p_220082_5_) { + if (world.isClientSide) return; - TileEntity tileEntity = world.getTileEntity(pos.up()); + TileEntity tileEntity = world.getBlockEntity(pos.above()); if (!(tileEntity instanceof BasinTileEntity)) return; BasinTileEntity basin = (BasinTileEntity) tileEntity; @@ -84,14 +83,14 @@ public class BlazeBurnerBlock extends Block implements ITE p_149666_2_) { - p_149666_2_.add(AllItems.EMPTY_BLAZE_BURNER.asStack()); - super.fillItemGroup(p_149666_1_, p_149666_2_); + public void fillItemCategory(ItemGroup group, NonNullList list) { + list.add(AllItems.EMPTY_BLAZE_BURNER.asStack()); + super.fillItemCategory(group, list); } @Nullable @@ -106,73 +105,79 @@ public class BlazeBurnerBlock extends Block implements ITE p.sendBreakAnimation(hand)); - world.setBlockState(pos, AllBlocks.LIT_BLAZE_BURNER.getDefaultState()); + heldItem.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand)); + world.setBlockAndUpdate(pos, AllBlocks.LIT_BLAZE_BURNER.getDefaultState()); return ActionResultType.SUCCESS; } return ActionResultType.PASS; } - ActionResult res = tryInsert(state, world, pos, dontConsume ? heldItem.copy() : heldItem, forceOverflow, false); - ItemStack leftover = res.getResult(); - if (!world.isRemote && !dontConsume && !leftover.isEmpty()) { + boolean doNotConsume = player.isCreative(); + boolean forceOverflow = !(player instanceof FakePlayer); + + ActionResult res = tryInsert(state, world, pos, heldItem, doNotConsume, forceOverflow, false); + ItemStack leftover = res.getObject(); + if (!world.isClientSide && !doNotConsume && !leftover.isEmpty()) { if (heldItem.isEmpty()) { - player.setHeldItem(hand, leftover); - } else if (!player.inventory.addItemStackToInventory(leftover)) { - player.dropItem(leftover, false); + player.setItemInHand(hand, leftover); + } else if (!player.inventory.add(leftover)) { + player.drop(leftover, false); } } - return res.getType() == ActionResultType.SUCCESS ? res.getType() : ActionResultType.PASS; + return res.getResult() == ActionResultType.SUCCESS ? ActionResultType.SUCCESS : ActionResultType.PASS; } - public static ActionResult tryInsert(BlockState state, World world, BlockPos pos, ItemStack stack, boolean forceOverflow, - boolean simulate) { + public static ActionResult tryInsert(BlockState state, World world, BlockPos pos, ItemStack stack, boolean doNotConsume, + boolean forceOverflow, boolean simulate) { if (!state.hasTileEntity()) return ActionResult.fail(ItemStack.EMPTY); - TileEntity te = world.getTileEntity(pos); + TileEntity te = world.getBlockEntity(pos); if (!(te instanceof BlazeBurnerTileEntity)) return ActionResult.fail(ItemStack.EMPTY); BlazeBurnerTileEntity burnerTE = (BlazeBurnerTileEntity) te; + if (burnerTE.isCreativeFuel(stack)) { + if (!simulate) + burnerTE.applyCreativeFuel(); + return ActionResult.success(ItemStack.EMPTY); + } if (!burnerTE.tryUpdateFuel(stack, forceOverflow, simulate)) return ActionResult.fail(ItemStack.EMPTY); - - ItemStack container = stack.getContainerItem(); - if (!simulate && !world.isRemote) { - world.playSound(null, pos, SoundEvents.ENTITY_BLAZE_SHOOT, SoundCategory.BLOCKS, - .125f + world.rand.nextFloat() * .125f, .75f - world.rand.nextFloat() * .25f); - stack.shrink(1); - } - if (!container.isEmpty()) { - return ActionResult.success(container); + + if (!doNotConsume) { + ItemStack container = stack.getContainerItem(); + if (!world.isClientSide && !simulate) { + stack.shrink(1); + } + if (!container.isEmpty()) { + return ActionResult.success(container); + } } return ActionResult.success(ItemStack.EMPTY); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - ItemStack stack = context.getItem(); + ItemStack stack = context.getItemInHand(); Item item = stack.getItem(); - BlockState defaultState = getDefaultState(); + BlockState defaultState = defaultBlockState(); if (!(item instanceof BlazeBurnerBlockItem)) return defaultState; HeatLevel initialHeat = ((BlazeBurnerBlockItem) item).hasCapturedBlaze() ? HeatLevel.SMOULDERING : HeatLevel.NONE; - return defaultState.with(HEAT_LEVEL, initialHeat); + return defaultState.setValue(HEAT_LEVEL, initialHeat); } @Override @@ -183,83 +188,86 @@ public class BlazeBurnerBlock extends Block implements ITE= heatLevel.ordinal(); } + + @Override + public String getSerializedName() { + return Lang.asId(name()); + } } - - @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/processing/burner/BlazeBurnerBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlockItem.java index ee8b13bb2..8e033b5b5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlockItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlockItem.java @@ -49,12 +49,12 @@ public class BlazeBurnerBlockItem extends BlockItem { public static BlazeBurnerBlockItem withBlaze(Block block, Properties properties) { return new BlazeBurnerBlockItem(block, properties, true); } - + @Override - public void addToBlockToItemMap(Map p_195946_1_, Item p_195946_2_) { + public void registerBlocks(Map p_195946_1_, Item p_195946_2_) { if (!hasCapturedBlaze()) return; - super.addToBlockToItemMap(p_195946_1_, p_195946_2_); + super.registerBlocks(p_195946_1_, p_195946_2_); } private BlazeBurnerBlockItem(Block block, Properties properties, boolean capturedBlaze) { @@ -63,31 +63,31 @@ public class BlazeBurnerBlockItem extends BlockItem { } @Override - public void fillItemGroup(ItemGroup p_150895_1_, NonNullList p_150895_2_) { + public void fillItemCategory(ItemGroup p_150895_1_, NonNullList p_150895_2_) { if (!hasCapturedBlaze()) return; - super.fillItemGroup(p_150895_1_, p_150895_2_); + super.fillItemCategory(p_150895_1_, p_150895_2_); } @Override - public String getTranslationKey() { - return hasCapturedBlaze() ? super.getTranslationKey() : "item.create." + getRegistryName().getPath(); + public String getDescriptionId() { + return hasCapturedBlaze() ? super.getDescriptionId() : "item.create." + getRegistryName().getPath(); } @Override - public ActionResultType onItemUse(ItemUseContext context) { + public ActionResultType useOn(ItemUseContext context) { if (hasCapturedBlaze()) - return super.onItemUse(context); + return super.useOn(context); - World world = context.getWorld(); - BlockPos pos = context.getPos(); - TileEntity te = world.getTileEntity(pos); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); + TileEntity te = world.getBlockEntity(pos); PlayerEntity player = context.getPlayer(); if (!(te instanceof MobSpawnerTileEntity)) - return super.onItemUse(context); + return super.useOn(context); - AbstractSpawner spawner = ((MobSpawnerTileEntity) te).getSpawnerBaseLogic(); + AbstractSpawner spawner = ((MobSpawnerTileEntity) te).getSpawner(); List possibleSpawns = ObfuscationReflectionHelper.getPrivateValue(AbstractSpawner.class, spawner, "field_98285_e"); if (possibleSpawns.isEmpty()) { @@ -98,32 +98,32 @@ public class BlazeBurnerBlockItem extends BlockItem { ResourceLocation blazeId = EntityType.BLAZE.getRegistryName(); for (WeightedSpawnerEntity e : possibleSpawns) { - ResourceLocation spawnerEntityId = new ResourceLocation(e.getNbt() + ResourceLocation spawnerEntityId = new ResourceLocation(e.getTag() .getString("id")); if (!spawnerEntityId.equals(blazeId)) continue; spawnCaptureEffects(world, VecHelper.getCenterOf(pos)); - if (world.isRemote || player == null) + if (world.isClientSide || player == null) return ActionResultType.SUCCESS; - giveBurnerItemTo(player, context.getItem(), context.getHand()); + giveBurnerItemTo(player, context.getItemInHand(), context.getHand()); return ActionResultType.SUCCESS; } - return super.onItemUse(context); + return super.useOn(context); } @Override - public ActionResultType itemInteractionForEntity(ItemStack heldItem, PlayerEntity player, LivingEntity entity, Hand hand) { + public ActionResultType interactLivingEntity(ItemStack heldItem, PlayerEntity player, LivingEntity entity, Hand hand) { if (hasCapturedBlaze()) return ActionResultType.PASS; if (!(entity instanceof BlazeEntity)) return ActionResultType.PASS; - World world = player.world; - spawnCaptureEffects(world, entity.getPositionVec()); - if (world.isRemote) + World world = player.level; + spawnCaptureEffects(world, entity.position()); + if (world.isClientSide) return ActionResultType.FAIL; giveBurnerItemTo(player, heldItem, hand); @@ -136,18 +136,18 @@ public class BlazeBurnerBlockItem extends BlockItem { if (!player.isCreative()) heldItem.shrink(1); if (heldItem.isEmpty()) { - player.setHeldItem(hand, filled); + player.setItemInHand(hand, filled); return; } - player.inventory.placeItemBackInInventory(player.world, filled); + player.inventory.placeItemBackInInventory(player.level, filled); } private void spawnCaptureEffects(World world, Vector3d vec) { - if (world.isRemote) { + if (world.isClientSide) { for (int i = 0; i < 40; i++) { - Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, world.rand, .125f); + Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, world.random, .125f); world.addParticle(ParticleTypes.FLAME, vec.x, vec.y, vec.z, motion.x, motion.y, motion.z); - Vector3d circle = motion.mul(1, 0, 1) + Vector3d circle = motion.multiply(1, 0, 1) .normalize() .scale(.5f); world.addParticle(ParticleTypes.SMOKE, circle.x, vec.y, circle.z, 0, -0.125, 0); @@ -156,8 +156,8 @@ public class BlazeBurnerBlockItem extends BlockItem { } BlockPos soundPos = new BlockPos(vec); - world.playSound(null, soundPos, SoundEvents.ENTITY_BLAZE_HURT, SoundCategory.HOSTILE, .25f, .75f); - world.playSound(null, soundPos, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.HOSTILE, .5f, .75f); + world.playSound(null, soundPos, SoundEvents.BLAZE_HURT, SoundCategory.HOSTILE, .25f, .75f); + world.playSound(null, soundPos, SoundEvents.FIRE_EXTINGUISH, SoundCategory.HOSTILE, .5f, .75f); } public boolean hasCapturedBlaze() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerHandler.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerHandler.java index 07582c253..ffd36c804 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerHandler.java @@ -1,11 +1,22 @@ package com.simibubi.create.content.contraptions.processing.burner; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerTileEntity.FuelType; +import net.minecraft.block.BlockState; import net.minecraft.entity.projectile.EggEntity; +import net.minecraft.entity.projectile.PotionEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionUtils; +import net.minecraft.potion.Potions; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +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.RayTraceResult; import net.minecraft.util.math.vector.Vector3d; @@ -18,6 +29,11 @@ import net.minecraftforge.fml.common.Mod; public class BlazeBurnerHandler { @SubscribeEvent + public static void onThrowableImpact(ProjectileImpactEvent.Throwable event) { + thrownEggsGetEatenByBurner(event); + splashExtinguishesBurner(event); + } + public static void thrownEggsGetEatenByBurner(ProjectileImpactEvent.Throwable event) { if (!(event.getThrowable() instanceof EggEntity)) return; @@ -26,32 +42,71 @@ public class BlazeBurnerHandler { .getType() != RayTraceResult.Type.BLOCK) return; - TileEntity tile = event.getThrowable().world.getTileEntity(new BlockPos(event.getRayTraceResult() - .getHitVec())); + TileEntity tile = event.getThrowable().level.getBlockEntity(new BlockPos(event.getRayTraceResult() + .getLocation())); if (!(tile instanceof BlazeBurnerTileEntity)) { return; } event.setCanceled(true); event.getThrowable() - .setMotion(Vector3d.ZERO); + .setDeltaMovement(Vector3d.ZERO); event.getThrowable() .remove(); - World world = event.getThrowable().world; - if (world.isRemote) + World world = event.getThrowable().level; + if (world.isClientSide) return; - + BlazeBurnerTileEntity heater = (BlazeBurnerTileEntity) tile; - if (heater.activeFuel != FuelType.SPECIAL) { - heater.activeFuel = FuelType.NORMAL; - heater.remainingBurnTime = - MathHelper.clamp(heater.remainingBurnTime + 80, 0, BlazeBurnerTileEntity.maxHeatCapacity); - heater.updateBlockState(); - heater.notifyUpdate(); + if (!heater.isCreative()) { + if (heater.activeFuel != FuelType.SPECIAL) { + heater.activeFuel = FuelType.NORMAL; + heater.remainingBurnTime = + MathHelper.clamp(heater.remainingBurnTime + 80, 0, BlazeBurnerTileEntity.MAX_HEAT_CAPACITY); + heater.updateBlockState(); + heater.notifyUpdate(); + } + } + + AllSoundEvents.BLAZE_MUNCH.playOnServer(world, heater.getBlockPos()); + } + + public static void splashExtinguishesBurner(ProjectileImpactEvent.Throwable event) { + if (event.getThrowable().level.isClientSide) + return; + + if (!(event.getThrowable() instanceof PotionEntity)) + return; + PotionEntity entity = (PotionEntity) event.getThrowable(); + + if (event.getRayTraceResult() + .getType() != RayTraceResult.Type.BLOCK) + return; + + ItemStack stack = entity.getItem(); + Potion potion = PotionUtils.getPotion(stack); + if (potion == Potions.WATER && PotionUtils.getMobEffects(stack).isEmpty()) { + BlockRayTraceResult result = (BlockRayTraceResult) event.getRayTraceResult(); + World world = entity.level; + Direction face = result.getDirection(); + BlockPos pos = result.getBlockPos().relative(face); + + extinguishLitBurners(world, pos, face); + extinguishLitBurners(world, pos.relative(face.getOpposite()), face); + + for (Direction face1 : Direction.Plane.HORIZONTAL) { + extinguishLitBurners(world, pos.relative(face1), face1); + } + } + } + + private static void extinguishLitBurners(World world, BlockPos pos, Direction direction) { + BlockState state = world.getBlockState(pos); + if (AllBlocks.LIT_BLAZE_BURNER.has(state)) { + world.playSound(null, pos, SoundEvents.FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F); + world.setBlockAndUpdate(pos, AllBlocks.BLAZE_BURNER.getDefaultState()); } - - AllSoundEvents.BLAZE_MUNCH.playOnServer(world, heater.getPos()); } } 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..9f000b228 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; @@ -29,7 +29,7 @@ public class BlazeBurnerRenderer extends SafeTileEntityRenderer tileEntityTypeIn) { super(tileEntityTypeIn); activeFuel = FuelType.NONE; remainingBurnTime = 0; headAngle = LerpedFloat.angular(); + isCreative = false; + } + + public FuelType getActiveFuel() { + return activeFuel; + } + + public int getRemainingBurnTime() { + return remainingBurnTime; + } + + public boolean isCreative() { + return isCreative; } @Override public void tick() { super.tick(); - if (world.isRemote) { + + if (level.isClientSide) { tickRotation(); spawnParticles(getHeatLevelFromBlock(), 1); return; } + if (isCreative) + return; + if (remainingBurnTime > 0) remainingBurnTime--; @@ -65,25 +90,28 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { if (activeFuel == FuelType.SPECIAL) { activeFuel = FuelType.NORMAL; - remainingBurnTime = maxHeatCapacity / 2; + remainingBurnTime = MAX_HEAT_CAPACITY / 2; } else activeFuel = FuelType.NONE; + updateBlockState(); - notifyUpdate(); } private void tickRotation() { - ClientPlayerEntity player = Minecraft.getInstance().player; float target = 0; + ClientPlayerEntity player = Minecraft.getInstance().player; if (player != null) { - double x = player.getX(); - double z = player.getZ(); + double x; + double z; if (isVirtual()) { x = -4; z = -10; + } else { + x = player.getX(); + z = player.getZ(); } - double dx = x - (getPos().getX() + 0.5); - double dz = z - (getPos().getZ() + 0.5); + double dx = x - (getBlockPos().getX() + 0.5); + double dz = z - (getBlockPos().getZ() + 0.5); target = AngleHelper.deg(-MathHelper.atan2(dz, dx)) - 90; } target = headAngle.getValue() + AngleHelper.getShortestAngleDiff(headAngle.getValue(), target); @@ -96,8 +124,12 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { @Override public void write(CompoundNBT compound, boolean clientPacket) { - compound.putInt("fuelLevel", activeFuel.ordinal()); - compound.putInt("burnTimeRemaining", remainingBurnTime); + if (!isCreative) { + compound.putInt("fuelLevel", activeFuel.ordinal()); + compound.putInt("burnTimeRemaining", remainingBurnTime); + } else { + compound.putBoolean("isCreative", true); + } super.write(compound, clientPacket); } @@ -105,22 +137,44 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { activeFuel = FuelType.values()[compound.getInt("fuelLevel")]; remainingBurnTime = compound.getInt("burnTimeRemaining"); + isCreative = compound.getBoolean("isCreative"); super.fromTag(state, compound, clientPacket); } + public BlazeBurnerBlock.HeatLevel getHeatLevelFromBlock() { + return BlazeBurnerBlock.getHeatLevelOf(getBlockState()); + } + + public void updateBlockState() { + setBlockHeat(getHeatLevelFromFuelType(activeFuel)); + } + + protected void setBlockHeat(HeatLevel heat) { + HeatLevel inBlockState = getHeatLevelFromBlock(); + if (inBlockState == heat) + return; + level.setBlockAndUpdate(worldPosition, getBlockState().setValue(BlazeBurnerBlock.HEAT_LEVEL, heat)); + notifyUpdate(); + } + /** - * @return true if the heater updated its burn time and a item should be + * @return true if the heater updated its burn time and an item should be * consumed */ - boolean tryUpdateFuel(ItemStack itemStack, boolean forceOverflow, boolean simulate) { - FuelType newFuel = FuelType.NONE; - int newBurnTime = ForgeHooks.getBurnTime(itemStack); + protected boolean tryUpdateFuel(ItemStack itemStack, boolean forceOverflow, boolean simulate) { + if (isCreative) + return false; + + FuelType newFuel = FuelType.NONE; + int newBurnTime; - if (newBurnTime > 0) - newFuel = FuelType.NORMAL; if (AllItems.BLAZE_CAKE.isIn(itemStack)) { newBurnTime = 1000; newFuel = FuelType.SPECIAL; + } else { + newBurnTime = ForgeHooks.getBurnTime(itemStack); + if (newBurnTime > 0) + newFuel = FuelType.NORMAL; } if (newFuel == FuelType.NONE) @@ -131,9 +185,9 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { return false; if (newFuel == activeFuel) { - if (remainingBurnTime + newBurnTime > maxHeatCapacity && !forceOverflow) + if (remainingBurnTime + newBurnTime > MAX_HEAT_CAPACITY && !forceOverflow) return false; - newBurnTime = MathHelper.clamp(remainingBurnTime + newBurnTime, 0, maxHeatCapacity); + newBurnTime = MathHelper.clamp(remainingBurnTime + newBurnTime, 0, MAX_HEAT_CAPACITY); } if (simulate) @@ -142,28 +196,44 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { activeFuel = newFuel; remainingBurnTime = newBurnTime; - if (world.isRemote) { - HeatLevel level = getHeatLevelFromFuelType(newFuel); + if (level.isClientSide) { + HeatLevel level = getHeatLevelFromFuelType(activeFuel); for (int i = 0; i < 20; i++) spawnParticles(level, 1 + (.25 * (i / 4))); - return true; + } else { + playSound(); + updateBlockState(); } - updateBlockState(); return true; } - public BlazeBurnerBlock.HeatLevel getHeatLevelFromBlock() { - return BlazeBurnerBlock.getHeatLevelOf(getBlockState()); + protected void applyCreativeFuel() { + boolean wasCreative = isCreative; + + activeFuel = FuelType.NONE; + remainingBurnTime = 0; + isCreative = true; + + if (level.isClientSide) { + for (int i = 0; i < 30; i++) { + double burstMult = 1 + (.25 * (i / 4)); + spawnParticle(CREATIVE_PARTICLE_COLORS, 0.04F, 35, false, 0.03 * burstMult, 0.15 * burstMult); + } + } else { + playSound(); + if (wasCreative) + setBlockHeat(getHeatLevelFromBlock().nextActiveLevel()); + } } - public void updateBlockState() { - HeatLevel inBlockState = getHeatLevelFromBlock(); - HeatLevel inTE = getHeatLevelFromFuelType(activeFuel); - if (inBlockState == inTE) - return; - world.setBlockState(pos, getBlockState().with(BlazeBurnerBlock.HEAT_LEVEL, inTE)); - notifyUpdate(); + public boolean isCreativeFuel(ItemStack stack) { + return AllItems.CREATIVE_BLAZE_CAKE.isIn(stack); + } + + protected void playSound() { + level.playSound(null, worldPosition, SoundEvents.BLAZE_SHOOT, SoundCategory.BLOCKS, + .125f + level.random.nextFloat() * .125f, .75f - level.random.nextFloat() * .25f); } protected HeatLevel getHeatLevelFromFuelType(FuelType fuel) { @@ -173,7 +243,7 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { level = HeatLevel.SEETHING; break; case NORMAL: - boolean lowPercent = (double) remainingBurnTime / maxHeatCapacity < 0.1; + boolean lowPercent = (double) remainingBurnTime / MAX_HEAT_CAPACITY < 0.1; level = lowPercent ? HeatLevel.FADING : HeatLevel.KINDLED; break; default: @@ -183,13 +253,13 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { return level; } - private void spawnParticles(HeatLevel heatLevel, double burstMult) { - if (world == null) + protected void spawnParticles(HeatLevel heatLevel, double burstMult) { + if (level == null) return; if (heatLevel == BlazeBurnerBlock.HeatLevel.NONE) return; - Random r = world.getRandom(); + Random r = level.getRandom(); switch (heatLevel) { case SMOULDERING: if (r.nextDouble() > 0.25) @@ -216,20 +286,28 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { } } - private void spawnParticle(HeatLevel heatLevel, float scale, int avgAge, boolean hot, double speed, double spread) { - Random random = world.getRandom(); - Vector3d color = randomColor(heatLevel); - world.addOptionalParticle( - new CubeParticleData((float) color.x, (float) color.y, (float) color.z, scale, avgAge, hot), - (double) pos.getX() + 0.5D + (random.nextDouble() * 2.0 - 1D) * spread, - (double) pos.getY() + 0.6D + (random.nextDouble() / 4.0), - (double) pos.getZ() + 0.5D + (random.nextDouble() * 2.0 - 1D) * spread, 0.0D, speed, 0.0D); + protected void spawnParticle(Color color, float scale, int avgAge, boolean hot, double speed, double spread) { + Random random = level.getRandom(); + level.addAlwaysVisibleParticle( + new CubeParticleData(color.getRedAsFloat(), color.getGreenAsFloat(), color.getBlueAsFloat(), scale, avgAge, hot), + (double) worldPosition.getX() + 0.5D + (random.nextDouble() * 2.0 - 1D) * spread, + (double) worldPosition.getY() + 0.6D + (random.nextDouble() / 4.0), + (double) worldPosition.getZ() + 0.5D + (random.nextDouble() * 2.0 - 1D) * spread, 0.0D, speed, 0.0D); } - private static Vector3d randomColor(BlazeBurnerBlock.HeatLevel heatLevel) { - if (heatLevel == BlazeBurnerBlock.HeatLevel.NONE) - return new Vector3d(0, 0, 0); - return ColorHelper.getRGB(heatParticleColors[heatLevel.ordinal() - 1][(int) (Math.random() * 4)]); + protected void spawnParticle(Color[] colors, float scale, int avgAge, boolean hot, double speed, double spread) { + if (colors.length == 0) + return; + + spawnParticle(colors[(int) (Math.random() * colors.length)], scale, avgAge, hot, speed, spread); + } + + protected void spawnParticle(HeatLevel heatLevel, float scale, int avgAge, boolean hot, double speed, double spread) { + spawnParticle(PARTICLE_COLORS[heatLevel.ordinal()], scale, avgAge, hot, speed, spread); + } + + public enum FuelType { + NONE, NORMAL, SPECIAL } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/LitBlazeBurnerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/LitBlazeBurnerBlock.java index cfe315f79..f81829625 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/LitBlazeBurnerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/LitBlazeBurnerBlock.java @@ -4,16 +4,20 @@ import java.util.Random; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.utility.Lang; import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.particles.ParticleTypes; import net.minecraft.pathfinding.PathType; +import net.minecraft.state.EnumProperty; +import net.minecraft.state.StateContainer.Builder; +import net.minecraft.tags.ItemTags; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; +import net.minecraft.util.IStringSerializable; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; @@ -25,43 +29,48 @@ 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.common.ToolType; public class LitBlazeBurnerBlock extends Block { -// 1.16: add a soul fire variant + public static final EnumProperty FLAME_TYPE = EnumProperty.create("flame_type", FlameType.class); -// public enum FlameType implements IStringSerializable { -// REGULAR, SOULFIRE; -// -// @Override -// public String getName() { -// return Lang.asId(name()); -// } -// -// } - - public LitBlazeBurnerBlock(Properties p_i48440_1_) { - super(p_i48440_1_); + public LitBlazeBurnerBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(FLAME_TYPE, FlameType.REGULAR)); } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder); + builder.add(FLAME_TYPE); + } + + @Override + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult blockRayTraceResult) { - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getItemInHand(hand); - // Check for 'Shovels' - if (!heldItem.canHarvestBlock(Blocks.SNOW.getDefaultState())) - return ActionResultType.PASS; - - world.playSound(player, pos, SoundEvents.ENTITY_GENERIC_EXTINGUISH_FIRE, SoundCategory.BLOCKS, .5f, 2); - - if (world.isRemote) + if (heldItem.getToolTypes().contains(ToolType.SHOVEL)) { + world.playSound(player, pos, SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundCategory.BLOCKS, 0.5f, 2); + if (world.isClientSide) + return ActionResultType.SUCCESS; + heldItem.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand)); + world.setBlockAndUpdate(pos, AllBlocks.BLAZE_BURNER.getDefaultState()); return ActionResultType.SUCCESS; - if (!player.isCreative()) - heldItem.damageItem(1, player, p -> p.sendBreakAnimation(hand)); + } - world.setBlockState(pos, AllBlocks.BLAZE_BURNER.getDefaultState()); - return ActionResultType.SUCCESS; + if (state.getValue(FLAME_TYPE) == FlameType.REGULAR) { + if (heldItem.getItem().is(ItemTags.SOUL_FIRE_BASE_BLOCKS)) { + world.playSound(player, pos, SoundEvents.SOUL_SAND_PLACE, SoundCategory.BLOCKS, 1.0f, world.random.nextFloat() * 0.4F + 0.8F); + if (world.isClientSide) + return ActionResultType.SUCCESS; + world.setBlockAndUpdate(pos, defaultBlockState().setValue(FLAME_TYPE, FlameType.SOUL)); + return ActionResultType.SUCCESS; + } + } + + return ActionResultType.PASS; } @Override @@ -77,19 +86,30 @@ public class LitBlazeBurnerBlock extends Block { } @OnlyIn(Dist.CLIENT) - public void animateTick(BlockState p_180655_1_, World world, BlockPos pos, Random random) { - world.addOptionalParticle(ParticleTypes.LARGE_SMOKE, true, + public void animateTick(BlockState state, World world, BlockPos pos, Random random) { + world.addAlwaysVisibleParticle(ParticleTypes.LARGE_SMOKE, true, (double) pos.getX() + 0.5D + random.nextDouble() / 3.0D * (double) (random.nextBoolean() ? 1 : -1), (double) pos.getY() + random.nextDouble() + random.nextDouble(), (double) pos.getZ() + 0.5D + random.nextDouble() / 3.0D * (double) (random.nextBoolean() ? 1 : -1), 0.0D, 0.07D, 0.0D); if (random.nextInt(10) == 0) { - world.playSound((double) ((float) pos.getX() + 0.5F), (double) ((float) pos.getY() + 0.5F), - (double) ((float) pos.getZ() + 0.5F), SoundEvents.BLOCK_CAMPFIRE_CRACKLE, SoundCategory.BLOCKS, + world.playLocalSound((double) ((float) pos.getX() + 0.5F), (double) ((float) pos.getY() + 0.5F), + (double) ((float) pos.getZ() + 0.5F), SoundEvents.CAMPFIRE_CRACKLE, SoundCategory.BLOCKS, 0.25F + random.nextFloat() * .25f, random.nextFloat() * 0.7F + 0.6F, false); } + if (state.getValue(FLAME_TYPE) == FlameType.SOUL) { + if (random.nextInt(8) == 0) { + world.addParticle(ParticleTypes.SOUL, + pos.getX() + 0.5F + random.nextDouble() / 4 * (random.nextBoolean() ? 1 : -1), + pos.getY() + 0.3F + random.nextDouble() / 2, + pos.getZ() + 0.5F + random.nextDouble() / 4 * (random.nextBoolean() ? 1 : -1), + 0.0, random.nextDouble() * 0.04 + 0.04, 0.0); + } + return; + } + if (random.nextInt(5) == 0) { for (int i = 0; i < random.nextInt(1) + 1; ++i) { world.addParticle(ParticleTypes.LAVA, (double) ((float) pos.getX() + 0.5F), @@ -98,15 +118,15 @@ public class LitBlazeBurnerBlock extends Block { } } } - + @Override - public boolean hasComparatorInputOverride(BlockState p_149740_1_) { + public boolean hasAnalogOutputSignal(BlockState p_149740_1_) { return true; } - + @Override - public int getComparatorInputOverride(BlockState state, World p_180641_2_, BlockPos p_180641_3_) { - return 1; + public int getAnalogOutputSignal(BlockState state, World p_180641_2_, BlockPos p_180641_3_) { + return state.getValue(FLAME_TYPE) == FlameType.REGULAR ? 1 : 2; } @Override @@ -115,10 +135,28 @@ public class LitBlazeBurnerBlock extends Block { return AllBlocks.BLAZE_BURNER.get() .getCollisionShape(state, reader, pos, context); } - + @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } + public static int getLight(BlockState state) { + if (state.getValue(FLAME_TYPE) == FlameType.SOUL) + return 9; + else + return 12; + } + + public enum FlameType implements IStringSerializable { + + REGULAR, SOUL; + + @Override + public String getSerializedName() { + return Lang.asId(name()); + } + + } + } 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..a05ec6708 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 @@ -56,19 +56,19 @@ public class GantryShaftBlock extends DirectionalKineticBlock { START, MIDDLE, END, SINGLE; @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(PART, POWERED)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(PART, POWERED)); } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - ItemStack heldItem = player.getHeldItem(hand); + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { + ItemStack heldItem = player.getItemInHand(hand); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); if (!placementHelper.matchesItem(heldItem)) @@ -80,25 +80,25 @@ public class GantryShaftBlock extends DirectionalKineticBlock { @Override public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, ISelectionContext p_220053_4_) { - return AllShapes.EIGHT_VOXEL_POLE.get(state.get(FACING) + return AllShapes.EIGHT_VOXEL_POLE.get(state.getValue(FACING) .getAxis()); } @Override - public BlockRenderType getRenderType(BlockState state) { + public BlockRenderType getRenderShape(BlockState state) { return BlockRenderType.ENTITYBLOCK_ANIMATED; } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbour, IWorld world, + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbour, IWorld world, BlockPos pos, BlockPos neighbourPos) { - Direction facing = state.get(FACING); + Direction facing = state.getValue(FACING); Axis axis = facing.getAxis(); if (direction.getAxis() != axis) return state; - boolean connect = AllBlocks.GANTRY_SHAFT.has(neighbour) && neighbour.get(FACING) == facing; + boolean connect = AllBlocks.GANTRY_SHAFT.has(neighbour) && neighbour.getValue(FACING) == facing; - Part part = state.get(PART); + Part part = state.getValue(PART); if (direction.getAxisDirection() == facing.getAxisDirection()) { if (connect) { if (part == Part.END) @@ -125,60 +125,74 @@ public class GantryShaftBlock extends DirectionalKineticBlock { } } - return state.with(PART, part); + return state.setValue(PART, part); } public GantryShaftBlock(Properties properties) { super(properties); - setDefaultState(getDefaultState().with(POWERED, false) - .with(PART, Part.SINGLE)); + registerDefaultState(defaultBlockState().setValue(POWERED, false) + .setValue(PART, Part.SINGLE)); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { BlockState state = super.getStateForPlacement(context); - BlockPos pos = context.getPos(); - World world = context.getWorld(); - Direction face = context.getFace(); + BlockPos pos = context.getClickedPos(); + World world = context.getLevel(); + Direction face = context.getClickedFace(); - BlockState neighbour = world.getBlockState(pos.offset(state.get(FACING) + BlockState neighbour = world.getBlockState(pos.relative(state.getValue(FACING) .getOpposite())); BlockState clickedState = - AllBlocks.GANTRY_SHAFT.has(neighbour) ? neighbour : world.getBlockState(pos.offset(face.getOpposite())); + AllBlocks.GANTRY_SHAFT.has(neighbour) ? neighbour : world.getBlockState(pos.relative(face.getOpposite())); - if (AllBlocks.GANTRY_SHAFT.has(clickedState) && clickedState.get(FACING) - .getAxis() == state.get(FACING) + if (AllBlocks.GANTRY_SHAFT.has(clickedState) && clickedState.getValue(FACING) + .getAxis() == state.getValue(FACING) .getAxis()) { - Direction facing = clickedState.get(FACING); - state = state.with(FACING, context.getPlayer() == null || !context.getPlayer() - .isSneaking() ? facing : facing.getOpposite()); + Direction facing = clickedState.getValue(FACING); + state = state.setValue(FACING, context.getPlayer() == null || !context.getPlayer() + .isShiftKeyDown() ? facing : facing.getOpposite()); } - return state.with(POWERED, shouldBePowered(state, world, pos)); + return state.setValue(POWERED, shouldBePowered(state, world, pos)); } @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { ActionResultType onWrenched = super.onWrenched(state, context); - if (onWrenched.isAccepted()) { - BlockPos pos = context.getPos(); - World world = context.getWorld(); + if (onWrenched.consumesAction()) { + BlockPos pos = context.getClickedPos(); + World world = context.getLevel(); neighborChanged(world.getBlockState(pos), world, pos, state.getBlock(), pos, false); } return onWrenched; } + @Override + public void onPlace(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, worldIn, pos, oldState, isMoving); + + if (!worldIn.isClientSide() && oldState.getBlock().is(AllBlocks.GANTRY_SHAFT.get())) { + Part oldPart = oldState.getValue(PART), part = state.getValue(PART); + if ((oldPart != Part.MIDDLE && part == Part.MIDDLE) || (oldPart == Part.SINGLE && part != Part.SINGLE)) { + TileEntity te = worldIn.getBlockEntity(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_) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; - boolean previouslyPowered = state.get(POWERED); - boolean shouldPower = worldIn.isBlockPowered(pos); // shouldBePowered(state, worldIn, pos); + boolean previouslyPowered = state.getValue(POWERED); + boolean shouldPower = worldIn.hasNeighborSignal(pos); // shouldBePowered(state, worldIn, pos); if (!previouslyPowered && !shouldPower && shouldBePowered(state, worldIn, pos)) { - worldIn.setBlockState(pos, state.with(POWERED, true), 3); + worldIn.setBlock(pos, state.setValue(POWERED, true), 3); return; } @@ -187,52 +201,52 @@ public class GantryShaftBlock extends DirectionalKineticBlock { // Collect affected gantry shafts List toUpdate = new ArrayList<>(); - Direction facing = state.get(FACING); + Direction facing = state.getValue(FACING); Axis axis = facing.getAxis(); for (Direction d : Iterate.directionsInAxis(axis)) { - BlockPos currentPos = pos.offset(d); + BlockPos currentPos = pos.relative(d); while (true) { - if (!worldIn.isBlockPresent(currentPos)) + if (!worldIn.isLoaded(currentPos)) break; BlockState currentState = worldIn.getBlockState(currentPos); if (!(currentState.getBlock() instanceof GantryShaftBlock)) break; - if (currentState.get(FACING) != facing) + if (currentState.getValue(FACING) != facing) break; - if (!shouldPower && currentState.get(POWERED) && worldIn.isBlockPowered(currentPos)) + if (!shouldPower && currentState.getValue(POWERED) && worldIn.hasNeighborSignal(currentPos)) return; - if (currentState.get(POWERED) == shouldPower) + if (currentState.getValue(POWERED) == shouldPower) break; toUpdate.add(currentPos); - currentPos = currentPos.offset(d); + currentPos = currentPos.relative(d); } } toUpdate.add(pos); for (BlockPos blockPos : toUpdate) { BlockState blockState = worldIn.getBlockState(blockPos); - TileEntity te = worldIn.getTileEntity(blockPos); + TileEntity te = worldIn.getBlockEntity(blockPos); if (te instanceof KineticTileEntity) ((KineticTileEntity) te).detachKinetics(); if (blockState.getBlock() instanceof GantryShaftBlock) - worldIn.setBlockState(blockPos, blockState.with(POWERED, shouldPower), 2); + worldIn.setBlock(blockPos, blockState.setValue(POWERED, shouldPower), 2); } } protected boolean shouldBePowered(BlockState state, World worldIn, BlockPos pos) { - boolean shouldPower = worldIn.isBlockPowered(pos); + boolean shouldPower = worldIn.hasNeighborSignal(pos); - Direction facing = state.get(FACING); + Direction facing = state.getValue(FACING); for (Direction d : Iterate.directionsInAxis(facing.getAxis())) { - BlockPos neighbourPos = pos.offset(d); - if (!worldIn.isBlockPresent(neighbourPos)) + BlockPos neighbourPos = pos.relative(d); + if (!worldIn.isLoaded(neighbourPos)) continue; BlockState neighbourState = worldIn.getBlockState(neighbourPos); if (!(neighbourState.getBlock() instanceof GantryShaftBlock)) continue; - if (neighbourState.get(FACING) != facing) + if (neighbourState.getValue(FACING) != facing) continue; - shouldPower |= neighbourState.get(POWERED); + shouldPower |= neighbourState.getValue(POWERED); } return shouldPower; @@ -240,13 +254,13 @@ public class GantryShaftBlock extends DirectionalKineticBlock { @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.get(FACING) + return face.getAxis() == state.getValue(FACING) .getAxis(); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(FACING) + return state.getValue(FACING) .getAxis(); } @@ -258,9 +272,9 @@ public class GantryShaftBlock extends DirectionalKineticBlock { @Override protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) { return super.areStatesKineticallyEquivalent(oldState, newState) - && oldState.get(POWERED) == newState.get(POWERED); + && oldState.getValue(POWERED) == newState.getValue(POWERED); } - + @Override public float getParticleTargetRadius() { return .35f; @@ -270,16 +284,16 @@ public class GantryShaftBlock extends DirectionalKineticBlock { public float getParticleInitialRadius() { return .25f; } - + @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } public static class PlacementHelper extends PoleHelper { public PlacementHelper() { - super(AllBlocks.GANTRY_SHAFT::has, s -> s.get(FACING) + super(AllBlocks.GANTRY_SHAFT::has, s -> s.getValue(FACING) .getAxis(), FACING); } @@ -291,7 +305,7 @@ public class GantryShaftBlock extends DirectionalKineticBlock { @Override public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) { PlacementOffset offset = super.getOffset(player, world, state, pos, ray); - offset.withTransform(offset.getTransform().andThen(s -> s.with(POWERED, state.get(POWERED)))); + offset.withTransform(offset.getTransform().andThen(s -> s.setValue(POWERED, state.getValue(POWERED)))); return offset; } } 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..2d29850bb 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,27 +19,29 @@ 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()) + if (d.getAxis() == getBlockState().getValue(GantryShaftBlock.FACING) + .getAxis()) continue; - BlockPos offset = pos.offset(d); - BlockState pinionState = world.getBlockState(offset); + BlockPos offset = worldPosition.relative(d); + BlockState pinionState = level.getBlockState(offset); if (!AllBlocks.GANTRY_CARRIAGE.has(pinionState)) continue; - if (pinionState.get(GantryCarriageBlock.FACING) != d) + if (pinionState.getValue(GantryCarriageBlock.FACING) != d) continue; - TileEntity tileEntity = world.getTileEntity(offset); + TileEntity tileEntity = level.getBlockEntity(offset); if (tileEntity instanceof GantryCarriageTileEntity) ((GantryCarriageTileEntity) tileEntity).queueAssembly(); } + } + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + checkAttachedCarriageBlocks(); } @Override @@ -50,37 +52,37 @@ public class GantryShaftTileEntity extends KineticTileEntity { if (connectedViaAxes) return defaultModifier; - if (!stateFrom.get(GantryShaftBlock.POWERED)) + if (!stateFrom.getValue(GantryShaftBlock.POWERED)) return defaultModifier; if (!AllBlocks.GANTRY_CARRIAGE.has(stateTo)) return defaultModifier; - Direction direction = Direction.getFacingFromVector(diff.getX(), diff.getY(), diff.getZ()); - if (stateTo.get(GantryCarriageBlock.FACING) != direction) + Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); + if (stateTo.getValue(GantryCarriageBlock.FACING) != direction) return defaultModifier; - return GantryCarriageTileEntity.getGantryPinionModifier(stateFrom.get(GantryShaftBlock.FACING), - stateTo.get(GantryCarriageBlock.FACING)); + return GantryCarriageTileEntity.getGantryPinionModifier(stateFrom.getValue(GantryShaftBlock.FACING), + stateTo.getValue(GantryCarriageBlock.FACING)); } @Override public boolean isCustomConnection(KineticTileEntity other, BlockState state, BlockState otherState) { if (!AllBlocks.GANTRY_CARRIAGE.has(otherState)) return false; - final BlockPos diff = other.getPos() - .subtract(pos); - Direction direction = Direction.getFacingFromVector(diff.getX(), diff.getY(), diff.getZ()); - return otherState.get(GantryCarriageBlock.FACING) == direction; + final BlockPos diff = other.getBlockPos() + .subtract(worldPosition); + Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); + return otherState.getValue(GantryCarriageBlock.FACING) == direction; } public boolean canAssembleOn() { BlockState blockState = getBlockState(); if (!AllBlocks.GANTRY_SHAFT.has(blockState)) return false; - if (blockState.get(GantryShaftBlock.POWERED)) + if (blockState.getValue(GantryShaftBlock.POWERED)) return false; float speed = getPinionMovementSpeed(); - switch (blockState.get(GantryShaftBlock.PART)) { + switch (blockState.getValue(GantryShaftBlock.PART)) { case END: return speed < 0; case MIDDLE: @@ -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/SpeedControllerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java index 46a4f25d4..c0838a5c9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java @@ -50,27 +50,27 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - BlockState above = context.getWorld() - .getBlockState(context.getPos() - .up()); - if (ICogWheel.isLargeCog(above) && above.get(CogWheelBlock.AXIS) + BlockState above = context.getLevel() + .getBlockState(context.getClickedPos() + .above()); + if (ICogWheel.isLargeCog(above) && above.getValue(CogWheelBlock.AXIS) .isHorizontal()) - return getDefaultState().with(HORIZONTAL_AXIS, above.get(CogWheelBlock.AXIS) == Axis.X ? Axis.Z : Axis.X); + return defaultBlockState().setValue(HORIZONTAL_AXIS, above.getValue(CogWheelBlock.AXIS) == Axis.X ? Axis.Z : Axis.X); return super.getStateForPlacement(context); } @Override public void neighborChanged(BlockState state, World world, BlockPos pos, Block p_220069_4_, BlockPos neighbourPos, boolean p_220069_6_) { - if (neighbourPos.equals(pos.up())) + if (neighbourPos.equals(pos.above())) withTileEntityDo(world, pos, SpeedControllerTileEntity::updateBracket); } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getItemInHand(hand); IPlacementHelper helper = PlacementHelpers.get(placementHelperId); if (helper.matchesItem(heldItem)) return helper.getOffset(player, world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); @@ -97,18 +97,18 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements @Override public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) { - BlockPos newPos = pos.up(); + BlockPos newPos = pos.above(); if (!world.getBlockState(newPos) .getMaterial() .isReplaceable()) return PlacementOffset.fail(); - Axis newAxis = state.get(HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X; + Axis newAxis = state.getValue(HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X; if (!CogWheelBlock.isValidCogwheelPosition(true, world, newPos, newAxis)) return PlacementOffset.fail(); - return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis)); + return PlacementOffset.success(newPos, s -> s.setValue(CogWheelBlock.AXIS, newAxis)); } } 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..54349d915 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; @@ -31,30 +31,30 @@ 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/SequencedGearshiftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java index eac794939..f66821680 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java @@ -46,8 +46,8 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(STATE, VERTICAL)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(STATE, VERTICAL)); } @Override @@ -63,18 +63,18 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen @Override public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; - if (!worldIn.getPendingBlockTicks() - .isTickPending(pos, this)) - worldIn.getPendingBlockTicks() + if (!worldIn.getBlockTicks() + .willTickThisTick(pos, this)) + worldIn.getBlockTicks() .scheduleTick(pos, this, 0); } @Override - public void scheduledTick(BlockState state, ServerWorld worldIn, BlockPos pos, Random r) { - boolean previouslyPowered = state.get(STATE) != 0; - boolean isPowered = worldIn.isBlockPowered(pos); + public void tick(BlockState state, ServerWorld worldIn, BlockPos pos, Random r) { + boolean previouslyPowered = state.getValue(STATE) != 0; + boolean isPowered = worldIn.hasNeighborSignal(pos); withTileEntityDo(worldIn, pos, sgte -> sgte.onRedstoneUpdate(isPowered, previouslyPowered)); } @@ -85,21 +85,21 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - if (state.get(VERTICAL)) + if (state.getValue(VERTICAL)) return face.getAxis() .isVertical(); return super.hasShaftTowards(world, pos, state, face); } @Override - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + public ActionResultType use(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - ItemStack held = player.getHeldItemMainhand(); + ItemStack held = player.getMainHandItem(); if (AllItems.WRENCH.isIn(held)) return ActionResultType.PASS; if (held.getItem() instanceof BlockItem) { BlockItem blockItem = (BlockItem) held.getItem(); - if (blockItem.getBlock() instanceof KineticBlock && hasShaftTowards(worldIn, pos, state, hit.getFace())) + if (blockItem.getBlock() instanceof KineticBlock && hasShaftTowards(worldIn, pos, state, hit.getDirection())) return ActionResultType.PASS; } @@ -118,7 +118,7 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen public BlockState getStateForPlacement(BlockItemUseContext context) { Axis preferredAxis = RotatedPillarKineticBlock.getPreferredAxis(context); if (preferredAxis != null && (context.getPlayer() == null || !context.getPlayer() - .isSneaking())) + .isShiftKeyDown())) return withAxis(preferredAxis, context); return withAxis(context.getNearestLookingDirection() .getAxis(), context); @@ -128,9 +128,9 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen public ActionResultType onWrenched(BlockState state, ItemUseContext context) { BlockState newState = state; - if (context.getFace() + if (context.getClickedFace() .getAxis() != Axis.Y) - if (newState.get(HORIZONTAL_AXIS) != context.getFace() + if (newState.getValue(HORIZONTAL_AXIS) != context.getClickedFace() .getAxis()) newState = newState.cycle(VERTICAL); @@ -138,16 +138,16 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen } private BlockState withAxis(Axis axis, BlockItemUseContext context) { - BlockState state = getDefaultState().with(VERTICAL, axis.isVertical()); + BlockState state = defaultBlockState().setValue(VERTICAL, axis.isVertical()); if (axis.isVertical()) - return state.with(HORIZONTAL_AXIS, context.getPlacementHorizontalFacing() + return state.setValue(HORIZONTAL_AXIS, context.getHorizontalDirection() .getAxis()); - return state.with(HORIZONTAL_AXIS, axis); + return state.setValue(HORIZONTAL_AXIS, axis); } @Override public Axis getRotationAxis(BlockState state) { - if (state.get(VERTICAL)) + if (state.getValue(VERTICAL)) return Axis.Y; return super.getRotationAxis(state); } @@ -158,13 +158,13 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen } @Override - public boolean hasComparatorInputOverride(BlockState p_149740_1_) { + public boolean hasAnalogOutputSignal(BlockState p_149740_1_) { return true; } @Override - public int getComparatorInputOverride(BlockState state, World world, BlockPos pos) { - return state.get(STATE) + public int getAnalogOutputSignal(BlockState state, World world, BlockPos pos) { + return state.getValue(STATE) .intValue(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftGenerator.java index 86b5f5b59..9301fecdd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftGenerator.java @@ -13,19 +13,19 @@ public class SequencedGearshiftGenerator extends SpecialBlockStateGen { @Override protected int getXRotation(BlockState state) { - return state.get(SequencedGearshiftBlock.VERTICAL) ? 90 : 0; + return state.getValue(SequencedGearshiftBlock.VERTICAL) ? 90 : 0; } @Override protected int getYRotation(BlockState state) { - return state.get(SequencedGearshiftBlock.HORIZONTAL_AXIS) == Axis.X ? 90 : 0; + return state.getValue(SequencedGearshiftBlock.HORIZONTAL_AXIS) == Axis.X ? 90 : 0; } @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { String variant = "idle"; - int seq = state.get(SequencedGearshiftBlock.STATE); + int seq = state.getValue(SequencedGearshiftBlock.STATE); if (seq > 0) variant = "seq_" + seq; return prov.models() diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java index fb073cbc2..30a7063fc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java @@ -14,7 +14,6 @@ import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Lang; -import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.nbt.ListNBT; import net.minecraft.util.math.BlockPos; @@ -27,7 +26,6 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { private final AllGuiTextures background = AllGuiTextures.SEQUENCER; private IconButton confirmButton; - private final ITextComponent title = Lang.translate("gui.sequenced_gearshift.title"); private ListNBT compareTag; private Vector instructions; private BlockPos pos; @@ -35,28 +33,37 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { private Vector> inputs; public SequencedGearshiftScreen(SequencedGearshiftTileEntity te) { + super(Lang.translate("gui.sequenced_gearshift.title")); this.instructions = te.instructions; - this.pos = te.getPos(); + this.pos = te.getBlockPos(); compareTag = Instruction.serializeAll(instructions); } @Override protected void init() { - setWindowSize(background.width + 50, background.height); + setWindowSize(background.width, background.height); + setWindowOffset(-20, 0); super.init(); widgets.clear(); + int x = guiLeft; + int y = guiTop; + inputs = new Vector<>(5); for (int row = 0; row < inputs.capacity(); row++) inputs.add(new Vector<>(3)); for (int row = 0; row < instructions.size(); row++) - initInputsOfRow(row); + initInputsOfRow(row, x, y); + + confirmButton = + new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + widgets.add(confirmButton); } - public void initInputsOfRow(int row) { - int x = guiLeft + 30; - int y = guiTop + 18; + public void initInputsOfRow(int row, int backgroundX, int backgroundY) { + int x = backgroundX + 30; + int y = backgroundY + 18; int rowHeight = 22; Vector rowInputs = inputs.get(row); @@ -83,10 +90,6 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { widgets.addAll(rowInputs); updateParamsOfRow(row); - - confirmButton = - new IconButton(guiLeft + background.width - 33, guiTop + background.height - 24, AllIcons.I_CONFIRM); - widgets.add(confirmButton); } public void updateParamsOfRow(int row) { @@ -123,43 +126,44 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { } @Override - protected void renderWindow(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { - int hFontColor = 0xD3CBBE; - background.draw(matrixStack, this, guiLeft, guiTop); + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + background.draw(ms, this, x, y); for (int row = 0; row < instructions.capacity(); row++) { AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY; int yOffset = toDraw.height * row; if (row >= instructions.size()) { - toDraw.draw(matrixStack, guiLeft, guiTop + 14 + yOffset); + toDraw.draw(ms, x, y + 14 + yOffset); continue; } Instruction instruction = instructions.get(row); SequencerInstructions def = instruction.instruction; - def.background.draw(matrixStack, guiLeft, guiTop + 14 + yOffset); + def.background.draw(ms, x, y + 14 + yOffset); - label(matrixStack, 36, yOffset - 3, Lang.translate(def.translationKey)); + label(ms, 36, yOffset - 3, Lang.translate(def.translationKey)); if (def.hasValueParameter) { String text = def.formatValue(instruction.value); - int stringWidth = textRenderer.getStringWidth(text); - label(matrixStack, 90 + (12 - stringWidth / 2), yOffset - 3, new StringTextComponent(text)); + int stringWidth = font.width(text); + label(ms, 90 + (12 - stringWidth / 2), yOffset - 3, new StringTextComponent(text)); } if (def.hasSpeedParameter) - label(matrixStack, 127, yOffset - 3, instruction.speedModifier.label); + label(ms, 127, yOffset - 3, instruction.speedModifier.label); } - textRenderer.drawWithShadow(matrixStack, title, guiLeft - 3 + (background.width - textRenderer.getWidth(title)) / 2, guiTop + 3, - 0xffffff); + drawCenteredString(ms, font, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); GuiGameElement.of(renderedItem) - .at(guiLeft + background.width + 10, guiTop + 100, -150) + .at(x + background.width + 6, y + background.height - 56, -200) .scale(5) - .render(matrixStack); + .render(ms); } - private void label(MatrixStack matrixStack, int x, int y, ITextComponent text) { - textRenderer.drawWithShadow(matrixStack, text, guiLeft + x, guiTop + 26 + y, 0xFFFFEE); + private void label(MatrixStack ms, int x, int y, ITextComponent text) { + font.drawShadow(ms, text, guiLeft + x, guiTop + 26 + y, 0xFFFFEE); } public void sendPacket() { @@ -189,7 +193,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { } else { if (index + 1 < instructions.capacity() && index + 1 == instructions.size()) { instructions.add(new Instruction(SequencerInstructions.END)); - initInputsOfRow(index + 1); + initInputsOfRow(index + 1, guiLeft, guiTop); } } } @@ -197,7 +201,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { @Override public boolean mouseClicked(double x, double y, int button) { if (confirmButton.isHovered()) { - Minecraft.getInstance().player.closeScreen(); + minecraft.player.closeContainer(); return true; } 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..4801c13ac 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; } @@ -33,12 +35,13 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { if (isIdle()) return; - if (world.isRemote) + if (level.isClientSide) return; if (currentInstructionDuration < 0) 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; } @@ -76,8 +78,8 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { return; if (isPowered == isRunning) return; - if (!world.isBlockPowered(pos)) { - world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, 0), 3); + if (!level.hasNeighborSignal(worldPosition)) { + level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3); return; } if (getSpeed() == 0) @@ -109,9 +111,10 @@ 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); + if (!level.hasNeighborSignal(worldPosition)) + level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3); else sendData(); return; @@ -120,8 +123,9 @@ 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); + level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3); } public Instruction getInstruction(int instructionIndex) { @@ -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..45a30857e 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 @@ -13,8 +13,10 @@ import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; +import com.simibubi.create.content.contraptions.relays.belt.BeltSlicer.Feedback; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType; import com.simibubi.create.content.contraptions.relays.belt.transport.BeltMovementHandler.TransportedEntityInfo; +import com.simibubi.create.content.contraptions.relays.belt.transport.BeltTunnelInteractionHandler; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement; @@ -83,38 +85,36 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE p_149666_2_) { + public void fillItemCategory(ItemGroup p_149666_1_, NonNullList p_149666_2_) { p_149666_2_.add(AllItems.BELT_CONNECTOR.asStack()); } @Override protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) { - return super.areStatesKineticallyEquivalent(oldState, newState) && oldState.get(PART) == newState.get(PART); + return super.areStatesKineticallyEquivalent(oldState, newState) + && oldState.getValue(PART) == newState.getValue(PART); } @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { if (face.getAxis() != getRotationAxis(state)) return false; - try { - return getTileEntity(world, pos).hasPulley(); - } catch (TileEntityException e) { - } - return false; + return getTileEntityOptional(world, pos).map(BeltTileEntity::hasPulley) + .orElse(false); } @Override public Axis getRotationAxis(BlockState state) { - if (state.get(SLOPE) == BeltSlope.SIDEWAYS) + if (state.getValue(SLOPE) == BeltSlope.SIDEWAYS) return Axis.Y; - return state.get(HORIZONTAL_FACING) - .rotateY() + return state.getValue(HORIZONTAL_FACING) + .getClockWise() .getAxis(); } @@ -124,20 +124,11 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE getDrops(BlockState state, net.minecraft.loot.LootContext.Builder builder) { List drops = super.getDrops(state, builder); - TileEntity tileEntity = builder.get(LootParameters.BLOCK_ENTITY); + TileEntity tileEntity = builder.getOptionalParameter(LootParameters.BLOCK_ENTITY); if (tileEntity instanceof BeltTileEntity && ((BeltTileEntity) tileEntity).hasPulley()) drops.addAll(AllBlocks.SHAFT.getDefaultState() .getDrops(builder)); @@ -145,7 +136,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE 0) + if (entityIn.getDeltaMovement().y > 0) return; if (!entityIn.isAlive()) return; + if (BeltTunnelInteractionHandler.getTunnelOnPosition(worldIn, pos) != null) + return; withTileEntityDo(worldIn, pos, te -> { ItemEntity itemEntity = (ItemEntity) entityIn; IItemHandler handler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) @@ -220,7 +213,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE te.applyColor(DyeColor.getColor(heldItem))); return ActionResultType.SUCCESS; } + if (isConnector) + return BeltSlicer.useConnector(state, world, pos, player, handIn, hit, new Feedback()); + if (isWrench) + return BeltSlicer.useWrench(state, world, pos, player, handIn, hit, new Feedback()); + BeltTileEntity belt = BeltHelper.getSegmentTE(world, pos); if (belt == null) return ActionResultType.PASS; @@ -263,7 +264,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE te.setCasingType(CasingType.BRASS)); @@ -297,7 +298,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE te.setCasingType(CasingType.ANDESITE)); @@ -309,33 +310,33 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE te.setCasingType(CasingType.NONE)); return ActionResultType.SUCCESS; } - if (state.get(PART) == BeltPart.PULLEY) { - if (world.isRemote) + if (state.getValue(PART) == BeltPart.PULLEY) { + if (world.isClientSide) return ActionResultType.SUCCESS; - KineticTileEntity.switchToBlockState(world, pos, state.with(PART, BeltPart.MIDDLE)); + KineticTileEntity.switchToBlockState(world, pos, state.setValue(PART, BeltPart.MIDDLE)); if (player != null && !player.isCreative()) player.inventory.placeItemBackInInventory(world, AllBlocks.SHAFT.asStack()); return ActionResultType.SUCCESS; } - return ActionResultType.FAIL; + return ActionResultType.PASS; } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(SLOPE, PART, CASING); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override @@ -367,22 +368,19 @@ 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 @@ -391,15 +389,15 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE required = new ArrayList<>(); - if (state.get(PART) != BeltPart.MIDDLE) + if (state.getValue(PART) != BeltPart.MIDDLE) required.add(AllBlocks.SHAFT.asStack()); - if (state.get(PART) == BeltPart.START) + if (state.getValue(PART) == BeltPart.START) required.add(AllItems.BELT_CONNECTOR.asStack()); if (required.isEmpty()) return ItemRequirement.NONE; @@ -602,22 +578,22 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE owner) { - super(owner); - } + public BeltData(Instancer owner) { + super(owner); + } public BeltData setRotation(Quaternion q) { - this.qX = q.getX(); - this.qY = q.getY(); - this.qZ = q.getZ(); - this.qW = q.getW(); + this.qX = q.i(); + this.qY = q.j(); + this.qZ = q.k(); + this.qW = q.r(); markDirty(); return this; } @@ -39,32 +38,30 @@ public class BeltData extends KineticData { TextureAtlasSprite source = spriteShift.getOriginal(); TextureAtlasSprite target = spriteShift.getTarget(); - this.sourceU = source.getMinU(); - this.sourceV = source.getMinV(); - this.minU = target.getMinU(); - this.minV = target.getMinV(); - this.maxU = target.getMaxU(); - this.maxV = target.getMaxV(); + this.sourceU = source.getU0(); + this.sourceV = source.getV0(); + this.minU = target.getU0(); + this.minV = target.getV0(); + this.maxU = target.getU1(); + this.maxV = target.getV1(); 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/BeltGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java index 791849cd7..cf99ded1a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java @@ -15,35 +15,35 @@ public class BeltGenerator extends SpecialBlockStateGen { @Override protected int getXRotation(BlockState state) { - Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); - BeltSlope slope = state.get(BeltBlock.SLOPE); + Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); return slope == BeltSlope.VERTICAL ? 90 : slope == BeltSlope.SIDEWAYS && direction.getAxisDirection() == AxisDirection.NEGATIVE ? 180 : 0; } @Override protected int getYRotation(BlockState state) { - Boolean casing = state.get(BeltBlock.CASING); - BeltSlope slope = state.get(BeltBlock.SLOPE); + Boolean casing = state.getValue(BeltBlock.CASING); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); boolean flip = slope == BeltSlope.UPWARD; boolean rotate = casing && slope == BeltSlope.VERTICAL; - Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); + Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING); return horizontalAngle(direction) + (flip ? 180 : 0) + (rotate ? 90 : 0); } @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - Boolean casing = state.get(BeltBlock.CASING); + Boolean casing = state.getValue(BeltBlock.CASING); if (!casing) return prov.models() .getExistingFile(prov.modLoc("block/belt/particle")); - BeltPart part = state.get(BeltBlock.PART); - Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); - BeltSlope slope = state.get(BeltBlock.SLOPE); + BeltPart part = state.getValue(BeltBlock.PART); + Direction direction = state.getValue(BeltBlock.HORIZONTAL_FACING); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); boolean downward = slope == BeltSlope.DOWNWARD; boolean diagonal = slope == BeltSlope.UPWARD || downward; boolean vertical = slope == BeltSlope.VERTICAL; @@ -63,8 +63,8 @@ public class BeltGenerator extends SpecialBlockStateGen { slope = BeltSlope.SIDEWAYS; String path = "block/" + (casing ? "belt_casing/" : "belt/"); - String slopeName = slope.getString(); - String partName = part.getString(); + String slopeName = slope.getSerializedName(); + String partName = part.getSerializedName(); if (diagonal) slopeName = "diagonal"; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java index 9ce688a16..4377ee9c4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java @@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.relays.belt; import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.block.BlockState; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; @@ -18,13 +19,13 @@ public class BeltHelper { return stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY) .isPresent() || stack.getItem() - .isIn(AllItemTags.UPRIGHT_ON_BELT.tag); + .is(AllItemTags.UPRIGHT_ON_BELT.tag); } public static BeltTileEntity getSegmentTE(IWorld world, BlockPos pos) { if (!world.isAreaLoaded(pos, 0)) return null; - TileEntity tileEntity = world.getTileEntity(pos); + TileEntity tileEntity = world.getBlockEntity(pos); if (!(tileEntity instanceof BeltTileEntity)) return null; return (BeltTileEntity) tileEntity; @@ -46,36 +47,37 @@ public class BeltHelper { public static BeltTileEntity getBeltAtSegment(BeltTileEntity controller, int segment) { BlockPos pos = getPositionForOffset(controller, segment); - TileEntity te = controller.getWorld() - .getTileEntity(pos); + TileEntity te = controller.getLevel() + .getBlockEntity(pos); if (te == null || !(te instanceof BeltTileEntity)) return null; return (BeltTileEntity) te; } public static BlockPos getPositionForOffset(BeltTileEntity controller, int offset) { - BlockPos pos = controller.getPos(); + BlockPos pos = controller.getBlockPos(); Vector3i vec = controller.getBeltFacing() - .getDirectionVec(); + .getNormal(); BeltSlope slope = controller.getBlockState() - .get(BeltBlock.SLOPE); + .getValue(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - return pos.add(offset * vec.getX(), MathHelper.clamp(offset, 0, controller.beltLength - 1) * verticality, + return pos.offset(offset * vec.getX(), MathHelper.clamp(offset, 0, controller.beltLength - 1) * verticality, offset * vec.getZ()); } public static Vector3d getVectorForOffset(BeltTileEntity controller, float offset) { BeltSlope slope = controller.getBlockState() - .get(BeltBlock.SLOPE); + .getValue(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; float verticalMovement = verticality; if (offset < .5) verticalMovement = 0; verticalMovement = verticalMovement * (Math.min(offset, controller.beltLength - .5f) - .5f); - Vector3d vec = VecHelper.getCenterOf(controller.getPos()); - Vector3d horizontalMovement = Vector3d.of(controller.getBeltFacing() - .getDirectionVec()).scale(offset - .5f); + Vector3d vec = VecHelper.getCenterOf(controller.getBlockPos()); + Vector3d horizontalMovement = Vector3d.atLowerCornerOf(controller.getBeltFacing() + .getNormal()) + .scale(offset - .5f); if (slope == BeltSlope.VERTICAL) horizontalMovement = Vector3d.ZERO; @@ -85,4 +87,16 @@ public class BeltHelper { return vec; } + public static Vector3d getBeltVector(BlockState state) { + BeltSlope slope = state.getValue(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + Vector3d horizontalMovement = Vector3d.atLowerCornerOf(state.getValue(BeltBlock.HORIZONTAL_FACING) + .getNormal()); + if (slope == BeltSlope.VERTICAL) + return new Vector3d(0, state.getValue(BeltBlock.HORIZONTAL_FACING) + .getAxisDirection() + .getStep(), 0); + return new Vector3d(0, verticality, 0).add(horizontalMovement); + } + } 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..749cc33c7 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,19 +3,19 @@ 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.material.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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; import net.minecraft.item.DyeColor; import net.minecraft.util.Direction; @@ -35,16 +35,16 @@ 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; keys = new ArrayList<>(2); - beltSlope = blockState.get(BeltBlock.SLOPE); - facing = blockState.get(BeltBlock.HORIZONTAL_FACING); + beltSlope = blockState.getValue(BeltBlock.SLOPE); + facing = blockState.getValue(BeltBlock.HORIZONTAL_FACING); upward = beltSlope == BeltSlope.UPWARD; diagonal = beltSlope.isDiagonal(); sideways = beltSlope == BeltSlope.SIDEWAYS; @@ -52,7 +52,7 @@ public class BeltInstance extends KineticTileInstance { alongX = facing.getAxis() == Direction.Axis.X; alongZ = facing.getAxis() == Direction.Axis.Z; - BeltPart part = blockState.get(BeltBlock.PART); + BeltPart part = blockState.getValue(BeltBlock.PART); boolean start = part == BeltPart.START; boolean end = part == BeltPart.END; DyeColor color = tile.color.orElse(null); @@ -61,7 +61,9 @@ 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.defaultSolid() + .material(AllMaterialSpecs.BELTS) + .getModel(beltPartial, blockState); keys.add(setup(beltModel.createInstance(), bottom, spriteShift)); @@ -69,7 +71,7 @@ public class BeltInstance extends KineticTileInstance { } if (tile.hasPulley()) { - InstancedModel pulleyModel = getPulleyModel(); + Instancer pulleyModel = getPulleyModel(); pulleyKey = setup(pulleyModel.createInstance()); } @@ -121,14 +123,14 @@ public class BeltInstance extends KineticTileInstance { return speed; } - private InstancedModel getPulleyModel() { + private Instancer getPulleyModel() { Direction dir = getOrientation(); Direction.Axis axis = dir.getAxis(); Supplier ms = () -> { MatrixStack modelTransform = new MatrixStack(); - MatrixStacker msr = MatrixStacker.of(modelTransform); + MatrixTransformStack msr = MatrixTransformStack.of(modelTransform); msr.centre(); if (axis == Direction.Axis.X) msr.rotateY(90); @@ -144,8 +146,8 @@ public class BeltInstance extends KineticTileInstance { } private Direction getOrientation() { - Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING) - .rotateY(); + Direction dir = blockState.getValue(BeltBlock.HORIZONTAL_FACING) + .getClockWise(); if (beltSlope == BeltSlope.SIDEWAYS) dir = Direction.UP; @@ -155,7 +157,7 @@ public class BeltInstance extends KineticTileInstance { private BeltData setup(BeltData key, boolean bottom, SpriteShiftEntry spriteShift) { boolean downward = beltSlope == BeltSlope.DOWNWARD; float rotX = (!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0) + (downward ? 180 : 0) + (sideways ? 90 : 0) + (vertical && alongZ ? 180 : 0); - float rotY = facing.getHorizontalAngle() + ((diagonal ^ alongX) && !downward ? 180 : 0) + (sideways && alongZ ? 180 : 0) + (vertical && alongX ? 90 : 0); + float rotY = facing.toYRot() + ((diagonal ^ alongX) && !downward ? 180 : 0) + (sideways && alongZ ? 180 : 0) + (vertical && alongX ? 90 : 0); float rotZ = (sideways ? 90 : 0) + (vertical && alongX ? 90 : 0); Quaternion q = new Quaternion(rotX, rotY, rotZ, true); @@ -167,8 +169,8 @@ public class BeltInstance extends KineticTileInstance { .setRotationOffset(bottom ? 0.5f : 0f) .setColor(tile) .setPosition(getInstancePosition()) - .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) - .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + .setBlockLight(world.getBrightness(LightType.BLOCK, pos)) + .setSkyLight(world.getBrightness(LightType.SKY, pos)); return key; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstancedModel.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstancedModel.java 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/BeltModel.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java index 668cbad48..5a1539690 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java @@ -51,7 +51,7 @@ public class BeltModel extends BakedModelWrapper { TextureAtlasSprite original = quad.getSprite(); TextureAtlasSprite target = spriteShift.getTarget(); BakedQuad newQuad = QuadHelper.clone(quad); - int[] vertexData = newQuad.getVertexData(); + int[] vertexData = newQuad.getVertices(); for (int vertex = 0; vertex < vertexData.length; vertex += format.getIntegerSize()) { int uvOffset = 16 / 4; @@ -60,9 +60,9 @@ public class BeltModel extends BakedModelWrapper { float u = Float.intBitsToFloat(vertexData[uIndex]); float v = Float.intBitsToFloat(vertexData[vIndex]); vertexData[uIndex] = - Float.floatToRawIntBits(target.getInterpolatedU(SuperByteBuffer.getUnInterpolatedU(original, u))); + Float.floatToRawIntBits(target.getU(SuperByteBuffer.getUnInterpolatedU(original, u))); vertexData[vIndex] = - Float.floatToRawIntBits(target.getInterpolatedV(SuperByteBuffer.getUnInterpolatedV(original, v))); + Float.floatToRawIntBits(target.getV(SuperByteBuffer.getUnInterpolatedV(original, v))); } quads.set(i, newQuad); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java index 90c20c6eb..d864d7bb8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java @@ -8,7 +8,7 @@ public enum BeltPart implements IStringSerializable { START, MIDDLE, END, PULLEY; @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } } \ No newline at end of file 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..1fad982ec 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,9 @@ 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.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -15,13 +18,10 @@ 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; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import net.minecraft.block.BlockState; @@ -49,7 +49,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { } @Override - public boolean isGlobalRenderer(BeltTileEntity te) { + public boolean shouldRenderOffScreen(BeltTileEntity te) { return te.isController(); } @@ -57,14 +57,14 @@ 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.getLevel())) { BlockState blockState = te.getBlockState(); if (!AllBlocks.BELT.has(blockState)) return; - BeltSlope beltSlope = blockState.get(BeltBlock.SLOPE); - BeltPart part = blockState.get(BeltBlock.PART); - Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING); + BeltSlope beltSlope = blockState.getValue(BeltBlock.SLOPE); + BeltPart part = blockState.getValue(BeltBlock.PART); + Direction facing = blockState.getValue(BeltBlock.HORIZONTAL_FACING); AxisDirection axisDirection = facing.getAxisDirection(); boolean downward = beltSlope == BeltSlope.DOWNWARD; @@ -76,9 +76,9 @@ public class BeltRenderer extends SafeTileEntityRenderer { boolean alongX = facing.getAxis() == Axis.X; MatrixStack localTransforms = new MatrixStack(); - MatrixStacker msr = MatrixStacker.of(localTransforms); - IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); - float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()); + MatrixTransformStack msr = MatrixTransformStack.of(localTransforms); + IVertexBuilder vb = buffer.getBuffer(RenderType.solid()); + float renderTick = AnimationTickHolder.getRenderTime(te.getLevel()); msr.centre(); msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0)); @@ -106,13 +106,13 @@ public class BeltRenderer extends SafeTileEntityRenderer { // UV shift float speed = te.getSpeed(); if (speed != 0 || te.color.isPresent()) { - float time = renderTick * axisDirection.getOffset(); + float time = renderTick * axisDirection.getStep(); if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX || sideways && axisDirection == AxisDirection.NEGATIVE) speed = -speed; float scrollMult = diagonal ? 3f / 8f : 0.5f; - float spriteSize = spriteShift.getTarget().getMaxV() - spriteShift.getTarget().getMinV(); + float spriteSize = spriteShift.getTarget().getV1() - spriteShift.getTarget().getV0(); double scroll = speed * time / (31.5 * 16) + (bottom ? 0.5 : 0.0); scroll = scroll - Math.floor(scroll); @@ -130,11 +130,11 @@ public class BeltRenderer extends SafeTileEntityRenderer { } if (te.hasPulley()) { - Direction dir = sideways ? Direction.UP : blockState.get(BeltBlock.HORIZONTAL_FACING).rotateY(); + Direction dir = sideways ? Direction.UP : blockState.getValue(BeltBlock.HORIZONTAL_FACING).getClockWise(); Supplier matrixStackSupplier = () -> { MatrixStack stack = new MatrixStack(); - MatrixStacker stacker = MatrixStacker.of(stack); + MatrixTransformStack stacker = MatrixTransformStack.of(stack); stacker.centre(); if (dir.getAxis() == Axis.X) stacker.rotateY(90); if (dir.getAxis() == Axis.Y) stacker.rotateX(90); @@ -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); } } @@ -183,26 +183,26 @@ public class BeltRenderer extends SafeTileEntityRenderer { if (te.beltLength == 0) return; - ms.push(); + ms.pushPose(); Direction beltFacing = te.getBeltFacing(); Vector3i directionVec = beltFacing - .getDirectionVec(); - Vector3d beltStartOffset = Vector3d.of(directionVec).scale(-.5) + .getNormal(); + Vector3d beltStartOffset = Vector3d.atLowerCornerOf(directionVec).scale(-.5) .add(.5, 13 / 16f + .125f, .5); ms.translate(beltStartOffset.x, beltStartOffset.y, beltStartOffset.z); BeltSlope slope = te.getBlockState() - .get(BeltBlock.SLOPE); + .getValue(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; boolean slopeAlongX = beltFacing .getAxis() == Axis.X; - boolean onContraption = te.getWorld() instanceof WrappedWorld; + boolean onContraption = te.getLevel() instanceof WrappedWorld; for (TransportedItemStack transported : te.getInventory() .getTransportedItems()) { - ms.push(); - MatrixStacker.of(ms) + ms.pushPose(); + MatrixTransformStack.of(ms) .nudge(transported.angle); float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition); float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset); @@ -218,7 +218,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { if (offset < .5) verticalMovement = 0; verticalMovement = verticalMovement * (Math.min(offset, te.beltLength - .5f) - .5f); - Vector3d offsetVec = Vector3d.of(directionVec).scale(offset) + Vector3d offsetVec = Vector3d.atLowerCornerOf(directionVec).scale(offset) .add(0, verticalMovement, 0); boolean onSlope = slope != BeltSlope.HORIZONTAL && MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset; @@ -230,7 +230,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { ms.translate(offsetVec.x, offsetVec.y, offsetVec.z); boolean alongX = beltFacing - .rotateY() + .getClockWise() .getAxis() == Axis.X; if (!alongX) sideOffset *= -1; @@ -239,42 +239,42 @@ public class BeltRenderer extends SafeTileEntityRenderer { ItemRenderer itemRenderer = Minecraft.getInstance() .getItemRenderer(); boolean renderUpright = BeltHelper.isItemUpright(transported.stack); - boolean blockItem = itemRenderer.getItemModelWithOverrides(transported.stack, te.getWorld(), null) + boolean blockItem = itemRenderer.getModel(transported.stack, te.getLevel(), null) .isGui3d(); int count = (int) (MathHelper.log2((int) (transported.stack.getCount()))) / 2; Random r = new Random(transported.angle); - if (Minecraft.getInstance().gameSettings.graphicsMode == GraphicsFanciness.FANCY) { - Vector3d shadowPos = Vector3d.of(te.getPos()).add(beltStartOffset.scale(1) + if (Minecraft.getInstance().options.graphicsMode == GraphicsFanciness.FANCY) { + Vector3d shadowPos = Vector3d.atLowerCornerOf(te.getBlockPos()).add(beltStartOffset.scale(1) .add(offsetVec) .add(alongX ? sideOffset : 0, .39, alongX ? 0 : sideOffset)); ShadowRenderHelper.renderShadow(ms, buffer, shadowPos, .75f, blockItem ? .2f : .2f); } if (renderUpright) { - Entity renderViewEntity = Minecraft.getInstance().renderViewEntity; + Entity renderViewEntity = Minecraft.getInstance().cameraEntity; if (renderViewEntity != null) { - Vector3d positionVec = renderViewEntity.getPositionVec(); + Vector3d positionVec = renderViewEntity.position(); Vector3d vectorForOffset = BeltHelper.getVectorForOffset(te, offset); Vector3d diff = vectorForOffset.subtract(positionVec); float yRot = (float) MathHelper.atan2(diff.z, -diff.x); - ms.multiply(Vector3f.POSITIVE_Y.getRadialQuaternion((float) (yRot + Math.PI / 2))); + ms.mulPose(Vector3f.YP.rotation((float) (yRot + Math.PI / 2))); } ms.translate(0, 3 / 32d, 1 / 16f); } if (!renderUpright) - ms.multiply(new Vector3f(slopeAlongX ? 0 : 1, 0, slopeAlongX ? 1 : 0).getDegreesQuaternion(slopeAngle)); + ms.mulPose(new Vector3f(slopeAlongX ? 0 : 1, 0, slopeAlongX ? 1 : 0).rotationDegrees(slopeAngle)); if (onSlope) ms.translate(0, 1 / 8f, 0); for (int i = 0; i <= count; i++) { - ms.push(); + ms.pushPose(); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(transported.angle)); + ms.mulPose(Vector3f.YP.rotationDegrees(transported.angle)); if (!blockItem && !renderUpright) { ms.translate(0, -.09375, 0); - ms.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(90)); + ms.mulPose(Vector3f.XP.rotationDegrees(90)); } if (blockItem) { @@ -282,27 +282,27 @@ public class BeltRenderer extends SafeTileEntityRenderer { } ms.scale(.5f, .5f, .5f); - itemRenderer.renderItem(transported.stack, TransformType.FIXED, stackLight, overlay, ms, buffer); - ms.pop(); + itemRenderer.renderStatic(transported.stack, TransformType.FIXED, stackLight, overlay, ms, buffer); + ms.popPose(); if (!renderUpright) { if (!blockItem) - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(10)); + ms.mulPose(Vector3f.YP.rotationDegrees(10)); ms.translate(0, blockItem ? 1 / 64d : 1 / 16d, 0); } else ms.translate(0, 0, -1 / 16f); } - ms.pop(); + ms.popPose(); } - ms.pop(); + ms.popPose(); } protected int getPackedLight(BeltTileEntity controller, float beltPos) { int segment = (int) Math.floor(beltPos) * 2; - - if (controller.light == null || segment >= controller.light.length) return 0; + if (controller.light == null || segment >= controller.light.length || segment < 0) + return 0; return (controller.light[segment + 1] << 20) | (controller.light[segment] << 4); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java index 572fc124d..aa20a4d02 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.contraptions.relays.belt; -import static net.minecraft.block.Block.makeCuboidShape; +import static net.minecraft.block.Block.box; import java.util.HashMap; import java.util.Map; @@ -76,27 +76,27 @@ public class BeltShapes { FLAT_FULL_PART = makeFlatFull(), FLAT_END_PART = makeFlatEnding(); - private static final VoxelShape SOUTH_MASK = makeCuboidShape(0,-5,8,16,16+5,16); - private static final VoxelShape NORTH_MASK = makeCuboidShape(0,-5,0,16,16+5,8); + private static final VoxelShape SOUTH_MASK = box(0,-5,8,16,16+5,16); + private static final VoxelShape NORTH_MASK = box(0,-5,0,16,16+5,8); //Vertical Shapes private static final VoxelShaper VERTICAL_FULL = VerticalBeltShaper.make(FLAT_FULL_PART), VERTICAL_END = VerticalBeltShaper.make(compose(FLAT_END_PART, FLAT_FULL_PART)), VERTICAL_START = VerticalBeltShaper.make(compose(FLAT_FULL_PART, FLAT_END_PART)); - + //Flat Shapes private static final VoxelShaper FLAT_FULL = VoxelShaper.forHorizontalAxis(FLAT_FULL_PART, Axis.Z), FLAT_END = VoxelShaper.forHorizontal(compose(FLAT_END_PART, FLAT_FULL_PART), Direction.SOUTH), FLAT_START = VoxelShaper.forHorizontal(compose(FLAT_FULL_PART, FLAT_END_PART), Direction.SOUTH); - + //Sideways Shapes private static final VoxelShaper SIDE_FULL = VoxelShaper.forHorizontalAxis(SIDEWAYS_FULL_PART, Axis.Z), SIDE_END = VoxelShaper.forHorizontal(compose(SIDEWAYS_END_PART, SIDEWAYS_FULL_PART), Direction.SOUTH), SIDE_START = VoxelShaper.forHorizontal(compose(SIDEWAYS_FULL_PART, SIDEWAYS_END_PART), Direction.SOUTH); - + //Sloped Shapes private static final VoxelShaper SLOPE_DESC = VoxelShaper.forHorizontal(SLOPE_DESC_PART, Direction.SOUTH), @@ -107,20 +107,20 @@ public class BeltShapes { SLOPE_ASC_START = VoxelShaper.forHorizontal(compose(SLOPE_ASC_PART, FLAT_END_PART), Direction.SOUTH); private static final VoxelShaper - PARTIAL_CASING = VoxelShaper.forHorizontal(makeCuboidShape(0, 0, 5, 16, 11, 16), Direction.SOUTH); + PARTIAL_CASING = VoxelShaper.forHorizontal(box(0, 0, 5, 16, 11, 16), Direction.SOUTH); static Map cache = new HashMap<>(); static Map collisionCache = new HashMap<>(); private static VoxelShape compose(VoxelShape southPart, VoxelShape northPart){ return VoxelShapes.or( - VoxelShapes.combine(SOUTH_MASK, southPart, IBooleanFunction.AND), - VoxelShapes.combine(NORTH_MASK, northPart, IBooleanFunction.AND) + VoxelShapes.joinUnoptimized(SOUTH_MASK, southPart, IBooleanFunction.AND), + VoxelShapes.joinUnoptimized(NORTH_MASK, northPart, IBooleanFunction.AND) ); } private static VoxelShape makeSlopePart(boolean ascendingInstead) { - VoxelShape slice = makeCuboidShape(1, 0, 16, 15, 11, 15); + VoxelShape slice = box(1, 0, 16, 15, 11, 15); VoxelShape result = VoxelShapes.empty(); for (int i = 0; i < 16; i++) { @@ -129,7 +129,7 @@ public class BeltShapes { result = VoxelShapes.or( result,//move slice i voxels "right" and i-5 voxels "down" - slice.withOffset(0, yOffset / 16f, -i / 16f)); + slice.move(0, yOffset / 16f, -i / 16f)); } return result; @@ -137,24 +137,24 @@ public class BeltShapes { private static VoxelShape makeFlatEnding(){ return VoxelShapes.or( - makeCuboidShape(1,4,0,15,12,16), - makeCuboidShape(1,3,1,15,13,15) + box(1,4,0,15,12,16), + box(1,3,1,15,13,15) ); } private static VoxelShape makeFlatFull(){ - return makeCuboidShape(1,3,0,15,13,16); + return box(1,3,0,15,13,16); } - + private static VoxelShape makeSidewaysEnding(){ return VoxelShapes.or( - makeCuboidShape(4,1,0,12,15,16), - makeCuboidShape(3,1,1,13,15,15) + box(4,1,0,12,15,16), + box(3,1,1,13,15,15) ); } - + private static VoxelShape makeSidewaysFull(){ - return makeCuboidShape(3,1,0,13,15,16); + return box(3,1,0,13,15,16); } public static VoxelShape getShape(BlockState state) { @@ -164,20 +164,20 @@ public class BeltShapes { cache.put(state, createdShape); return createdShape; } - + public static VoxelShape getCollisionShape(BlockState state) { if (collisionCache.containsKey(state)) return collisionCache.get(state); - VoxelShape createdShape = VoxelShapes.combine(AllShapes.BELT_COLLISION_MASK, getShape(state), IBooleanFunction.AND); + VoxelShape createdShape = VoxelShapes.joinUnoptimized(AllShapes.BELT_COLLISION_MASK, getShape(state), IBooleanFunction.AND); collisionCache.put(state, createdShape); return createdShape; } private static VoxelShape getBeltShape(BlockState state) { - Direction facing = state.get(BeltBlock.HORIZONTAL_FACING); + Direction facing = state.getValue(BeltBlock.HORIZONTAL_FACING); Axis axis = facing.getAxis(); - BeltPart part = state.get(BeltBlock.PART); - BeltSlope slope = state.get(BeltBlock.SLOPE); + BeltPart part = state.getValue(BeltBlock.PART); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); //vertical if (slope == BeltSlope.VERTICAL) { @@ -194,7 +194,7 @@ public class BeltShapes { //flat ending return (part == BeltPart.START ? FLAT_START : FLAT_END).get(facing); } - + //sideways part if (slope == BeltSlope.SIDEWAYS) { if (part == BeltPart.MIDDLE || part == BeltPart.PULLEY) @@ -217,12 +217,12 @@ public class BeltShapes { } private static VoxelShape getCasingShape(BlockState state) { - if (!state.get(BeltBlock.CASING)) + if (!state.getValue(BeltBlock.CASING)) return VoxelShapes.empty(); - Direction facing = state.get(BeltBlock.HORIZONTAL_FACING); - BeltPart part = state.get(BeltBlock.PART); - BeltSlope slope = state.get(BeltBlock.SLOPE); + Direction facing = state.getValue(BeltBlock.HORIZONTAL_FACING); + BeltPart part = state.getValue(BeltBlock.PART); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); if (slope == BeltSlope.VERTICAL) return VoxelShapes.empty(); @@ -242,7 +242,7 @@ public class BeltShapes { return slope == BeltSlope.DOWNWARD ? AllShapes.CASING_11PX.get(Direction.UP) : PARTIAL_CASING.get(facing); //something went wrong - return VoxelShapes.fullCube(); + return VoxelShapes.block(); } private static class VerticalBeltShaper extends VoxelShaper { @@ -254,7 +254,7 @@ public class BeltShapes { Direction.Plane.HORIZONTAL,//idk, this can probably be improved :S direction -> new Vector3d( direction.getAxisDirection() == Direction.AxisDirection.POSITIVE ? 0 : 180, - -direction.getHorizontalAngle(), + -direction.toYRot(), 0)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlicer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlicer.java new file mode 100644 index 000000000..40d842bad --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlicer.java @@ -0,0 +1,472 @@ +package com.simibubi.create.content.contraptions.relays.belt; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType; +import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorItem; +import com.simibubi.create.content.contraptions.relays.belt.transport.BeltInventory; +import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.DyeColor; +import net.minecraft.item.ItemStack; +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.SoundCategory; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.util.Constants.BlockFlags; + +public class BeltSlicer { + + public static class Feedback { + int color = 0xffffff; + AxisAlignedBB bb; + String langKey; + TextFormatting formatting = TextFormatting.WHITE; + } + + public static ActionResultType useWrench(BlockState state, World world, BlockPos pos, PlayerEntity player, + Hand handIn, BlockRayTraceResult hit, Feedback feedBack) { + BeltTileEntity controllerTE = BeltHelper.getControllerTE(world, pos); + if (controllerTE == null) + return ActionResultType.PASS; + if (state.getValue(BeltBlock.CASING) && hit.getDirection() != Direction.UP) + return ActionResultType.PASS; + if (state.getValue(BeltBlock.PART) == BeltPart.PULLEY && hit.getDirection() + .getAxis() != Axis.Y) + return ActionResultType.PASS; + + int beltLength = controllerTE.beltLength; + if (beltLength == 2) + return ActionResultType.FAIL; + + BlockPos beltVector = new BlockPos(BeltHelper.getBeltVector(state)); + BeltPart part = state.getValue(BeltBlock.PART); + List beltChain = BeltBlock.getBeltChain(world, controllerTE.getBlockPos()); + boolean creative = player.isCreative(); + + // Shorten from End + if (hoveringEnd(state, hit)) { + if (world.isClientSide) + return ActionResultType.SUCCESS; + + for (BlockPos blockPos : beltChain) { + BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + if (belt == null) + continue; + belt.detachKinetics(); + belt.invalidateItemHandler(); + belt.beltLength = 0; + } + + BeltInventory inventory = controllerTE.inventory; + BlockPos next = part == BeltPart.END ? pos.subtract(beltVector) : pos.offset(beltVector); + BlockState replacedState = world.getBlockState(next); + BeltTileEntity segmentTE = BeltHelper.getSegmentTE(world, next); + KineticTileEntity.switchToBlockState(world, next, + state.setValue(BeltBlock.CASING, segmentTE != null && segmentTE.casing != CasingType.NONE)); + world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3 | BlockFlags.IS_MOVING); + world.removeBlockEntity(pos); + world.levelEvent(2001, pos, Block.getId(state)); + + if (!creative && AllBlocks.BELT.has(replacedState) + && replacedState.getValue(BeltBlock.PART) == BeltPart.PULLEY) + player.inventory.placeItemBackInInventory(world, AllBlocks.SHAFT.asStack()); + + // Eject overshooting items + if (part == BeltPart.END && inventory != null) { + List toEject = new ArrayList<>(); + for (TransportedItemStack transportedItemStack : inventory.getTransportedItems()) + if (transportedItemStack.beltPosition > beltLength - 1) + toEject.add(transportedItemStack); + toEject.forEach(inventory::eject); + toEject.forEach(inventory.getTransportedItems()::remove); + } + + // Transfer items to new controller + if (part == BeltPart.START && segmentTE != null && inventory != null) { + controllerTE.inventory = null; + segmentTE.inventory = null; + segmentTE.setController(next); + for (TransportedItemStack transportedItemStack : inventory.getTransportedItems()) { + transportedItemStack.beltPosition -= 1; + if (transportedItemStack.beltPosition <= 0) { + ItemEntity entity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + 11 / 16f, + pos.getZ() + .5f, transportedItemStack.stack); + entity.setDeltaMovement(Vector3d.ZERO); + entity.setDefaultPickUpDelay(); + entity.hurtMarked = true; + world.addFreshEntity(entity); + } else + segmentTE.getInventory() + .addItem(transportedItemStack); + } + } + + return ActionResultType.SUCCESS; + } + + BeltTileEntity segmentTE = BeltHelper.getSegmentTE(world, pos); + if (segmentTE == null) + return ActionResultType.PASS; + + // Split in half + int hitSegment = segmentTE.index; + Vector3d centerOf = VecHelper.getCenterOf(hit.getBlockPos()); + Vector3d subtract = hit.getLocation() + .subtract(centerOf); + boolean towardPositive = subtract.dot(Vector3d.atLowerCornerOf(beltVector)) > 0; + BlockPos next = !towardPositive ? pos.subtract(beltVector) : pos.offset(beltVector); + + if (hitSegment == 0 || hitSegment == 1 && !towardPositive) + return ActionResultType.FAIL; + if (hitSegment == controllerTE.beltLength - 1 || hitSegment == controllerTE.beltLength - 2 && towardPositive) + return ActionResultType.FAIL; + + // Look for shafts + if (!creative) { + int requiredShafts = 0; + if (!segmentTE.hasPulley()) + requiredShafts++; + BlockState other = world.getBlockState(next); + if (AllBlocks.BELT.has(other) && other.getValue(BeltBlock.PART) == BeltPart.MIDDLE) + requiredShafts++; + + int amountRetrieved = 0; + Search: while (true) { + for (int i = 0; i < player.inventory.getContainerSize(); ++i) { + if (amountRetrieved == requiredShafts) + break Search; + + ItemStack itemstack = player.inventory.getItem(i); + if (itemstack.isEmpty()) + continue; + int count = itemstack.getCount(); + if (AllBlocks.SHAFT.isIn(itemstack)) { + int taken = Math.min(count, requiredShafts - amountRetrieved); + if (taken == count) + player.inventory.setItem(i, ItemStack.EMPTY); + else + itemstack.shrink(taken); + amountRetrieved += taken; + } + } + + player.inventory.placeItemBackInInventory(world, AllBlocks.SHAFT.asStack(amountRetrieved)); + return ActionResultType.FAIL; + } + } + + if (!world.isClientSide) { + for (BlockPos blockPos : beltChain) { + BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + if (belt == null) + continue; + belt.detachKinetics(); + belt.invalidateItemHandler(); + belt.beltLength = 0; + } + + BeltInventory inventory = controllerTE.inventory; + KineticTileEntity.switchToBlockState(world, pos, + state.setValue(BeltBlock.PART, towardPositive ? BeltPart.END : BeltPart.START)); + KineticTileEntity.switchToBlockState(world, next, world.getBlockState(next) + .setValue(BeltBlock.PART, towardPositive ? BeltPart.START : BeltPart.END)); + world.playSound(null, pos, SoundEvents.WOOL_HIT, + player == null ? SoundCategory.BLOCKS : SoundCategory.PLAYERS, 0.5F, 2.3F); + + // Transfer items to new controller + BeltTileEntity newController = towardPositive ? BeltHelper.getSegmentTE(world, next) : segmentTE; + if (newController != null && inventory != null) { + newController.inventory = null; + newController.setController(newController.getBlockPos()); + for (Iterator iterator = inventory.getTransportedItems() + .iterator(); iterator.hasNext();) { + TransportedItemStack transportedItemStack = iterator.next(); + float newPosition = transportedItemStack.beltPosition - hitSegment - (towardPositive ? 1 : 0); + if (newPosition <= 0) + continue; + transportedItemStack.beltPosition = newPosition; + iterator.remove(); + newController.getInventory() + .addItem(transportedItemStack); + } + } + } + + return ActionResultType.SUCCESS; + } + + public static ActionResultType useConnector(BlockState state, World world, BlockPos pos, PlayerEntity player, + Hand handIn, BlockRayTraceResult hit, Feedback feedBack) { + BeltTileEntity controllerTE = BeltHelper.getControllerTE(world, pos); + if (controllerTE == null) + return ActionResultType.PASS; + + int beltLength = controllerTE.beltLength; + if (beltLength == BeltConnectorItem.maxLength()) + return ActionResultType.FAIL; + + BlockPos beltVector = new BlockPos(BeltHelper.getBeltVector(state)); + BeltPart part = state.getValue(BeltBlock.PART); + Direction facing = state.getValue(BeltBlock.HORIZONTAL_FACING); + List beltChain = BeltBlock.getBeltChain(world, controllerTE.getBlockPos()); + boolean creative = player.isCreative(); + + if (!hoveringEnd(state, hit)) + return ActionResultType.PASS; + + BlockPos next = part == BeltPart.START ? pos.subtract(beltVector) : pos.offset(beltVector); + BeltTileEntity mergedController = null; + int mergedBeltLength = 0; + + // Merge Belts / Extend at End + BlockState nextState = world.getBlockState(next); + if (!nextState.getMaterial() + .isReplaceable()) { + if (!AllBlocks.BELT.has(nextState)) + return ActionResultType.FAIL; + if (!beltStatesCompatible(state, nextState)) + return ActionResultType.FAIL; + + mergedController = BeltHelper.getControllerTE(world, next); + if (mergedController == null) + return ActionResultType.FAIL; + if (mergedController.beltLength + beltLength > BeltConnectorItem.maxLength()) + return ActionResultType.FAIL; + + mergedBeltLength = mergedController.beltLength; + + if (!world.isClientSide) { + boolean flipBelt = facing != nextState.getValue(BeltBlock.HORIZONTAL_FACING); + Optional color = controllerTE.color; + for (BlockPos blockPos : BeltBlock.getBeltChain(world, mergedController.getBlockPos())) { + BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + if (belt == null) + continue; + belt.detachKinetics(); + belt.invalidateItemHandler(); + belt.beltLength = 0; + belt.color = color; + if (flipBelt) + world.setBlock(blockPos, flipBelt(world.getBlockState(blockPos)), 3 | BlockFlags.IS_MOVING); + } + + // Reverse items + if (flipBelt && mergedController.inventory != null) { + List transportedItems = mergedController.inventory.getTransportedItems(); + for (TransportedItemStack transportedItemStack : transportedItems) { + transportedItemStack.beltPosition = mergedBeltLength - transportedItemStack.beltPosition; + transportedItemStack.prevBeltPosition = + mergedBeltLength - transportedItemStack.prevBeltPosition; + } + } + } + } + + if (!world.isClientSide) { + for (BlockPos blockPos : beltChain) { + BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + if (belt == null) + continue; + belt.detachKinetics(); + belt.invalidateItemHandler(); + belt.beltLength = 0; + } + + BeltInventory inventory = controllerTE.inventory; + KineticTileEntity.switchToBlockState(world, pos, state.setValue(BeltBlock.PART, BeltPart.MIDDLE)); + + if (mergedController == null) { + // Attach at end + world.setBlock(next, state.setValue(BeltBlock.CASING, false), 3 | BlockFlags.IS_MOVING); + BeltTileEntity segmentTE = BeltHelper.getSegmentTE(world, next); + if (segmentTE != null) + segmentTE.color = controllerTE.color; + world.playSound(null, pos, SoundEvents.WOOL_PLACE, + player == null ? SoundCategory.BLOCKS : SoundCategory.PLAYERS, 0.5F, 1F); + + // Transfer items to new controller + if (part == BeltPart.START && segmentTE != null && inventory != null) { + segmentTE.setController(next); + for (TransportedItemStack transportedItemStack : inventory.getTransportedItems()) { + transportedItemStack.beltPosition += 1; + segmentTE.getInventory() + .addItem(transportedItemStack); + } + } + + } else { + // Merge with other + BeltInventory mergedInventory = mergedController.inventory; + world.playSound(null, pos, SoundEvents.WOOL_HIT, + player == null ? SoundCategory.BLOCKS : SoundCategory.PLAYERS, 0.5F, 1.3F); + BeltTileEntity segmentTE = BeltHelper.getSegmentTE(world, next); + KineticTileEntity.switchToBlockState(world, next, + state.setValue(BeltBlock.CASING, segmentTE != null && segmentTE.casing != CasingType.NONE) + .setValue(BeltBlock.PART, BeltPart.MIDDLE)); + + if (!creative) + player.inventory.placeItemBackInInventory(world, AllBlocks.SHAFT.asStack(2)); + + // Transfer items to other controller + BlockPos search = controllerTE.getBlockPos(); + for (int i = 0; i < 10000; i++) { + BlockState blockState = world.getBlockState(search); + if (!AllBlocks.BELT.has(blockState)) + break; + if (blockState.getValue(BeltBlock.PART) != BeltPart.START) { + search = search.subtract(beltVector); + continue; + } + + BeltTileEntity newController = BeltHelper.getSegmentTE(world, search); + + if (newController != controllerTE && inventory != null) { + newController.setController(search); + controllerTE.inventory = null; + for (TransportedItemStack transportedItemStack : inventory.getTransportedItems()) { + transportedItemStack.beltPosition += mergedBeltLength; + newController.getInventory() + .addItem(transportedItemStack); + } + } + + if (newController != mergedController && mergedInventory != null) { + newController.setController(search); + mergedController.inventory = null; + for (TransportedItemStack transportedItemStack : mergedInventory.getTransportedItems()) { + if (newController == controllerTE) + transportedItemStack.beltPosition += beltLength; + newController.getInventory() + .addItem(transportedItemStack); + } + } + + break; + } + } + } + return ActionResultType.SUCCESS; + } + + static boolean beltStatesCompatible(BlockState state, BlockState nextState) { + Direction facing1 = state.getValue(BeltBlock.HORIZONTAL_FACING); + BeltSlope slope1 = state.getValue(BeltBlock.SLOPE); + Direction facing2 = nextState.getValue(BeltBlock.HORIZONTAL_FACING); + BeltSlope slope2 = nextState.getValue(BeltBlock.SLOPE); + + switch (slope1) { + case UPWARD: + if (slope2 == BeltSlope.DOWNWARD) + return facing1 == facing2.getOpposite(); + return slope2 == slope1 && facing1 == facing2; + case DOWNWARD: + if (slope2 == BeltSlope.UPWARD) + return facing1 == facing2.getOpposite(); + return slope2 == slope1 && facing1 == facing2; + default: + return slope2 == slope1 && facing2.getAxis() == facing1.getAxis(); + } + } + + static BlockState flipBelt(BlockState state) { + Direction facing = state.getValue(BeltBlock.HORIZONTAL_FACING); + BeltSlope slope = state.getValue(BeltBlock.SLOPE); + BeltPart part = state.getValue(BeltBlock.PART); + + if (slope == BeltSlope.UPWARD) + state = state.setValue(BeltBlock.SLOPE, BeltSlope.DOWNWARD); + else if (slope == BeltSlope.DOWNWARD) + state = state.setValue(BeltBlock.SLOPE, BeltSlope.UPWARD); + + if (part == BeltPart.END) + state = state.setValue(BeltBlock.PART, BeltPart.START); + else if (part == BeltPart.START) + state = state.setValue(BeltBlock.PART, BeltPart.END); + + return state.setValue(BeltBlock.HORIZONTAL_FACING, facing.getOpposite()); + } + + static boolean hoveringEnd(BlockState state, BlockRayTraceResult hit) { + BeltPart part = state.getValue(BeltBlock.PART); + if (part == BeltPart.MIDDLE || part == BeltPart.PULLEY) + return false; + + Vector3d beltVector = BeltHelper.getBeltVector(state); + Vector3d centerOf = VecHelper.getCenterOf(hit.getBlockPos()); + Vector3d subtract = hit.getLocation() + .subtract(centerOf); + + return subtract.dot(beltVector) > 0 == (part == BeltPart.END); + } + + @OnlyIn(Dist.CLIENT) + public static void tickHoveringInformation() { + Minecraft mc = Minecraft.getInstance(); + RayTraceResult target = mc.hitResult; + if (target == null || !(target instanceof BlockRayTraceResult)) + return; + + BlockRayTraceResult result = (BlockRayTraceResult) target; + ClientWorld world = mc.level; + BlockPos pos = result.getBlockPos(); + BlockState state = world.getBlockState(pos); + ItemStack held = mc.player.getItemInHand(Hand.MAIN_HAND); + ItemStack heldOffHand = mc.player.getItemInHand(Hand.OFF_HAND); + + if (mc.player.isShiftKeyDown()) + return; + if (!AllBlocks.BELT.has(state)) + return; + + Feedback feedback = new Feedback(); + + // TODO: Populate feedback in the methods for clientside + if (AllItems.WRENCH.isIn(held) || AllItems.WRENCH.isIn(heldOffHand)) + useWrench(state, world, pos, mc.player, Hand.MAIN_HAND, result, feedback); + else if (AllItems.BELT_CONNECTOR.isIn(held) || AllItems.BELT_CONNECTOR.isIn(heldOffHand)) + useConnector(state, world, pos, mc.player, Hand.MAIN_HAND, result, feedback); + else + return; + + if (feedback.langKey != null) + mc.player.displayClientMessage(Lang.translate(feedback.langKey) + .withStyle(feedback.formatting), true); + else + mc.player.displayClientMessage(new StringTextComponent(""), true); + + if (feedback.bb != null) + CreateClient.OUTLINER.chaseAABB("BeltSlicer", feedback.bb) + .lineWidth(1 / 16f) + .colored(feedback.color); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java index ba8b4a8f5..16114f955 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java @@ -8,7 +8,7 @@ public enum BeltSlope implements IStringSerializable { HORIZONTAL, UPWARD, DOWNWARD, VERTICAL, SIDEWAYS; @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } 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..ee3cd3801 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; @@ -101,12 +101,13 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList @Override public void tick() { - super.tick(); - // Init belt if (beltLength == 0) - BeltBlock.initBelt(world, pos); - if (!AllBlocks.BELT.has(world.getBlockState(pos))) + BeltBlock.initBelt(level, worldPosition); + + super.tick(); + + if (!AllBlocks.BELT.has(level.getBlockState(worldPosition))) return; initializeItemHandler(); @@ -115,7 +116,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList if (!isController()) return; - if (light == null && world.isRemote) { + if (light == null && level.isClientSide) { initializeLight(); LightUpdater.getInstance() .startListening(getBeltVolume(), this); @@ -134,7 +135,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList passengers.forEach((entity, info) -> { boolean canBeTransported = BeltMovementHandler.canBeTransported(entity); boolean leftTheBelt = - info.getTicksSinceLastCollision() > ((getBlockState().get(BeltBlock.SLOPE) != HORIZONTAL) ? 3 : 1); + info.getTicksSinceLastCollision() > ((getBlockState().getValue(BeltBlock.SLOPE) != HORIZONTAL) ? 3 : 1); if (!canBeTransported || leftTheBelt) { toRemove.add(entity); return; @@ -158,15 +159,15 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList if (!isController()) return super.makeRenderBoundingBox(); else - return super.makeRenderBoundingBox().grow(beltLength + 1); + return super.makeRenderBoundingBox().inflate(beltLength + 1); } protected void initializeItemHandler() { - if (world.isRemote || itemHandler.isPresent()) + if (level.isClientSide || itemHandler.isPresent()) return; - if (!world.isBlockPresent(controller)) + if (!level.isLoaded(controller)) return; - TileEntity te = world.getTileEntity(controller); + TileEntity te = level.getBlockEntity(controller); if (te == null || !(te instanceof BeltTileEntity)) return; BeltInventory inventory = ((BeltTileEntity) te).getInventory(); @@ -187,8 +188,8 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList } @Override - public void remove() { - super.remove(); + public void setRemoved() { + super.setRemoved(); itemHandler.invalidate(); } @@ -211,10 +212,11 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList @Override protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { + int prevBeltLength = beltLength; super.fromTag(state, compound, clientPacket); if (compound.getBoolean("IsController")) - controller = pos; + controller = worldPosition; color = compound.contains("Dye") ? Optional.of(NBTHelper.readEnum(compound, "Dye", DyeColor.class)) : Optional.empty(); @@ -223,8 +225,10 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList if (!isController()) controller = NBTUtil.readBlockPos(compound.getCompound("Controller")); trackerUpdateTag = compound; - beltLength = compound.getInt("Length"); index = compound.getInt("Index"); + beltLength = compound.getInt("Length"); + if (prevBeltLength != beltLength) + light = null; } if (isController()) @@ -240,8 +244,8 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList return; if (!isVirtual()) requestModelDataUpdate(); - if (hasWorld()) - world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 16); + if (hasLevel()) + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); } @Override @@ -260,23 +264,23 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList } else if (color.isPresent() && color.get() == colorIn) return; - for (BlockPos blockPos : BeltBlock.getBeltChain(world, getController())) { - BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + for (BlockPos blockPos : BeltBlock.getBeltChain(level, getController())) { + BeltTileEntity belt = BeltHelper.getSegmentTE(level, blockPos); if (belt == null) continue; belt.color = Optional.ofNullable(colorIn); - belt.markDirty(); + belt.setChanged(); belt.sendData(); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(belt)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(belt)); } } public BeltTileEntity getControllerTE() { if (controller == null) return null; - if (!world.isBlockPresent(controller)) + if (!level.isLoaded(controller)) return null; - TileEntity te = world.getTileEntity(controller); + TileEntity te = level.getBlockEntity(controller); if (te == null || !(te instanceof BeltTileEntity)) return null; return (BeltTileEntity) te; @@ -287,12 +291,12 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList } public BlockPos getController() { - return controller == null ? pos : controller; + return controller == null ? worldPosition : controller; } public boolean isController() { - return controller != null && pos.getX() == controller.getX() && pos.getY() == controller.getY() - && pos.getZ() == controller.getZ(); + return controller != null && worldPosition.getX() == controller.getX() && worldPosition.getY() == controller.getY() + && worldPosition.getZ() == controller.getZ(); } public float getBeltMovementSpeed() { @@ -301,7 +305,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList public float getDirectionAwareBeltMovementSpeed() { int offset = getBeltFacing().getAxisDirection() - .getOffset(); + .getStep(); if (getBeltFacing().getAxis() == Axis.X) offset *= -1; return getBeltMovementSpeed() * offset; @@ -310,7 +314,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList public boolean hasPulley() { if (!AllBlocks.BELT.has(getBlockState())) return false; - return getBlockState().get(BeltBlock.PART) != MIDDLE; + return getBlockState().getValue(BeltBlock.PART) != MIDDLE; } protected boolean isLastBelt() { @@ -318,15 +322,15 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList return false; Direction direction = getBeltFacing(); - if (getBlockState().get(BeltBlock.SLOPE) == BeltSlope.VERTICAL) + if (getBlockState().getValue(BeltBlock.SLOPE) == BeltSlope.VERTICAL) return false; - BeltPart part = getBlockState().get(BeltBlock.PART); + BeltPart part = getBlockState().getValue(BeltBlock.PART); if (part == MIDDLE) return false; boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection() - .getOffset() == 1)) ^ direction.getAxis() == Axis.X; + .getStep() == 1)) ^ direction.getAxis() == Axis.X; return part == BeltPart.START ^ movingPositively; } @@ -343,16 +347,16 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList return BlockPos.ZERO; final BlockState blockState = getBlockState(); - final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); - final BeltSlope slope = blockState.get(BeltBlock.SLOPE); - final BeltPart part = blockState.get(BeltBlock.PART); + final Direction beltFacing = blockState.getValue(BlockStateProperties.HORIZONTAL_FACING); + final BeltSlope slope = blockState.getValue(BeltBlock.SLOPE); + final BeltPart part = blockState.getValue(BeltBlock.PART); final Axis axis = beltFacing.getAxis(); - Direction movementFacing = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis); - boolean notHorizontal = blockState.get(BeltBlock.SLOPE) != HORIZONTAL; + Direction movementFacing = Direction.get(axis == Axis.X ? NEGATIVE : POSITIVE, axis); + boolean notHorizontal = blockState.getValue(BeltBlock.SLOPE) != HORIZONTAL; if (getSpeed() < 0) movementFacing = movementFacing.getOpposite(); - Vector3i movement = movementFacing.getDirectionVec(); + Vector3i movement = movementFacing.getNormal(); boolean slopeBeforeHalf = (part == BeltPart.END) == (beltFacing.getAxisDirection() == POSITIVE); boolean onSlope = notHorizontal && (part == MIDDLE || slopeBeforeHalf == firstHalf || ignoreHalves); @@ -366,12 +370,12 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList public Direction getMovementFacing() { Axis axis = getBeltFacing().getAxis(); - return Direction.getFacingFromAxisDirection(axis, + return Direction.fromAxisAndDirection(axis, getBeltMovementSpeed() < 0 ^ axis == Axis.X ? NEGATIVE : POSITIVE); } protected Direction getBeltFacing() { - return getBlockState().get(BlockStateProperties.HORIZONTAL_FACING); + return getBlockState().getValue(BlockStateProperties.HORIZONTAL_FACING); } public BeltInventory getInventory() { @@ -408,15 +412,15 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList if (casing == type) return; if (casing != CasingType.NONE) - world.playEvent(2001, pos, - Block.getStateId(casing == CasingType.ANDESITE ? AllBlocks.ANDESITE_CASING.getDefaultState() + level.levelEvent(2001, worldPosition, + Block.getId(casing == CasingType.ANDESITE ? AllBlocks.ANDESITE_CASING.getDefaultState() : AllBlocks.BRASS_CASING.getDefaultState())); casing = type; boolean shouldBlockHaveCasing = type != CasingType.NONE; BlockState blockState = getBlockState(); - if (blockState.get(BeltBlock.CASING) != shouldBlockHaveCasing) - KineticTileEntity.switchToBlockState(world, pos, blockState.with(BeltBlock.CASING, shouldBlockHaveCasing)); - markDirty(); + if (blockState.getValue(BeltBlock.CASING) != shouldBlockHaveCasing) + KineticTileEntity.switchToBlockState(level, worldPosition, blockState.setValue(BeltBlock.CASING, shouldBlockHaveCasing)); + setChanged(); sendData(); } @@ -424,8 +428,8 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList if (getSpeed() == 0) return false; BlockState state = getBlockState(); - if (state.contains(BeltBlock.SLOPE) - && (state.get(BeltBlock.SLOPE) == BeltSlope.SIDEWAYS || state.get(BeltBlock.SLOPE) == BeltSlope.VERTICAL)) + if (state.hasProperty(BeltBlock.SLOPE) + && (state.getValue(BeltBlock.SLOPE) == BeltSlope.SIDEWAYS || state.getValue(BeltBlock.SLOPE) == BeltSlope.VERTICAL)) return false; return getMovementFacing() != side.getOpposite(); } @@ -441,7 +445,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList if (nextInventory == null) return inserted; - TileEntity teAbove = world.getTileEntity(pos.up()); + TileEntity teAbove = level.getBlockEntity(worldPosition.above()); if (teAbove instanceof BrassTunnelTileEntity) { BrassTunnelTileEntity tunnelTE = (BrassTunnelTileEntity) teAbove; if (tunnelTE.hasDistributionBehaviour()) { @@ -475,7 +479,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList .isVertical()) { if (movementFacing != side) { transportedStack.sideOffset = side.getAxisDirection() - .getOffset() * .35f; + .getStep() * .35f; if (side.getAxis() == Axis.X) transportedStack.sideOffset *= -1; } else @@ -490,7 +494,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList BeltTunnelInteractionHandler.flapTunnel(nextInventory, index, side.getOpposite(), true); nextInventory.addItem(transportedStack); - nextBeltController.markDirty(); + nextBeltController.setChanged(); nextBeltController.sendData(); return empty; } @@ -505,8 +509,8 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList @Override protected boolean canPropagateDiagonally(IRotate block, BlockState state) { - return state.contains(BeltBlock.SLOPE) - && (state.get(BeltBlock.SLOPE) == BeltSlope.UPWARD || state.get(BeltBlock.SLOPE) == BeltSlope.DOWNWARD); + return state.hasProperty(BeltBlock.SLOPE) + && (state.getValue(BeltBlock.SLOPE) == BeltSlope.UPWARD || state.getValue(BeltBlock.SLOPE) == BeltSlope.DOWNWARD); } @Override @@ -517,19 +521,24 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList return 0; } + public void invalidateItemHandler() { + itemHandler.invalidate(); + } + @Override - public boolean shouldRenderAsTE() { - if (world == null) + public boolean shouldRenderNormally() { + if (level == null) return isController(); BlockState state = getBlockState(); - return state != null && state.contains(BeltBlock.PART) && state.get(BeltBlock.PART) == BeltPart.START; + return state != null && state.hasProperty(BeltBlock.PART) && state.getValue(BeltBlock.PART) == BeltPart.START; } @Override public boolean onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed) { - if (this.removed) { + if (this.remove) return true; - } + if (this.level == null || this.light == null) + return false; GridAlignedBB beltVolume = getBeltVolume(); @@ -547,7 +556,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList private GridAlignedBB getBeltVolume() { BlockPos endPos = BeltHelper.getPositionForOffset(this, beltLength - 1); - GridAlignedBB bb = GridAlignedBB.from(pos, endPos); + GridAlignedBB bb = GridAlignedBB.from(worldPosition, endPos); bb.fixMinMax(); return bb; } @@ -556,40 +565,40 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList if (beltLength > 0) { light = new byte[beltLength * 2]; - Vector3i vec = getBeltFacing().getDirectionVec(); - BeltSlope slope = getBlockState().get(BeltBlock.SLOPE); + Vector3i vec = getBeltFacing().getNormal(); + BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; BlockPos.Mutable pos = new BlockPos.Mutable(controller.getX(), controller.getY(), controller.getZ()); for (int i = 0; i < beltLength * 2; i += 2) { - light[i] = (byte) world.getLightLevel(LightType.BLOCK, pos); - light[i + 1] = (byte) world.getLightLevel(LightType.SKY, pos); + light[i] = (byte) level.getBrightness(LightType.BLOCK, pos); + light[i + 1] = (byte) level.getBrightness(LightType.SKY, pos); pos.move(vec.getX(), verticality, vec.getZ()); } } } private void updateBlockLight() { - Vector3i vec = getBeltFacing().getDirectionVec(); - BeltSlope slope = getBlockState().get(BeltBlock.SLOPE); + Vector3i vec = getBeltFacing().getNormal(); + BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; BlockPos.Mutable pos = new BlockPos.Mutable(controller.getX(), controller.getY(), controller.getZ()); for (int i = 0; i < beltLength * 2; i += 2) { - light[i] = (byte) world.getLightLevel(LightType.BLOCK, pos); + light[i] = (byte) level.getBrightness(LightType.BLOCK, pos); pos.move(vec.getX(), verticality, vec.getZ()); } } private void updateSkyLight() { - Vector3i vec = getBeltFacing().getDirectionVec(); - BeltSlope slope = getBlockState().get(BeltBlock.SLOPE); + Vector3i vec = getBeltFacing().getNormal(); + BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; BlockPos.Mutable pos = new BlockPos.Mutable(controller.getX(), controller.getY(), controller.getZ()); for (int i = 1; i < beltLength * 2; i += 2) { - light[i] = (byte) world.getLightLevel(LightType.SKY, pos); + light[i] = (byte) level.getBrightness(LightType.SKY, pos); pos.move(vec.getX(), verticality, vec.getZ()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorHandler.java index 420cf78e5..d6c8d2719 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorHandler.java @@ -29,15 +29,15 @@ public class BeltConnectorHandler { public static void tick() { PlayerEntity player = Minecraft.getInstance().player; - World world = Minecraft.getInstance().world; + World world = Minecraft.getInstance().level; if (player == null || world == null) return; - if (Minecraft.getInstance().currentScreen != null) + if (Minecraft.getInstance().screen != null) return; for (Hand hand : Hand.values()) { - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getItemInHand(hand); if (!AllItems.BELT_CONNECTOR.isIn(heldItem)) continue; @@ -50,12 +50,12 @@ public class BeltConnectorHandler { BlockPos first = NBTUtil.readBlockPos(tag.getCompound("FirstPulley")); - if (!world.getBlockState(first).contains(BlockStateProperties.AXIS)) + if (!world.getBlockState(first).hasProperty(BlockStateProperties.AXIS)) continue; Axis axis = world.getBlockState(first) - .get(BlockStateProperties.AXIS); + .getValue(BlockStateProperties.AXIS); - RayTraceResult rayTrace = Minecraft.getInstance().objectMouseOver; + RayTraceResult rayTrace = Minecraft.getInstance().hitResult; if (rayTrace == null || !(rayTrace instanceof BlockRayTraceResult)) { if (r.nextInt(50) == 0) { world.addParticle(new RedstoneParticleData(.3f, .9f, .5f, 1), @@ -65,25 +65,25 @@ public class BeltConnectorHandler { return; } - BlockPos selected = ((BlockRayTraceResult) rayTrace).getPos(); + BlockPos selected = ((BlockRayTraceResult) rayTrace).getBlockPos(); if (world.getBlockState(selected) .getMaterial() .isReplaceable()) return; if (!ShaftBlock.isShaft(world.getBlockState(selected))) - selected = selected.offset(((BlockRayTraceResult) rayTrace).getFace()); - if (!selected.withinDistance(first, AllConfigs.SERVER.kinetics.maxBeltLength.get())) + selected = selected.relative(((BlockRayTraceResult) rayTrace).getDirection()); + if (!selected.closerThan(first, AllConfigs.SERVER.kinetics.maxBeltLength.get())) return; boolean canConnect = BeltConnectorItem.validateAxis(world, selected) && BeltConnectorItem.canConnect(world, first, selected); - Vector3d start = Vector3d.of(first); - Vector3d end = Vector3d.of(selected); + Vector3d start = Vector3d.atLowerCornerOf(first); + Vector3d end = Vector3d.atLowerCornerOf(selected); Vector3d actualDiff = end.subtract(start); - end = end.subtract(axis.getCoordinate(actualDiff.x, 0, 0), axis.getCoordinate(0, actualDiff.y, 0), - axis.getCoordinate(0, 0, actualDiff.z)); + end = end.subtract(axis.choose(actualDiff.x, 0, 0), axis.choose(0, actualDiff.y, 0), + axis.choose(0, 0, actualDiff.z)); Vector3d diff = end.subtract(start); double x = Math.abs(diff.x); @@ -98,7 +98,7 @@ public class BeltConnectorHandler { for (int i = -1; i <= 1; i++) for (int j = -1; j <= 1; j++) for (int k = -1; k <= 1; k++) { - if (axis.getCoordinate(i, j, k) != 0) + if (axis.choose(i, j, k) != 0) continue; if (axis == Axis.Y && i != 0 && k != 0) continue; 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..45507b9fd 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 @@ -15,6 +15,7 @@ import com.simibubi.create.content.contraptions.relays.elementary.AbstractShaftB import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; @@ -31,6 +32,8 @@ import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.NonNullList; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -41,44 +44,44 @@ public class BeltConnectorItem extends BlockItem { } @Override - public String getTranslationKey() { - return getDefaultTranslationKey(); + public String getDescriptionId() { + return getOrCreateDescriptionId(); } @Override - public void fillItemGroup(ItemGroup p_150895_1_, NonNullList p_150895_2_) { - if (p_150895_1_ == Create.baseCreativeTab) + public void fillItemCategory(ItemGroup p_150895_1_, NonNullList p_150895_2_) { + if (p_150895_1_ == Create.BASE_CREATIVE_TAB) return; - super.fillItemGroup(p_150895_1_, p_150895_2_); + super.fillItemCategory(p_150895_1_, p_150895_2_); } @Nonnull @Override - public ActionResultType onItemUse(ItemUseContext context) { + public ActionResultType useOn(ItemUseContext context) { PlayerEntity playerEntity = context.getPlayer(); - if (playerEntity != null && playerEntity.isSneaking()) { - context.getItem() + if (playerEntity != null && playerEntity.isShiftKeyDown()) { + context.getItemInHand() .setTag(null); return ActionResultType.SUCCESS; } - World world = context.getWorld(); - BlockPos pos = context.getPos(); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); boolean validAxis = validateAxis(world, pos); - if (world.isRemote) + if (world.isClientSide) return validAxis ? ActionResultType.SUCCESS : ActionResultType.FAIL; - CompoundNBT tag = context.getItem() + CompoundNBT tag = context.getItemInHand() .getOrCreateTag(); BlockPos firstPulley = null; // Remove first if no longer existant or valid if (tag.contains("FirstPulley")) { firstPulley = NBTUtil.readBlockPos(tag.getCompound("FirstPulley")); - if (!validateAxis(world, firstPulley) || !firstPulley.withinDistance(pos, maxLength() * 2)) { + if (!validateAxis(world, firstPulley) || !firstPulley.closerThan(pos, maxLength() * 2)) { tag.remove("FirstPulley"); - context.getItem() + context.getItemInHand() .setTag(tag); } } @@ -95,37 +98,39 @@ public class BeltConnectorItem extends BlockItem { createBelts(world, firstPulley, pos); AllTriggers.triggerFor(AllTriggers.CONNECT_BELT, playerEntity); if (!playerEntity.isCreative()) - context.getItem() + context.getItemInHand() .shrink(1); } - if (!context.getItem() + if (!context.getItemInHand() .isEmpty()) { - context.getItem() + context.getItemInHand() .setTag(null); - playerEntity.getCooldownTracker() - .setCooldown(this, 5); + playerEntity.getCooldowns() + .addCooldown(this, 5); } return ActionResultType.SUCCESS; } tag.put("FirstPulley", NBTUtil.writeBlockPos(pos)); - context.getItem() + context.getItemInHand() .setTag(tag); - playerEntity.getCooldownTracker() - .setCooldown(this, 5); + playerEntity.getCooldowns() + .addCooldown(this, 5); return ActionResultType.SUCCESS; } public static void createBelts(World world, BlockPos start, BlockPos end) { + world.playSound(null, new BlockPos(VecHelper.getCenterOf(start.offset(end)) + .scale(.5f)), SoundEvents.WOOL_PLACE, SoundCategory.BLOCKS, 0.5F, 1F); BeltSlope slope = getSlopeBetween(start, end); Direction facing = getFacingFromTo(start, end); BlockPos diff = end.subtract(start); if (diff.getX() == diff.getZ()) - facing = Direction.getFacingFromAxis(facing.getAxisDirection(), world.getBlockState(start) - .get(BlockStateProperties.AXIS) == Axis.X ? Axis.Z : Axis.X); + facing = Direction.get(facing.getAxisDirection(), world.getBlockState(start) + .getValue(BlockStateProperties.AXIS) == Axis.X ? Axis.Z : Axis.X); List beltsToCreate = getBeltChainBetween(start, end, slope, facing); BlockState beltBlock = AllBlocks.BELT.getDefaultState(); @@ -136,11 +141,11 @@ public class BeltConnectorItem extends BlockItem { boolean pulley = ShaftBlock.isShaft(shaftState); if (part == BeltPart.MIDDLE && pulley) part = BeltPart.PULLEY; - if (pulley && shaftState.get(AbstractShaftBlock.AXIS) == Axis.Y) + if (pulley && shaftState.getValue(AbstractShaftBlock.AXIS) == Axis.Y) slope = BeltSlope.SIDEWAYS; - world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope) - .with(BeltBlock.PART, part) - .with(BeltBlock.HORIZONTAL_FACING, facing), 3); + KineticTileEntity.switchToBlockState(world, pos, beltBlock.setValue(BeltBlock.SLOPE, slope) + .setValue(BeltBlock.PART, part) + .setValue(BeltBlock.HORIZONTAL_FACING, facing)); } } @@ -152,10 +157,10 @@ public class BeltConnectorItem extends BlockItem { if (diff.getX() == 0 && diff.getZ() == 0) axisDirection = diff.getY() > 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE; else - axisDirection = beltAxis.getCoordinate(diff.getX(), 0, diff.getZ()) > 0 ? AxisDirection.POSITIVE - : AxisDirection.NEGATIVE; + axisDirection = + beltAxis.choose(diff.getX(), 0, diff.getZ()) > 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE; - return Direction.getFacingFromAxis(axisDirection, beltAxis); + return Direction.get(axisDirection, beltAxis); } private static BeltSlope getSlopeBetween(BlockPos start, BlockPos end) { @@ -169,7 +174,8 @@ public class BeltConnectorItem extends BlockItem { return BeltSlope.HORIZONTAL; } - private static List getBeltChainBetween(BlockPos start, BlockPos end, BeltSlope slope, Direction direction) { + private static List getBeltChainBetween(BlockPos start, BlockPos end, BeltSlope slope, + Direction direction) { List positions = new LinkedList<>(); int limit = 1000; BlockPos current = start; @@ -178,13 +184,13 @@ public class BeltConnectorItem extends BlockItem { positions.add(current); if (slope == BeltSlope.VERTICAL) { - current = current.up(direction.getAxisDirection() == AxisDirection.POSITIVE ? 1 : -1); + current = current.above(direction.getAxisDirection() == AxisDirection.POSITIVE ? 1 : -1); continue; } - current = current.offset(direction); + current = current.relative(direction); if (slope != BeltSlope.HORIZONTAL) - current = current.up(slope == BeltSlope.UPWARD ? 1 : -1); + current = current.above(slope == BeltSlope.UPWARD ? 1 : -1); } while (!current.equals(end) && limit-- > 0); @@ -197,12 +203,12 @@ public class BeltConnectorItem extends BlockItem { return false; if (!world.isAreaLoaded(second, 1)) return false; - if (!second.withinDistance(first, maxLength())) + if (!second.closerThan(first, maxLength())) return false; BlockPos diff = second.subtract(first); Axis shaftAxis = world.getBlockState(first) - .get(BlockStateProperties.AXIS); + .getValue(BlockStateProperties.AXIS); int x = diff.getX(); int y = diff.getY(); @@ -210,18 +216,18 @@ public class BeltConnectorItem extends BlockItem { int sames = ((Math.abs(x) == Math.abs(y)) ? 1 : 0) + ((Math.abs(y) == Math.abs(z)) ? 1 : 0) + ((Math.abs(z) == Math.abs(x)) ? 1 : 0); - if (shaftAxis.getCoordinate(x, y, z) != 0) + if (shaftAxis.choose(x, y, z) != 0) return false; if (sames != 1) return false; if (shaftAxis != world.getBlockState(second) - .get(BlockStateProperties.AXIS)) + .getValue(BlockStateProperties.AXIS)) return false; if (shaftAxis == Axis.Y && x != 0 && z != 0) return false; - TileEntity tileEntity = world.getTileEntity(first); - TileEntity tileEntity2 = world.getTileEntity(second); + TileEntity tileEntity = world.getBlockEntity(first); + TileEntity tileEntity2 = world.getBlockEntity(second); if (!(tileEntity instanceof KineticTileEntity)) return false; @@ -235,10 +241,10 @@ public class BeltConnectorItem extends BlockItem { BlockPos step = new BlockPos(Math.signum(diff.getX()), Math.signum(diff.getY()), Math.signum(diff.getZ())); int limit = 1000; - for (BlockPos currentPos = first.add(step); !currentPos.equals(second) && limit-- > 0; currentPos = - currentPos.add(step)) { + for (BlockPos currentPos = first.offset(step); !currentPos.equals(second) && limit-- > 0; currentPos = + currentPos.offset(step)) { BlockState blockState = world.getBlockState(currentPos); - if (ShaftBlock.isShaft(blockState) && blockState.get(AbstractShaftBlock.AXIS) == shaftAxis) + if (ShaftBlock.isShaft(blockState) && blockState.getValue(AbstractShaftBlock.AXIS) == shaftAxis) continue; if (!blockState.getMaterial() .isReplaceable()) @@ -249,7 +255,7 @@ public class BeltConnectorItem extends BlockItem { } - protected static Integer maxLength() { + public static Integer maxLength() { return AllConfigs.SERVER.kinetics.maxBeltLength.get(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java index 39400e412..8399a5788 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java @@ -26,12 +26,12 @@ public class BeltCrusherInteractionHandler { for (int segment = firstUpcomingSegment; beltMovementPositive ? segment <= nextOffset : segment + 1 >= nextOffset; segment += step) { BlockPos crusherPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment) - .up(); - World world = beltInventory.belt.getWorld(); + .above(); + World world = beltInventory.belt.getLevel(); BlockState crusherState = world.getBlockState(crusherPos); if (!(crusherState.getBlock() instanceof CrushingWheelControllerBlock)) continue; - Direction crusherFacing = crusherState.get(CrushingWheelControllerBlock.FACING); + Direction crusherFacing = crusherState.getValue(CrushingWheelControllerBlock.FACING); Direction movementFacing = beltInventory.belt.getMovementFacing(); if (crusherFacing != movementFacing) continue; @@ -46,7 +46,7 @@ public class BeltCrusherInteractionHandler { return false; currentItem.beltPosition = crusherEntry; - TileEntity te = world.getTileEntity(crusherPos); + TileEntity te = world.getBlockEntity(crusherPos); if (!(te instanceof CrushingWheelControllerTileEntity)) return true; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java index 8ea4af97f..b2c504191 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java @@ -28,21 +28,21 @@ public class BeltFunnelInteractionHandler { for (int segment = firstUpcomingSegment; beltMovementPositive ? segment <= nextOffset : segment + 1 >= nextOffset; segment += step) { BlockPos funnelPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment) - .up(); - World world = beltInventory.belt.getWorld(); + .above(); + World world = beltInventory.belt.getLevel(); BlockState funnelState = world.getBlockState(funnelPos); if (!(funnelState.getBlock() instanceof BeltFunnelBlock)) continue; - Direction funnelFacing = funnelState.get(BeltFunnelBlock.HORIZONTAL_FACING); + Direction funnelFacing = funnelState.getValue(BeltFunnelBlock.HORIZONTAL_FACING); Direction movementFacing = beltInventory.belt.getMovementFacing(); boolean blocking = funnelFacing == movementFacing.getOpposite(); if (funnelFacing == movementFacing) continue; - if (funnelState.get(BeltFunnelBlock.SHAPE) == Shape.PUSHING) + if (funnelState.getValue(BeltFunnelBlock.SHAPE) == Shape.PUSHING) continue; float funnelEntry = segment + .5f; - if (funnelState.get(BeltFunnelBlock.SHAPE) == Shape.EXTENDED) + if (funnelState.getValue(BeltFunnelBlock.SHAPE) == Shape.EXTENDED) funnelEntry += .499f * (beltMovementPositive ? -1 : 1); boolean hasCrossed = nextOffset > funnelEntry && beltMovementPositive @@ -52,13 +52,13 @@ public class BeltFunnelInteractionHandler { if (blocking) currentItem.beltPosition = funnelEntry; - if (world.isRemote || funnelState.method_28500(BeltFunnelBlock.POWERED).orElse(false)) + if (world.isClientSide || funnelState.getOptionalValue(BeltFunnelBlock.POWERED).orElse(false)) if (blocking) return true; else continue; - TileEntity te = world.getTileEntity(funnelPos); + TileEntity te = world.getBlockEntity(funnelPos); if (!(te instanceof FunnelTileEntity)) return true; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java index d445f9567..a7e684e09 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java @@ -55,7 +55,7 @@ public class BeltInventory { toInsert.clear(); items.removeAll(toRemove); toRemove.clear(); - belt.markDirty(); + belt.setChanged(); belt.sendData(); } @@ -66,7 +66,7 @@ public class BeltInventory { if (beltMovementPositive != belt.getDirectionAwareBeltMovementSpeed() > 0) { beltMovementPositive = !beltMovementPositive; Collections.reverse(items); - belt.markDirty(); + belt.setChanged(); belt.sendData(); } @@ -79,10 +79,10 @@ public class BeltInventory { float beltSpeed = belt.getDirectionAwareBeltMovementSpeed(); Direction movementFacing = belt.getMovementFacing(); boolean horizontal = belt.getBlockState() - .get(BeltBlock.SLOPE) == BeltSlope.HORIZONTAL; + .getValue(BeltBlock.SLOPE) == BeltSlope.HORIZONTAL; float spacing = 1; - World world = belt.getWorld(); - boolean onClient = world.isRemote && !belt.isVirtual(); + World world = belt.getLevel(); + boolean onClient = world.isClientSide && !belt.isVirtual(); // resolve ending only when items will reach it this tick Ending ending = Ending.UNRESOLVED; @@ -105,7 +105,7 @@ public class BeltInventory { movement *= ServerSpeedProvider.get(); // Don't move if held by processing (client) - if (world.isRemote && currentItem.locked) + if (world.isClientSide && currentItem.locked) continue; // Don't move if held by external components @@ -256,7 +256,7 @@ public class BeltInventory { continue; if (stackHandlerBehaviour == null) continue; - if (BeltProcessingBehaviour.isBlocked(belt.getWorld(), BeltHelper.getPositionForOffset(belt, segment))) + if (BeltProcessingBehaviour.isBlocked(belt.getLevel(), BeltHelper.getPositionForOffset(belt, segment))) continue; ProcessingResult result = processingBehaviour.handleReceivedItem(currentItem, stackHandlerBehaviour); @@ -276,12 +276,12 @@ public class BeltInventory { } protected BeltProcessingBehaviour getBeltProcessingAtSegment(int segment) { - return TileEntityBehaviour.get(belt.getWorld(), BeltHelper.getPositionForOffset(belt, segment) - .up(2), BeltProcessingBehaviour.TYPE); + return TileEntityBehaviour.get(belt.getLevel(), BeltHelper.getPositionForOffset(belt, segment) + .above(2), BeltProcessingBehaviour.TYPE); } protected TransportedItemStackHandlerBehaviour getTransportedItemStackHandlerAtSegment(int segment) { - return TileEntityBehaviour.get(belt.getWorld(), BeltHelper.getPositionForOffset(belt, segment), + return TileEntityBehaviour.get(belt.getLevel(), BeltHelper.getPositionForOffset(belt, segment), TransportedItemStackHandlerBehaviour.TYPE); } @@ -296,7 +296,7 @@ public class BeltInventory { } private Ending resolveEnding() { - World world = belt.getWorld(); + World world = belt.getLevel(); BlockPos nextPosition = BeltHelper.getPositionForOffset(belt, beltMovementPositive ? belt.beltLength : -1); // if (AllBlocks.BRASS_BELT_FUNNEL.has(world.getBlockState(lastPosition.up()))) @@ -397,15 +397,15 @@ public class BeltInventory { ItemStack ejected = stack.stack; Vector3d outPos = BeltHelper.getVectorForOffset(belt, stack.beltPosition); float movementSpeed = Math.max(Math.abs(belt.getBeltMovementSpeed()), 1 / 8f); - Vector3d outMotion = Vector3d.of(belt.getBeltChainDirection()).scale(movementSpeed) + Vector3d outMotion = Vector3d.atLowerCornerOf(belt.getBeltChainDirection()).scale(movementSpeed) .add(0, 1 / 8f, 0); outPos = outPos.add(outMotion.normalize().scale(0.001)); - ItemEntity entity = new ItemEntity(belt.getWorld(), outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); - entity.setMotion(outMotion); - entity.setDefaultPickupDelay(); - entity.velocityChanged = true; - belt.getWorld() - .addEntity(entity); + ItemEntity entity = new ItemEntity(belt.getLevel(), outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); + entity.setDeltaMovement(outMotion); + entity.setDefaultPickUpDelay(); + entity.hurtMarked = true; + belt.getLevel() + .addFreshEntity(entity); } public void ejectAll() { @@ -434,7 +434,7 @@ public class BeltInventory { toRemove.add(transported); } if (dirty) { - belt.markDirty(); + belt.setChanged(); belt.sendData(); } } 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..6983ce99b 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 @@ -43,7 +43,7 @@ public class BeltMovementHandler { public void refresh(BlockPos collision, BlockState belt) { ticksSinceLastCollision = 0; - lastCollidedPos = new BlockPos(collision).toImmutable(); + lastCollidedPos = new BlockPos(collision).immutable(); lastCollidedState = belt; } @@ -60,19 +60,19 @@ public class BeltMovementHandler { public static boolean canBeTransported(Entity entity) { if (!entity.isAlive()) return false; - if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isSneaking()) + if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isShiftKeyDown()) return false; return true; } public static void transportEntity(BeltTileEntity beltTe, Entity entityIn, TransportedEntityInfo info) { BlockPos pos = info.lastCollidedPos; - World world = beltTe.getWorld(); - TileEntity te = world.getTileEntity(pos); - TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getBlockPos()); + World world = beltTe.getLevel(); + TileEntity te = world.getBlockEntity(pos); + TileEntity tileEntityBelowPassenger = world.getBlockEntity(entityIn.blockPosition()); BlockState blockState = info.lastCollidedState; Direction movementFacing = - Direction.getFacingFromAxisDirection(blockState.get(BlockStateProperties.HORIZONTAL_FACING) + Direction.fromAxisAndDirection(blockState.getValue(BlockStateProperties.HORIZONTAL_FACING) .getAxis(), beltTe.getSpeed() < 0 ? POSITIVE : NEGATIVE); boolean collidedWithBelt = te instanceof BeltTileEntity; @@ -85,7 +85,7 @@ public class BeltMovementHandler { // Too slow boolean notHorizontal = beltTe.getBlockState() - .get(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL; + .getValue(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL; if (Math.abs(beltTe.getSpeed()) < 1) return; @@ -95,20 +95,19 @@ public class BeltMovementHandler { // Lock entities in place boolean isPlayer = entityIn instanceof PlayerEntity; - if (entityIn instanceof LivingEntity && !isPlayer) { - ((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 10, 1, false, false)); - } + if (entityIn instanceof LivingEntity && !isPlayer) + ((LivingEntity) entityIn).addEffect(new EffectInstance(Effects.MOVEMENT_SLOWDOWN, 10, 1, false, false)); - final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); - final BeltSlope slope = blockState.get(BeltBlock.SLOPE); + final Direction beltFacing = blockState.getValue(BlockStateProperties.HORIZONTAL_FACING); + final BeltSlope slope = blockState.getValue(BeltBlock.SLOPE); final Axis axis = beltFacing.getAxis(); float movementSpeed = beltTe.getBeltMovementSpeed(); - final Direction movementDirection = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis); + final Direction movementDirection = Direction.get(axis == Axis.X ? NEGATIVE : POSITIVE, axis); - Vector3i centeringDirection = Direction.getFacingFromAxis(POSITIVE, beltFacing.rotateY() + Vector3i centeringDirection = Direction.get(POSITIVE, beltFacing.getClockWise() .getAxis()) - .getDirectionVec(); - Vector3d movement = Vector3d.of(movementDirection.getDirectionVec()) + .getNormal(); + Vector3d movement = Vector3d.atLowerCornerOf(movementDirection.getNormal()) .scale(movementSpeed); double diffCenter = @@ -116,7 +115,7 @@ public class BeltMovementHandler { if (Math.abs(diffCenter) > 48 / 64f) return; - BeltPart part = blockState.get(BeltBlock.PART); + BeltPart part = blockState.getValue(BeltBlock.PART); float top = 13 / 16f; boolean onSlope = notHorizontal && (part == BeltPart.MIDDLE || part == BeltPart.PULLEY || part == (slope == BeltSlope.UPWARD ? BeltPart.END : BeltPart.START) && entityIn.getY() - pos.getY() < top @@ -133,17 +132,19 @@ public class BeltMovementHandler { } if (movingUp) - movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0); + movement = movement.add(0, Math.abs(axis.choose(movement.x, movement.y, movement.z)), 0); if (movingDown) - movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0); + movement = movement.add(0, -Math.abs(axis.choose(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; + Vector3d centering = Vector3d.atLowerCornerOf(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4); - if (!isPlayer) { + if (!(entityIn instanceof LivingEntity) + || ((LivingEntity) entityIn).zza == 0 && ((LivingEntity) entityIn).xxa == 0) movement = movement.add(centering); - entityIn.stepHeight = 1; - } + + float step = entityIn.maxUpStep; + if (!isPlayer) + entityIn.maxUpStep = 1; // Entity Collisions if (Math.abs(movementSpeed) < .5f) { @@ -151,12 +152,12 @@ public class BeltMovementHandler { .scale(0.5); AxisAlignedBB bb = entityIn.getBoundingBox(); AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); - checkBB = checkBB.offset(checkDistance) - .grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)); - List list = world.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB); + checkBB = checkBB.move(checkDistance) + .inflate(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)); + List list = world.getEntities(entityIn, checkBB); list.removeIf(e -> shouldIgnoreBlocking(entityIn, e)); if (!list.isEmpty()) { - entityIn.setMotion(0, 0, 0); + entityIn.setDeltaMovement(0, 0, 0); info.ticksSinceLastCollision--; return; } @@ -168,27 +169,30 @@ public class BeltMovementHandler { float minVelocity = .13f; float yMovement = (float) -(Math.max(Math.abs(movement.y), minVelocity)); entityIn.move(SELF, new Vector3d(0, yMovement, 0)); - entityIn.move(SELF, movement.mul(1, 0, 1)); + entityIn.move(SELF, movement.multiply(1, 0, 1)); } else if (movingDown) { - entityIn.move(SELF, movement.mul(1, 0, 1)); - entityIn.move(SELF, movement.mul(0, 1, 0)); + entityIn.move(SELF, movement.multiply(1, 0, 1)); + entityIn.move(SELF, movement.multiply(0, 1, 0)); } else { entityIn.move(SELF, movement); } + + entityIn.onGround = true; if (!isPlayer) - entityIn.stepHeight = step; + entityIn.maxUpStep = step; - boolean movedPastEndingSlope = onSlope && (AllBlocks.BELT.has(world.getBlockState(entityIn.getBlockPos())) - || AllBlocks.BELT.has(world.getBlockState(entityIn.getBlockPos() - .down()))); + boolean movedPastEndingSlope = onSlope && (AllBlocks.BELT.has(world.getBlockState(entityIn.blockPosition())) + || AllBlocks.BELT.has(world.getBlockState(entityIn.blockPosition() + .below()))); if (movedPastEndingSlope && !movingDown && Math.abs(movementSpeed) > 0) - entityIn.setPosition(entityIn.getX(), entityIn.getY() + movement.y, entityIn.getZ()); + entityIn.setPos(entityIn.getX(), entityIn.getY() + movement.y, entityIn.getZ()); if (movedPastEndingSlope) { - entityIn.setMotion(movement); - entityIn.velocityChanged = true; + entityIn.setDeltaMovement(movement); + entityIn.hurtMarked = 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..4dee31a2e 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 @@ -40,11 +40,11 @@ public class BeltTunnelInteractionHandler { return true; } - World world = beltInventory.belt.getWorld(); - boolean onServer = !world.isRemote || beltInventory.belt.isVirtual(); + World world = beltInventory.belt.getLevel(); + boolean onServer = !world.isClientSide || 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()) { @@ -54,7 +54,7 @@ public class BeltTunnelInteractionHandler { brassTunnel.setStackToDistribute(current.stack); current.stack = ItemStack.EMPTY; beltInventory.belt.sendData(); - beltInventory.belt.markDirty(); + beltInventory.belt.setChanged(); } removed = true; } @@ -62,17 +62,17 @@ public class BeltTunnelInteractionHandler { BlockState blockState = nextTunnel.getBlockState(); if (current.stack.getCount() > 1 && AllBlocks.ANDESITE_TUNNEL.has(blockState) && BeltTunnelBlock.isJunction(blockState) - && movementFacing.getAxis() == blockState.get(BeltTunnelBlock.HORIZONTAL_AXIS)) { + && movementFacing.getAxis() == blockState.getValue(BeltTunnelBlock.HORIZONTAL_AXIS)) { for (Direction d : Iterate.horizontalDirections) { - if (d.getAxis() == blockState.get(BeltTunnelBlock.HORIZONTAL_AXIS)) + if (d.getAxis() == blockState.getValue(BeltTunnelBlock.HORIZONTAL_AXIS)) continue; if (!nextTunnel.flaps.containsKey(d)) continue; - BlockPos outpos = nextTunnel.getPos() - .down() - .offset(d); - if (!world.isBlockPresent(outpos)) + BlockPos outpos = nextTunnel.getBlockPos() + .below() + .relative(d); + if (!world.isLoaded(outpos)) return true; DirectBeltInputBehaviour behaviour = TileEntityBehaviour.get(world, outpos, DirectBeltInputBehaviour.TYPE); @@ -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) @@ -110,13 +110,13 @@ public class BeltTunnelInteractionHandler { Direction movementDirection) { BeltTileEntity belt = beltInventory.belt; BlockPos pos = BeltHelper.getPositionForOffset(belt, offset) - .up(); - if (!(belt.getWorld() + .above(); + if (!(belt.getLevel() .getBlockState(pos) .getBlock() instanceof BrassTunnelBlock)) return false; - TileEntity te = belt.getWorld() - .getTileEntity(pos); + TileEntity te = belt.getLevel() + .getBlockEntity(pos); if (te == null || !(te instanceof BrassTunnelTileEntity)) return false; BrassTunnelTileEntity tunnel = (BrassTunnelTileEntity) te; @@ -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) + .getValue(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL) return null; - BlockPos pos = BeltHelper.getPositionForOffset(belt, offset) - .up(); - if (!(belt.getWorld() - .getBlockState(pos) - .getBlock() instanceof BeltTunnelBlock)) + return getTunnelOnPosition(belt.getLevel(), BeltHelper.getPositionForOffset(belt, offset)); + } + + public static BeltTunnelTileEntity getTunnelOnPosition(World world, BlockPos pos) { + pos = pos.above(); + if (!(world.getBlockState(pos).getBlock() instanceof BeltTunnelBlock)) return null; - TileEntity te = belt.getWorld() - .getTileEntity(pos); + TileEntity te = world.getBlockEntity(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/ItemHandlerBeltSegment.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/ItemHandlerBeltSegment.java index 896051089..c29866810 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/ItemHandlerBeltSegment.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/ItemHandlerBeltSegment.java @@ -35,7 +35,7 @@ public class ItemHandlerBeltSegment implements IItemHandler { newStack.beltPosition = offset + .5f + (beltInventory.beltMovementPositive ? -1 : 1) / 16f; newStack.prevBeltPosition = newStack.beltPosition; this.beltInventory.addItem(newStack); - this.beltInventory.belt.markDirty(); + this.beltInventory.belt.setChanged(); this.beltInventory.belt.sendData(); } return ItemStack.EMPTY; @@ -52,7 +52,7 @@ public class ItemHandlerBeltSegment implements IItemHandler { amount = Math.min(amount, transported.stack.getCount()); ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount); if (!simulate) { - this.beltInventory.belt.markDirty(); + this.beltInventory.belt.setChanged(); this.beltInventory.belt.sendData(); } return extracted; 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..522d43fb2 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; @@ -73,7 +73,7 @@ public class TransportedItemStack implements Comparable { nbt.putFloat("PrevOffset", prevSideOffset); nbt.putInt("InSegment", insertedAt); nbt.putInt("Angle", angle); - nbt.putInt("InDirection", insertedFrom.getIndex()); + nbt.putInt("InDirection", insertedFrom.get3DDataValue()); if (locked) nbt.putBoolean("Locked", locked); if (lockedExternally) @@ -82,14 +82,14 @@ public class TransportedItemStack implements Comparable { } public static TransportedItemStack read(CompoundNBT nbt) { - TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item"))); + TransportedItemStack stack = new TransportedItemStack(ItemStack.of(nbt.getCompound("Item"))); stack.beltPosition = nbt.getFloat("Pos"); stack.prevBeltPosition = nbt.getFloat("PrevPos"); stack.sideOffset = nbt.getFloat("Offset"); stack.prevSideOffset = nbt.getFloat("PrevOffset"); stack.insertedAt = nbt.getInt("InSegment"); stack.angle = nbt.getInt("Angle"); - stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection")); + stack.insertedFrom = Direction.from3DDataValue(nbt.getInt("InDirection")); stack.locked = nbt.getBoolean("Locked"); stack.lockedExternally = nbt.getBoolean("LockedExternally"); return stack; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractShaftBlock.java index ec3e1aff9..992bb5a84 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractShaftBlock.java @@ -35,7 +35,7 @@ public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock public AbstractShaftBlock(Properties properties) { super(properties); - setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); + registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); } @Override @@ -44,7 +44,7 @@ public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock } @Override - public PushReaction getPushReaction(BlockState state) { + public PushReaction getPistonPushReaction(BlockState state) { return PushReaction.NORMAL; } @@ -55,52 +55,52 @@ public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock @Override @SuppressWarnings("deprecation") - public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { + public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { if (state != newState && !isMoving) - removeBracket(world, pos, true).ifPresent(stack -> Block.spawnAsEntity(world, pos, stack)); - super.onReplaced(state, world, pos, newState, isMoving); + removeBracket(world, pos, true).ifPresent(stack -> Block.popResource(world, pos, stack)); + super.onRemove(state, world, pos, newState, isMoving); } // IRotate: @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.get(AXIS); + return face.getAxis() == state.getValue(AXIS); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(AXIS); + return state.getValue(AXIS); } @Override public FluidState getFluidState(BlockState state) { - return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) - : Fluids.EMPTY.getDefaultState(); + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) + : Fluids.EMPTY.defaultFluidState(); } @Override - protected void fillStateContainer(Builder builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(BlockStateProperties.WATERLOGGED); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world, BlockPos pos, BlockPos neighbourPos) { - if (state.get(BlockStateProperties.WATERLOGGED)) { - world.getPendingFluidTicks() - .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + if (state.getValue(BlockStateProperties.WATERLOGGED)) { + world.getLiquidTicks() + .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } return state; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - FluidState ifluidstate = context.getWorld() - .getFluidState(context.getPos()); - return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, - Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + FluidState ifluidstate = context.getLevel() + .getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, + Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)); } @Override @@ -110,13 +110,13 @@ public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock return Optional.empty(); BlockState bracket = behaviour.getBracket(); behaviour.removeBracket(inOnReplacedContext); - if (bracket == Blocks.AIR.getDefaultState()) + if (bracket == Blocks.AIR.defaultBlockState()) return Optional.empty(); return Optional.of(new ItemStack(bracket.getBlock())); } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } 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..e4a432b7f 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); @@ -67,8 +67,8 @@ public class BracketedKineticBlockModel extends BakedModelWrapper { public void putBracket(BlockState state) { this.bracket = Minecraft.getInstance() - .getBlockRendererDispatcher() - .getModelForState(state); + .getBlockRenderer() + .getBlockModel(state); } public IBakedModel getBracket() { 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..1e677317c 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; @@ -63,8 +64,8 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { public void removeBracket(boolean inOnReplacedContext) { World world = getWorld(); - if (!world.isRemote) - world.playEvent(2001, getPos(), Block.getStateId(getBracket())); + if (!world.isClientSide) + world.levelEvent(2001, getPos(), Block.getId(getBracket())); this.bracket = Optional.empty(); reRender = true; if (inOnReplacedContext) @@ -73,12 +74,22 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { tileEntity.notifyUpdate(); } - public boolean isBacketPresent() { - return getBracket() != Blocks.AIR.getDefaultState(); + public boolean isBracketPresent() { + return getBracket() != Blocks.AIR.defaultBlockState(); } public BlockState getBracket() { - return bracket.orElse(Blocks.AIR.getDefaultState()); + return bracket.orElse(Blocks.AIR.defaultBlockState()); + } + + @Override + public ItemRequirement getRequiredItems() { + return ItemRequirement.of(getBracket(), null); + } + + @Override + public boolean isSafeNBT() { + return true; } @Override @@ -97,7 +108,7 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { if (nbt.contains("Bracket")) bracket = Optional.of(NBTUtil.readBlockState(nbt.getCompound("Bracket"))); if (clientPacket && nbt.contains("Redraw")) - getWorld().notifyBlockUpdate(getPos(), tileEntity.getBlockState(), tileEntity.getBlockState(), 16); + getWorld().sendBlockUpdated(getPos(), tileEntity.getBlockState(), tileEntity.getBlockState(), 16); super.read(nbt, clientPacket); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java index 7662c10f5..b22bb9457 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java @@ -54,12 +54,12 @@ public class CogWheelBlock extends AbstractShaftBlock implements ICogWheel { @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return (isLarge ? AllShapes.LARGE_GEAR : AllShapes.SMALL_GEAR).get(state.get(AXIS)); + return (isLarge ? AllShapes.LARGE_GEAR : AllShapes.SMALL_GEAR).get(state.getValue(AXIS)); } @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - return isValidCogwheelPosition(ICogWheel.isLargeCog(state), worldIn, pos, state.get(AXIS)); + public boolean canSurvive(BlockState state, IWorldReader worldIn, BlockPos pos) { + return isValidCogwheelPosition(ICogWheel.isLargeCog(state), worldIn, pos, state.getValue(AXIS)); } public static boolean isValidCogwheelPosition(boolean large, IWorldReader worldIn, BlockPos pos, Axis cogAxis) { @@ -67,9 +67,9 @@ public class CogWheelBlock extends AbstractShaftBlock implements ICogWheel { if (facing.getAxis() == cogAxis) continue; - BlockPos offsetPos = pos.offset(facing); + BlockPos offsetPos = pos.relative(facing); BlockState blockState = worldIn.getBlockState(offsetPos); - if (blockState.contains(AXIS) && facing.getAxis() == blockState.get(AXIS)) + if (blockState.hasProperty(AXIS) && facing.getAxis() == blockState.getValue(AXIS)) continue; if (ICogWheel.isLargeCog(blockState) || large && ICogWheel.isSmallCog(blockState)) @@ -79,16 +79,16 @@ public class CogWheelBlock extends AbstractShaftBlock implements ICogWheel { } protected Axis getAxisForPlacement(BlockItemUseContext context) { - if (context.getPlayer() != null && context.getPlayer().isSneaking()) - return context.getFace().getAxis(); + if (context.getPlayer() != null && context.getPlayer().isShiftKeyDown()) + return context.getClickedFace().getAxis(); - World world = context.getWorld(); - BlockState stateBelow = world.getBlockState(context.getPos().down()); + World world = context.getLevel(); + BlockState stateBelow = world.getBlockState(context.getClickedPos().below()); if (AllBlocks.ROTATION_SPEED_CONTROLLER.has(stateBelow) && isLargeCog()) - return stateBelow.get(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X; + return stateBelow.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X; - BlockPos placedOnPos = context.getPos().offset(context.getFace().getOpposite()); + BlockPos placedOnPos = context.getClickedPos().relative(context.getClickedFace().getOpposite()); BlockState placedAgainst = world.getBlockState(placedOnPos); Block block = placedAgainst.getBlock(); @@ -96,15 +96,15 @@ public class CogWheelBlock extends AbstractShaftBlock implements ICogWheel { return ((IRotate) block).getRotationAxis(placedAgainst); Axis preferredAxis = getPreferredAxis(context); - return preferredAxis != null ? preferredAxis : context.getFace().getAxis(); + return preferredAxis != null ? preferredAxis : context.getClickedFace().getAxis(); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - boolean shouldWaterlog = context.getWorld().getFluidState(context.getPos()).getFluid() == Fluids.WATER; - return this.getDefaultState() - .with(AXIS, getAxisForPlacement(context)) - .with(BlockStateProperties.WATERLOGGED, shouldWaterlog); + boolean shouldWaterlog = context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER; + return this.defaultBlockState() + .setValue(AXIS, getAxisForPlacement(context)) + .setValue(BlockStateProperties.WATERLOGGED, shouldWaterlog); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java index a1e96d272..23b34992a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java @@ -46,21 +46,21 @@ public class CogwheelBlockItem extends BlockItem { @Override public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) { - World world = context.getWorld(); - BlockPos pos = context.getPos(); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); BlockState state = world.getBlockState(pos); IPlacementHelper helper = PlacementHelpers.get(placementHelperId); PlayerEntity player = context.getPlayer(); - BlockRayTraceResult ray = new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true); - if (helper.matchesState(state) && player != null && !player.isSneaking()) { + BlockRayTraceResult ray = new BlockRayTraceResult(context.getClickLocation(), context.getClickedFace(), pos, true); + if (helper.matchesState(state) && player != null && !player.isShiftKeyDown()) { return helper.getOffset(player, world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray); } if (integratedCogHelperId != -1) { helper = PlacementHelpers.get(integratedCogHelperId); - if (helper.matchesState(state) && player != null && !player.isSneaking()) { + if (helper.matchesState(state) && player != null && !player.isShiftKeyDown()) { return helper.getOffset(player, world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray); } } @@ -71,33 +71,33 @@ public class CogwheelBlockItem extends BlockItem { @Override // Trigger cogwheel criterion protected boolean placeBlock(BlockItemUseContext context, BlockState state) { - triggerShiftingGearsAdvancement(context.getWorld(), context.getPos(), state, context.getPlayer()); + triggerShiftingGearsAdvancement(context.getLevel(), context.getClickedPos(), state, context.getPlayer()); return super.placeBlock(context, state); } protected void triggerShiftingGearsAdvancement(World world, BlockPos pos, BlockState state, PlayerEntity player) { - if (world.isRemote || player == null) + if (world.isClientSide || player == null) return; - Axis axis = state.get(CogWheelBlock.AXIS); + Axis axis = state.getValue(CogWheelBlock.AXIS); for (Axis perpendicular1 : Iterate.axes) { if (perpendicular1 == axis) continue; - Direction d1 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, perpendicular1); + Direction d1 = Direction.get(AxisDirection.POSITIVE, perpendicular1); for (Axis perpendicular2 : Iterate.axes) { if (perpendicular1 == perpendicular2) continue; if (axis == perpendicular2) continue; - Direction d2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, perpendicular2); + Direction d2 = Direction.get(AxisDirection.POSITIVE, perpendicular2); for (int offset1 : Iterate.positiveAndNegative) { for (int offset2 : Iterate.positiveAndNegative) { - BlockPos connectedPos = pos.offset(d1, offset1) - .offset(d2, offset2); + BlockPos connectedPos = pos.relative(d1, offset1) + .relative(d2, offset2); BlockState blockState = world.getBlockState(connectedPos); if (!(blockState.getBlock() instanceof CogWheelBlock)) continue; - if (blockState.get(CogWheelBlock.AXIS) != axis) + if (blockState.getValue(CogWheelBlock.AXIS) != axis) continue; if (ICogWheel.isLargeCog(blockState) == large) continue; @@ -123,12 +123,12 @@ public class CogwheelBlockItem extends BlockItem { if (!((CogWheelBlock) state.getBlock()).isLarge) { List directions = - IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS)); + IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), state.getValue(AXIS)); for (Direction dir : directions) { - BlockPos newPos = pos.offset(dir); + BlockPos newPos = pos.relative(dir); - if (!CogWheelBlock.isValidCogwheelPosition(false, world, newPos, state.get(AXIS))) + if (!CogWheelBlock.isValidCogwheelPosition(false, world, newPos, state.getValue(AXIS))) continue; if (!world.getBlockState(newPos) @@ -136,7 +136,7 @@ public class CogwheelBlockItem extends BlockItem { .isReplaceable()) continue; - return PlacementOffset.success(newPos, s -> s.with(AXIS, state.get(AXIS))); + return PlacementOffset.success(newPos, s -> s.setValue(AXIS, state.getValue(AXIS))); } @@ -161,13 +161,13 @@ public class CogwheelBlockItem extends BlockItem { return PlacementOffset.fail(); if (((CogWheelBlock) state.getBlock()).isLarge) { - Direction side = IPlacementHelper.orderedByDistanceOnlyAxis(pos, ray.getHitVec(), state.get(AXIS)) + Direction side = IPlacementHelper.orderedByDistanceOnlyAxis(pos, ray.getLocation(), state.getValue(AXIS)) .get(0); List directions = - IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS)); + IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), state.getValue(AXIS)); for (Direction dir : directions) { - BlockPos newPos = pos.offset(dir) - .offset(side); + BlockPos newPos = pos.relative(dir) + .relative(side); if (!CogWheelBlock.isValidCogwheelPosition(true, world, newPos, dir.getAxis())) continue; @@ -177,7 +177,7 @@ public class CogwheelBlockItem extends BlockItem { .isReplaceable()) continue; - return PlacementOffset.success(newPos, s -> s.with(AXIS, dir.getAxis())); + return PlacementOffset.success(newPos, s -> s.setValue(AXIS, dir.getAxis())); } return PlacementOffset.fail(); @@ -198,34 +198,34 @@ public class CogwheelBlockItem extends BlockItem { @Override public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) { // diagonal gears of different size - Direction closest = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS)) + Direction closest = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), state.getValue(AXIS)) .get(0); - List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), - state.get(AXIS), d -> d.getAxis() != closest.getAxis()); + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), + state.getValue(AXIS), d -> d.getAxis() != closest.getAxis()); for (Direction dir : directions) { - BlockPos newPos = pos.offset(dir) - .offset(closest); + BlockPos newPos = pos.relative(dir) + .relative(closest); if (!world.getBlockState(newPos) .getMaterial() .isReplaceable()) continue; - if (!CogWheelBlock.isValidCogwheelPosition(ICogWheel.isLargeCog(state), world, newPos, state.get(AXIS))) + if (!CogWheelBlock.isValidCogwheelPosition(ICogWheel.isLargeCog(state), world, newPos, state.getValue(AXIS))) continue; - return PlacementOffset.success(newPos, s -> s.with(AXIS, state.get(AXIS))); + return PlacementOffset.success(newPos, s -> s.setValue(AXIS, state.getValue(AXIS))); } return PlacementOffset.fail(); } protected boolean hitOnShaft(BlockState state, BlockRayTraceResult ray) { - return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS)) - .getBoundingBox() - .grow(0.001) - .contains(ray.getHitVec() - .subtract(ray.getHitVec() + return AllShapes.SIX_VOXEL_POLE.get(state.getValue(AXIS)) + .bounds() + .inflate(0.001) + .contains(ray.getLocation() + .subtract(ray.getLocation() .align(Iterate.axisSet))); } } @@ -245,14 +245,14 @@ public class CogwheelBlockItem extends BlockItem { @Override public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) { - Direction face = ray.getFace(); + Direction face = ray.getDirection(); Axis newAxis; - if (state.contains(HorizontalKineticBlock.HORIZONTAL_FACING)) - newAxis = state.get(HorizontalKineticBlock.HORIZONTAL_FACING) + if (state.hasProperty(HorizontalKineticBlock.HORIZONTAL_FACING)) + newAxis = state.getValue(HorizontalKineticBlock.HORIZONTAL_FACING) .getAxis(); - else if (state.contains(DirectionalKineticBlock.FACING)) - newAxis = state.get(DirectionalKineticBlock.FACING) + else if (state.hasProperty(DirectionalKineticBlock.FACING)) + newAxis = state.getValue(DirectionalKineticBlock.FACING) .getAxis(); else newAxis = Axis.Y; @@ -261,11 +261,11 @@ public class CogwheelBlockItem extends BlockItem { return PlacementOffset.fail(); List directions = - IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), face.getAxis(), newAxis); + IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), face.getAxis(), newAxis); for (Direction d : directions) { - BlockPos newPos = pos.offset(face) - .offset(d); + BlockPos newPos = pos.relative(face) + .relative(d); if (!world.getBlockState(newPos) .getMaterial() @@ -275,7 +275,7 @@ public class CogwheelBlockItem extends BlockItem { if (!CogWheelBlock.isValidCogwheelPosition(false, world, newPos, newAxis)) return PlacementOffset.fail(); - return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis)); + return PlacementOffset.success(newPos, s -> s.setValue(CogWheelBlock.AXIS, newAxis)); } return PlacementOffset.fail(); @@ -298,14 +298,14 @@ public class CogwheelBlockItem extends BlockItem { @Override public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) { - Direction face = ray.getFace(); + Direction face = ray.getDirection(); Axis newAxis; - if (state.contains(HorizontalKineticBlock.HORIZONTAL_FACING)) - newAxis = state.get(HorizontalKineticBlock.HORIZONTAL_FACING) + if (state.hasProperty(HorizontalKineticBlock.HORIZONTAL_FACING)) + newAxis = state.getValue(HorizontalKineticBlock.HORIZONTAL_FACING) .getAxis(); - else if (state.contains(DirectionalKineticBlock.FACING)) - newAxis = state.get(DirectionalKineticBlock.FACING) + else if (state.hasProperty(DirectionalKineticBlock.FACING)) + newAxis = state.getValue(DirectionalKineticBlock.FACING) .getAxis(); else newAxis = Axis.Y; @@ -313,10 +313,10 @@ public class CogwheelBlockItem extends BlockItem { if (face.getAxis() == newAxis) return PlacementOffset.fail(); - List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), newAxis); + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), newAxis); for (Direction d : directions) { - BlockPos newPos = pos.offset(d); + BlockPos newPos = pos.relative(d); if (!world.getBlockState(newPos) .getMaterial() @@ -328,7 +328,7 @@ public class CogwheelBlockItem extends BlockItem { return PlacementOffset.success() .at(newPos) - .withTransform(s -> s.with(CogWheelBlock.AXIS, newAxis)); + .withTransform(s -> s.setValue(CogWheelBlock.AXIS, newAxis)); } return PlacementOffset.fail(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java index 51c02d3af..c00d1a77f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java @@ -40,7 +40,7 @@ public class ShaftBlock extends AbstractShaftBlock { @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS)); + return AllShapes.SIX_VOXEL_POLE.get(state.getValue(AXIS)); } @Override @@ -54,12 +54,12 @@ public class ShaftBlock extends AbstractShaftBlock { } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - if (player.isSneaking() || !player.isAllowEdit()) + if (player.isShiftKeyDown() || !player.mayBuild()) return ActionResultType.PASS; - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getItemInHand(hand); for (EncasedShaftBlock encasedShaft : new EncasedShaftBlock[] { AllBlocks.ANDESITE_ENCASED_SHAFT.get(), AllBlocks.BRASS_ENCASED_SHAFT.get() }) { @@ -67,12 +67,12 @@ public class ShaftBlock extends AbstractShaftBlock { .isIn(heldItem)) continue; - if (world.isRemote) + if (world.isClientSide) return ActionResultType.SUCCESS; AllTriggers.triggerFor(AllTriggers.CASING_SHAFT, player); - KineticTileEntity.switchToBlockState(world, pos, encasedShaft.getDefaultState() - .with(AXIS, state.get(AXIS))); + KineticTileEntity.switchToBlockState(world, pos, encasedShaft.defaultBlockState() + .setValue(AXIS, state.getValue(AXIS))); return ActionResultType.SUCCESS; } @@ -90,7 +90,7 @@ public class ShaftBlock extends AbstractShaftBlock { private PlacementHelper(){ super( state -> state.getBlock() instanceof AbstractShaftBlock, - state -> state.get(AXIS), + state -> state.getValue(AXIS), AXIS ); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java index 5c651a8a7..4545e3f4a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java @@ -27,7 +27,7 @@ public class SimpleKineticTileEntity extends KineticTileEntity { @Override public AxisAlignedBB makeRenderBoundingBox() { - return new AxisAlignedBB(pos).grow(1); + return new AxisAlignedBB(worldPosition).inflate(1); } @Override @@ -35,10 +35,10 @@ public class SimpleKineticTileEntity extends KineticTileEntity { if (!ICogWheel.isLargeCog(state)) return super.addPropagationLocations(block, state, neighbours); - BlockPos.getAllInBox(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) + BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) .forEach(offset -> { - if (offset.distanceSq(0, 0, 0, false) == BlockPos.ZERO.distanceSq(1, 1, 0, false)) - neighbours.add(pos.add(offset)); + if (offset.distSqr(0, 0, 0, false) == BlockPos.ZERO.distSqr(1, 1, 0, false)) + neighbours.add(worldPosition.offset(offset)); }); return neighbours; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AbstractEncasedShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AbstractEncasedShaftBlock.java index df29e6e41..2dcbf534f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AbstractEncasedShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AbstractEncasedShaftBlock.java @@ -21,8 +21,8 @@ public abstract class AbstractEncasedShaftBlock extends RotatedPillarKineticBloc } @Override - protected void fillStateContainer(StateContainer.Builder builder) { - super.fillStateContainer(builder); + protected void createBlockStateDefinition(StateContainer.Builder builder) { + super.createBlockStateDefinition(builder); } @Override @@ -31,28 +31,28 @@ public abstract class AbstractEncasedShaftBlock extends RotatedPillarKineticBloc } @Override - public PushReaction getPushReaction(@Nullable BlockState state) { + public PushReaction getPistonPushReaction(@Nullable BlockState state) { return PushReaction.NORMAL; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { if (context.getPlayer() != null && context.getPlayer() - .isSneaking()) + .isShiftKeyDown()) return super.getStateForPlacement(context); Direction.Axis preferredAxis = getPreferredAxis(context); - return this.getDefaultState() - .with(AXIS, preferredAxis == null ? context.getNearestLookingDirection() + return this.defaultBlockState() + .setValue(AXIS, preferredAxis == null ? context.getNearestLookingDirection() .getAxis() : preferredAxis); } @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.get(AXIS); + return face.getAxis() == state.getValue(AXIS); } @Override public Direction.Axis getRotationAxis(BlockState state) { - return state.get(AXIS); + return state.getValue(AXIS); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyBlock.java index 5ecd6ee43..54b44f711 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyBlock.java @@ -20,12 +20,12 @@ public class AdjustablePulleyBlock extends EncasedBeltBlock implements ITE builder) { - super.fillStateContainer(builder.add(POWERED)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED)); } @Override @@ -34,8 +34,8 @@ public class AdjustablePulleyBlock extends EncasedBeltBlock implements ITE builder) { - super.fillStateContainer(builder.add(PART, CONNECTED_ALONG_FIRST_COORDINATE)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(PART, CONNECTED_ALONG_FIRST_COORDINATE)); } @Override @@ -58,28 +58,28 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock { Axis placedAxis = context.getNearestLookingDirection() .getAxis(); Axis axis = context.getPlayer() != null && context.getPlayer() - .isSneaking() ? placedAxis : getPreferredAxis(context); + .isShiftKeyDown() ? placedAxis : getPreferredAxis(context); if (axis == null) axis = placedAxis; - BlockState state = getDefaultState().with(AXIS, axis); + BlockState state = defaultBlockState().setValue(AXIS, axis); for (Direction facing : Iterate.directions) { if (facing.getAxis() == axis) continue; - BlockPos pos = context.getPos(); - BlockPos offset = pos.offset(facing); - state = updatePostPlacement(state, facing, context.getWorld() - .getBlockState(offset), context.getWorld(), pos, offset); + BlockPos pos = context.getClickedPos(); + BlockPos offset = pos.relative(facing); + state = updateShape(state, facing, context.getLevel() + .getBlockState(offset), context.getLevel(), pos, offset); } return state; } @Override - public BlockState updatePostPlacement(BlockState stateIn, Direction face, BlockState neighbour, IWorld worldIn, + public BlockState updateShape(BlockState stateIn, Direction face, BlockState neighbour, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) { - Part part = stateIn.get(PART); - Axis axis = stateIn.get(AXIS); - boolean connectionAlongFirst = stateIn.get(CONNECTED_ALONG_FIRST_COORDINATE); + Part part = stateIn.getValue(PART); + Axis axis = stateIn.getValue(AXIS); + boolean connectionAlongFirst = stateIn.getValue(CONNECTED_ALONG_FIRST_COORDINATE); Axis connectionAxis = connectionAlongFirst ? (axis == Axis.X ? Axis.Y : Axis.X) : (axis == Axis.Z ? Axis.Y : Axis.Z); @@ -94,19 +94,19 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock { if (facingAlongFirst != connectionAlongFirst || part == Part.NONE) return stateIn; if (part == Part.MIDDLE) - return stateIn.with(PART, positive ? Part.END : Part.START); + return stateIn.setValue(PART, positive ? Part.END : Part.START); if ((part == Part.START) == positive) - return stateIn.with(PART, Part.NONE); + return stateIn.setValue(PART, Part.NONE); return stateIn; } - Part otherPart = neighbour.get(PART); - Axis otherAxis = neighbour.get(AXIS); - boolean otherConnection = neighbour.get(CONNECTED_ALONG_FIRST_COORDINATE); + Part otherPart = neighbour.getValue(PART); + Axis otherAxis = neighbour.getValue(AXIS); + boolean otherConnection = neighbour.getValue(CONNECTED_ALONG_FIRST_COORDINATE); Axis otherConnectionAxis = otherConnection ? (otherAxis == Axis.X ? Axis.Y : Axis.X) : (otherAxis == Axis.Z ? Axis.Y : Axis.Z); - if (neighbour.get(AXIS) == faceAxis) + if (neighbour.getValue(AXIS) == faceAxis) return stateIn; if (otherPart != Part.NONE && otherConnectionAxis != faceAxis) return stateIn; @@ -121,34 +121,34 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock { if ((part == Part.START) != positive) part = Part.MIDDLE; - return stateIn.with(PART, part) - .with(CONNECTED_ALONG_FIRST_COORDINATE, connectionAlongFirst); + return stateIn.setValue(PART, part) + .setValue(CONNECTED_ALONG_FIRST_COORDINATE, connectionAlongFirst); } @Override public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { - if (originalState.get(PART) == Part.NONE) + if (originalState.getValue(PART) == Part.NONE) return super.getRotatedBlockState(originalState, targetedFace); return super.getRotatedBlockState(originalState, - Direction.getFacingFromAxis(AxisDirection.POSITIVE, getConnectionAxis(originalState))); + Direction.get(AxisDirection.POSITIVE, getConnectionAxis(originalState))); } @Override public BlockState updateAfterWrenched(BlockState newState, ItemUseContext context) { // Blocks.AIR.getDefaultState() // .updateNeighbors(context.getWorld(), context.getPos(), 1); - Axis axis = newState.get(AXIS); - newState = getDefaultState().with(AXIS, axis); - if (newState.contains(BlockStateProperties.POWERED)) - newState = newState.with(BlockStateProperties.POWERED, context.getWorld() - .isBlockPowered(context.getPos())); + Axis axis = newState.getValue(AXIS); + newState = defaultBlockState().setValue(AXIS, axis); + if (newState.hasProperty(BlockStateProperties.POWERED)) + newState = newState.setValue(BlockStateProperties.POWERED, context.getLevel() + .hasNeighborSignal(context.getClickedPos())); for (Direction facing : Iterate.directions) { if (facing.getAxis() == axis) continue; - BlockPos pos = context.getPos(); - BlockPos offset = pos.offset(facing); - newState = updatePostPlacement(newState, facing, context.getWorld() - .getBlockState(offset), context.getWorld(), pos, offset); + BlockPos pos = context.getClickedPos(); + BlockPos offset = pos.relative(facing); + newState = updateShape(newState, facing, context.getLevel() + .getBlockState(offset), context.getLevel(), pos, offset); } // newState.updateNeighbors(context.getWorld(), context.getPos(), 1 | 2); return newState; @@ -156,16 +156,16 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock { @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.get(AXIS); + return face.getAxis() == state.getValue(AXIS); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(AXIS); + return state.getValue(AXIS); } public static boolean areBlocksConnected(BlockState state, BlockState other, Direction facing) { - Part part = state.get(PART); + Part part = state.getValue(PART); Axis connectionAxis = getConnectionAxis(state); Axis otherConnectionAxis = getConnectionAxis(other); @@ -182,8 +182,8 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock { } protected static Axis getConnectionAxis(BlockState state) { - Axis axis = state.get(AXIS); - boolean connectionAlongFirst = state.get(CONNECTED_ALONG_FIRST_COORDINATE); + Axis axis = state.getValue(AXIS); + boolean connectionAlongFirst = state.getValue(CONNECTED_ALONG_FIRST_COORDINATE); Axis connectionAxis = connectionAlongFirst ? (axis == Axis.X ? Axis.Y : Axis.X) : (axis == Axis.Z ? Axis.Y : Axis.Z); return connectionAxis; @@ -208,7 +208,7 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock { START, MIDDLE, END, NONE; @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltGenerator.java index 5ef334001..0e75bbb16 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltGenerator.java @@ -22,9 +22,9 @@ public class EncasedBeltGenerator extends SpecialBlockStateGen { @Override protected int getXRotation(BlockState state) { - EncasedBeltBlock.Part part = state.get(EncasedBeltBlock.PART); - boolean connectedAlongFirst = state.get(EncasedBeltBlock.CONNECTED_ALONG_FIRST_COORDINATE); - Axis axis = state.get(EncasedBeltBlock.AXIS); + EncasedBeltBlock.Part part = state.getValue(EncasedBeltBlock.PART); + boolean connectedAlongFirst = state.getValue(EncasedBeltBlock.CONNECTED_ALONG_FIRST_COORDINATE); + Axis axis = state.getValue(EncasedBeltBlock.AXIS); if (part == Part.NONE) return axis == Axis.Y ? 90 : 0; @@ -37,9 +37,9 @@ public class EncasedBeltGenerator extends SpecialBlockStateGen { @Override protected int getYRotation(BlockState state) { - EncasedBeltBlock.Part part = state.get(EncasedBeltBlock.PART); - boolean connectedAlongFirst = state.get(EncasedBeltBlock.CONNECTED_ALONG_FIRST_COORDINATE); - Axis axis = state.get(EncasedBeltBlock.AXIS); + EncasedBeltBlock.Part part = state.getValue(EncasedBeltBlock.PART); + boolean connectedAlongFirst = state.getValue(EncasedBeltBlock.CONNECTED_ALONG_FIRST_COORDINATE); + Axis axis = state.getValue(EncasedBeltBlock.AXIS); if (part == Part.NONE) return axis == Axis.X ? 90 : 0; @@ -58,8 +58,8 @@ public class EncasedBeltGenerator extends SpecialBlockStateGen { } protected String getModelSuffix(BlockState state) { - EncasedBeltBlock.Part part = state.get(EncasedBeltBlock.PART); - Axis axis = state.get(EncasedBeltBlock.AXIS); + EncasedBeltBlock.Part part = state.getValue(EncasedBeltBlock.PART); + Axis axis = state.getValue(EncasedBeltBlock.AXIS); if (part == Part.NONE) return "single"; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCTBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCTBehaviour.java index 0676729fa..566a6f150 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCTBehaviour.java @@ -22,7 +22,7 @@ public class EncasedCTBehaviour extends ConnectedTextureBehaviour { Direction face) { if (isBeingBlocked(state, reader, pos, otherPos, face)) return false; - CasingConnectivity cc = CreateClient.getCasingConnectivity(); + CasingConnectivity cc = CreateClient.CASING_CONNECTIVITY; CasingConnectivity.Entry entry = cc.get(state); CasingConnectivity.Entry otherEntry = cc.get(other); if (entry == null || otherEntry == null) 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..7ff8a064f 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,23 +36,23 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock implements ISpe public TileEntity createTileEntity(BlockState state, IBlockReader world) { return AllTileEntities.ENCASED_SHAFT.create(); } - + public BlockEntry getCasing() { return casing; } @Override public ActionResultType onSneakWrenched(BlockState state, ItemUseContext context) { - if (context.getWorld().isRemote) + if (context.getLevel().isClientSide) return ActionResultType.SUCCESS; - context.getWorld().playEvent(2001, context.getPos(), Block.getStateId(state)); - KineticTileEntity.switchToBlockState(context.getWorld(), context.getPos(), AllBlocks.SHAFT.getDefaultState().with(AXIS, state.get(AXIS))); + context.getLevel().levelEvent(2001, context.getClickedPos(), Block.getId(state)); + KineticTileEntity.switchToBlockState(context.getLevel(), context.getClickedPos(), AllBlocks.SHAFT.getDefaultState().setValue(AXIS, state.getValue(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/GearshiftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/GearshiftBlock.java index 9e381f491..c96a2cb6d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/GearshiftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/GearshiftBlock.java @@ -27,7 +27,7 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(POWERED); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - return super.getStateForPlacement(context).with(POWERED, - context.getWorld().isBlockPowered(context.getPos())); + return super.getStateForPlacement(context).setValue(POWERED, + context.getLevel().hasNeighborSignal(context.getClickedPos())); } @Override public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - if (worldIn.isRemote) + if (worldIn.isClientSide) return; - boolean previouslyPowered = state.get(POWERED); - if (previouslyPowered != worldIn.isBlockPowered(pos)) { + boolean previouslyPowered = state.getValue(POWERED); + if (previouslyPowered != worldIn.hasNeighborSignal(pos)) { detachKinetics(worldIn, pos, true); - worldIn.setBlockState(pos, state.cycle(POWERED), 2); + worldIn.setBlock(pos, state.cycle(POWERED), 2); } } @@ -66,19 +66,19 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE 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..dc5193c81 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.Instancer; +import com.jozufozu.flywheel.backend.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.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..f3e93c84d 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,12 +28,12 @@ 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.getLevel())) return; Block block = te.getBlockState().getBlock(); final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState()); - final BlockPos pos = te.getPos(); - float time = AnimationTickHolder.getRenderTime(te.getWorld()); + final BlockPos pos = te.getBlockPos(); + float time = AnimationTickHolder.getRenderTime(te.getLevel()); for (Direction direction : Iterate.directions) { Axis axis = direction.getAxis(); @@ -54,7 +54,7 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer { SuperByteBuffer superByteBuffer = PartialBufferer.getFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), direction); kineticRotationTransform(superByteBuffer, te, axis, angle, light); - superByteBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + superByteBuffer.renderInto(ms, buffer.getBuffer(RenderType.solid())); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeBlock.java index 7278da542..bc2b9b445 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeBlock.java @@ -5,7 +5,7 @@ import java.util.Random; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; @@ -38,7 +38,7 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { SPEED, STRESS; @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } } @@ -70,9 +70,9 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { /* * FIXME: Is there a new way of doing this in 1.16? Or cn we just delete it? - * + * * @SuppressWarnings("deprecation") - * + * * @Override * public MaterialColor getMaterialColor(BlockState state, IBlockReader worldIn, BlockPos pos) { * return Blocks.SPRUCE_PLANKS.getMaterialColor(state, worldIn, pos); @@ -81,28 +81,28 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - World world = context.getWorld(); - Direction face = context.getFace(); - BlockPos placedOnPos = context.getPos() - .offset(context.getFace() + World world = context.getLevel(); + Direction face = context.getClickedFace(); + BlockPos placedOnPos = context.getClickedPos() + .relative(context.getClickedFace() .getOpposite()); BlockState placedOnState = world.getBlockState(placedOnPos); Block block = placedOnState.getBlock(); if (block instanceof IRotate && ((IRotate) block).hasShaftTowards(world, placedOnPos, placedOnState, face)) { - BlockState toPlace = getDefaultState(); - Direction horizontalFacing = context.getPlacementHorizontalFacing(); + BlockState toPlace = defaultBlockState(); + Direction horizontalFacing = context.getHorizontalDirection(); Direction nearestLookingDirection = context.getNearestLookingDirection(); boolean lookPositive = nearestLookingDirection.getAxisDirection() == AxisDirection.POSITIVE; if (face.getAxis() == Axis.X) { - toPlace = toPlace.with(FACING, lookPositive ? Direction.NORTH : Direction.SOUTH) - .with(AXIS_ALONG_FIRST_COORDINATE, true); + toPlace = toPlace.setValue(FACING, lookPositive ? Direction.NORTH : Direction.SOUTH) + .setValue(AXIS_ALONG_FIRST_COORDINATE, true); } else if (face.getAxis() == Axis.Y) { - toPlace = toPlace.with(FACING, horizontalFacing.getOpposite()) - .with(AXIS_ALONG_FIRST_COORDINATE, horizontalFacing.getAxis() == Axis.X); + toPlace = toPlace.setValue(FACING, horizontalFacing.getOpposite()) + .setValue(AXIS_ALONG_FIRST_COORDINATE, horizontalFacing.getAxis() == Axis.X); } else { - toPlace = toPlace.with(FACING, lookPositive ? Direction.WEST : Direction.EAST) - .with(AXIS_ALONG_FIRST_COORDINATE, false); + toPlace = toPlace.setValue(FACING, lookPositive ? Direction.WEST : Direction.EAST) + .setValue(AXIS_ALONG_FIRST_COORDINATE, false); } return toPlace; @@ -113,12 +113,12 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { @Override protected Direction getFacingForPlacement(BlockItemUseContext context) { - return context.getFace(); + return context.getClickedFace(); } @Override protected boolean getAxisAlignmentForPlacement(BlockItemUseContext context) { - return context.getPlacementHorizontalFacing() + return context.getHorizontalDirection() .getAxis() != Axis.X; } @@ -126,21 +126,21 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { if (face.getAxis() .isVertical()) return false; - if (face == state.get(FACING) + if (face == state.getValue(FACING) .getOpposite()) return false; if (face.getAxis() == getRotationAxis(state)) return false; - if (getRotationAxis(state) == Axis.Y && face != state.get(FACING)) + if (getRotationAxis(state) == Axis.Y && face != state.getValue(FACING)) return false; - if (!Block.shouldSideBeRendered(state, world, pos, face) && !(world instanceof WrappedWorld)) + if (!Block.shouldRenderFace(state, world, pos, face) && !(world instanceof WrappedWorld)) return false; return true; } @Override public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) { - TileEntity te = worldIn.getTileEntity(pos); + TileEntity te = worldIn.getBlockEntity(pos); if (te == null || !(te instanceof GaugeTileEntity)) return; GaugeTileEntity gaugeTE = (GaugeTileEntity) te; @@ -152,10 +152,10 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { if (!shouldRenderHeadOnFace(worldIn, pos, stateIn, face)) continue; - Vector3d rgb = ColorHelper.getRGB(color); - Vector3d faceVec = Vector3d.of(face.getDirectionVec()); - Direction positiveFacing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, face.getAxis()); - Vector3d positiveFaceVec = Vector3d.of(positiveFacing.getDirectionVec()); + Vector3d rgb = Color.vectorFromRGB(color); + Vector3d faceVec = Vector3d.atLowerCornerOf(face.getNormal()); + Direction positiveFacing = Direction.get(AxisDirection.POSITIVE, face.getAxis()); + Vector3d positiveFaceVec = Vector3d.atLowerCornerOf(positiveFacing.getNormal()); int particleCount = gaugeTE.dialTarget > 1 ? 4 : 1; if (particleCount == 1 && rand.nextFloat() > 1 / 4f) @@ -163,7 +163,7 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { for (int i = 0; i < particleCount; i++) { Vector3d mul = VecHelper.offsetRandomly(Vector3d.ZERO, rand, .25f) - .mul(new Vector3d(1, 1, 1).subtract(positiveFaceVec)) + .multiply(new Vector3d(1, 1, 1).subtract(positiveFaceVec)) .normalize() .scale(.3f); Vector3d offset = VecHelper.getCenterOf(pos) @@ -179,17 +179,17 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return GAUGE.get(state.get(FACING), state.get(AXIS_ALONG_FIRST_COORDINATE)); + return GAUGE.get(state.getValue(FACING), state.getValue(AXIS_ALONG_FIRST_COORDINATE)); } @Override - public boolean hasComparatorInputOverride(BlockState state) { + public boolean hasAnalogOutputSignal(BlockState state) { return true; } @Override - public int getComparatorInputOverride(BlockState blockState, World worldIn, BlockPos pos) { - TileEntity te = worldIn.getTileEntity(pos); + public int getAnalogOutputSignal(BlockState blockState, World worldIn, BlockPos pos) { + TileEntity te = worldIn.getBlockEntity(pos); if (te instanceof GaugeTileEntity) { GaugeTileEntity gaugeTileEntity = (GaugeTileEntity) te; return MathHelper.ceil(MathHelper.clamp(gaugeTileEntity.dialTarget * 14, 0, 15)); @@ -198,7 +198,7 @@ public class GaugeBlock extends DirectionalAxisKineticBlock { } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } } 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..f38497777 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,18 +2,19 @@ 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.material.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.jozufozu.flywheel.util.transform.TransformStack; 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; -import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.util.Direction; import net.minecraft.util.math.MathHelper; @@ -24,7 +25,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,11 +33,11 @@ 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); + MatrixTransformStack msr = MatrixTransformStack.of(ms); msr.translate(getInstancePosition()); float progress = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState); @@ -53,7 +54,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()); } @@ -61,12 +62,12 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns public void beginFrame() { GaugeTileEntity gaugeTile = (GaugeTileEntity) tile; - if (MathHelper.epsilonEquals(gaugeTile.prevDialState, gaugeTile.dialState)) + if (MathHelper.equal(gaugeTile.prevDialState, gaugeTile.dialState)) return; float progress = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState); - MatrixStacker msr = MatrixStacker.of(ms); + MatrixTransformStack msr = MatrixTransformStack.of(ms); for (DialFace faceEntry : faces) { faceEntry.updateTransform(msr, progress); @@ -88,7 +89,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 { @@ -99,10 +100,10 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns this.face = face; } - private void setupTransform(MatrixStacker msr, float progress) { + private void setupTransform(MatrixTransformStack msr, float progress) { float dialPivot = 5.75f / 16; - ms.push(); + ms.pushPose(); rotateToFace(msr); getSecond().setTransform(ms); @@ -113,13 +114,13 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns getFirst().setTransform(ms); - ms.pop(); + ms.popPose(); } - private void updateTransform(MatrixStacker msr, float progress) { + private void updateTransform(MatrixTransformStack msr, float progress) { float dialPivot = 5.75f / 16; - ms.push(); + ms.pushPose(); rotateToFace(msr) .translate(0, dialPivot, dialPivot) @@ -128,12 +129,12 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns getFirst().setTransform(ms); - ms.pop(); + ms.popPose(); } - protected MatrixStacker rotateToFace(MatrixStacker msr) { + protected TransformStack rotateToFace(TransformStack msr) { return msr.centre() - .rotate(Direction.UP, (float) ((-face.getHorizontalAngle() - 90) / 180 * Math.PI)) + .rotate(Direction.UP, (float) ((-face.toYRot() - 90) / 180 * Math.PI)) .unCentre(); } @@ -144,23 +145,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..ebd9bfad8 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,14 +10,11 @@ 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; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction; import net.minecraft.util.math.MathHelper; @@ -40,12 +39,12 @@ 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.getLevel())) return; super.renderSafe(te, partialTicks, ms, buffer, light, overlay); + BlockState gaugeState = te.getBlockState(); GaugeTileEntity gaugeTE = (GaugeTileEntity) te; - int lightCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), gaugeState, te.getPos()); PartialModel partialModel = (type == Type.SPEED ? AllBlockPartials.GAUGE_HEAD_SPEED : AllBlockPartials.GAUGE_HEAD_STRESS); SuperByteBuffer headBuffer = @@ -56,20 +55,19 @@ public class GaugeRenderer extends KineticTileEntityRenderer { float progress = MathHelper.lerp(partialTicks, gaugeTE.prevDialState, gaugeTE.dialState); for (Direction facing : Iterate.directions) { - if (!((GaugeBlock) gaugeState.getBlock()).shouldRenderHeadOnFace(te.getWorld(), te.getPos(), gaugeState, + if (!((GaugeBlock) gaugeState.getBlock()).shouldRenderHeadOnFace(te.getLevel(), te.getBlockPos(), gaugeState, facing)) continue; - IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); + IVertexBuilder vb = buffer.getBuffer(RenderType.solid()); rotateBufferTowards(dialBuffer, facing).translate(0, dialPivot, dialPivot) .rotate(Direction.EAST, (float) (Math.PI / 2 * -progress)) .translate(0, -dialPivot, -dialPivot) - .light(lightCoords) + .light(light) .renderInto(ms, vb); - rotateBufferTowards(headBuffer, facing).light(lightCoords) + rotateBufferTowards(headBuffer, facing).light(light) .renderInto(ms, vb); } - } @Override @@ -78,7 +76,7 @@ public class GaugeRenderer extends KineticTileEntityRenderer { } protected SuperByteBuffer rotateBufferTowards(SuperByteBuffer buffer, Direction target) { - return buffer.rotateCentered(Direction.UP, (float) ((-target.getHorizontalAngle() - 90) / 180 * Math.PI)); + return buffer.rotateCentered(Direction.UP, (float) ((-target.toYRot() - 90) / 180 * Math.PI)); } } 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..dfe96cf3c 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 @@ -41,19 +41,19 @@ public class GaugeTileEntity extends KineticTileEntity implements IHaveGoggleInf super.tick(); prevDialState = dialState; dialState += (dialTarget - dialState) * .125f; - if (dialState > 1 && world.rand.nextFloat() < 1 / 2f) - dialState -= (dialState - 1) * world.rand.nextFloat(); + if (dialState > 1 && level.random.nextFloat() < 1 / 2f) + dialState -= (dialState - 1) * level.random.nextFloat(); } @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - tooltip.add(componentSpacing.copy().append(Lang.translate("gui.gauge.info_header"))); + tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.gauge.info_header"))); return true; } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java index 1bdb7b191..d0c152453 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java @@ -6,7 +6,7 @@ import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; import com.simibubi.create.content.contraptions.goggles.GogglesItem; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.tileentity.TileEntityType; @@ -26,13 +26,13 @@ public class SpeedGaugeTileEntity extends GaugeTileEntity { float speed = Math.abs(getSpeed()); color = speed == 0 ? 0x333333 - : ColorHelper.mixColors(SpeedLevel.of(speed) + : Color.mixColors(SpeedLevel.of(speed) .getColor(), 0xffffff, .25f); if (speed == 69) - AllTriggers.triggerForNearbyPlayers(AllTriggers.SPEED_READ, world, pos, 6, GogglesItem::canSeeParticles); + AllTriggers.triggerForNearbyPlayers(AllTriggers.SPEED_READ, level, worldPosition, 6, GogglesItem::canSeeParticles); dialTarget = getDialTarget(speed); - markDirty(); + setChanged(); } public static float getDialTarget(float speed) { @@ -59,8 +59,8 @@ public class SpeedGaugeTileEntity extends GaugeTileEntity { public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { super.addToGoggleTooltip(tooltip, isPlayerSneaking); - tooltip.add(componentSpacing.copy().append(Lang.translate("gui.speedometer.title").formatted(TextFormatting.GRAY))); - tooltip.add(componentSpacing.copy().append(SpeedLevel.getFormattedSpeedText(speed, isOverStressed()))); + tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.speedometer.title").withStyle(TextFormatting.GRAY))); + tooltip.add(componentSpacing.plainCopy().append(SpeedLevel.getFormattedSpeedText(speed, isOverStressed()))); return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java index 470522dff..25cb21200 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java @@ -5,7 +5,7 @@ import java.util.List; import com.simibubi.create.content.contraptions.base.IRotate.StressImpact; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.foundation.item.ItemDescription; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.tileentity.TileEntityType; @@ -35,15 +35,15 @@ public class StressGaugeTileEntity extends GaugeTileEntity { if (dialTarget > 0) { if (dialTarget < .5f) - color = ColorHelper.mixColors(0x00FF00, 0xFFFF00, dialTarget * 2); + color = Color.mixColors(0x00FF00, 0xFFFF00, dialTarget * 2); else if (dialTarget < 1) - color = ColorHelper.mixColors(0xFFFF00, 0xFF0000, (dialTarget) * 2 - 1); + color = Color.mixColors(0xFFFF00, 0xFF0000, (dialTarget) * 2 - 1); else color = 0xFF0000; } sendData(); - markDirty(); + setChanged(); } @Override @@ -51,7 +51,7 @@ public class StressGaugeTileEntity extends GaugeTileEntity { super.onSpeedChanged(prevSpeed); if (getSpeed() == 0) { dialTarget = 0; - markDirty(); + setChanged(); return; } @@ -68,30 +68,30 @@ public class StressGaugeTileEntity extends GaugeTileEntity { double capacity = getNetworkCapacity(); double stressFraction = getNetworkStress() / (capacity == 0 ? 1 : capacity); - tooltip.add(componentSpacing.copy().append(Lang.translate("gui.stressometer.title").formatted(TextFormatting.GRAY))); + tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.stressometer.title").withStyle(TextFormatting.GRAY))); if (getTheoreticalSpeed() == 0) - tooltip.add(new StringTextComponent(spacing + ItemDescription.makeProgressBar(3, -1)).append(Lang.translate("gui.stressometer.no_rotation")).formatted(TextFormatting.DARK_GRAY)); + tooltip.add(new StringTextComponent(spacing + ItemDescription.makeProgressBar(3, -1)).append(Lang.translate("gui.stressometer.no_rotation")).withStyle(TextFormatting.DARK_GRAY)); // tooltip.add(new StringTextComponent(TextFormatting.DARK_GRAY + ItemDescription.makeProgressBar(3, -1) // + Lang.translate("gui.stressometer.no_rotation"))); else { - tooltip.add(componentSpacing.copy().append(StressImpact.getFormattedStressText(stressFraction))); + tooltip.add(componentSpacing.plainCopy().append(StressImpact.getFormattedStressText(stressFraction))); - tooltip.add(componentSpacing.copy().append(Lang.translate("gui.stressometer.capacity").formatted(TextFormatting.GRAY))); + tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.stressometer.capacity").withStyle(TextFormatting.GRAY))); double remainingCapacity = capacity - getNetworkStress(); ITextComponent su = Lang.translate("generic.unit.stress"); - IFormattableTextComponent stressTooltip = componentSpacing.copy() + IFormattableTextComponent stressTooltip = componentSpacing.plainCopy() .append(new StringTextComponent(" " + IHaveGoggleInformation.format(remainingCapacity)) - .append(su.copy()) - .formatted(StressImpact.of(stressFraction).getRelativeColor())); + .append(su.plainCopy()) + .withStyle(StressImpact.of(stressFraction).getRelativeColor())); if (remainingCapacity != capacity) { stressTooltip - .append(new StringTextComponent(" / ").formatted(TextFormatting.GRAY)) + .append(new StringTextComponent(" / ").withStyle(TextFormatting.GRAY)) .append(new StringTextComponent(IHaveGoggleInformation.format(capacity)) - .append(su.copy()) - .formatted(TextFormatting.DARK_GRAY)); + .append(su.plainCopy()) + .withStyle(TextFormatting.DARK_GRAY)); } tooltip.add(stressTooltip); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxBlock.java index bb867e1a0..83a2a74a9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxBlock.java @@ -35,20 +35,20 @@ public class GearboxBlock extends RotatedPillarKineticBlock { } @Override - public PushReaction getPushReaction(BlockState state) { + public PushReaction getPistonPushReaction(BlockState state) { return PushReaction.PUSH_ONLY; } @Override - public void fillItemGroup(ItemGroup group, NonNullList items) { - super.fillItemGroup(group, items); + public void fillItemCategory(ItemGroup group, NonNullList items) { + super.fillItemCategory(group, items); items.add(AllItems.VERTICAL_GEARBOX.asStack()); } @SuppressWarnings("deprecation") @Override public List getDrops(BlockState state, Builder builder) { - if (state.get(AXIS).isVertical()) + if (state.getValue(AXIS).isVertical()) return super.getDrops(state, builder); return Arrays.asList(new ItemStack(AllItems.VERTICAL_GEARBOX.get())); } @@ -56,25 +56,25 @@ public class GearboxBlock extends RotatedPillarKineticBlock { @Override public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos, PlayerEntity player) { - if (state.get(AXIS).isVertical()) + if (state.getValue(AXIS).isVertical()) return super.getPickBlock(state, target, world, pos, player); return new ItemStack(AllItems.VERTICAL_GEARBOX.get()); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - return getDefaultState().with(AXIS, Axis.Y); + return defaultBlockState().setValue(AXIS, Axis.Y); } // IRotate: @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() != state.get(AXIS); + return face.getAxis() != state.getValue(AXIS); } @Override public Axis getRotationAxis(BlockState state) { - return state.get(AXIS); + return state.getValue(AXIS); } } 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..da4b1f8f6 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.Instancer; +import com.jozufozu.flywheel.backend.material.InstanceMaterial; +import com.jozufozu.flywheel.backend.material.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,29 +22,29 @@ 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); - final Direction.Axis boxAxis = blockState.get(BlockStateProperties.AXIS); + final Direction.Axis boxAxis = blockState.getValue(BlockStateProperties.AXIS); - int blockLight = world.getLightLevel(LightType.BLOCK, pos); - int skyLight = world.getLightLevel(LightType.SKY, pos); + int blockLight = world.getBrightness(LightType.BLOCK, pos); + int skyLight = world.getBrightness(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(); - key.setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + key.setRotationAxis(Direction.get(Direction.AxisDirection.POSITIVE, axis).step()) .setRotationalSpeed(getSpeed(direction)) .setRotationOffset(getRotationOffset(axis)).setColor(tile) .setPosition(getInstancePosition()) @@ -70,7 +70,7 @@ public class GearboxInstance extends KineticTileInstance { protected void updateSourceFacing() { if (tile.hasSource()) { BlockPos source = tile.source.subtract(pos); - sourceFacing = Direction.getFacingFromVector(source.getX(), source.getY(), source.getZ()); + sourceFacing = Direction.getNearest(source.getX(), source.getY(), source.getZ()); } else { sourceFacing = null; } 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..2bd534af4 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,11 +27,11 @@ 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.getLevel())) return; - final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS); - final BlockPos pos = te.getPos(); - float time = AnimationTickHolder.getRenderTime(te.getWorld()); + final Axis boxAxis = te.getBlockState().getValue(BlockStateProperties.AXIS); + final BlockPos pos = te.getBlockPos(); + float time = AnimationTickHolder.getRenderTime(te.getLevel()); for (Direction direction : Iterate.directions) { final Axis axis = direction.getAxis(); @@ -43,8 +43,8 @@ public class GearboxRenderer extends KineticTileEntityRenderer { float angle = (time * te.getSpeed() * 3f / 10) % 360; if (te.getSpeed() != 0 && te.hasSource()) { - BlockPos source = te.source.subtract(te.getPos()); - Direction sourceFacing = Direction.getFacingFromVector(source.getX(), source.getY(), source.getZ()); + BlockPos source = te.source.subtract(te.getBlockPos()); + Direction sourceFacing = Direction.getNearest(source.getX(), source.getY(), source.getZ()); if (sourceFacing.getAxis() == direction.getAxis()) angle *= sourceFacing == direction ? 1 : -1; else if (sourceFacing.getAxisDirection() == direction.getAxisDirection()) @@ -55,7 +55,7 @@ public class GearboxRenderer extends KineticTileEntityRenderer { angle = angle / 180f * (float) Math.PI; kineticRotationTransform(shaft, te, axis, angle, light); - shaft.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + shaft.renderInto(ms, buffer.getBuffer(RenderType.solid())); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearshiftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearshiftTileEntity.java index a819022c1..2e4b6cf62 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearshiftTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearshiftTileEntity.java @@ -15,7 +15,7 @@ public class GearshiftTileEntity extends SplitShaftTileEntity { @Override public float getRotationSpeedModifier(Direction face) { if (hasSource()) { - if (face != getSourceFacing() && getBlockState().get(BlockStateProperties.POWERED)) + if (face != getSourceFacing() && getBlockState().getValue(BlockStateProperties.POWERED)) return -1; } return 1; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/VerticalGearboxItem.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/VerticalGearboxItem.java index 153b85154..23832729b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/VerticalGearboxItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/VerticalGearboxItem.java @@ -27,25 +27,25 @@ public class VerticalGearboxItem extends BlockItem { } @Override - public void fillItemGroup(ItemGroup p_150895_1_, NonNullList p_150895_2_) { + public void fillItemCategory(ItemGroup p_150895_1_, NonNullList p_150895_2_) { } @Override - public String getTranslationKey() { + public String getDescriptionId() { return "item.create.vertical_gearbox"; } @Override - public void addToBlockToItemMap(Map p_195946_1_, Item p_195946_2_) { + public void registerBlocks(Map p_195946_1_, Item p_195946_2_) { } @Override - protected boolean onBlockPlaced(BlockPos pos, World world, PlayerEntity player, ItemStack stack, BlockState state) { + protected boolean updateCustomBlockEntityTag(BlockPos pos, World world, PlayerEntity player, ItemStack stack, BlockState state) { Axis prefferedAxis = null; for (Direction side : Iterate.horizontalDirections) { - BlockState blockState = world.getBlockState(pos.offset(side)); + BlockState blockState = world.getBlockState(pos.relative(side)); if (blockState.getBlock() instanceof IRotate) { - if (((IRotate) blockState.getBlock()).hasShaftTowards(world, pos.offset(side), blockState, + if (((IRotate) blockState.getBlock()).hasShaftTowards(world, pos.relative(side), blockState, side.getOpposite())) if (prefferedAxis != null && prefferedAxis != side.getAxis()) { prefferedAxis = null; @@ -56,11 +56,11 @@ public class VerticalGearboxItem extends BlockItem { } } - Axis axis = prefferedAxis == null ? player.getHorizontalFacing() - .rotateY() + Axis axis = prefferedAxis == null ? player.getDirection() + .getClockWise() .getAxis() : prefferedAxis == Axis.X ? Axis.Z : Axis.X; - world.setBlockState(pos, state.with(BlockStateProperties.AXIS, axis)); - return super.onBlockPlaced(pos, world, player, stack, state); + world.setBlockAndUpdate(pos, state.setValue(BlockStateProperties.AXIS, axis)); + return super.updateCustomBlockEntityTag(pos, world, player, stack, state); } } 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..7c6102815 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 @@ -27,43 +27,43 @@ import net.minecraft.world.server.ServerWorld; public interface IWrenchable { default ActionResultType onWrenched(BlockState state, ItemUseContext context) { - World world = context.getWorld(); - BlockState rotated = getRotatedBlockState(state, context.getFace()); - if (!rotated.isValidPosition(world, context.getPos())) + World world = context.getLevel(); + BlockState rotated = getRotatedBlockState(state, context.getClickedFace()); + if (!rotated.canSurvive(world, context.getClickedPos())) return ActionResultType.PASS; - KineticTileEntity.switchToBlockState(world, context.getPos(), updateAfterWrenched(rotated, context)); + KineticTileEntity.switchToBlockState(world, context.getClickedPos(), updateAfterWrenched(rotated, context)); - TileEntity te = context.getWorld() - .getTileEntity(context.getPos()); + TileEntity te = context.getLevel() + .getBlockEntity(context.getClickedPos()); if (te != null) - te.updateContainingBlockInfo(); + te.clearCache(); if (te instanceof GeneratingKineticTileEntity) { ((GeneratingKineticTileEntity) te).reActivateSource = true; } - if (world.getBlockState(context.getPos()) != state) - playRotateSound(world, context.getPos()); + if (world.getBlockState(context.getClickedPos()) != state) + playRotateSound(world, context.getClickedPos()); return ActionResultType.SUCCESS; } default BlockState updateAfterWrenched(BlockState newState, ItemUseContext context) { // return newState; - return Block.getValidBlockForPosition(newState, context.getWorld(), context.getPos()); + return Block.updateFromNeighbourShapes(newState, context.getLevel(), context.getClickedPos()); } default ActionResultType onSneakWrenched(BlockState state, ItemUseContext context) { - World world = context.getWorld(); - BlockPos pos = context.getPos(); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); PlayerEntity player = context.getPlayer(); if (world instanceof ServerWorld) { if (player != null && !player.isCreative()) - Block.getDrops(state, (ServerWorld) world, pos, world.getTileEntity(pos), player, context.getItem()) + Block.getDrops(state, (ServerWorld) world, pos, world.getBlockEntity(pos), player, context.getItemInHand()) .forEach(itemStack -> { player.inventory.placeItemBackInInventory(world, itemStack); }); - state.spawnAdditionalDrops((ServerWorld) world, pos, ItemStack.EMPTY); + state.spawnAfterBreak((ServerWorld) world, pos, ItemStack.EMPTY); world.destroyBlock(pos, false); playRemoveSound(world, pos); } @@ -71,53 +71,53 @@ 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) { BlockState newState = originalState; if (targetedFace.getAxis() == Direction.Axis.Y) { - if (originalState.contains(HorizontalAxisKineticBlock.HORIZONTAL_AXIS)) - return originalState.with(HorizontalAxisKineticBlock.HORIZONTAL_AXIS, DirectionHelper - .rotateAround(VoxelShaper.axisAsFace(originalState.get(HorizontalAxisKineticBlock.HORIZONTAL_AXIS)), + if (originalState.hasProperty(HorizontalAxisKineticBlock.HORIZONTAL_AXIS)) + return originalState.setValue(HorizontalAxisKineticBlock.HORIZONTAL_AXIS, DirectionHelper + .rotateAround(VoxelShaper.axisAsFace(originalState.getValue(HorizontalAxisKineticBlock.HORIZONTAL_AXIS)), targetedFace.getAxis()) .getAxis()); - if (originalState.contains(HorizontalKineticBlock.HORIZONTAL_FACING)) - return originalState.with(HorizontalKineticBlock.HORIZONTAL_FACING, DirectionHelper - .rotateAround(originalState.get(HorizontalKineticBlock.HORIZONTAL_FACING), targetedFace.getAxis())); + if (originalState.hasProperty(HorizontalKineticBlock.HORIZONTAL_FACING)) + return originalState.setValue(HorizontalKineticBlock.HORIZONTAL_FACING, DirectionHelper + .rotateAround(originalState.getValue(HorizontalKineticBlock.HORIZONTAL_FACING), targetedFace.getAxis())); } - if (originalState.contains(RotatedPillarKineticBlock.AXIS)) - return originalState.with(RotatedPillarKineticBlock.AXIS, + if (originalState.hasProperty(RotatedPillarKineticBlock.AXIS)) + return originalState.setValue(RotatedPillarKineticBlock.AXIS, DirectionHelper - .rotateAround(VoxelShaper.axisAsFace(originalState.get(RotatedPillarKineticBlock.AXIS)), + .rotateAround(VoxelShaper.axisAsFace(originalState.getValue(RotatedPillarKineticBlock.AXIS)), targetedFace.getAxis()) .getAxis()); - if (!originalState.contains(DirectionalKineticBlock.FACING)) + if (!originalState.hasProperty(DirectionalKineticBlock.FACING)) return originalState; - Direction stateFacing = originalState.get(DirectionalKineticBlock.FACING); + Direction stateFacing = originalState.getValue(DirectionalKineticBlock.FACING); if (stateFacing.getAxis() .equals(targetedFace.getAxis())) { - if (originalState.contains(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) + if (originalState.hasProperty(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) return originalState.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE); else return originalState; } else { do { - newState = newState.with(DirectionalKineticBlock.FACING, - DirectionHelper.rotateAround(newState.get(DirectionalKineticBlock.FACING), targetedFace.getAxis())); + newState = newState.setValue(DirectionalKineticBlock.FACING, + DirectionHelper.rotateAround(newState.getValue(DirectionalKineticBlock.FACING), targetedFace.getAxis())); if (targetedFace.getAxis() == Direction.Axis.Y - && newState.contains(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) + && newState.hasProperty(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) newState = newState.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE); - } while (newState.get(DirectionalKineticBlock.FACING) + } while (newState.getValue(DirectionalKineticBlock.FACING) .getAxis() .equals(targetedFace.getAxis())); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchableWithBracket.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchableWithBracket.java index e2c79126c..9161d4309 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchableWithBracket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchableWithBracket.java @@ -29,22 +29,22 @@ public interface IWrenchableWithBracket extends IWrenchable { } default boolean tryRemoveBracket(ItemUseContext context) { - World world = context.getWorld(); - BlockPos pos = context.getPos(); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); Optional bracket = removeBracket(world, pos, false); BlockState blockState = world.getBlockState(pos); if (bracket.isPresent()) { PlayerEntity player = context.getPlayer(); - if (!world.isRemote && !player.isCreative()) + if (!world.isClientSide && !player.isCreative()) player.inventory.placeItemBackInInventory(world, bracket.get()); - if (!world.isRemote && AllBlocks.FLUID_PIPE.has(blockState)) { + if (!world.isClientSide && AllBlocks.FLUID_PIPE.has(blockState)) { Axis preferred = FluidPropagator.getStraightPipeAxis(blockState); Direction preferredDirection = - preferred == null ? Direction.UP : Direction.getFacingFromAxis(AxisDirection.POSITIVE, preferred); + preferred == null ? Direction.UP : Direction.get(AxisDirection.POSITIVE, preferred); BlockState updated = AllBlocks.FLUID_PIPE.get() .updateBlockState(blockState, preferredDirection, null, world, pos); if (updated != blockState) - world.setBlockState(pos, updated); + world.setBlockAndUpdate(pos, updated); } return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItem.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItem.java index 74a3cb2c3..79131ad98 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItem.java @@ -3,7 +3,11 @@ package com.simibubi.create.content.contraptions.wrench; import javax.annotation.Nonnull; import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllTags; +import com.simibubi.create.Create; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity; @@ -13,6 +17,9 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; import net.minecraft.util.ActionResultType; import net.minecraft.util.DamageSource; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; import net.minecraftforge.event.entity.player.AttackEntityEvent; public class WrenchItem extends Item { @@ -23,34 +30,59 @@ public class WrenchItem extends Item { @Nonnull @Override - public ActionResultType onItemUse(ItemUseContext context) { + public ActionResultType useOn(ItemUseContext context) { PlayerEntity player = context.getPlayer(); - if (player == null || !player.isAllowEdit()) - return super.onItemUse(context); + if (player == null || !player.mayBuild()) + return super.useOn(context); - BlockState state = context.getWorld() - .getBlockState(context.getPos()); - if (!(state.getBlock() instanceof IWrenchable)) - return super.onItemUse(context); - IWrenchable actor = (IWrenchable) state.getBlock(); + BlockState state = context.getLevel() + .getBlockState(context.getClickedPos()); + Block block = state.getBlock(); - if (player.isSneaking()) + if (!(block instanceof IWrenchable)) { + if (canWrenchPickup(state)) + return onItemUseOnOther(context); + return super.useOn(context); + } + + IWrenchable actor = (IWrenchable) block; + if (player.isShiftKeyDown()) return actor.onSneakWrenched(state, context); return actor.onWrenched(state, context); } - + + private boolean canWrenchPickup(BlockState state) { + return AllTags.AllBlockTags.WRENCH_PICKUP.matches(state); + } + + private ActionResultType onItemUseOnOther(ItemUseContext context) { + PlayerEntity player = context.getPlayer(); + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); + BlockState state = world.getBlockState(pos); + if (!(world instanceof ServerWorld)) + return ActionResultType.SUCCESS; + if (player != null && !player.isCreative()) + Block.getDrops(state, (ServerWorld) world, pos, world.getBlockEntity(pos), player, context.getItemInHand()) + .forEach(itemStack -> player.inventory.placeItemBackInInventory(world, itemStack)); + state.spawnAfterBreak((ServerWorld) world, pos, ItemStack.EMPTY); + world.destroyBlock(pos, false); + AllSoundEvents.WRENCH_REMOVE.playOnServer(world, pos, 1, Create.RANDOM.nextFloat() * .5f + .5f); + return ActionResultType.SUCCESS; + } + public static void wrenchInstaKillsMinecarts(AttackEntityEvent event) { Entity target = event.getTarget(); if (!(target instanceof AbstractMinecartEntity)) return; PlayerEntity player = event.getPlayer(); - ItemStack heldItem = player.getHeldItemMainhand(); + ItemStack heldItem = player.getMainHandItem(); if (!AllItems.WRENCH.isIn(heldItem)) return; if (player.isCreative()) return; AbstractMinecartEntity minecart = (AbstractMinecartEntity) target; - minecart.attackEntityFrom(DamageSource.causePlayerDamage(player), 100); + minecart.hurt(DamageSource.playerAttack(player), 100); } - + } 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..dbc677fd0 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,12 +1,13 @@ 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; import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.ItemCameraTransforms; import net.minecraft.item.ItemStack; import net.minecraft.util.math.vector.Vector3f; @@ -20,10 +21,15 @@ public class WrenchItemRenderer extends CustomRenderedItemModelRenderer onItemRightClick(World p_77659_1_, PlayerEntity p_77659_2_, Hand p_77659_3_) { - p_77659_2_.setActiveHand(p_77659_3_); - return ActionResult.success(p_77659_2_.getHeldItem(p_77659_3_)); + public ActionResult use(World p_77659_1_, PlayerEntity p_77659_2_, Hand p_77659_3_) { + p_77659_2_.startUsingItem(p_77659_3_); + return ActionResult.success(p_77659_2_.getItemInHand(p_77659_3_)); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java b/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java index 60c3e3754..63b4d989f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java +++ b/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java @@ -1,7 +1,7 @@ package com.simibubi.create.content.curiosities; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.color.IItemColor; @@ -9,20 +9,20 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; public class ChromaticCompoundColor implements IItemColor { - + @Override public int getColor(ItemStack stack, int layer) { Minecraft mc = Minecraft.getInstance(); float pt = AnimationTickHolder.getPartialTicks(); - float progress = (float) ((mc.player.getYaw(pt)) / 180 * Math.PI) + (AnimationTickHolder.getRenderTime() / 10f); + float progress = (float) ((mc.player.getViewYRot(pt)) / 180 * Math.PI) + (AnimationTickHolder.getRenderTime() / 10f); if (layer == 0) - return ColorHelper.mixColors(0x6e5773, 0x6B3074, ((float) MathHelper.sin(progress) + 1) / 2); + return Color.mixColors(0x6e5773, 0x6B3074, ((float) MathHelper.sin(progress) + 1) / 2); if (layer == 1) - return ColorHelper.mixColors(0xd45d79, 0x6e5773, + return Color.mixColors(0xd45d79, 0x6e5773, ((float) MathHelper.sin((float) (progress + Math.PI)) + 1) / 2); if (layer == 2) - return ColorHelper.mixColors(0xea9085, 0xd45d79, + return Color.mixColors(0xea9085, 0xd45d79, ((float) MathHelper.sin((float) (progress * 1.5f + Math.PI)) + 1) / 2); return 0; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java b/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java index 3b7d0ae2d..698024c61 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java @@ -2,15 +2,22 @@ package com.simibubi.create.content.curiosities; import java.util.Random; +import org.apache.commons.lang3.mutable.MutableBoolean; + import com.simibubi.create.AllItems; +import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.CRecipes; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.item.ItemEntity; +import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; @@ -34,7 +41,7 @@ public class ChromaticCompoundItem extends Item { } @Override - public boolean shouldSyncTag() { + public boolean shouldOverrideMultiplayerNbt() { return true; } @@ -54,7 +61,7 @@ public class ChromaticCompoundItem extends Item { @Override public int getRGBDurabilityForDisplay(ItemStack stack) { - return ColorHelper.mixColors(0x413c69, 0xFFFFFF, (float) (1 - getDurabilityForDisplay(stack))); + return Color.mixColors(0x413c69, 0xFFFFFF, (float) (1 - getDurabilityForDisplay(stack))); } @Override @@ -65,15 +72,15 @@ public class ChromaticCompoundItem extends Item { @Override public boolean onEntityItemUpdate(ItemStack stack, ItemEntity entity) { double y = entity.getY(); - double yMotion = entity.getMotion().y; - World world = entity.world; + double yMotion = entity.getDeltaMovement().y; + World world = entity.level; CompoundNBT data = entity.getPersistentData(); CompoundNBT itemData = entity.getItem() .getOrCreateTag(); - Vector3d positionVec = entity.getPositionVec(); + Vector3d positionVec = entity.position(); CRecipes config = AllConfigs.SERVER.recipes; - if (world.isRemote) { + if (world.isClientSide) { int light = itemData.getInt("CollectingLight"); if (random.nextInt(config.lightSourceCountForRefinedRadiance.get() + 20) < light) { Vector3d start = VecHelper.offsetRandomly(positionVec, random, 3); @@ -100,11 +107,11 @@ public class ChromaticCompoundItem extends Item { if (itemData.getInt("CollectingLight") >= config.lightSourceCountForRefinedRadiance.get()) { ItemStack newStack = AllItems.REFINED_RADIANCE.asStack(); ItemEntity newEntity = new ItemEntity(world, entity.getX(), entity.getY(), entity.getZ(), newStack); - newEntity.setMotion(entity.getMotion()); + newEntity.setDeltaMovement(entity.getDeltaMovement()); newEntity.getPersistentData() .putBoolean("JustCreated", true); itemData.remove("CollectingLight"); - world.addEntity(newEntity); + world.addFreshEntity(newEntity); stack.split(1); entity.setItem(stack); @@ -125,17 +132,17 @@ public class ChromaticCompoundItem extends Item { while (testPos.getY() > 0) { testPos.move(Direction.DOWN); BlockState state = world.getBlockState(testPos); - if (state.getOpacity(world, testPos) >= 15 && state.getBlock() != Blocks.BEDROCK) + if (state.getLightBlock(world, testPos) >= 15 && state.getBlock() != Blocks.BEDROCK) break; if (state.getBlock() == Blocks.BEACON) { - TileEntity te = world.getTileEntity(testPos); + TileEntity te = world.getBlockEntity(testPos); if (!(te instanceof BeaconTileEntity)) break; BeaconTileEntity bte = (BeaconTileEntity) te; - if (bte.getLevels() != 0 && !bte.beamSegments.isEmpty()) + if (bte.getLevels() != 0 && !bte.beamSections.isEmpty()) isOverBeacon = true; break; @@ -151,7 +158,7 @@ public class ChromaticCompoundItem extends Item { } // Find a light source and eat it. - Random r = world.rand; + Random r = world.random; int range = 3; float rate = 1 / 2f; if (r.nextFloat() > rate) @@ -159,33 +166,74 @@ public class ChromaticCompoundItem extends Item { BlockPos randomOffset = new BlockPos(VecHelper.offsetRandomly(positionVec, r, range)); BlockState state = world.getBlockState(randomOffset); + + TransportedItemStackHandlerBehaviour behaviour = + TileEntityBehaviour.get(world, randomOffset, TransportedItemStackHandlerBehaviour.TYPE); + + // Find a placed light source + if (behaviour == null) { + if (checkLight(stack, entity, world, itemData, positionVec, randomOffset, state)) + world.destroyBlock(randomOffset, false); + return false; + } + + // Find a light source from a depot/belt (chunk rebuild safe) + MutableBoolean success = new MutableBoolean(false); + behaviour.handleProcessingOnAllItems(ts -> { + + ItemStack heldStack = ts.stack; + if (!(heldStack.getItem() instanceof BlockItem)) + return TransportedResult.doNothing(); + + BlockItem blockItem = (BlockItem) heldStack.getItem(); + if (blockItem.getBlock() == null) + return TransportedResult.doNothing(); + + BlockState stateToCheck = blockItem.getBlock() + .defaultBlockState(); + + if (!success.getValue() + && checkLight(stack, entity, world, itemData, positionVec, randomOffset, stateToCheck)) { + success.setTrue(); + if (ts.stack.getCount() == 1) + return TransportedResult.removeItem(); + TransportedItemStack left = ts.copy(); + left.stack.shrink(1); + return TransportedResult.convertTo(left); + } + + return TransportedResult.doNothing(); + + }); + return false; + } + + public boolean checkLight(ItemStack stack, ItemEntity entity, World world, CompoundNBT itemData, + Vector3d positionVec, BlockPos randomOffset, BlockState state) { if (state.getLightValue(world, randomOffset) == 0) return false; - if (state.getBlockHardness(world, randomOffset) == -1) + if (state.getDestroySpeed(world, randomOffset) == -1) return false; if (state.getBlock() == Blocks.BEACON) return false; - RayTraceContext context = new RayTraceContext(positionVec, VecHelper.getCenterOf(randomOffset), - BlockMode.COLLIDER, FluidMode.NONE, entity); - if (!randomOffset.equals(world.rayTraceBlocks(context) - .getPos())) + RayTraceContext context = new RayTraceContext(positionVec.add(new Vector3d(0, 0.5, 0)), + VecHelper.getCenterOf(randomOffset), BlockMode.COLLIDER, FluidMode.NONE, entity); + if (!randomOffset.equals(world.clip(context) + .getBlockPos())) return false; - world.destroyBlock(randomOffset, false); - ItemStack newStack = stack.split(1); newStack.getOrCreateTag() .putInt("CollectingLight", itemData.getInt("CollectingLight") + 1); ItemEntity newEntity = new ItemEntity(world, entity.getX(), entity.getY(), entity.getZ(), newStack); - newEntity.setMotion(entity.getMotion()); - newEntity.setDefaultPickupDelay(); - world.addEntity(newEntity); + newEntity.setDeltaMovement(entity.getDeltaMovement()); + newEntity.setDefaultPickUpDelay(); + world.addFreshEntity(newEntity); entity.lifespan = 6000; if (stack.isEmpty()) entity.remove(); - - return false; + return true; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/NoGravMagicalDohickyItem.java b/src/main/java/com/simibubi/create/content/curiosities/NoGravMagicalDohickyItem.java index 2921241d3..328164c20 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/NoGravMagicalDohickyItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/NoGravMagicalDohickyItem.java @@ -19,13 +19,13 @@ public class NoGravMagicalDohickyItem extends Item { @Override public boolean onEntityItemUpdate(ItemStack stack, ItemEntity entity) { - World world = entity.world; - Vector3d pos = entity.getPositionVec(); + World world = entity.level; + Vector3d pos = entity.position(); CompoundNBT persistentData = entity.getPersistentData(); - if (world.isRemote) { - if (world.rand.nextFloat() < getIdleParticleChance(entity)) { - Vector3d ppos = VecHelper.offsetRandomly(pos, world.rand, .5f); + if (world.isClientSide) { + if (world.random.nextFloat() < getIdleParticleChance(entity)) { + Vector3d ppos = VecHelper.offsetRandomly(pos, world.random, .5f); world.addParticle(ParticleTypes.END_ROD, ppos.x, pos.y, ppos.z, 0, -.1f, 0); } @@ -33,7 +33,7 @@ public class NoGravMagicalDohickyItem extends Item { Vector3d basemotion = new Vector3d(0, 1, 0); world.addParticle(ParticleTypes.FLASH, pos.x, pos.y, pos.z, 0, 0, 0); for (int i = 0; i < 20; i++) { - Vector3d motion = VecHelper.offsetRandomly(basemotion, world.rand, 1); + Vector3d motion = VecHelper.offsetRandomly(basemotion, world.random, 1); world.addParticle(ParticleTypes.WITCH, pos.x, pos.y, pos.z, motion.x, motion.y, motion.z); world.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, motion.x, motion.y, motion.z); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/RefinedRadianceItem.java b/src/main/java/com/simibubi/create/content/curiosities/RefinedRadianceItem.java index c853d6be7..c6aab3c8c 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/RefinedRadianceItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/RefinedRadianceItem.java @@ -11,15 +11,15 @@ public class RefinedRadianceItem extends NoGravMagicalDohickyItem { } @Override - public boolean hasEffect(ItemStack stack) { + public boolean isFoil(ItemStack stack) { return true; } @Override protected void onCreated(ItemEntity entity, CompoundNBT persistentData) { super.onCreated(entity, persistentData); - entity.setMotion(entity.getMotion() - .add(0, .15f, 0)); + entity.setDeltaMovement(entity.getDeltaMovement() + .add(0, .25f, 0)); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/ShadowSteelItem.java b/src/main/java/com/simibubi/create/content/curiosities/ShadowSteelItem.java index 007e0f627..9f59e52c8 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ShadowSteelItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/ShadowSteelItem.java @@ -14,13 +14,13 @@ public class ShadowSteelItem extends NoGravMagicalDohickyItem { protected void onCreated(ItemEntity entity, CompoundNBT persistentData) { super.onCreated(entity, persistentData); float yMotion = (entity.fallDistance + 3) / 50f; - entity.setMotion(0, yMotion, 0); + entity.setDeltaMovement(0, yMotion, 0); } @Override protected float getIdleParticleChance(ItemEntity entity) { return (float) (MathHelper.clamp(entity.getItem() - .getCount() - 10, MathHelper.clamp(entity.getMotion().y * 20, 5, 20), 100) / 64f); + .getCount() - 10, MathHelper.clamp(entity.getDeltaMovement().y * 20, 5, 20), 100) / 64f); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java b/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java index 65768046d..dc4725be6 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java @@ -20,60 +20,60 @@ public class TreeFertilizerItem extends Item { } @Override - public ActionResultType onItemUse(ItemUseContext context) { - BlockState state = context.getWorld() - .getBlockState(context.getPos()); + public ActionResultType useOn(ItemUseContext context) { + BlockState state = context.getLevel() + .getBlockState(context.getClickedPos()); Block block = state.getBlock(); if (block instanceof SaplingBlock) { - if (context.getWorld().isRemote) { - BoneMealItem.spawnBonemealParticles(context.getWorld(), context.getPos(), 100); + if (context.getLevel().isClientSide) { + BoneMealItem.addGrowthParticles(context.getLevel(), context.getClickedPos(), 100); return ActionResultType.SUCCESS; } - BlockPos saplingPos = context.getPos(); - TreesDreamWorld world = new TreesDreamWorld((ServerWorld) context.getWorld(), saplingPos); + BlockPos saplingPos = context.getClickedPos(); + TreesDreamWorld world = new TreesDreamWorld((ServerWorld) context.getLevel(), saplingPos); - for (BlockPos pos : BlockPos.getAllInBoxMutable(-1, 0, -1, 1, 0, 1)) { - if (context.getWorld() - .getBlockState(saplingPos.add(pos)) + for (BlockPos pos : BlockPos.betweenClosed(-1, 0, -1, 1, 0, 1)) { + if (context.getLevel() + .getBlockState(saplingPos.offset(pos)) .getBlock() == block) - world.setBlockState(pos.up(10), state.with(SaplingBlock.STAGE, 1)); + world.setBlockAndUpdate(pos.above(10), state.setValue(SaplingBlock.STAGE, 1)); } - ((SaplingBlock) block).grow(world, world.getRandom(), BlockPos.ZERO.up(10), - state.with(SaplingBlock.STAGE, 1)); + ((SaplingBlock) block).performBonemeal(world, world.getRandom(), BlockPos.ZERO.above(10), + state.setValue(SaplingBlock.STAGE, 1)); for (BlockPos pos : world.blocksAdded.keySet()) { - BlockPos actualPos = pos.add(saplingPos).down(10); + BlockPos actualPos = pos.offset(saplingPos).below(10); BlockState newState = world.blocksAdded.get(pos); // Don't replace Bedrock - if (context.getWorld() + if (context.getLevel() .getBlockState(actualPos) - .getBlockHardness(context.getWorld(), actualPos) == -1) + .getDestroySpeed(context.getLevel(), actualPos) == -1) continue; // Don't replace solid blocks with leaves - if (!newState.isNormalCube(world, pos) - && !context.getWorld() + if (!newState.isRedstoneConductor(world, pos) + && !context.getLevel() .getBlockState(actualPos) - .getCollisionShape(context.getWorld(), actualPos) + .getCollisionShape(context.getLevel(), actualPos) .isEmpty()) continue; - context.getWorld() - .setBlockState(actualPos, newState); + context.getLevel() + .setBlockAndUpdate(actualPos, newState); } if (context.getPlayer() != null && !context.getPlayer() .isCreative()) - context.getItem() + context.getItemInHand() .shrink(1); return ActionResultType.SUCCESS; } - return super.onItemUse(context); + return super.useOn(context); } private class TreesDreamWorld extends PlacementSimulationServerWorld { @@ -83,7 +83,7 @@ public class TreeFertilizerItem extends Item { protected TreesDreamWorld(ServerWorld wrapped, BlockPos saplingPos) { super(wrapped); this.saplingPos = saplingPos; - soil = wrapped.getBlockState(saplingPos.down()); + soil = wrapped.getBlockState(saplingPos.below()); } @Override @@ -94,10 +94,10 @@ public class TreeFertilizerItem extends Item { } @Override - public boolean setBlockState(BlockPos pos, BlockState newState, int flags) { + public boolean setBlock(BlockPos pos, BlockState newState, int flags) { if (newState.getBlock() == Blocks.PODZOL) return true; - return super.setBlockState(pos, newState, flags); + return super.setBlock(pos, newState, flags); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java b/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java index 1b0f7f6e1..5129dbbdf 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java @@ -16,7 +16,7 @@ import net.minecraftforge.api.distmarker.OnlyIn; public enum AllArmorMaterials implements IArmorMaterial { COPPER("copper", 7, new int[] { 1, 3, 4, 2 }, 25, AllSoundEvents.COPPER_ARMOR_EQUIP.getMainEvent(), 0.0F, 0.0F, - () -> Ingredient.fromItems(AllItems.COPPER_INGOT.get())) + () -> Ingredient.of(AllItems.COPPER_INGOT.get())) ; @@ -42,24 +42,24 @@ public enum AllArmorMaterials implements IArmorMaterial { this.repairMaterial = new LazyValue<>(p_i231593_10_); } - public int getDurability(EquipmentSlotType p_200896_1_) { + public int getDurabilityForSlot(EquipmentSlotType p_200896_1_) { return MAX_DAMAGE_ARRAY[p_200896_1_.getIndex()] * this.maxDamageFactor; } - public int getDamageReductionAmount(EquipmentSlotType p_200902_1_) { + public int getDefenseForSlot(EquipmentSlotType p_200902_1_) { return this.damageReductionAmountArray[p_200902_1_.getIndex()]; } - public int getEnchantability() { + public int getEnchantmentValue() { return this.enchantability; } - public SoundEvent getSoundEvent() { + public SoundEvent getEquipSound() { return this.soundEvent; } - public Ingredient getRepairMaterial() { - return this.repairMaterial.getValue(); + public Ingredient getRepairIngredient() { + return this.repairMaterial.get(); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/BackTankUtil.java b/src/main/java/com/simibubi/create/content/curiosities/armor/BackTankUtil.java new file mode 100644 index 000000000..a53b0d477 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/BackTankUtil.java @@ -0,0 +1,114 @@ +package com.simibubi.create.content.curiosities.armor; + +import com.simibubi.create.AllEnchantments; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.config.AllConfigs; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class BackTankUtil { + + public static ItemStack get(LivingEntity entity) { + for (ItemStack itemStack : entity.getArmorSlots()) + if (AllItems.COPPER_BACKTANK.isIn(itemStack)) + return itemStack; + return ItemStack.EMPTY; + } + + public static boolean hasAirRemaining(ItemStack backtank) { + return getAir(backtank) > 0; + } + + public static float getAir(ItemStack backtank) { + CompoundNBT tag = backtank.getOrCreateTag(); + return Math.min(tag.getFloat("Air"), maxAir(backtank)); + } + + public static void consumeAir(ItemStack backtank, float i) { + CompoundNBT tag = backtank.getOrCreateTag(); + tag.putFloat("Air", Math.min(getAir(backtank) - i, maxAir(backtank))); + backtank.setTag(tag); + } + + public static int maxAir(ItemStack backtank) { + return maxAir(EnchantmentHelper.getItemEnchantmentLevel(AllEnchantments.CAPACITY.get(), backtank)); + } + + public static int maxAir(int enchantLevel) { + return AllConfigs.SERVER.curiosities.airInBacktank.get() + + AllConfigs.SERVER.curiosities.enchantedBacktankCapacity.get() * enchantLevel; + } + + public static int maxAirWithoutEnchants() { + return AllConfigs.SERVER.curiosities.airInBacktank.get(); + } + + public static boolean canAbsorbDamage(LivingEntity entity, int usesPerTank) { + if (usesPerTank == 0) + return true; + if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative()) + return true; + ItemStack backtank = get(entity); + if (backtank.isEmpty()) + return false; + if (!hasAirRemaining(backtank)) + return false; + float cost = ((float) maxAirWithoutEnchants()) / usesPerTank; + consumeAir(backtank, cost); + return true; + } + + // For Air-using tools + + @OnlyIn(Dist.CLIENT) + public static int getRGBDurabilityForDisplay(ItemStack stack, int usesPerTank) { + if (usesPerTank == 0) + return 0; + ClientPlayerEntity player = Minecraft.getInstance().player; + if (player == null) + return 0; + ItemStack backtank = get(player); + if (backtank.isEmpty() || !hasAirRemaining(backtank)) + return MathHelper.hsvToRgb( + Math.max(0.0F, (float) (1.0F - getDurabilityForDisplay(stack, usesPerTank))) / 3.0F, 1.0F, 1.0F); + return backtank.getItem() + .getRGBDurabilityForDisplay(backtank); + } + + @OnlyIn(Dist.CLIENT) + public static double getDurabilityForDisplay(ItemStack stack, int usesPerTank) { + if (usesPerTank == 0) + return 0; + ClientPlayerEntity player = Minecraft.getInstance().player; + if (player == null) + return 0; + ItemStack backtank = get(player); + if (backtank.isEmpty() || !hasAirRemaining(backtank)) + return (double) stack.getDamageValue() / (double) stack.getMaxDamage(); + return backtank.getItem() + .getDurabilityForDisplay(backtank); + } + + @OnlyIn(Dist.CLIENT) + public static boolean showDurabilityBar(ItemStack stack, int usesPerTank) { + if (usesPerTank == 0) + return false; + ClientPlayerEntity player = Minecraft.getInstance().player; + if (player == null) + return false; + ItemStack backtank = get(player); + if (backtank.isEmpty() || !hasAirRemaining(backtank)) + return stack.isDamaged(); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CapacityEnchantment.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CapacityEnchantment.java new file mode 100644 index 000000000..49b31df0d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/CapacityEnchantment.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.curiosities.armor; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentType; +import net.minecraft.inventory.EquipmentSlotType; +import net.minecraft.item.ItemStack; + +public class CapacityEnchantment extends Enchantment { + + public CapacityEnchantment(Rarity p_i46731_1_, EnchantmentType p_i46731_2_, EquipmentSlotType[] p_i46731_3_) { + super(p_i46731_1_, p_i46731_2_, p_i46731_3_); + } + + @Override + public int getMaxLevel() { + return 3; + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack) { + return stack.getItem() instanceof ICapacityEnchantable; + } + + public interface ICapacityEnchantable { + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperArmorItem.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperArmorItem.java index 01ccb623e..d036b562e 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperArmorItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperArmorItem.java @@ -3,26 +3,31 @@ package com.simibubi.create.content.curiosities.armor; import com.simibubi.create.Create; import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ArmorItem; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; public class CopperArmorItem extends ArmorItem { + public static final ResourceLocation TEXTURE = Create.asResource("textures/models/armor/copper.png"); + private static final String TEXTURE_STRING = TEXTURE.toString(); + public CopperArmorItem(EquipmentSlotType p_i48534_2_, Properties p_i48534_3_) { - super(AllArmorMaterials.COPPER, p_i48534_2_, p_i48534_3_); + super(AllArmorMaterials.COPPER, p_i48534_2_, p_i48534_3_.stacksTo(1)); } public boolean isWornBy(Entity entity) { - for (ItemStack itemStack : entity.getArmorInventoryList()) - if (itemStack.getItem() == this) - return true; - return false; + if (!(entity instanceof LivingEntity)) + return false; + LivingEntity livingEntity = (LivingEntity) entity; + return livingEntity.getItemBySlot(slot).getItem() == this; } @Override public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlotType slot, String type) { - return String.format("%s:textures/models/armor/copper.png", Create.ID); + return TEXTURE_STRING; } } 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..d6a54c9dd 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 @@ -9,18 +9,21 @@ import com.simibubi.create.foundation.gui.GuiGameElement; 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.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import net.minecraft.block.BlockState; import net.minecraft.client.MainWindow; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.renderer.Atlases; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer.Impl; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererManager; +import net.minecraft.client.renderer.entity.IEntityRenderer; import net.minecraft.client.renderer.entity.LivingRenderer; +import net.minecraft.client.renderer.entity.PlayerRenderer; import net.minecraft.client.renderer.entity.layers.LayerRenderer; import net.minecraft.client.renderer.entity.model.BipedModel; import net.minecraft.client.renderer.entity.model.EntityModel; @@ -34,42 +37,39 @@ import net.minecraft.util.text.StringTextComponent; public class CopperBacktankArmorLayer> extends LayerRenderer { - private LivingRenderer renderer; - - public CopperBacktankArmorLayer(LivingRenderer renderer) { + public CopperBacktankArmorLayer(IEntityRenderer renderer) { super(renderer); - this.renderer = renderer; - renderer.addLayer(this); } @Override public void render(MatrixStack ms, IRenderTypeBuffer buffer, int light, LivingEntity entity, float yaw, float pitch, float pt, float p_225628_8_, float p_225628_9_, float p_225628_10_) { - if (entity.getPose() == Pose.SLEEPING) return; if (!AllItems.COPPER_BACKTANK.get() .isWornBy(entity)) return; - M entityModel = renderer.getEntityModel(); + M entityModel = getParentModel(); if (!(entityModel instanceof BipedModel)) return; - ms.push(); BipedModel model = (BipedModel) entityModel; + RenderType renderType = Atlases.cutoutBlockSheet(); BlockState renderedState = AllBlocks.COPPER_BACKTANK.getDefaultState() - .with(CopperBacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); - RenderType renderType = RenderType.getCutout(); - - SuperByteBuffer backtank = CreateClient.bufferCache.renderBlock(renderedState); + .setValue(CopperBacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); + 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.pushPose(); + + model.body.translateAndRotate(ms); ms.translate(-1 / 2f, 10 / 16f, 1f); ms.scale(1, -1, -1); - backtank.light(light) + + backtank.forEntityRender() + .light(light) .renderInto(ms, buffer.getBuffer(renderType)); cogs.matrixStacker() @@ -77,30 +77,32 @@ public class CopperBacktankArmorLayer renderer : renderManager.renderers.values()) registerOn(renderer); } - private static void registerOn(EntityRenderer entityRenderer) { + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static void registerOn(EntityRenderer entityRenderer) { if (!(entityRenderer instanceof LivingRenderer)) return; - new CopperBacktankArmorLayer<>((LivingRenderer) entityRenderer); + LivingRenderer livingRenderer = (LivingRenderer) entityRenderer; + if (!(livingRenderer.getModel() instanceof BipedModel)) + return; + CopperBacktankArmorLayer layer = new CopperBacktankArmorLayer<>(livingRenderer); + livingRenderer.addLayer((CopperBacktankArmorLayer) layer); } public static void renderRemainingAirOverlay(MatrixStack ms, Impl buffers, int light, int overlay, float pt) { @@ -112,30 +114,30 @@ public class CopperBacktankArmorLayer builder) { + protected void createBlockStateDefinition(Builder builder) { builder.add(BlockStateProperties.WATERLOGGED); - super.fillStateContainer(builder); + super.createBlockStateDefinition(builder); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState p_149740_1_) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState p_180641_1_, World world, BlockPos pos) { + return getTileEntityOptional(world, pos).map(CopperBacktankTileEntity::getComparatorOutput) + .orElse(0); } @Override - public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world, BlockPos pos, BlockPos neighbourPos) { - if (state.get(BlockStateProperties.WATERLOGGED)) { - world.getPendingFluidTicks() - .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + if (state.getValue(BlockStateProperties.WATERLOGGED)) { + world.getLiquidTicks() + .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); } return state; } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { - FluidState ifluidstate = context.getWorld() - .getFluidState(context.getPos()); - return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, - Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + FluidState ifluidstate = context.getLevel() + .getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, + Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)); } @Override @@ -89,55 +104,68 @@ public class CopperBacktankBlock extends HorizontalKineticBlock } @Override - public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { - super.onBlockPlacedBy(worldIn, pos, state, placer, stack); - if (worldIn.isRemote) + public void setPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + super.setPlacedBy(worldIn, pos, state, placer, stack); + if (worldIn.isClientSide) return; if (stack == null) return; withTileEntityDo(worldIn, pos, te -> { + te.setCapacityEnchantLevel(EnchantmentHelper.getItemEnchantmentLevel(AllEnchantments.CAPACITY.get(), stack)); te.setAirLevel(stack.getOrCreateTag() .getInt("Air")); - if (stack.hasDisplayName()) - te.setCustomName(stack.getDisplayName()); + if (stack.isEnchanted()) + te.setEnchantmentTag(stack.getEnchantmentTags()); + if (stack.hasCustomHoverName()) + te.setCustomName(stack.getHoverName()); }); } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand p_225533_5_, + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand p_225533_5_, BlockRayTraceResult p_225533_6_) { if (player == null) return ActionResultType.PASS; if (player instanceof FakePlayer) return ActionResultType.PASS; - if (player.isSneaking()) + if (player.isShiftKeyDown()) return ActionResultType.PASS; - if (player.getHeldItemMainhand() + if (player.getMainHandItem() .getItem() instanceof BlockItem) return ActionResultType.PASS; - if (!player.getItemStackFromSlot(EquipmentSlotType.CHEST) + if (!player.getItemBySlot(EquipmentSlotType.CHEST) .isEmpty()) return ActionResultType.PASS; - if (!world.isRemote) { - world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, .75f, 1); - player.setItemStackToSlot(EquipmentSlotType.CHEST, getItem(world, pos, state)); + if (!world.isClientSide) { + world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundCategory.PLAYERS, .75f, 1); + player.setItemSlot(EquipmentSlotType.CHEST, getCloneItemStack(world, pos, state)); world.destroyBlock(pos, false); } return ActionResultType.SUCCESS; } @Override - public ItemStack getItem(IBlockReader p_185473_1_, BlockPos p_185473_2_, BlockState p_185473_3_) { + public ItemStack getCloneItemStack(IBlockReader p_185473_1_, BlockPos p_185473_2_, BlockState p_185473_3_) { ItemStack item = AllItems.COPPER_BACKTANK.asStack(); Optional tileEntityOptional = getTileEntityOptional(p_185473_1_, p_185473_2_); + int air = tileEntityOptional.map(CopperBacktankTileEntity::getAirLevel) .orElse(0); + CompoundNBT tag = item.getOrCreateTag(); + tag.putInt("Air", air); + + ListNBT enchants = tileEntityOptional.map(CopperBacktankTileEntity::getEnchantmentTag) + .orElse(new ListNBT()); + if (!enchants.isEmpty()) { + ListNBT enchantmentTagList = item.getEnchantmentTags(); + enchantmentTagList.addAll(enchants); + tag.put("Enchantments", enchantmentTagList); + } + ITextComponent customName = tileEntityOptional.map(CopperBacktankTileEntity::getCustomName) .orElse(null); - item.getOrCreateTag() - .putInt("Air", air); if (customName != null) - item.setDisplayName(customName); + item.setHoverName(customName); return item; } @@ -158,7 +186,7 @@ public class CopperBacktankBlock extends HorizontalKineticBlock } @Override - public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { + public boolean isPathfindable(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } 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..ad251f267 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.material.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/CopperBacktankItem.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankItem.java index 571f8097d..81df65440 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankItem.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.curiosities.armor; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.curiosities.armor.CapacityEnchantment.ICapacityEnchantable; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.BlockItem; @@ -12,8 +12,9 @@ import net.minecraft.util.ActionResultType; import net.minecraft.util.NonNullList; import net.minecraft.util.math.MathHelper; -public class CopperBacktankItem extends CopperArmorItem { +public class CopperBacktankItem extends CopperArmorItem implements ICapacityEnchantable { + public static final int DURABILITY_BAR = 0xefefef; private BlockItem blockItem; public CopperBacktankItem(Properties p_i48534_3_, BlockItem blockItem) { @@ -22,28 +23,33 @@ public class CopperBacktankItem extends CopperArmorItem { } @Override - public ActionResultType onItemUse(ItemUseContext p_195939_1_) { - return blockItem.onItemUse(p_195939_1_); + public ActionResultType useOn(ItemUseContext p_195939_1_) { + return blockItem.useOn(p_195939_1_); } @Override - public boolean isDamageable() { + public boolean canBeDepleted() { return false; } + + @Override + public boolean isEnchantable(ItemStack p_77616_1_) { + return true; + } @Override public int getRGBDurabilityForDisplay(ItemStack stack) { - return 0xefefef; + return DURABILITY_BAR; } @Override - public void fillItemGroup(ItemGroup p_150895_1_, NonNullList p_150895_2_) { - if (!isInGroup(p_150895_1_)) + public void fillItemCategory(ItemGroup p_150895_1_, NonNullList p_150895_2_) { + if (!allowdedIn(p_150895_1_)) return; ItemStack stack = new ItemStack(this); CompoundNBT nbt = new CompoundNBT(); - nbt.putInt("Air", AllConfigs.SERVER.curiosities.maxAirInBacktank.get()); + nbt.putInt("Air", BackTankUtil.maxAirWithoutEnchants()); stack.setTag(nbt); p_150895_2_.add(stack); } @@ -51,7 +57,7 @@ public class CopperBacktankItem extends CopperArmorItem { @Override public double getDurabilityForDisplay(ItemStack stack) { return 1 - MathHelper - .clamp(getRemainingAir(stack) / ((float) AllConfigs.SERVER.curiosities.maxAirInBacktank.get()), 0, 1); + .clamp(getRemainingAir(stack) / ((float) BackTankUtil.maxAir(stack)), 0, 1); } @Override @@ -63,5 +69,5 @@ public class CopperBacktankItem extends CopperArmorItem { CompoundNBT orCreateTag = stack.getOrCreateTag(); return orCreateTag.getInt("Air"); } - + } 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..387f26e67 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 @@ -10,6 +10,7 @@ import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -26,19 +27,19 @@ public class CopperBacktankRenderer extends KineticTileEntityRenderer { int light, int overlay) { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); + BlockState blockState = te.getBlockState(); SuperByteBuffer cogs = - CreateClient.bufferCache.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, te.getBlockState()); + CreateClient.BUFFER_CACHE.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, blockState); cogs.matrixStacker() .centre() - .rotateY(180 + AngleHelper.horizontalAngle(te.getBlockState() - .get(CopperBacktankBlock.HORIZONTAL_FACING))) + .rotateY(180 + AngleHelper.horizontalAngle(blockState.getValue(CopperBacktankBlock.HORIZONTAL_FACING))) .unCentre() .translate(0, 6.5f / 16, 11f / 16) .rotate(Direction.EAST, - AngleHelper.rad(te.getSpeed() / 4f * AnimationTickHolder.getRenderTime(te.getWorld()) % 360)) + AngleHelper.rad(te.getSpeed() / 4f * AnimationTickHolder.getRenderTime(te.getLevel()) % 360)) .translate(0, -6.5f / 16, -11f / 16); cogs.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .renderInto(ms, buffer.getBuffer(RenderType.solid())); } @Override 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..b03b79038 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 @@ -5,12 +5,15 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.particle.AirParticleData; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.tileEntity.ComparatorUtil; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; import net.minecraft.particles.ParticleTypes; +import net.minecraft.state.BooleanProperty; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction.Axis; import net.minecraft.util.INameable; @@ -18,6 +21,7 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.common.util.Constants.NBT; public class CopperBacktankTileEntity extends KineticTileEntity implements INameable { @@ -25,8 +29,12 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName public int airLevelTimer; private ITextComponent customName; + private int capacityEnchantLevel; + private ListNBT enchantmentTag; + public CopperBacktankTileEntity(TileEntityType typeIn) { super(typeIn); + enchantmentTag = new ListNBT(); } @Override @@ -34,34 +42,94 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName super.tick(); if (getSpeed() == 0) return; + + BlockState state = getBlockState(); + BooleanProperty waterProperty = BlockStateProperties.WATERLOGGED; + if (state.hasProperty(waterProperty) && state.getValue(waterProperty)) + return; + if (airLevelTimer > 0) { airLevelTimer--; return; } - int max = getMaxAir(); - if (world.isRemote) { - Vector3d centerOf = VecHelper.getCenterOf(pos); - Vector3d v = VecHelper.offsetRandomly(centerOf, Create.random, .65f); + int max = BackTankUtil.maxAir(capacityEnchantLevel); + if (level.isClientSide) { + Vector3d centerOf = VecHelper.getCenterOf(worldPosition); + 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); + level.addParticle(new AirParticleData(1, .05f), v.x, v.y, v.z, m.x, m.y, m.z); return; } if (airLevel == max) return; + int prevComparatorLevel = getComparatorOutput(); float abs = Math.abs(getSpeed()); int increment = MathHelper.clamp(((int) abs - 100) / 20, 1, 5); airLevel = Math.min(max, airLevel + increment); + if (getComparatorOutput() != prevComparatorLevel && !level.isClientSide) + level.updateNeighbourForOutputSignal(worldPosition, state.getBlock()); if (airLevel == max) sendData(); airLevelTimer = MathHelper.clamp((int) (128f - abs / 5f) - 108, 0, 20); } - protected int getMaxAir() { - return AllConfigs.SERVER.curiosities.maxAirInBacktank.get(); + public int getComparatorOutput() { + int max = BackTankUtil.maxAir(capacityEnchantLevel); + return ComparatorUtil.fractionToRedstoneLevel(airLevel / (float) max); + } + + @Override + protected void write(CompoundNBT compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("Air", airLevel); + compound.putInt("Timer", airLevelTimer); + compound.putInt("CapacityEnchantment", capacityEnchantLevel); + if (this.customName != null) + compound.putString("CustomName", ITextComponent.Serializer.toJson(this.customName)); + compound.put("Enchantments", enchantmentTag); + } + + @Override + protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { + super.fromTag(state, compound, clientPacket); + int prev = airLevel; + capacityEnchantLevel = compound.getInt("CapacityEnchantment"); + airLevel = compound.getInt("Air"); + airLevelTimer = compound.getInt("Timer"); + enchantmentTag = compound.getList("Enchantments", NBT.TAG_COMPOUND); + if (compound.contains("CustomName", 8)) + this.customName = ITextComponent.Serializer.fromJson(compound.getString("CustomName")); + if (prev != 0 && prev != airLevel && airLevel == BackTankUtil.maxAir(capacityEnchantLevel) && clientPacket) + playFilledEffect(); + } + + protected void playFilledEffect() { + AllSoundEvents.CONFIRM.playAt(level, worldPosition, 0.4f, 1, true); + Vector3d baseMotion = new Vector3d(.25, 0.1, 0); + Vector3d baseVec = VecHelper.getCenterOf(worldPosition); + for (int i = 0; i < 360; i += 10) { + Vector3d m = VecHelper.rotate(baseMotion, i, Axis.Y); + Vector3d v = baseVec.add(m.normalize() + .scale(.25f)); + + level.addParticle(ParticleTypes.SPIT, v.x, v.y, v.z, m.x, m.y, m.z); + } + } + + @Override + public ITextComponent getName() { + return this.customName != null ? this.customName + : new TranslationTextComponent(AllItems.COPPER_BACKTANK.get() + .getDescriptionId()); + } + + @Override + public boolean shouldRenderNormally() { + return true; } public int getAirLevel() { @@ -81,50 +149,16 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName return customName; } - @Override - protected void write(CompoundNBT compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.putInt("Air", airLevel); - compound.putInt("Timer", airLevelTimer); - if (this.customName != null) - compound.putString("CustomName", ITextComponent.Serializer.toJson(this.customName)); + public ListNBT getEnchantmentTag() { + return enchantmentTag; } - @Override - protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { - super.fromTag(state, compound, clientPacket); - int prev = airLevel; - airLevel = compound.getInt("Air"); - airLevelTimer = compound.getInt("Timer"); - if (compound.contains("CustomName", 8)) - this.customName = ITextComponent.Serializer.fromJson(compound.getString("CustomName")); - if (prev != 0 && prev != airLevel && airLevel == getMaxAir() && clientPacket) - playFilledEffect(); + public void setEnchantmentTag(ListNBT enchantmentTag) { + this.enchantmentTag = enchantmentTag; } - protected void playFilledEffect() { - AllSoundEvents.CONFIRM.playAt(world, pos, 0.4f, 1, true); - Vector3d baseMotion = new Vector3d(.25, 0.1, 0); - Vector3d baseVec = VecHelper.getCenterOf(pos); - for (int i = 0; i < 360; i += 10) { - Vector3d m = VecHelper.rotate(baseMotion, i, Axis.Y); - Vector3d v = baseVec.add(m.normalize() - .scale(.25f)); - - world.addParticle(ParticleTypes.SPIT, v.x, v.y, v.z, m.x, m.y, m.z); - } - } - - @Override - public ITextComponent getName() { - return this.customName != null ? this.customName - : new TranslationTextComponent(AllItems.COPPER_BACKTANK.get() - .getTranslationKey()); - } - - @Override - public boolean shouldRenderAsTE() { - return true; + public void setCapacityEnchantLevel(int capacityEnchantLevel) { + this.capacityEnchantLevel = capacityEnchantLevel; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/DivingBootsItem.java b/src/main/java/com/simibubi/create/content/curiosities/armor/DivingBootsItem.java index 9b83bbb72..bde20ed32 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/DivingBootsItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/DivingBootsItem.java @@ -26,9 +26,9 @@ public class DivingBootsItem extends CopperArmorItem { if (!affects(entity)) return; - Vector3d motion = entity.getMotion(); - Boolean isJumping = ObfuscationReflectionHelper.getPrivateValue(LivingEntity.class, entity, "field_70703_bu"); - entity.onGround |= entity.collidedVertically; + Vector3d motion = entity.getDeltaMovement(); + Boolean isJumping = ObfuscationReflectionHelper.getPrivateValue(LivingEntity.class, entity, "field_70703_bu"); // jumping + entity.onGround |= entity.verticalCollision; if (isJumping && entity.onGround) { motion = motion.add(0, .5f, 0); @@ -38,10 +38,10 @@ public class DivingBootsItem extends CopperArmorItem { } float multiplier = 1.3f; - if (motion.mul(1, 0, 1) - .length() < 0.145f && (entity.moveForward > 0 || entity.moveStrafing != 0) && !entity.isSneaking()) - motion = motion.mul(multiplier, 1, multiplier); - entity.setMotion(motion); + if (motion.multiply(1, 0, 1) + .length() < 0.145f && (entity.zza > 0 || entity.xxa != 0) && !entity.isShiftKeyDown()) + motion = motion.multiply(multiplier, 1, multiplier); + entity.setDeltaMovement(motion); } protected static boolean affects(LivingEntity entity) { @@ -59,7 +59,7 @@ public class DivingBootsItem extends CopperArmorItem { return false; if (entity instanceof PlayerEntity) { PlayerEntity playerEntity = (PlayerEntity) entity; - if (playerEntity.abilities.isFlying) + if (playerEntity.abilities.flying) return false; } 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..18d5f81ed 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,12 @@ 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; @@ -23,50 +24,41 @@ public class DivingHelmetItem extends CopperArmorItem { @SubscribeEvent public static void breatheUnderwater(LivingUpdateEvent event) { LivingEntity entity = event.getEntityLiving(); - World world = entity.world; + World world = entity.level; boolean second = world.getGameTime() % 20 == 0; - boolean drowning = entity.getAir() == 0; - - if (world.isRemote) + boolean drowning = entity.getAirSupply() == 0; + + if (world.isClientSide) entity.getPersistentData() .remove("VisualBacktankAir"); if (!AllItems.DIVING_HELMET.get() .isWornBy(entity)) return; - if (!entity.isInWater()) + if (!entity.isEyeInFluid(FluidTags.WATER)) + return; + if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative()) return; - ItemStack backtank = ItemStack.EMPTY; - for (ItemStack itemStack : entity.getArmorInventoryList()) { - if (AllItems.COPPER_BACKTANK.isIn(itemStack)) { - backtank = itemStack; - break; - } - } - + ItemStack backtank = BackTankUtil.get(entity); if (backtank.isEmpty()) return; - - CompoundNBT tag = backtank.getOrCreateTag(); - int airRemaining = tag.getInt("Air"); - if (airRemaining == 0) + if (!BackTankUtil.hasAirRemaining(backtank)) return; if (drowning) - entity.setAir(10); + entity.setAirSupply(10); - if (world.isRemote) + if (world.isClientSide) entity.getPersistentData() - .putInt("VisualBacktankAir", airRemaining); + .putInt("VisualBacktankAir", (int) BackTankUtil.getAir(backtank)); if (!second) return; - entity.setAir(Math.min(entity.getMaxAir(), entity.getAir() + 10)); - entity.addPotionEffect(new EffectInstance(Effects.WATER_BREATHING, 30, 0, true, false, true)); - tag.putInt("Air", airRemaining - 1); - backtank.setTag(tag); + entity.setAirSupply(Math.min(entity.getMaxAirSupply(), entity.getAirSupply() + 10)); + entity.addEffect(new EffectInstance(Effects.WATER_BREATHING, 30, 0, true, false, true)); + BackTankUtil.consumeAir(backtank, 1); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellBlock.java b/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellBlock.java new file mode 100644 index 000000000..c3f4e7bc5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellBlock.java @@ -0,0 +1,99 @@ +package com.simibubi.create.content.curiosities.bell; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllShapes; +import com.simibubi.create.foundation.block.ITE; + +import net.minecraft.block.BellBlock; +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.state.properties.BellAttachment; +import net.minecraft.stats.Stats; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.World; + +public abstract class AbstractBellBlock extends BellBlock implements ITE { + + public AbstractBellBlock(Properties properties) { + super(properties); + } + + @Override + @Nullable + public TileEntity newBlockEntity(IBlockReader block) { + return null; + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader reader, BlockPos pos, ISelectionContext selection) { + Direction facing = state.getValue(FACING); + switch (state.getValue(ATTACHMENT)) { + case CEILING: + return AllShapes.BELL_CEILING.get(facing); + case DOUBLE_WALL: + return AllShapes.BELL_DOUBLE_WALL.get(facing); + case FLOOR: + return AllShapes.BELL_FLOOR.get(facing); + case SINGLE_WALL: + return AllShapes.BELL_WALL.get(facing); + default: + return VoxelShapes.block(); + } + } + + @Override + public boolean onHit(World world, BlockState state, BlockRayTraceResult hit, @Nullable PlayerEntity player, + boolean flag) { + BlockPos pos = hit.getBlockPos(); + Direction direction = hit.getDirection(); + if (direction == null) + direction = world.getBlockState(pos) + .getValue(FACING); + + if (!this.canRingFrom(state, direction, hit.getLocation().y - pos.getY())) + return false; + + TE te = getTileEntity(world, pos); + if (te == null || !te.ring(world, pos, direction)) + return false; + + if (!world.isClientSide) { + playSound(world, pos); + if (player != null) + player.awardStat(Stats.BELL_RING); + } + + return true; + } + + public boolean canRingFrom(BlockState state, Direction hitDir, double heightChange) { + if (hitDir.getAxis() == Direction.Axis.Y) + return false; + if (heightChange > 0.8124) + return false; + + Direction direction = state.getValue(FACING); + BellAttachment bellAttachment = state.getValue(ATTACHMENT); + switch (bellAttachment) { + case FLOOR: + case CEILING: + return direction.getAxis() == hitDir.getAxis(); + case SINGLE_WALL: + case DOUBLE_WALL: + return direction.getAxis() != hitDir.getAxis(); + default: + return false; + } + } + + public abstract void playSound(World world, BlockPos pos); + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellTileEntity.java new file mode 100644 index 000000000..0957d7f19 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellTileEntity.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.curiosities.bell; + +import java.util.List; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; + +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public abstract class AbstractBellTileEntity extends SmartTileEntity { + + public static final int RING_DURATION = 74; + + public boolean isRinging; + public int ringingTicks; + public Direction ringDirection; + + public AbstractBellTileEntity(TileEntityType type) { + super(type); + } + + @Override + public void addBehaviours(List behaviours) { } + + public boolean ring(World world, BlockPos pos, Direction direction) { + isRinging = true; + ringingTicks = 0; + ringDirection = direction; + return true; + }; + + @Override + public void tick() { + super.tick(); + + if (isRinging) { + ++ringingTicks; + } + + if (ringingTicks >= RING_DURATION) { + isRinging = false; + ringingTicks = 0; + } + } + + public abstract PartialModel getBellModel(); + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/BasicParticleData.java b/src/main/java/com/simibubi/create/content/curiosities/bell/BasicParticleData.java new file mode 100644 index 000000000..4ff8f8328 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/BasicParticleData.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.curiosities.bell; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.mojang.brigadier.StringReader; +import com.mojang.serialization.Codec; +import com.simibubi.create.content.contraptions.particle.ICustomParticleDataWithSprite; + +import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.client.particle.IAnimatedSprite; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleManager; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.network.PacketBuffer; +import net.minecraft.particles.IParticleData; +import net.minecraft.particles.ParticleType; +import net.minecraft.util.registry.Registry; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public abstract class BasicParticleData implements IParticleData, ICustomParticleDataWithSprite> { + + public BasicParticleData() { } + + @Override + public IDeserializer> getDeserializer() { + BasicParticleData data = this; + return new IParticleData.IDeserializer>() { + @Override + public BasicParticleData fromCommand(ParticleType> arg0, StringReader reader) { + return data; + } + + @Override + public BasicParticleData fromNetwork(ParticleType> type, PacketBuffer buffer) { + return data; + } + }; + } + + @Override + public Codec> getCodec(ParticleType> type) { + return Codec.unit(this); + } + + public interface IBasicParticleFactory { + U makeParticle(ClientWorld worldIn, double x, double y, double z, double vx, double vy, double vz, IAnimatedSprite sprite); + } + + @OnlyIn(Dist.CLIENT) + public abstract IBasicParticleFactory getBasicFactory(); + + @Override + @OnlyIn(Dist.CLIENT) + public ParticleManager.IParticleMetaFactory> getMetaFactory() { + return animatedSprite -> (data, worldIn, x, y, z, vx, vy, vz) -> + getBasicFactory().makeParticle(worldIn, x, y, z, vx, vy, vz, animatedSprite); + } + + @Override + public String writeToString() { + return Registry.PARTICLE_TYPE.getKey(getType()).toString(); + } + + @Override + public void writeToNetwork(PacketBuffer buffer) { } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/BellRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/bell/BellRenderer.java new file mode 100644 index 000000000..c32fce701 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/BellRenderer.java @@ -0,0 +1,49 @@ +package com.simibubi.create.content.curiosities.bell; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.render.PartialBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.block.BellBlock; +import net.minecraft.block.BlockState; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.state.properties.BellAttachment; +import net.minecraft.util.Direction; +import net.minecraft.util.math.MathHelper; + +public class BellRenderer extends SafeTileEntityRenderer { + + public BellRenderer(TileEntityRendererDispatcher dispatcher) { + super(dispatcher); + } + + @Override + protected void renderSafe(TE te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + BlockState state = te.getBlockState(); + Direction facing = state.getValue(BellBlock.FACING); + BellAttachment attachment = state.getValue(BellBlock.ATTACHMENT); + + SuperByteBuffer bell = PartialBufferer.get(te.getBellModel(), state); + + if (te.isRinging) + bell.rotateCentered(te.ringDirection.getCounterClockWise(), getSwingAngle(te.ringingTicks + partialTicks)); + + float rY = AngleHelper.horizontalAngle(facing); + if (attachment == BellAttachment.SINGLE_WALL || attachment == BellAttachment.DOUBLE_WALL) + rY += 90; + bell.rotateCentered(Direction.UP, AngleHelper.rad(rY)); + + bell.light(light) + .renderInto(ms, buffer.getBuffer(RenderType.cutout())); + } + + public static float getSwingAngle(float time) { + float t = time / 1.5f; + return 1.2f * MathHelper.sin(t / (float) Math.PI) / (2.5f + t / 3.0f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/CustomRotationParticle.java b/src/main/java/com/simibubi/create/content/curiosities/bell/CustomRotationParticle.java new file mode 100644 index 000000000..66e708d8d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/CustomRotationParticle.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.curiosities.bell; + +import com.jozufozu.flywheel.backend.OptifineHandler; +import com.mojang.blaze3d.vertex.IVertexBuilder; + +import net.minecraft.client.particle.IAnimatedSprite; +import net.minecraft.client.particle.SimpleAnimatedParticle; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.vector.Vector3f; + +public class CustomRotationParticle extends SimpleAnimatedParticle { + + protected boolean mirror; + protected int loopLength; + + public CustomRotationParticle(ClientWorld worldIn, double x, double y, double z, IAnimatedSprite spriteSet, float yAccel) { + super(worldIn, x, y, z, spriteSet, yAccel); + } + + public void selectSpriteLoopingWithAge(IAnimatedSprite sprite) { + int loopFrame = age % loopLength; + this.setSprite(sprite.get(loopFrame, loopLength)); + } + + public Quaternion getCustomRotation(ActiveRenderInfo camera, float partialTicks) { + Quaternion quaternion = new Quaternion(camera.rotation()); + if (roll != 0.0F) { + float angle = MathHelper.lerp(partialTicks, oRoll, roll); + quaternion.mul(Vector3f.ZP.rotation(angle)); + } + return quaternion; + } + + @Override + public void render(IVertexBuilder builder, ActiveRenderInfo camera, float partialTicks) { + Vector3d cameraPos = camera.getPosition(); + float originX = (float) (MathHelper.lerp(partialTicks, xo, x) - cameraPos.x()); + float originY = (float) (MathHelper.lerp(partialTicks, yo, y) - cameraPos.y()); + float originZ = (float) (MathHelper.lerp(partialTicks, zo, z) - cameraPos.z()); + + Vector3f[] vertices = new Vector3f[] { + new Vector3f(-1.0F, -1.0F, 0.0F), + new Vector3f(-1.0F, 1.0F, 0.0F), + new Vector3f(1.0F, 1.0F, 0.0F), + new Vector3f(1.0F, -1.0F, 0.0F) + }; + float scale = getQuadSize(partialTicks); + + Quaternion rotation = getCustomRotation(camera, partialTicks); + for(int i = 0; i < 4; ++i) { + Vector3f vertex = vertices[i]; + vertex.transform(rotation); + vertex.mul(scale); + vertex.add(originX, originY, originZ); + } + + float minU = mirror ? getU1() : getU0(); + float maxU = mirror ? getU0() : getU1(); + float minV = getV0(); + float maxV = getV1(); + int brightness = OptifineHandler.usingShaders() ? LightTexture.pack(12, 15 ) : getLightColor(partialTicks); + builder.vertex(vertices[0].x(), vertices[0].y(), vertices[0].z()).uv(maxU, maxV).color(rCol, gCol, bCol, alpha).uv2(brightness).endVertex(); + builder.vertex(vertices[1].x(), vertices[1].y(), vertices[1].z()).uv(maxU, minV).color(rCol, gCol, bCol, alpha).uv2(brightness).endVertex(); + builder.vertex(vertices[2].x(), vertices[2].y(), vertices[2].z()).uv(minU, minV).color(rCol, gCol, bCol, alpha).uv2(brightness).endVertex(); + builder.vertex(vertices[3].x(), vertices[3].y(), vertices[3].z()).uv(minU, maxV).color(rCol, gCol, bCol, alpha).uv2(brightness).endVertex(); + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellBlock.java b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellBlock.java new file mode 100644 index 000000000..7b02626a5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellBlock.java @@ -0,0 +1,39 @@ +package com.simibubi.create.content.curiosities.bell; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllTileEntities; + +import net.minecraft.block.BlockState; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.World; + +public class HauntedBellBlock extends AbstractBellBlock { + + public HauntedBellBlock(Properties properties) { + super(properties); + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return AllTileEntities.HAUNTED_BELL.create(); + } + + @Override + public Class getTileEntityClass() { + return HauntedBellTileEntity.class; + } + + @Override + public void playSound(World world, BlockPos pos) { + AllSoundEvents.HAUNTED_BELL_USE.playOnServer(world, pos, 4f, 1f); + } + + @Override + public void onPlace(BlockState state, World world, BlockPos pos, BlockState oldState, boolean isMoving) { + if (oldState.getBlock() != this) + withTileEntityDo(world, pos, HauntedBellTileEntity::startEffect); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellMovementBehaviour.java new file mode 100644 index 000000000..bbd46e191 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellMovementBehaviour.java @@ -0,0 +1,44 @@ +package com.simibubi.create.content.curiosities.bell; + +import com.simibubi.create.content.contraptions.components.actors.BellMovementBehaviour; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; + +import net.minecraft.util.math.BlockPos; + +public class HauntedBellMovementBehaviour extends BellMovementBehaviour { + + public static final int DISTANCE = 3; + + @Override + public void tick(MovementContext context) { + int recharge = getRecharge(context); + if (recharge > 0) + setRecharge(context, recharge - 1); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { + if (!context.world.isClientSide && getRecharge(context) == 0) { + HauntedBellPulser.sendPulse(context.world, pos, DISTANCE, false); + setRecharge(context, HauntedBellTileEntity.RECHARGE_TICKS); + playSound(context); + } + } + + @Override + public void writeExtraData(MovementContext context) { + context.tileData.putInt("Recharge", getRecharge(context)); + } + + private int getRecharge(MovementContext context) { + if (!(context.temporaryData instanceof Integer) && context.world != null) { + context.temporaryData = context.tileData.getInt("Recharge"); + } + return (Integer) context.temporaryData; + } + + private void setRecharge(MovementContext context, int value) { + context.temporaryData = value; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellPulser.java b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellPulser.java new file mode 100644 index 000000000..a26c96c1f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellPulser.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.curiosities.bell; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.IntAttached; + +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.network.PacketDistributor; + +@EventBusSubscriber +public class HauntedBellPulser { + + public static final int DISTANCE = 3; + public static final int RECHARGE_TICKS = 8; + public static final int WARMUP_TICKS = 10; + + public static final Cache> WARMUP = CacheBuilder.newBuilder() + .expireAfterAccess(250, TimeUnit.MILLISECONDS) + .build(); + + @SubscribeEvent + public static void hauntedBellCreatesPulse(TickEvent.PlayerTickEvent event) { + if (event.phase != TickEvent.Phase.END) + return; + if (event.side != LogicalSide.SERVER) + return; + if (event.player.isSpectator()) + return; + if (!event.player.isHolding(AllBlocks.HAUNTED_BELL::is)) + return; + + Entity player = event.player; + boolean firstPulse = false; + + try { + IntAttached ticker = WARMUP.get(player.getUUID(), () -> IntAttached.with(WARMUP_TICKS, player)); + firstPulse = ticker.getFirst() + .intValue() == 1; + ticker.decrement(); + if (!ticker.isOrBelowZero()) + return; + } catch (ExecutionException e) { + } + + long gameTime = player.level.getGameTime(); + if (firstPulse || gameTime % RECHARGE_TICKS != 0) + sendPulse(player.level, event.player.blockPosition(), DISTANCE, false); + } + + public static void sendPulse(World world, BlockPos pos, int distance, boolean canOverlap) { + Chunk chunk = world.getChunkAt(pos); + AllPackets.channel.send(PacketDistributor.TRACKING_CHUNK.with(() -> chunk), + new SoulPulseEffectPacket(pos, distance, canOverlap)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellTileEntity.java new file mode 100644 index 000000000..4847c815e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellTileEntity.java @@ -0,0 +1,108 @@ +package com.simibubi.create.content.curiosities.bell; + +import java.util.List; +import java.util.Random; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; + +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class HauntedBellTileEntity extends AbstractBellTileEntity { + + public static final int DISTANCE = 10; + public static final int RECHARGE_TICKS = 65; + public static final int EFFECT_TICKS = 20; + + public int effectTicks = 0; + + public HauntedBellTileEntity(TileEntityType type) { + super(type); + } + + @Override + public void addBehaviours(List behaviours) { } + + @Override + public PartialModel getBellModel() { + return AllBlockPartials.HAUNTED_BELL; + } + + @Override + public boolean ring(World world, BlockPos pos, Direction direction) { + if (isRinging && ringingTicks < RECHARGE_TICKS) + return false; + + if (!super.ring(world, pos, direction)) + return false; + + if (!world.isClientSide) + HauntedBellPulser.sendPulse(world, pos, DISTANCE, false); + + startEffect(); + + return true; + } + + public void startEffect() { + effectTicks = EFFECT_TICKS; + sendData(); + } + + @Override + protected void write(CompoundNBT compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("EffectTicks", effectTicks); + } + + @Override + protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { + super.fromTag(state, compound, clientPacket); + effectTicks = compound.getInt("EffectTicks"); + } + + @Override + public void tick() { + super.tick(); + + if (effectTicks <= 0) + return; + effectTicks--; + + if (!level.isClientSide) + return; + + Random rand = level.getRandom(); + if (rand.nextFloat() > 0.25f) + return; + + spawnParticle(rand); + playSound(rand); + } + + protected void spawnParticle(Random rand) { + double x = worldPosition.getX() + rand.nextDouble(); + double y = worldPosition.getY() + 0.5; + double z = worldPosition.getZ() + rand.nextDouble(); + double vx = rand.nextDouble() * 0.04 - 0.02; + double vy = 0.1; + double vz = rand.nextDouble() * 0.04 - 0.02; + level.addParticle(ParticleTypes.SOUL, x, y, z, vx, vy, vz); + } + + protected void playSound(Random rand) { + float vol = rand.nextFloat() * 0.4F + rand.nextFloat() > 0.9F ? 0.6F : 0.0F; + float pitch = 0.6F + rand.nextFloat() * 0.4F; + level.playSound(null, worldPosition, SoundEvents.SOUL_ESCAPE, SoundCategory.BLOCKS, vol, pitch); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellBlock.java b/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellBlock.java new file mode 100644 index 000000000..e701844c1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellBlock.java @@ -0,0 +1,96 @@ +package com.simibubi.create.content.curiosities.bell; + +import java.util.Random; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllTileEntities; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; + +public class PeculiarBellBlock extends AbstractBellBlock { + + public PeculiarBellBlock(Properties properties) { + super(properties); + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return AllTileEntities.PECULIAR_BELL.create(); + } + + @Override + public Class getTileEntityClass() { + return PeculiarBellTileEntity.class; + } + + @Override + public void playSound(World world, BlockPos pos) { + AllSoundEvents.PECULIAR_BELL_USE.playOnServer(world, pos, 2f, 0.94f); + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext ctx) { + BlockState newState = super.getStateForPlacement(ctx); + if (newState == null) + return null; + + World world = ctx.getLevel(); + BlockPos pos = ctx.getClickedPos(); + return tryConvert(world, pos, newState, world.getBlockState(pos.relative(Direction.DOWN))); + } + + @Override + public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, IWorld world, + BlockPos currentPos, BlockPos facingPos) { + BlockState newState = super.updateShape(state, facing, facingState, world, currentPos, facingPos); + if (facing != Direction.DOWN) + return newState; + + return tryConvert(world, currentPos, newState, facingState); + } + + protected BlockState tryConvert(IWorld world, BlockPos pos, BlockState state, BlockState underState) { + if (!AllBlocks.PECULIAR_BELL.has(state)) + return state; + + Block underBlock = underState.getBlock(); + if (!(Blocks.SOUL_FIRE.is(underBlock) || Blocks.SOUL_CAMPFIRE.is(underBlock))) + return state; + + if (world.isClientSide()) { + spawnConversionParticles(world, pos); + } else if (world instanceof World) { + AllSoundEvents.HAUNTED_BELL_CONVERT.playOnServer((World) world, pos); + } + + return AllBlocks.HAUNTED_BELL.getDefaultState() + .setValue(HauntedBellBlock.FACING, state.getValue(FACING)) + .setValue(HauntedBellBlock.ATTACHMENT, state.getValue(ATTACHMENT)) + .setValue(HauntedBellBlock.POWERED, state.getValue(POWERED)); + } + + public void spawnConversionParticles(IWorld world, BlockPos blockPos) { + Random random = world.getRandom(); + int num = random.nextInt(10) + 15; + for (int i = 0; i < num; i++) { + float pitch = random.nextFloat() * 120 - 90; + float yaw = random.nextFloat() * 360; + Vector3d vel = Vector3d.directionFromRotation(pitch, yaw).scale(random.nextDouble() * 0.1 + 0.1); + Vector3d pos = Vector3d.atCenterOf(blockPos); + world.addParticle(ParticleTypes.SOUL_FIRE_FLAME, pos.x, pos.y, pos.z, vel.x, vel.y, vel.z); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellTileEntity.java new file mode 100644 index 000000000..e58434e49 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellTileEntity.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.curiosities.bell; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllBlockPartials; + +import net.minecraft.tileentity.TileEntityType; + +public class PeculiarBellTileEntity extends AbstractBellTileEntity { + + public PeculiarBellTileEntity(TileEntityType type) { + super(type); + } + + @Override + public PartialModel getBellModel() { + return AllBlockPartials.PECULIAR_BELL; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulBaseParticle.java b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulBaseParticle.java new file mode 100644 index 000000000..d65e73073 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulBaseParticle.java @@ -0,0 +1,54 @@ +package com.simibubi.create.content.curiosities.bell; + +import com.simibubi.create.AllParticleTypes; + +import net.minecraft.client.particle.IAnimatedSprite; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.particles.ParticleType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3f; + +public class SoulBaseParticle extends CustomRotationParticle { + + private final IAnimatedSprite animatedSprite; + + public SoulBaseParticle(ClientWorld worldIn, double x, double y, double z, double vx, double vy, double vz, + IAnimatedSprite spriteSet) { + super(worldIn, x, y, z, spriteSet, 0); + this.animatedSprite = spriteSet; + this.quadSize = 0.5f; + this.setSize(this.quadSize, this.quadSize); + this.loopLength = 16 + (int) (this.random.nextFloat() * 2f - 1f); + this.lifetime = (int) (90.0F / (this.random.nextFloat() * 0.36F + 0.64F)); + this.selectSpriteLoopingWithAge(animatedSprite); + this.stoppedByCollision = true; // disable movement + } + + @Override + public void tick() { + selectSpriteLoopingWithAge(animatedSprite); + + BlockPos pos = new BlockPos(x, y, z); + if (age++ >= lifetime || !SoulPulseEffect.isDark(level, pos)) + remove(); + } + + @Override + public Quaternion getCustomRotation(ActiveRenderInfo camera, float partialTicks) { + return Vector3f.XP.rotationDegrees(90); + } + + public static class Data extends BasicParticleData { + @Override + public IBasicParticleFactory getBasicFactory() { + return SoulBaseParticle::new; + } + + @Override + public ParticleType getType() { + return AllParticleTypes.SOUL_BASE.get(); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulParticle.java b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulParticle.java new file mode 100644 index 000000000..32eb92bdf --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulParticle.java @@ -0,0 +1,264 @@ +package com.simibubi.create.content.curiosities.bell; + +import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.simibubi.create.AllParticleTypes; + +import net.minecraft.client.particle.IAnimatedSprite; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.particles.IParticleData; +import net.minecraft.particles.ParticleType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3f; + +public class SoulParticle extends CustomRotationParticle { + + private final IAnimatedSprite animatedSprite; + + protected int startTicks; + protected int endTicks; + protected int numLoops; + + protected int firstStartFrame = 0; + protected int startFrames = 17; + + protected int firstLoopFrame = 17; + protected int loopFrames = 16; + + protected int firstEndFrame = 33; + protected int endFrames = 20; + + protected AnimationStage animationStage; + + protected int totalFrames = 53; + protected int ticksPerFrame = 2; + + protected boolean isPerimeter = false; + protected boolean isExpandingPerimeter = false; + protected boolean isVisible = true; + protected int perimeterFrames = 8; + + public SoulParticle(ClientWorld worldIn, double x, double y, double z, double vx, double vy, double vz, + IAnimatedSprite spriteSet, IParticleData data) { + super(worldIn, x, y, z, spriteSet, 0); + this.animatedSprite = spriteSet; + this.quadSize = 0.5f; + this.setSize(this.quadSize, this.quadSize); + + this.loopLength = loopFrames + (int) (this.random.nextFloat() * 5f - 4f); + this.startTicks = startFrames + (int) (this.random.nextFloat() * 5f - 4f); + this.endTicks = endFrames + (int) (this.random.nextFloat() * 5f - 4f); + this.numLoops = (int) (1f + this.random.nextFloat() * 2f); + + this.setFrame(0); + this.stoppedByCollision = true; // disable movement + this.mirror = this.random.nextBoolean(); + + this.isPerimeter = data instanceof PerimeterData; + this.isExpandingPerimeter = data instanceof ExpandingPerimeterData; + this.animationStage = !isPerimeter ? new StartAnimation(this) : new PerimeterAnimation(this); + if (isPerimeter) { + yo = y -= .5f - 1 / 128f; + totalFrames = perimeterFrames; + isVisible = false; + } + } + + @Override + public void tick() { + animationStage.tick(); + animationStage = animationStage.getNext(); + + BlockPos pos = new BlockPos(x, y, z); + if (animationStage == null) + remove(); + if (!SoulPulseEffect.isDark(level, pos)) { + isVisible = true; + if (!isPerimeter) + remove(); + } else if (isPerimeter) + isVisible = false; + } + + @Override + public void render(IVertexBuilder builder, ActiveRenderInfo camera, float partialTicks) { + if (!isVisible) + return; + super.render(builder, camera, partialTicks); + } + + public void setFrame(int frame) { + if (frame >= 0 && frame < totalFrames) + setSprite(animatedSprite.get(frame, totalFrames)); + } + + @Override + public Quaternion getCustomRotation(ActiveRenderInfo camera, float partialTicks) { + if (isPerimeter) + return Vector3f.XP.rotationDegrees(90); + return new Quaternion(0, -camera.getYRot(), 0, true); + } + + public static class Data extends BasicParticleData { + @Override + public IBasicParticleFactory getBasicFactory() { + return (worldIn, x, y, z, vx, vy, vz, spriteSet) -> new SoulParticle(worldIn, x, y, z, vx, vy, vz, + spriteSet, this); + } + + @Override + public ParticleType getType() { + return AllParticleTypes.SOUL.get(); + } + } + + public static class PerimeterData extends BasicParticleData { + @Override + public IBasicParticleFactory getBasicFactory() { + return (worldIn, x, y, z, vx, vy, vz, spriteSet) -> new SoulParticle(worldIn, x, y, z, vx, vy, vz, + spriteSet, this); + } + + @Override + public ParticleType getType() { + return AllParticleTypes.SOUL_PERIMETER.get(); + } + } + + public static class ExpandingPerimeterData extends PerimeterData { + @Override + public ParticleType getType() { + return AllParticleTypes.SOUL_EXPANDING_PERIMETER.get(); + } + } + + public static abstract class AnimationStage { + + protected final SoulParticle particle; + + protected int ticks; + protected int animAge; + + public AnimationStage(SoulParticle particle) { + this.particle = particle; + } + + public void tick() { + ticks++; + + if (ticks % particle.ticksPerFrame == 0) + animAge++; + } + + public float getAnimAge() { + return (float) animAge; + } + + public abstract AnimationStage getNext(); + } + + public static class StartAnimation extends AnimationStage { + + public StartAnimation(SoulParticle particle) { + super(particle); + } + + @Override + public void tick() { + super.tick(); + + particle.setFrame( + particle.firstStartFrame + (int) (getAnimAge() / (float) particle.startTicks * particle.startFrames)); + } + + @Override + public AnimationStage getNext() { + if (animAge < particle.startTicks) + return this; + else + return new LoopAnimation(particle); + } + } + + public static class LoopAnimation extends AnimationStage { + + int loops; + + public LoopAnimation(SoulParticle particle) { + super(particle); + } + + @Override + public void tick() { + super.tick(); + + int loopTick = getLoopTick(); + + if (loopTick == 0) + loops++; + + particle.setFrame(particle.firstLoopFrame + loopTick);// (int) (((float) loopTick / (float) + // particle.loopLength) * particle.loopFrames)); + + } + + private int getLoopTick() { + return animAge % particle.loopFrames; + } + + @Override + public AnimationStage getNext() { + if (loops <= particle.numLoops) + return this; + else + return new EndAnimation(particle); + } + } + + public static class EndAnimation extends AnimationStage { + + public EndAnimation(SoulParticle particle) { + super(particle); + } + + @Override + public void tick() { + super.tick(); + + particle.setFrame( + particle.firstEndFrame + (int) ((getAnimAge() / (float) particle.endTicks) * particle.endFrames)); + + } + + @Override + public AnimationStage getNext() { + if (animAge < particle.endTicks) + return this; + else + return null; + } + } + + public static class PerimeterAnimation extends AnimationStage { + + public PerimeterAnimation(SoulParticle particle) { + super(particle); + } + + @Override + public void tick() { + super.tick(); + particle.setFrame((int) getAnimAge() % particle.perimeterFrames); + } + + @Override + public AnimationStage getNext() { + if (animAge < (particle.isExpandingPerimeter ? 8 + : particle.startTicks + particle.endTicks + particle.numLoops * particle.loopLength)) + return this; + else + return null; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffect.java b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffect.java new file mode 100644 index 000000000..437555c64 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffect.java @@ -0,0 +1,165 @@ +package com.simibubi.create.content.curiosities.bell; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.simibubi.create.content.curiosities.bell.SoulParticle.ExpandingPerimeterData; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.entity.EntitySpawnPlacementRegistry; +import net.minecraft.entity.EntityType; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.LightType; +import net.minecraft.world.World; +import net.minecraft.world.spawner.WorldEntitySpawner; + +public class SoulPulseEffect { + + public static final int MAX_DISTANCE = 11; + private static final List> LAYERS = genLayers(); + + private static final int WAITING_TICKS = 100; + public static final int TICKS_PER_LAYER = 6; + private int ticks; + public final BlockPos pos; + public final int distance; + public final List added; + + public SoulPulseEffect(BlockPos pos, int distance, boolean canOverlap) { + this.ticks = TICKS_PER_LAYER * distance; + this.pos = pos; + this.distance = distance; + this.added = canOverlap ? null : new ArrayList<>(); + } + + public boolean finished() { + return ticks <= -WAITING_TICKS; + } + + public boolean canOverlap() { + return added == null; + } + + public List tick(World world) { + if (finished()) + return null; + + ticks--; + if (ticks < 0 || ticks % TICKS_PER_LAYER != 0) + return null; + + List spawns = getPotentialSoulSpawns(world); + while (spawns.isEmpty() && ticks > 0) { + ticks -= TICKS_PER_LAYER; + spawns.addAll(getPotentialSoulSpawns(world)); + } + return spawns; + } + + public int currentLayerIdx() { + return distance - ticks / TICKS_PER_LAYER - 1; + } + + public List getPotentialSoulSpawns(World world) { + if (world == null) + return new ArrayList<>(); + + return getLayer(currentLayerIdx()).map(p -> p.offset(pos)) + .filter(p -> canSpawnSoulAt(world, p, true)) + .collect(Collectors.toList()); + } + + public static boolean isDark(World world, BlockPos at) { + return world.getBrightness(LightType.BLOCK, at) < 8; + } + + public static boolean canSpawnSoulAt(World world, BlockPos at, boolean ignoreLight) { + EntityType dummy = EntityType.ZOMBIE; + double dummyWidth = 0.2, dummyHeight = 0.75; + double w2 = dummyWidth / 2; + + return world != null + && WorldEntitySpawner + .isSpawnPositionOk(EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, world, at, dummy) + && (ignoreLight || isDark(world, at)) + && world + .getBlockCollisions(null, + new AxisAlignedBB(at.getX() + 0.5 - w2, at.getY(), at.getZ() + 0.5 - w2, at.getX() + 0.5 + w2, + at.getY() + dummyHeight, at.getZ() + 0.5 + w2), + (a, b) -> true) + .allMatch(VoxelShape::isEmpty); + } + + public void spawnParticles(World world, BlockPos at) { + if (world == null || !world.isClientSide) + return; + + Vector3d p = Vector3d.atLowerCornerOf(at); + if (canOverlap()) + world.addAlwaysVisibleParticle(((int) Math.round(VecHelper.getCenterOf(pos) + .distanceTo(VecHelper.getCenterOf(at)))) >= distance ? new SoulParticle.PerimeterData() + : new ExpandingPerimeterData(), + p.x + 0.5, p.y + 0.5, p.z + 0.5, 0, 0, 0); + if (world.getBrightness(LightType.BLOCK, at) < 8) { + world.addAlwaysVisibleParticle(new SoulParticle.Data(), p.x + 0.5, p.y + 0.5, p.z + 0.5, 0, 0, 0); + world.addParticle(new SoulBaseParticle.Data(), p.x + 0.5, p.y + 0.01, p.z + 0.5, 0, 0, 0); + } + } + + private static List> genLayers() { + List> layers = new ArrayList<>(); + for (int i = 0; i < MAX_DISTANCE; i++) + layers.add(new ArrayList<>()); + + for (int x = 0; x < MAX_DISTANCE; x++) { + for (int y = 0; y < MAX_DISTANCE; y++) { + for (int z = 0; z < MAX_DISTANCE; z++) { + BlockPos candidate = new BlockPos(x, y, z); + + int dist = (int) Math.round(Math.sqrt(candidate.distSqr(0, 0, 0, false))); + if (dist > MAX_DISTANCE) + continue; + if (dist <= 0) + dist = 1; + + List layer = layers.get(dist - 1); + int start = layer.size(), end = start + 1; + layer.add(candidate); + + if (candidate.getX() != 0) { + layer.add(new BlockPos(-candidate.getX(), candidate.getY(), candidate.getZ())); + end += 1; + } + if (candidate.getY() != 0) { + for (int i = start; i < end; i++) { + BlockPos prev = layer.get(i); + layer.add(new BlockPos(prev.getX(), -prev.getY(), prev.getZ())); + } + end += end - start; + } + if (candidate.getZ() != 0) { + for (int i = start; i < end; i++) { + BlockPos prev = layer.get(i); + layer.add(new BlockPos(prev.getX(), prev.getY(), -prev.getZ())); + } + } + } + } + } + + return layers; + } + + public static Stream getLayer(int idx) { + if (idx < 0 || idx >= MAX_DISTANCE) + return Stream.empty(); + return LAYERS.get(idx) + .stream(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectHandler.java b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectHandler.java new file mode 100644 index 000000000..c52d112bd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectHandler.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.curiosities.bell; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class SoulPulseEffectHandler { + + private List pulses; + private Set occupied; + + public SoulPulseEffectHandler() { + pulses = new ArrayList<>(); + occupied = new HashSet<>(); + } + + public void tick(World world) { + for (SoulPulseEffect pulse : pulses) { + List spawns = pulse.tick(world); + if (spawns == null) + continue; + + if (pulse.canOverlap()) { + for (BlockPos pos : spawns) { + pulse.spawnParticles(world, pos); + } + } else { + for (BlockPos pos : spawns) { + if (occupied.contains(pos)) + continue; + + pulse.spawnParticles(world, pos); + pulse.added.add(pos); + occupied.add(pos); + } + } + } + + for (SoulPulseEffect pulse : pulses) { + if (pulse.finished() && !pulse.canOverlap()) + occupied.removeAll(pulse.added); + } + pulses.removeIf(SoulPulseEffect::finished); + } + + public void addPulse(SoulPulseEffect pulse) { + pulses.add(pulse); + } + + public void refresh() { + pulses.clear(); + occupied.clear(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectPacket.java b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectPacket.java new file mode 100644 index 000000000..939c4aaf4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectPacket.java @@ -0,0 +1,45 @@ +package com.simibubi.create.content.curiosities.bell; + +import java.util.function.Supplier; + +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.network.NetworkEvent; + +public class SoulPulseEffectPacket extends SimplePacketBase { + + public BlockPos pos; + public int distance; + public boolean canOverlap; + + public SoulPulseEffectPacket(BlockPos pos, int distance, boolean overlaps) { + this.pos = pos; + this.distance = distance; + this.canOverlap = overlaps; + } + + public SoulPulseEffectPacket(PacketBuffer buffer) { + pos = buffer.readBlockPos(); + distance = buffer.readInt(); + canOverlap = buffer.readBoolean(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeBlockPos(pos); + buffer.writeInt(distance); + buffer.writeBoolean(canOverlap); + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + CreateClient.SOUL_PULSE_EFFECT_HANDLER.addPulse(new SoulPulseEffect(pos, distance, canOverlap)); + }); + context.get().setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/ConfigureSymmetryWandPacket.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/ConfigureSymmetryWandPacket.java new file mode 100644 index 000000000..9484111cc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/ConfigureSymmetryWandPacket.java @@ -0,0 +1,50 @@ +package com.simibubi.create.content.curiosities.symmetry; + +import java.util.function.Supplier; + +import com.simibubi.create.content.curiosities.symmetry.mirror.SymmetryMirror; +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.minecraft.util.Hand; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class ConfigureSymmetryWandPacket extends SimplePacketBase { + + protected Hand hand; + protected SymmetryMirror mirror; + + public ConfigureSymmetryWandPacket(Hand hand, SymmetryMirror mirror) { + this.hand = hand; + this.mirror = mirror; + } + + public ConfigureSymmetryWandPacket(PacketBuffer buffer) { + hand = buffer.readEnum(Hand.class); + mirror = SymmetryMirror.fromNBT(buffer.readNbt()); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeEnum(hand); + buffer.writeNbt(mirror.writeToNbt()); + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + ServerPlayerEntity player = context.get().getSender(); + if (player == null) { + return; + } + ItemStack stack = player.getItemInHand(hand); + if (stack.getItem() instanceof SymmetryWandItem) { + SymmetryWandItem.configureSettings(stack, mirror); + } + }); + context.get().setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java index 5ad5d2c63..90609b6a3 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java @@ -43,7 +43,7 @@ public class SymmetryEffectPacket extends SimplePacketBase { public void handle(Supplier ctx) { ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - if (Minecraft.getInstance().player.getPositionVec().distanceTo(Vector3d.of(mirror)) > 100) + if (Minecraft.getInstance().player.position().distanceTo(Vector3d.atLowerCornerOf(mirror)) > 100) return; for (BlockPos to : positions) SymmetryHandler.drawEffect(mirror, to); diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryHandler.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryHandler.java index d21926abf..644999081 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryHandler.java @@ -46,19 +46,19 @@ public class SymmetryHandler { @SubscribeEvent(priority = EventPriority.LOWEST) public static void onBlockPlaced(EntityPlaceEvent event) { if (event.getWorld() - .isRemote()) + .isClientSide()) return; if (!(event.getEntity() instanceof PlayerEntity)) return; PlayerEntity player = (PlayerEntity) event.getEntity(); PlayerInventory inv = player.inventory; - for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { - if (!inv.getStackInSlot(i) + for (int i = 0; i < PlayerInventory.getSelectionSize(); i++) { + if (!inv.getItem(i) .isEmpty() - && inv.getStackInSlot(i) + && inv.getItem(i) .getItem() == AllItems.WAND_OF_SYMMETRY.get()) { - SymmetryWandItem.apply(player.world, inv.getStackInSlot(i), player, event.getPos(), + SymmetryWandItem.apply(player.level, inv.getItem(i), player, event.getPos(), event.getPlacedBlock()); } } @@ -67,15 +67,15 @@ public class SymmetryHandler { @SubscribeEvent(priority = EventPriority.LOWEST) public static void onBlockDestroyed(BreakEvent event) { if (event.getWorld() - .isRemote()) + .isClientSide()) return; PlayerEntity player = event.getPlayer(); PlayerInventory inv = player.inventory; - for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { - if (!inv.getStackInSlot(i) - .isEmpty() && AllItems.WAND_OF_SYMMETRY.isIn(inv.getStackInSlot(i))) { - SymmetryWandItem.remove(player.world, inv.getStackInSlot(i), player, event.getPos()); + for (int i = 0; i < PlayerInventory.getSelectionSize(); i++) { + if (!inv.getItem(i) + .isEmpty() && AllItems.WAND_OF_SYMMETRY.isIn(inv.getItem(i))) { + SymmetryWandItem.remove(player.level, inv.getItem(i), player, event.getPos()); } } } @@ -86,8 +86,8 @@ public class SymmetryHandler { Minecraft mc = Minecraft.getInstance(); ClientPlayerEntity player = mc.player; - for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { - ItemStack stackInSlot = player.inventory.getStackInSlot(i); + for (int i = 0; i < PlayerInventory.getSelectionSize(); i++) { + ItemStack stackInSlot = player.inventory.getItem(i); if (!AllItems.WAND_OF_SYMMETRY.isIn(stackInSlot)) continue; if (!SymmetryWandItem.isEnabled(stackInSlot)) @@ -103,29 +103,29 @@ public class SymmetryHandler { yShift = MathHelper.sin((float) (AnimationTickHolder.getRenderTime() * speed)) / 5f; IRenderTypeBuffer.Impl buffer = Minecraft.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - ActiveRenderInfo info = mc.gameRenderer.getActiveRenderInfo(); - Vector3d view = info.getProjectedView(); + .renderBuffers() + .bufferSource(); + ActiveRenderInfo info = mc.gameRenderer.getMainCamera(); + Vector3d view = info.getPosition(); MatrixStack ms = event.getMatrixStack(); - ms.push(); - ms.translate(-view.getX(), -view.getY(), -view.getZ()); + ms.pushPose(); + ms.translate(-view.x(), -view.y(), -view.z()); ms.translate(pos.getX(), pos.getY(), pos.getZ()); ms.translate(0, yShift + .2f, 0); mirror.applyModelTransform(ms); IBakedModel model = mirror.getModel() .get(); - IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid()); + IVertexBuilder builder = buffer.getBuffer(RenderType.solid()); - mc.getBlockRendererDispatcher() - .getBlockModelRenderer() - .renderModel(player.world, model, Blocks.AIR.getDefaultState(), pos, ms, builder, true, - player.world.getRandom(), MathHelper.getPositionRandom(pos), OverlayTexture.DEFAULT_UV, + mc.getBlockRenderer() + .getModelRenderer() + .renderModel(player.level, model, Blocks.AIR.defaultBlockState(), pos, ms, builder, true, + player.level.getRandom(), MathHelper.getSeed(pos), OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE); - buffer.draw(); - ms.pop(); + buffer.endBatch(); + ms.popPose(); } } @@ -137,16 +137,16 @@ public class SymmetryHandler { Minecraft mc = Minecraft.getInstance(); ClientPlayerEntity player = mc.player; - if (mc.world == null) + if (mc.level == null) return; - if (mc.isGamePaused()) + if (mc.isPaused()) return; tickCounter++; if (tickCounter % 10 == 0) { - for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { - ItemStack stackInSlot = player.inventory.getStackInSlot(i); + for (int i = 0; i < PlayerInventory.getSelectionSize(); i++) { + ItemStack stackInSlot = player.inventory.getItem(i); if (stackInSlot != null && AllItems.WAND_OF_SYMMETRY.isIn(stackInSlot) && SymmetryWandItem.isEnabled(stackInSlot)) { @@ -162,7 +162,7 @@ public class SymmetryHandler { Vector3d pos = mirror.getPosition() .add(0.5 + offsetX, 1 / 4d, 0.5 + offsetZ); Vector3d speed = new Vector3d(0, r.nextDouble() * 1 / 8f, 0); - mc.world.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, speed.z); + mc.level.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, speed.z); } } } @@ -171,8 +171,8 @@ public class SymmetryHandler { public static void drawEffect(BlockPos from, BlockPos to) { double density = 0.8f; - Vector3d start = Vector3d.of(from).add(0.5, 0.5, 0.5); - Vector3d end = Vector3d.of(to).add(0.5, 0.5, 0.5); + Vector3d start = Vector3d.atLowerCornerOf(from).add(0.5, 0.5, 0.5); + Vector3d end = Vector3d.atLowerCornerOf(to).add(0.5, 0.5, 0.5); Vector3d diff = end.subtract(start); Vector3d step = diff.normalize() @@ -184,18 +184,18 @@ public class SymmetryHandler { Vector3d pos = start.add(step.scale(i)); Vector3d speed = new Vector3d(0, r.nextDouble() * -40f, 0); - Minecraft.getInstance().world.addParticle(new RedstoneParticleData(1, 1, 1, 1), pos.x, pos.y, pos.z, + Minecraft.getInstance().level.addParticle(new RedstoneParticleData(1, 1, 1, 1), pos.x, pos.y, pos.z, speed.x, speed.y, speed.z); } Vector3d speed = new Vector3d(0, r.nextDouble() * 1 / 32f, 0); Vector3d pos = start.add(step.scale(2)); - Minecraft.getInstance().world.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, + Minecraft.getInstance().level.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, speed.z); speed = new Vector3d(0, r.nextDouble() * 1 / 32f, 0); pos = start.add(step.scale(steps)); - Minecraft.getInstance().world.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, + Minecraft.getInstance().level.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, speed.z); } 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..c2a39906a 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; @@ -52,40 +54,40 @@ public class SymmetryWandItem extends Item { private static final String ENABLE = "enable"; public SymmetryWandItem(Properties properties) { - super(properties.maxStackSize(1) + super(properties.stacksTo(1) .rarity(Rarity.UNCOMMON)); } @Nonnull @Override - public ActionResultType onItemUse(ItemUseContext context) { + public ActionResultType useOn(ItemUseContext context) { PlayerEntity player = context.getPlayer(); - BlockPos pos = context.getPos(); + BlockPos pos = context.getClickedPos(); if (player == null) return ActionResultType.PASS; - player.getCooldownTracker() - .setCooldown(this, 5); - ItemStack wand = player.getHeldItem(context.getHand()); + player.getCooldowns() + .addCooldown(this, 5); + ItemStack wand = player.getItemInHand(context.getHand()); checkNBT(wand); // Shift -> open GUI - if (player.isSneaking()) { - if (player.world.isRemote) { + if (player.isShiftKeyDown()) { + if (player.level.isClientSide) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { openWandGUI(wand, context.getHand()); }); - player.getCooldownTracker() - .setCooldown(this, 5); + player.getCooldowns() + .addCooldown(this, 5); } return ActionResultType.SUCCESS; } - if (context.getWorld().isRemote || context.getHand() != Hand.MAIN_HAND) + if (context.getLevel().isClientSide || context.getHand() != Hand.MAIN_HAND) return ActionResultType.SUCCESS; CompoundNBT compound = wand.getTag() .getCompound(SYMMETRY); - pos = pos.offset(context.getFace()); + pos = pos.relative(context.getClickedFace()); SymmetryMirror previousElement = SymmetryMirror.fromNBT(compound); // No Shift -> Make / Move Mirror @@ -96,7 +98,7 @@ public class SymmetryWandItem extends Item { if (previousElement instanceof EmptyMirror) { newElement.setOrientation( - (player.getHorizontalFacing() == Direction.NORTH || player.getHorizontalFacing() == Direction.SOUTH) + (player.getDirection() == Direction.NORTH || player.getDirection() == Direction.SOUTH) ? PlaneMirror.Align.XY.ordinal() : PlaneMirror.Align.YZ.ordinal()); newElement.enable = true; @@ -108,13 +110,13 @@ public class SymmetryWandItem extends Item { if (previousElement instanceof PlaneMirror) { previousElement.setOrientation( - (player.getHorizontalFacing() == Direction.NORTH || player.getHorizontalFacing() == Direction.SOUTH) + (player.getDirection() == Direction.NORTH || player.getDirection() == Direction.SOUTH) ? PlaneMirror.Align.XY.ordinal() : PlaneMirror.Align.YZ.ordinal()); } if (previousElement instanceof CrossPlaneMirror) { - float rotation = player.getRotationYawHead(); + float rotation = player.getYHeadRot(); float abs = Math.abs(rotation % 90); boolean diagonal = abs > 22 && abs < 45 + 22; previousElement @@ -128,23 +130,23 @@ public class SymmetryWandItem extends Item { wand.getTag() .put(SYMMETRY, compound); - player.setHeldItem(context.getHand(), wand); + player.setItemInHand(context.getHand(), wand); return ActionResultType.SUCCESS; } @Override - public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { - ItemStack wand = playerIn.getHeldItem(handIn); + public ActionResult use(World worldIn, PlayerEntity playerIn, Hand handIn) { + ItemStack wand = playerIn.getItemInHand(handIn); checkNBT(wand); // Shift -> Open GUI - if (playerIn.isSneaking()) { - if (worldIn.isRemote) { + if (playerIn.isShiftKeyDown()) { + if (worldIn.isClientSide) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - openWandGUI(playerIn.getHeldItem(handIn), handIn); + openWandGUI(playerIn.getItemInHand(handIn), handIn); }); - playerIn.getCooldownTracker() - .setCooldown(this, 5); + playerIn.getCooldowns() + .addCooldown(this, 5); } return new ActionResult(ActionResultType.SUCCESS, wand); } @@ -179,15 +181,20 @@ public class SymmetryWandItem extends Item { public static SymmetryMirror getMirror(ItemStack stack) { checkNBT(stack); - return SymmetryMirror.fromNBT((CompoundNBT) stack.getTag() + return SymmetryMirror.fromNBT(stack.getTag() .getCompound(SYMMETRY)); } + public static void configureSettings(ItemStack stack, SymmetryMirror mirror) { + checkNBT(stack); + stack.getTag().put(SYMMETRY, mirror.writeToNbt()); + } + public static void apply(World world, ItemStack wand, PlayerEntity player, BlockPos pos, BlockState block) { checkNBT(wand); if (!isEnabled(wand)) return; - if (!BlockItem.BLOCK_TO_ITEM.containsKey(block.getBlock())) + if (!BlockItem.BY_BLOCK.containsKey(block.getBlock())) return; Map blockSet = new HashMap<>(); @@ -196,7 +203,7 @@ public class SymmetryWandItem extends Item { .getCompound(SYMMETRY)); Vector3d mirrorPos = symmetry.getPosition(); - if (mirrorPos.distanceTo(Vector3d.of(pos)) > AllConfigs.SERVER.curiosities.maxSymmetryWandRange.get()) + if (mirrorPos.distanceTo(Vector3d.atLowerCornerOf(pos)) > AllConfigs.SERVER.curiosities.maxSymmetryWandRange.get()) return; if (!player.isCreative() && isHoldingBlock(player, block) && BlockHelper.findAndRemoveInInventory(block, player, 1) == 0) @@ -211,31 +218,40 @@ public class SymmetryWandItem extends Item { if (position.equals(pos)) continue; - if (world.canPlace(block, position, ISelectionContext.forEntity(player))) { + if (world.isUnobstructed(block, position, ISelectionContext.of(player))) { BlockState blockState = blockSet.get(position); for (Direction face : Iterate.directions) - blockState = blockState.updatePostPlacement(face, world.getBlockState(position.offset(face)), world, - position, position.offset(face)); + blockState = blockState.updateShape(face, world.getBlockState(position.relative(face)), world, + position, position.relative(face)); if (player.isCreative()) { - world.setBlockState(position, blockState); + world.setBlockAndUpdate(position, blockState); targets.add(position); continue; } 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) + if (toReplace.getDestroySpeed(world, position) == -1) continue; - BlockSnapshot blocksnapshot = BlockSnapshot.create(world.getRegistryKey(), world, position); + 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.dimension(), world, position); FluidState ifluidstate = world.getFluidState(position); - world.setBlockState(position, ifluidstate.getBlockState(), BlockFlags.UPDATE_NEIGHBORS); - world.setBlockState(position, blockState); + world.setBlock(position, ifluidstate.createLegacyBlock(), BlockFlags.UPDATE_NEIGHBORS); + world.setBlockAndUpdate(position, blockState); CompoundNBT wandNbt = wand.getOrCreateTag(); wandNbt.putBoolean("Simulate", true); @@ -256,14 +272,14 @@ public class SymmetryWandItem extends Item { private static boolean isHoldingBlock(PlayerEntity player, BlockState block) { ItemStack itemBlock = BlockHelper.getRequiredItem(block); - return player.getHeldItemMainhand() - .isItemEqual(itemBlock) - || player.getHeldItemOffhand() - .isItemEqual(itemBlock); + return player.getMainHandItem() + .sameItem(itemBlock) + || player.getOffhandItem() + .sameItem(itemBlock); } public static void remove(World world, ItemStack wand, PlayerEntity player, BlockPos pos) { - BlockState air = Blocks.AIR.getDefaultState(); + BlockState air = Blocks.AIR.defaultBlockState(); BlockState ogBlock = world.getBlockState(pos); checkNBT(wand); if (!isEnabled(wand)) @@ -275,7 +291,7 @@ public class SymmetryWandItem extends Item { .getCompound(SYMMETRY)); Vector3d mirrorPos = symmetry.getPosition(); - if (mirrorPos.distanceTo(Vector3d.of(pos)) > AllConfigs.SERVER.curiosities.maxSymmetryWandRange.get()) + if (mirrorPos.distanceTo(Vector3d.atLowerCornerOf(pos)) > AllConfigs.SERVER.curiosities.maxSymmetryWandRange.get()) return; symmetry.process(blockSet); @@ -294,16 +310,16 @@ public class SymmetryWandItem extends Item { BlockState blockstate = world.getBlockState(position); if (blockstate.getMaterial() != Material.AIR) { targets.add(position); - world.playEvent(2001, position, Block.getStateId(blockstate)); - world.setBlockState(position, air, 3); + world.levelEvent(2001, position, Block.getId(blockstate)); + world.setBlock(position, air, 3); if (!player.isCreative()) { - if (!player.getHeldItemMainhand() + if (!player.getMainHandItem() .isEmpty()) - player.getHeldItemMainhand() - .onBlockDestroyed(world, blockstate, position, player); - TileEntity tileentity = blockstate.hasTileEntity() ? world.getTileEntity(position) : null; - Block.spawnDrops(blockstate, world, pos, tileentity, player, player.getHeldItemMainhand()); // Add fortune, silk touch and other loot modifiers + player.getMainHandItem() + .mineBlock(world, blockstate, position, player); + TileEntity tileentity = blockstate.hasTileEntity() ? world.getBlockEntity(position) : null; + Block.dropResources(blockstate, world, pos, tileentity, player, player.getMainHandItem()); // Add fortune, silk touch and other loot modifiers } } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandScreen.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandScreen.java index bc2ebd9ef..875326f8b 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandScreen.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandScreen.java @@ -15,21 +15,19 @@ import com.simibubi.create.foundation.gui.widgets.Label; 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.networking.NbtPacket; import com.simibubi.create.foundation.utility.Lang; -import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Hand; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; -import net.minecraftforge.fml.network.PacketDistributor; public class SymmetryWandScreen extends AbstractSimiScreen { + private AllGuiTextures background; + private ScrollInput areaType; private Label labelType; private ScrollInput areaAlign; @@ -44,7 +42,7 @@ public class SymmetryWandScreen extends AbstractSimiScreen { private Hand hand; public SymmetryWandScreen(ItemStack wand, Hand hand) { - super(); + background = AllGuiTextures.WAND_OF_SYMMETRY; currentElement = SymmetryWandItem.getMirror(wand); if (currentElement instanceof EmptyMirror) { @@ -56,19 +54,23 @@ public class SymmetryWandScreen extends AbstractSimiScreen { @Override public void init() { + setWindowSize(background.width, background.height); + setWindowOffset(-20, 0); super.init(); - AllGuiTextures background = AllGuiTextures.WAND_OF_SYMMETRY; - this.setWindowSize(background.width + 50, background.height + 50); + widgets.clear(); - labelType = new Label(guiLeft + 49, guiTop + 28, StringTextComponent.EMPTY).colored(0xFFFFFFFF) + int x = guiLeft; + int y = guiTop; + + labelType = new Label(x + 49, y + 28, StringTextComponent.EMPTY).colored(0xFFFFFFFF) .withShadow(); - labelAlign = new Label(guiLeft + 49, guiTop + 50, StringTextComponent.EMPTY).colored(0xFFFFFFFF) + labelAlign = new Label(x + 49, y + 50, StringTextComponent.EMPTY).colored(0xFFFFFFFF) .withShadow(); int state = currentElement instanceof TriplePlaneMirror ? 2 : currentElement instanceof CrossPlaneMirror ? 1 : 0; - areaType = new SelectionScrollInput(guiLeft + 45, guiTop + 21, 109, 18).forOptions(SymmetryMirror.getMirrors()) - .titled(mirrorType.copy()) + areaType = new SelectionScrollInput(x + 45, y + 21, 109, 18).forOptions(SymmetryMirror.getMirrors()) + .titled(mirrorType.plainCopy()) .writingTo(labelType) .setState(state); @@ -86,28 +88,25 @@ public class SymmetryWandScreen extends AbstractSimiScreen { default: break; } - initAlign(currentElement); + initAlign(currentElement, x, y); }); - widgets.clear(); - - initAlign(currentElement); + initAlign(currentElement, x, y); widgets.add(labelAlign); widgets.add(areaType); widgets.add(labelType); - confirmButton = new IconButton(guiLeft + background.width - 33, guiTop + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); widgets.add(confirmButton); - } - private void initAlign(SymmetryMirror element) { + private void initAlign(SymmetryMirror element, int x, int y) { if (areaAlign != null) widgets.remove(areaAlign); - areaAlign = new SelectionScrollInput(guiLeft + 45, guiTop + 43, 109, 18).forOptions(element.getAlignToolTips()) - .titled(orientation.copy()) + areaAlign = new SelectionScrollInput(x + 45, y + 43, 109, 18).forOptions(element.getAlignToolTips()) + .titled(orientation.plainCopy()) .writingTo(labelAlign) .setState(element.getOrientationIndex()) .calling(element::setOrientation); @@ -116,45 +115,44 @@ public class SymmetryWandScreen extends AbstractSimiScreen { } @Override - protected void renderWindow(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { - AllGuiTextures.WAND_OF_SYMMETRY.draw(matrixStack, this, guiLeft, guiTop); - textRenderer.draw(matrixStack, wand.getDisplayName(), guiLeft + 11, guiTop + 4, 0x6B3802); - renderBlock(matrixStack); + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + background.draw(ms, this, x, y); + font.draw(ms, wand.getHoverName(), x + 11, y + 4, 0x6B3802); + + renderBlock(ms, x, y); GuiGameElement.of(wand) .scale(4) .rotate(-70, 20, 20) - .at(guiLeft + 170, guiTop + 490, -150) - .render(matrixStack); + .at(x + 178, y + 448, -150) + .render(ms); } - protected void renderBlock(MatrixStack ms) { - ms.push(); - ms.translate(guiLeft + 26f, guiTop + 39, 20); + protected void renderBlock(MatrixStack ms, int x, int y) { + ms.pushPose(); + ms.translate(x + 26, y + 39, 20); ms.scale(16, 16, 16); - ms.multiply(new Vector3f(.3f, 1f, 0f).getDegreesQuaternion(-22.5f)); + ms.mulPose(new Vector3f(.3f, 1f, 0f).rotationDegrees(-22.5f)); currentElement.applyModelTransform(ms); // RenderSystem.multMatrix(ms.peek().getModel()); GuiGameElement.of(currentElement.getModel()) .render(ms); - ms.pop(); + ms.popPose(); } @Override public void removed() { - ItemStack heldItem = client.player.getHeldItem(hand); - CompoundNBT compound = heldItem.getTag(); - compound.put(SymmetryWandItem.SYMMETRY, currentElement.writeToNbt()); - heldItem.setTag(compound); - AllPackets.channel.send(PacketDistributor.SERVER.noArg(), new NbtPacket(heldItem, hand)); - client.player.setHeldItem(hand, heldItem); - super.removed(); + SymmetryWandItem.configureSettings(wand, currentElement); + AllPackets.channel.sendToServer(new ConfigureSymmetryWandPacket(hand, currentElement)); } @Override public boolean mouseClicked(double x, double y, int button) { if (confirmButton.isHovered()) { - Minecraft.getInstance().player.closeScreen(); + onClose(); return true; } 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..ef8089330 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,11 +1,12 @@ 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; +import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.ItemCameraTransforms; import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; @@ -27,9 +28,14 @@ public class SymmetryWandItemRenderer extends CustomRenderedItemModelRenderer= 0 && slot < 9) + return stack; + return super.insertItem(slot, stack, simulate); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/RadialToolboxMenu.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/RadialToolboxMenu.java new file mode 100644 index 000000000..406f8cd54 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/RadialToolboxMenu.java @@ -0,0 +1,342 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import java.util.List; + +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllKeys; +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.networking.AllPackets; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraft.client.util.InputMappings; +import net.minecraft.item.DyeColor; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextFormatting; + +public class RadialToolboxMenu extends AbstractSimiScreen { + + public static enum State { + SELECT_BOX, SELECT_ITEM, SELECT_ITEM_UNEQUIP, DETACH + } + + private State state; + private int ticksOpen; + private int hoveredSlot; + private boolean scrollMode; + private int scrollSlot = 0; + private List toolboxes; + private ToolboxTileEntity selectedBox; + + private static final int DEPOSIT = -7; + private static final int UNEQUIP = -5; + + public RadialToolboxMenu(List toolboxes, State state) { + this.toolboxes = toolboxes; + this.state = state; + hoveredSlot = -1; + + if (state == State.SELECT_ITEM_UNEQUIP || state == State.SELECT_ITEM) + selectedBox = toolboxes.get(0); + } + + public void prevSlot(int slot) { + scrollSlot = slot; + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + float fade = MathHelper.clamp((ticksOpen + AnimationTickHolder.getPartialTicks()) / 10f, 1 / 512f, 1); + + hoveredSlot = -1; + MainWindow window = getMinecraft().getWindow(); + float hoveredX = mouseX - window.getGuiScaledWidth() / 2; + float hoveredY = mouseY - window.getGuiScaledHeight() / 2; + + float distance = hoveredX * hoveredX + hoveredY * hoveredY; + if (distance > 25 && distance < 10000) + hoveredSlot = + (MathHelper.floor((AngleHelper.deg(MathHelper.atan2(hoveredY, hoveredX)) + 360 + 180 - 22.5f)) % 360) + / 45; + boolean renderCenterSlot = state == State.SELECT_ITEM_UNEQUIP; + if (scrollMode && distance > 150) + scrollMode = false; + if (renderCenterSlot && distance <= 150) + hoveredSlot = UNEQUIP; + + ms.pushPose(); + ms.translate(width / 2, height / 2, 0); + ITextComponent tip = null; + + if (state == State.DETACH) { + + tip = Lang.translate("toolbox.outOfRange"); + if (hoveredX > -20 && hoveredX < 20 && hoveredY > -80 && hoveredY < -20) + hoveredSlot = UNEQUIP; + + ms.pushPose(); + AllGuiTextures.TOOLBELT_INACTIVE_SLOT.draw(ms, this, -12, -12); + GuiGameElement.of(AllBlocks.TOOLBOXES.get(DyeColor.BROWN) + .asStack()) + .at(-9, -9) + .render(ms); + + ms.translate(0, -40 + (10 * (1 - fade) * (1 - fade)), 0); + AllGuiTextures.TOOLBELT_SLOT.draw(ms, this, -12, -12); + ms.translate(-0.5, 0.5, 0); + AllIcons.I_DISABLE.draw(ms, this, -9, -9); + ms.translate(0.5, -0.5, 0); + if (!scrollMode && hoveredSlot == UNEQUIP) { + AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -13, -13); + tip = Lang.translate("toolbox.detach") + .withStyle(TextFormatting.GOLD); + } + ms.popPose(); + + } else { + + if (hoveredX > 60 && hoveredX < 100 && hoveredY > -20 && hoveredY < 20) + hoveredSlot = DEPOSIT; + + ms.pushPose(); + ms.translate(80 + (-5 * (1 - fade) * (1 - fade)), 0, 0); + AllGuiTextures.TOOLBELT_SLOT.draw(ms, this, -12, -12); + ms.translate(-0.5, 0.5, 0); + AllIcons.I_TOOLBOX.draw(ms, this, -9, -9); + ms.translate(0.5, -0.5, 0); + if (!scrollMode && hoveredSlot == DEPOSIT) { + AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -13, -13); + tip = Lang.translate(state == State.SELECT_BOX ? "toolbox.depositAll" : "toolbox.depositBox") + .withStyle(TextFormatting.GOLD); + } + ms.popPose(); + + for (int slot = 0; slot < 8; slot++) { + ms.pushPose(); + MatrixTransformStack.of(ms) + .rotateZ(slot * 45 - 45) + .translate(0, -40 + (10 * (1 - fade) * (1 - fade)), 0) + .rotateZ(-slot * 45 + 45); + ms.translate(-12, -12, 0); + + if (state == State.SELECT_ITEM || state == State.SELECT_ITEM_UNEQUIP) { + ToolboxInventory inv = selectedBox.inventory; + ItemStack stackInSlot = inv.filters.get(slot); + + if (!stackInSlot.isEmpty()) { + boolean empty = inv.getStackInSlot(slot * ToolboxInventory.STACKS_PER_COMPARTMENT) + .isEmpty(); + + (empty ? AllGuiTextures.TOOLBELT_INACTIVE_SLOT : AllGuiTextures.TOOLBELT_SLOT).draw(ms, this, 0, + 0); + GuiGameElement.of(stackInSlot) + .at(3, 3) + .render(ms); + + if (slot == (scrollMode ? scrollSlot : hoveredSlot) && !empty) { + AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -1, -1); + tip = stackInSlot.getHoverName(); + } + } else + AllGuiTextures.TOOLBELT_EMPTY_SLOT.draw(ms, this, 0, 0); + + } else if (state == State.SELECT_BOX) { + + if (slot < toolboxes.size()) { + AllGuiTextures.TOOLBELT_SLOT.draw(ms, this, 0, 0); + ToolboxTileEntity toolboxTileEntity = toolboxes.get(slot); + GuiGameElement.of(AllBlocks.TOOLBOXES.get(toolboxTileEntity.getColor()) + .asStack()) + .at(3, 3) + .render(ms); + + if (slot == (scrollMode ? scrollSlot : hoveredSlot)) { + AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -1, -1); + tip = toolboxTileEntity.getDisplayName(); + } + } else + AllGuiTextures.TOOLBELT_EMPTY_SLOT.draw(ms, this, 0, 0); + + } + + ms.popPose(); + } + + if (renderCenterSlot) { + ms.pushPose(); + AllGuiTextures.TOOLBELT_SLOT.draw(ms, this, -12, -12); + (scrollMode ? AllIcons.I_REFRESH : AllIcons.I_FLIP).draw(ms, this, -9, -9); + if (!scrollMode && UNEQUIP == hoveredSlot) { + AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -13, -13); + tip = Lang.translate("toolbox.unequip", minecraft.player.getMainHandItem() + .getHoverName()) + .withStyle(TextFormatting.GOLD); + } + ms.popPose(); + } + } + ms.popPose(); + + if (tip != null) { + int i1 = (int) (fade * 255.0F); + if (i1 > 255) + i1 = 255; + + if (i1 > 8) { + ms.pushPose(); + ms.translate((float) (width / 2), (float) (height - 68), 0.0F); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + int k1 = 16777215; + int k = i1 << 24 & -16777216; + int l = font.width(tip); + font.draw(ms, tip, (float) (-l / 2), -4.0F, k1 | k); + RenderSystem.disableBlend(); + ms.popPose(); + } + } + + } + + @Override + public void renderBackground(MatrixStack p_238651_1_, int p_238651_2_) { + int a = ((int) (0x50 * Math.min(1, (ticksOpen + AnimationTickHolder.getPartialTicks()) / 20f))) << 24; + fillGradient(p_238651_1_, 0, 0, this.width, this.height, 0x101010 | a, 0x101010 | a); + } + + @Override + public void tick() { + ticksOpen++; + super.tick(); + } + + @Override + public void removed() { + super.removed(); + + int selected = (scrollMode ? scrollSlot : hoveredSlot); + + if (selected == DEPOSIT) { + if (state == State.DETACH) + return; + else if (state == State.SELECT_BOX) + toolboxes.forEach(te -> AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(te.getBlockPos()))); + else + AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(selectedBox.getBlockPos())); + return; + } + + if (state == State.SELECT_BOX) + return; + + if (state == State.DETACH) { + if (selected == UNEQUIP) + AllPackets.channel.sendToServer( + new ToolboxEquipPacket(null, selected, Minecraft.getInstance().player.inventory.selected)); + return; + } + + if (selected == UNEQUIP) + AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected, + Minecraft.getInstance().player.inventory.selected)); + + if (selected < 0) + return; + ToolboxInventory inv = selectedBox.inventory; + ItemStack stackInSlot = inv.filters.get(selected); + if (stackInSlot.isEmpty()) + return; + if (inv.getStackInSlot(selected * ToolboxInventory.STACKS_PER_COMPARTMENT) + .isEmpty()) + return; + + AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected, + Minecraft.getInstance().player.inventory.selected)); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + MainWindow window = getMinecraft().getWindow(); + double hoveredX = mouseX - window.getGuiScaledWidth() / 2; + double hoveredY = mouseY - window.getGuiScaledHeight() / 2; + double distance = hoveredX * hoveredX + hoveredY * hoveredY; + if (distance <= 150) { + scrollMode = true; + scrollSlot = (((int) (scrollSlot - delta)) + 8) % 8; + for (int i = 0; i < 10; i++) { + + if (state == State.SELECT_ITEM || state == State.SELECT_ITEM_UNEQUIP) { + ToolboxInventory inv = selectedBox.inventory; + ItemStack stackInSlot = inv.filters.get(scrollSlot); + if (!stackInSlot.isEmpty() + && !inv.getStackInSlot(scrollSlot * ToolboxInventory.STACKS_PER_COMPARTMENT) + .isEmpty()) + break; + } + + if (state == State.SELECT_BOX) + if (scrollSlot < toolboxes.size()) + break; + + if (state == State.DETACH) + break; + + scrollSlot -= MathHelper.sign(delta); + scrollSlot = (scrollSlot + 8) % 8; + } + return true; + } + + return super.mouseScrolled(mouseX, mouseY, delta); + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + int selected = (scrollMode ? scrollSlot : hoveredSlot); + + if (selected == DEPOSIT) { + onClose(); + ToolboxHandlerClient.COOLDOWN = 2; + return true; + } + + if (state == State.SELECT_BOX && selected >= 0 && selected < toolboxes.size()) { + state = State.SELECT_ITEM; + selectedBox = toolboxes.get(selected); + return true; + } + + if (state == State.DETACH || state == State.SELECT_ITEM || state == State.SELECT_ITEM_UNEQUIP) { + if (selected == UNEQUIP || selected >= 0) { + onClose(); + ToolboxHandlerClient.COOLDOWN = 2; + return true; + } + } + + return super.mouseClicked(x, y, button); + } + + @Override + public boolean keyReleased(int code, int p_keyPressed_2_, int p_keyPressed_3_) { + InputMappings.Input mouseKey = InputMappings.getKey(code, p_keyPressed_2_); + if (AllKeys.TOOLBELT.getKeybind() + .isActiveAndMatches(mouseKey)) { + this.onClose(); + return true; + } + return super.keyReleased(code, p_keyPressed_2_, p_keyPressed_3_); + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxBlock.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxBlock.java new file mode 100644 index 000000000..4fe4c4615 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxBlock.java @@ -0,0 +1,190 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import static net.minecraft.state.properties.BlockStateProperties.WATERLOGGED; + +import java.util.Optional; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllShapes; +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.block.ITE; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.HorizontalBlock; +import net.minecraft.block.IWaterLoggable; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.DyeColor; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.nbt.CompoundNBT; +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.Hand; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.fml.network.NetworkHooks; + +public class ToolboxBlock extends HorizontalBlock implements IWaterLoggable, ITE { + + private final DyeColor color; + + public ToolboxBlock(Properties p_i48440_1_, DyeColor color) { + super(p_i48440_1_); + this.color = color; + registerDefaultState(super.defaultBlockState().setValue(WATERLOGGED, false)); + } + + @Override + public void fillItemCategory(ItemGroup group, NonNullList p_149666_2_) { + if (group != ItemGroup.TAB_SEARCH && color != DyeColor.BROWN) + return; + super.fillItemCategory(group, p_149666_2_); + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(WATERLOGGED) + .add(FACING)); + } + + @Override + public void setPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + super.setPlacedBy(worldIn, pos, state, placer, stack); + if (worldIn.isClientSide) + return; + if (stack == null) + return; + withTileEntityDo(worldIn, pos, te -> { + te.readInventory(stack.getOrCreateTag() + .getCompound("Inventory")); + if (stack.hasCustomHoverName()) + te.setCustomName(stack.getHoverName()); + }); + } + + @Override + public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean moving) { + if (state.hasTileEntity() && (!state.is(newState.getBlock()) || !newState.hasTileEntity())) + world.removeBlockEntity(pos); + } + + @Override + public void attack(BlockState state, World world, BlockPos pos, PlayerEntity player) { + if (player instanceof FakePlayer) + return; + if (world.isClientSide) + return; + withTileEntityDo(world, pos, ToolboxTileEntity::unequipTracked); + if (world instanceof ServerWorld) { + ItemStack cloneItemStack = getCloneItemStack(world, pos, state); + world.destroyBlock(pos, false); + if (world.getBlockState(pos) != state) + player.inventory.placeItemBackInInventory(world, cloneItemStack); + } + } + + @Override + public ItemStack getCloneItemStack(IBlockReader world, BlockPos pos, BlockState state) { + ItemStack item = new ItemStack(this); + Optional tileEntityOptional = getTileEntityOptional(world, pos); + + CompoundNBT tag = item.getOrCreateTag(); + CompoundNBT inv = tileEntityOptional.map(tb -> tb.inventory.serializeNBT()) + .orElse(new CompoundNBT()); + tag.put("Inventory", inv); + + ITextComponent customName = tileEntityOptional.map(ToolboxTileEntity::getCustomName) + .orElse(null); + if (customName != null) + item.setHoverName(customName); + return item; + } + + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world, + BlockPos pos, BlockPos neighbourPos) { + if (state.getValue(WATERLOGGED)) + world.getLiquidTicks() + .scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + return state; + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, + ISelectionContext p_220053_4_) { + return AllShapes.TOOLBOX.get(state.getValue(FACING)); + } + + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } + + @Override + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + BlockRayTraceResult ray) { + + if (player == null || player.isCrouching()) + return ActionResultType.PASS; + if (player instanceof FakePlayer) + return ActionResultType.PASS; + if (world.isClientSide) + return ActionResultType.SUCCESS; + + withTileEntityDo(world, pos, + toolbox -> NetworkHooks.openGui((ServerPlayerEntity) player, toolbox, toolbox::sendToContainer)); + return ActionResultType.SUCCESS; + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return AllTileEntities.TOOLBOX.create(); + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + FluidState ifluidstate = context.getLevel() + .getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(FACING, context.getHorizontalDirection() + .getOpposite()) + .setValue(WATERLOGGED, Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)); + } + + @Override + public Class getTileEntityClass() { + return ToolboxTileEntity.class; + } + + public DyeColor getColor() { + return color; + } + + public static Ingredient getMainBox() { + return Ingredient.of(AllBlocks.TOOLBOXES.get(DyeColor.BROWN) + .get()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxContainer.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxContainer.java new file mode 100644 index 000000000..7856d3bec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxContainer.java @@ -0,0 +1,158 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import static com.simibubi.create.content.curiosities.toolbox.ToolboxInventory.STACKS_PER_COMPARTMENT; + +import com.simibubi.create.AllContainerTypes; +import com.simibubi.create.foundation.gui.ContainerBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.world.ClientWorld; +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.nbt.CompoundNBT; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.items.SlotItemHandler; + +public class ToolboxContainer extends ContainerBase { + + public static ToolboxContainer create(int id, PlayerInventory inv, ToolboxTileEntity te) { + return new ToolboxContainer(AllContainerTypes.TOOLBOX.get(), id, inv, te); + } + + public ToolboxContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id, inv, extraData); + } + + public ToolboxContainer(ContainerType type, int id, PlayerInventory inv, ToolboxTileEntity te) { + super(type, id, inv, te); + te.startOpen(player); + } + + @Override + protected ToolboxTileEntity createOnClient(PacketBuffer extraData) { + BlockPos readBlockPos = extraData.readBlockPos(); + CompoundNBT readNbt = extraData.readNbt(); + + ClientWorld world = Minecraft.getInstance().level; + TileEntity tileEntity = world.getBlockEntity(readBlockPos); + if (tileEntity instanceof ToolboxTileEntity) { + ToolboxTileEntity toolbox = (ToolboxTileEntity) tileEntity; + toolbox.handleUpdateTag(toolbox.getBlockState(), readNbt); + return toolbox; + } + + return null; + } + + @Override + public ItemStack quickMoveStack(PlayerEntity player, int index) { + Slot clickedSlot = getSlot(index); + if (!clickedSlot.hasItem()) + return ItemStack.EMPTY; + + ItemStack stack = clickedSlot.getItem(); + int size = contentHolder.inventory.getSlots(); + if (index < size) { + moveItemStackTo(stack, size, slots.size(), false); + contentHolder.inventory.onContentsChanged(index); + } else + moveItemStackTo(stack, 0, size - 1, false); + + return ItemStack.EMPTY; + } + + @Override + protected void initAndReadInventory(ToolboxTileEntity contentHolder) { + + } + + @Override + public ItemStack clicked(int index, int flags, ClickType type, PlayerEntity player) { + int size = contentHolder.inventory.getSlots(); + + if (index >= 0 && index < size) { + + ItemStack itemInClickedSlot = getSlot(index).getItem(); + PlayerInventory playerInv = player.inventory; + ItemStack carried = playerInv.getCarried(); + + if (type == ClickType.PICKUP && !carried.isEmpty() && !itemInClickedSlot.isEmpty() + && ToolboxInventory.canItemsShareCompartment(itemInClickedSlot, carried)) { + int subIndex = index % STACKS_PER_COMPARTMENT; + if (subIndex != STACKS_PER_COMPARTMENT - 1) + return clicked(index - subIndex + STACKS_PER_COMPARTMENT - 1, flags, type, player); + } + + if (type == ClickType.PICKUP && carried.isEmpty() && itemInClickedSlot.isEmpty()) + if (!player.level.isClientSide) { + contentHolder.inventory.filters.set(index / STACKS_PER_COMPARTMENT, ItemStack.EMPTY); + contentHolder.sendData(); + } + + } + return super.clicked(index, flags, type, player); + } + + @Override + public boolean canDragTo(Slot slot) { + return slot.index > contentHolder.inventory.getSlots() && super.canDragTo(slot); + } + + public ItemStack getFilter(int compartment) { + return contentHolder.inventory.filters.get(compartment); + } + + public int totalCountInCompartment(int compartment) { + int count = 0; + int baseSlot = compartment * STACKS_PER_COMPARTMENT; + for (int i = 0; i < STACKS_PER_COMPARTMENT; i++) + count += getSlot(baseSlot + i).getItem() + .getCount(); + return count; + } + + public boolean renderPass; + + @Override + protected void addSlots() { + ToolboxInventory inventory = contentHolder.inventory; + + int x = 59; + int y = 37; + + int[] xOffsets = { x, x + 33, x + 66, x + 66 + 6, x + 66, x + 33, x, x - 6 }; + int[] yOffsets = { y, y - 6, y, y + 33, y + 66, y + 66 + 6, y + 66, y + 33 }; + + for (int compartment = 0; compartment < 8; compartment++) { + int baseIndex = compartment * STACKS_PER_COMPARTMENT; + + // Representative Slots + addSlot(new ToolboxSlot(this, inventory, baseIndex, xOffsets[compartment], yOffsets[compartment])); + + // Hidden Slots + for (int i = 1; i < STACKS_PER_COMPARTMENT; i++) + addSlot(new SlotItemHandler(inventory, baseIndex + i, -100, -100)); + } + + addPlayerSlots(-12, 166); + } + + @Override + protected void saveData(ToolboxTileEntity contentHolder) { + + } + + @Override + public void removed(PlayerEntity playerIn) { + super.removed(playerIn); + if (!playerIn.level.isClientSide) + contentHolder.stopOpen(playerIn); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDisposeAllPacket.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDisposeAllPacket.java new file mode 100644 index 000000000..071c61df6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDisposeAllPacket.java @@ -0,0 +1,81 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import java.util.function.Supplier; + +import org.apache.commons.lang3.mutable.MutableBoolean; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.network.NetworkEvent.Context; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ToolboxDisposeAllPacket extends SimplePacketBase { + + private BlockPos toolboxPos; + + public ToolboxDisposeAllPacket(BlockPos toolboxPos) { + this.toolboxPos = toolboxPos; + } + + public ToolboxDisposeAllPacket(PacketBuffer buffer) { + toolboxPos = buffer.readBlockPos(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeBlockPos(toolboxPos); + } + + @Override + public void handle(Supplier context) { + Context ctx = context.get(); + ctx.enqueueWork(() -> { + ServerPlayerEntity player = ctx.getSender(); + World world = player.level; + TileEntity blockEntity = world.getBlockEntity(toolboxPos); + + double maxRange = ToolboxHandler.getMaxRange(player); + if (player.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(), toolboxPos.getZ() + 0.5) > maxRange + * maxRange) + return; + if (!(blockEntity instanceof ToolboxTileEntity)) + return; + ToolboxTileEntity toolbox = (ToolboxTileEntity) blockEntity; + + CompoundNBT compound = player.getPersistentData() + .getCompound("CreateToolboxData"); + MutableBoolean sendData = new MutableBoolean(false); + + toolbox.inventory.inLimitedMode(inventory -> { + for (int i = 0; i < 36; i++) { + String key = String.valueOf(i); + if (compound.contains(key) && NBTUtil.readBlockPos(compound.getCompound(key) + .getCompound("Pos")) + .equals(toolboxPos)) { + ToolboxHandler.unequip(player, i, true); + sendData.setTrue(); + } + + ItemStack itemStack = player.inventory.getItem(i); + ItemStack remainder = ItemHandlerHelper.insertItemStacked(toolbox.inventory, itemStack, false); + if (remainder.getCount() != itemStack.getCount()) + player.inventory.setItem(i, remainder); + } + }); + + if (sendData.booleanValue()) + ToolboxHandler.syncData(player); + + }); + ctx.setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxEquipPacket.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxEquipPacket.java new file mode 100644 index 000000000..1c3b39e7a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxEquipPacket.java @@ -0,0 +1,108 @@ +package com.simibubi.create.content.curiosities.toolbox; + +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.nbt.CompoundNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.network.NetworkEvent.Context; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ToolboxEquipPacket extends SimplePacketBase { + + private BlockPos toolboxPos; + private int slot; + private int hotbarSlot; + + public ToolboxEquipPacket(BlockPos toolboxPos, int slot, int hotbarSlot) { + this.toolboxPos = toolboxPos; + this.slot = slot; + this.hotbarSlot = hotbarSlot; + } + + public ToolboxEquipPacket(PacketBuffer buffer) { + if (buffer.readBoolean()) + toolboxPos = buffer.readBlockPos(); + slot = buffer.readVarInt(); + hotbarSlot = buffer.readVarInt(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeBoolean(toolboxPos != null); + if (toolboxPos != null) + buffer.writeBlockPos(toolboxPos); + buffer.writeVarInt(slot); + buffer.writeVarInt(hotbarSlot); + } + + @Override + public void handle(Supplier context) { + Context ctx = context.get(); + ctx.enqueueWork(() -> { + ServerPlayerEntity player = ctx.getSender(); + World world = player.level; + + if (toolboxPos == null) { + ToolboxHandler.unequip(player, hotbarSlot, false); + ToolboxHandler.syncData(player); + return; + } + + TileEntity blockEntity = world.getBlockEntity(toolboxPos); + + double maxRange = ToolboxHandler.getMaxRange(player); + if (player.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(), toolboxPos.getZ() + 0.5) > maxRange + * maxRange) + return; + if (!(blockEntity instanceof ToolboxTileEntity)) + return; + + ToolboxHandler.unequip(player, hotbarSlot, false); + + if (slot < 0 || slot >= 8) { + ToolboxHandler.syncData(player); + return; + } + + ToolboxTileEntity toolboxTileEntity = (ToolboxTileEntity) blockEntity; + + ItemStack playerStack = player.inventory.getItem(hotbarSlot); + if (!playerStack.isEmpty() && !ToolboxInventory.canItemsShareCompartment(playerStack, + toolboxTileEntity.inventory.filters.get(slot))) { + toolboxTileEntity.inventory.inLimitedMode(inventory -> { + ItemStack remainder = ItemHandlerHelper.insertItemStacked(inventory, playerStack, false); + if (!remainder.isEmpty()) + remainder = ItemHandlerHelper.insertItemStacked(new ItemReturnInvWrapper(player.inventory), + remainder, false); + if (remainder.getCount() != playerStack.getCount()) + player.inventory.setItem(hotbarSlot, remainder); + }); + } + + CompoundNBT compound = player.getPersistentData() + .getCompound("CreateToolboxData"); + String key = String.valueOf(hotbarSlot); + + CompoundNBT data = new CompoundNBT(); + data.putInt("Slot", slot); + data.put("Pos", NBTUtil.writeBlockPos(toolboxPos)); + compound.put(key, data); + + player.getPersistentData() + .put("CreateToolboxData", compound); + + toolboxTileEntity.connectPlayer(slot, player, hotbarSlot); + ToolboxHandler.syncData(player); + }); + ctx.setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandler.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandler.java new file mode 100644 index 000000000..e21a775be --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandler.java @@ -0,0 +1,153 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import java.util.List; +import java.util.WeakHashMap; +import java.util.stream.Collectors; + +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.networking.ISyncPersistentData; +import com.simibubi.create.foundation.utility.WorldAttached; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.fml.network.PacketDistributor; + +public class ToolboxHandler { + + public static final WorldAttached> toolboxes = + new WorldAttached<>(w -> new WeakHashMap<>()); + + public static void onLoad(ToolboxTileEntity te) { + toolboxes.get(te.getLevel()) + .put(te.getBlockPos(), te); + } + + public static void onUnload(ToolboxTileEntity te) { + toolboxes.get(te.getLevel()) + .remove(te.getBlockPos()); + } + + static int validationTimer = 20; + + public static void entityTick(Entity entity, World world) { + if (world.isClientSide) + return; + if (!(world instanceof ServerWorld)) + return; + if (!(entity instanceof ServerPlayerEntity)) + return; + if (entity.tickCount % validationTimer != 0) + return; + + ServerPlayerEntity player = (ServerPlayerEntity) entity; + if (!player.getPersistentData() + .contains("CreateToolboxData")) + return; + + boolean sendData = false; + CompoundNBT compound = player.getPersistentData() + .getCompound("CreateToolboxData"); + for (int i = 0; i < 9; i++) { + String key = String.valueOf(i); + if (!compound.contains(key)) + continue; + + CompoundNBT data = compound.getCompound(key); + BlockPos pos = NBTUtil.readBlockPos(data.getCompound("Pos")); + int slot = data.getInt("Slot"); + + if (!world.isAreaLoaded(pos, 0)) + continue; + if (!(world.getBlockState(pos) + .getBlock() instanceof ToolboxBlock)) { + compound.remove(key); + sendData = true; + continue; + } + + TileEntity prevBlockEntity = world.getBlockEntity(pos); + if (prevBlockEntity instanceof ToolboxTileEntity) + ((ToolboxTileEntity) prevBlockEntity).connectPlayer(slot, player, i); + } + + if (sendData) + syncData(player); + } + + public static void playerLogin(PlayerEntity player) { + if (!(player instanceof ServerPlayerEntity)) + return; + if (player.getPersistentData() + .contains("CreateToolboxData") + && !player.getPersistentData() + .getCompound("CreateToolboxData") + .isEmpty()) { + syncData(player); + } + } + + public static void syncData(PlayerEntity player) { + AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), + new ISyncPersistentData.Packet(player)); + } + + public static List getNearest(IWorld world, PlayerEntity player, int maxAmount) { + Vector3d location = player.position(); + double maxRange = getMaxRange(player); + return toolboxes.get(world) + .keySet() + .stream() + .filter(p -> distance(location, p) < maxRange * maxRange) + .sorted((p1, p2) -> Double.compare(distance(location, p1), distance(location, p2))) + .limit(maxAmount) + .map(toolboxes.get(world)::get) + .collect(Collectors.toList()); + } + + public static void unequip(PlayerEntity player, int hotbarSlot, boolean keepItems) { + CompoundNBT compound = player.getPersistentData() + .getCompound("CreateToolboxData"); + World world = player.level; + String key = String.valueOf(hotbarSlot); + if (!compound.contains(key)) + return; + + CompoundNBT prevData = compound.getCompound(key); + BlockPos prevPos = NBTUtil.readBlockPos(prevData.getCompound("Pos")); + int prevSlot = prevData.getInt("Slot"); + + TileEntity prevBlockEntity = world.getBlockEntity(prevPos); + if (prevBlockEntity instanceof ToolboxTileEntity) { + ToolboxTileEntity toolbox = (ToolboxTileEntity) prevBlockEntity; + toolbox.unequip(prevSlot, player, hotbarSlot, keepItems || !ToolboxHandler.withinRange(player, toolbox)); + } + compound.remove(key); + } + + public static boolean withinRange(PlayerEntity player, ToolboxTileEntity box) { + if (player.level != box.getLevel()) + return false; + double maxRange = getMaxRange(player); + return distance(player.position(), box.getBlockPos()) < maxRange * maxRange; + } + + public static double distance(Vector3d location, BlockPos p) { + return location.distanceToSqr(p.getX() + 0.5f, p.getY(), p.getZ() + 0.5f); + } + + public static double getMaxRange(PlayerEntity player) { + return AllConfigs.SERVER.curiosities.toolboxRange.get() + .doubleValue(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandlerClient.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandlerClient.java new file mode 100644 index 000000000..741eb326b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandlerClient.java @@ -0,0 +1,185 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import static com.simibubi.create.foundation.gui.AllGuiTextures.TOOLBELT_HOTBAR_OFF; +import static com.simibubi.create.foundation.gui.AllGuiTextures.TOOLBELT_HOTBAR_ON; +import static com.simibubi.create.foundation.gui.AllGuiTextures.TOOLBELT_SELECTED_OFF; +import static com.simibubi.create.foundation.gui.AllGuiTextures.TOOLBELT_SELECTED_ON; + +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.AllKeys; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.networking.AllPackets; + +import net.minecraft.block.BlockState; +import net.minecraft.block.material.Material; +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.EntityRayTraceResult; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; + +public class ToolboxHandlerClient { + + static int COOLDOWN = 0; + + public static void clientTick() { + if (COOLDOWN > 0 && !AllKeys.TOOLBELT.isPressed()) + COOLDOWN--; + } + + public static boolean onPickItem() { + Minecraft mc = Minecraft.getInstance(); + ClientPlayerEntity player = mc.player; + if (player == null) + return false; + World level = player.level; + RayTraceResult hitResult = mc.hitResult; + + if (hitResult == null || hitResult.getType() == RayTraceResult.Type.MISS) + return false; + if (player.isCreative()) + return false; + + ItemStack result = ItemStack.EMPTY; + List toolboxes = ToolboxHandler.getNearest(player.level, player, 8); + + if (toolboxes.isEmpty()) + return false; + + if (hitResult.getType() == RayTraceResult.Type.BLOCK) { + BlockPos pos = ((BlockRayTraceResult) hitResult).getBlockPos(); + BlockState state = level.getBlockState(pos); + if (state.getMaterial() == Material.AIR) + return false; + result = state.getPickBlock(hitResult, level, pos, player); + + } else if (hitResult.getType() == RayTraceResult.Type.ENTITY) { + Entity entity = ((EntityRayTraceResult) hitResult).getEntity(); + result = entity.getPickedResult(hitResult); + } + + if (result.isEmpty()) + return false; + + for (ToolboxTileEntity toolboxTileEntity : toolboxes) { + ToolboxInventory inventory = toolboxTileEntity.inventory; + for (int comp = 0; comp < 8; comp++) { + ItemStack inSlot = inventory.takeFromCompartment(1, comp, true); + if (inSlot.isEmpty()) + continue; + if (inSlot.getItem() != result.getItem()) + continue; + if (!ItemStack.tagMatches(inSlot, result)) + continue; + + AllPackets.channel.sendToServer( + new ToolboxEquipPacket(toolboxTileEntity.getBlockPos(), comp, player.inventory.selected)); + return true; + } + + } + + return false; + } + + public static void onKeyInput(int key, boolean pressed) { + if (key != AllKeys.TOOLBELT.getBoundCode()) + return; + if (COOLDOWN > 0) + return; + ClientPlayerEntity player = Minecraft.getInstance().player; + if (player == null) + return; + World level = player.level; + + List toolboxes = ToolboxHandler.getNearest(player.level, player, 8); + CompoundNBT compound = player.getPersistentData() + .getCompound("CreateToolboxData"); + + String slotKey = String.valueOf(player.inventory.selected); + boolean equipped = compound.contains(slotKey); + + if (equipped) { + BlockPos pos = NBTUtil.readBlockPos(compound.getCompound(slotKey) + .getCompound("Pos")); + double max = ToolboxHandler.getMaxRange(player); + boolean canReachToolbox = ToolboxHandler.distance(player.position(), pos) < max * max; + + if (canReachToolbox) { + TileEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof ToolboxTileEntity) { + RadialToolboxMenu screen = new RadialToolboxMenu(ImmutableList.of((ToolboxTileEntity) blockEntity), + RadialToolboxMenu.State.SELECT_ITEM_UNEQUIP); + screen.prevSlot(compound.getCompound(slotKey) + .getInt("Slot")); + ScreenOpener.open(screen); + return; + } + } + + ScreenOpener.open(new RadialToolboxMenu(ImmutableList.of(), RadialToolboxMenu.State.DETACH)); + return; + } + + if (toolboxes.isEmpty()) + return; + + if (toolboxes.size() == 1) + ScreenOpener.open(new RadialToolboxMenu(toolboxes, RadialToolboxMenu.State.SELECT_ITEM)); + else + ScreenOpener.open(new RadialToolboxMenu(toolboxes, RadialToolboxMenu.State.SELECT_BOX)); + } + + public static void renderOverlay(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, + float partialTicks) { + MainWindow mainWindow = Minecraft.getInstance() + .getWindow(); + int x = mainWindow.getGuiScaledWidth() / 2 - 90; + int y = mainWindow.getGuiScaledHeight() - 23; + RenderSystem.enableDepthTest(); + + PlayerEntity player = Minecraft.getInstance().player; + CompoundNBT persistentData = player.getPersistentData(); + if (!persistentData.contains("CreateToolboxData")) + return; + + CompoundNBT compound = player.getPersistentData() + .getCompound("CreateToolboxData"); + + if (compound.isEmpty()) + return; + + ms.pushPose(); + for (int slot = 0; slot < 9; slot++) { + String key = String.valueOf(slot); + if (!compound.contains(key)) + continue; + BlockPos pos = NBTUtil.readBlockPos(compound.getCompound(key) + .getCompound("Pos")); + double max = ToolboxHandler.getMaxRange(player); + boolean selected = player.inventory.selected == slot; + int offset = selected ? 1 : 0; + AllGuiTextures texture = ToolboxHandler.distance(player.position(), pos) < max * max + ? selected ? TOOLBELT_SELECTED_ON : TOOLBELT_HOTBAR_ON + : selected ? TOOLBELT_SELECTED_OFF : TOOLBELT_HOTBAR_OFF; + texture.draw(ms, x + 20 * slot - offset, y + offset); + } + ms.popPose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxInventory.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxInventory.java new file mode 100644 index 000000000..a1c4dffec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxInventory.java @@ -0,0 +1,209 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import javax.annotation.Nonnull; + +import com.simibubi.create.AllItems; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +public class ToolboxInventory extends ItemStackHandler { + + public static final int STACKS_PER_COMPARTMENT = 4; + List filters; + boolean settling; + private ToolboxTileEntity te; + + private boolean limitedMode; + + public ToolboxInventory(ToolboxTileEntity te) { + super(8 * STACKS_PER_COMPARTMENT); + this.te = te; + limitedMode = false; + filters = new ArrayList<>(); + settling = false; + for (int i = 0; i < 8; i++) + filters.add(ItemStack.EMPTY); + } + + public void inLimitedMode(Consumer action) { + limitedMode = true; + action.accept(this); + limitedMode = false; + } + + public void settle(int compartment) { + int totalCount = 0; + boolean valid = true; + boolean shouldBeEmpty = false; + ItemStack sample = ItemStack.EMPTY; + + for (int i = 0; i < STACKS_PER_COMPARTMENT; i++) { + ItemStack stackInSlot = getStackInSlot(compartment * STACKS_PER_COMPARTMENT + i); + totalCount += stackInSlot.getCount(); + if (!shouldBeEmpty) + shouldBeEmpty = stackInSlot.isEmpty() || stackInSlot.getCount() != stackInSlot.getMaxStackSize(); + else if (!stackInSlot.isEmpty()) { + valid = false; + sample = stackInSlot; + } + } + + if (valid) + return; + + settling = true; + if (!sample.isStackable()) { + for (int i = 0; i < STACKS_PER_COMPARTMENT; i++) { + if (!getStackInSlot(compartment * STACKS_PER_COMPARTMENT + i).isEmpty()) + continue; + for (int j = i + 1; j < STACKS_PER_COMPARTMENT; j++) { + ItemStack stackInSlot = getStackInSlot(compartment * STACKS_PER_COMPARTMENT + j); + if (stackInSlot.isEmpty()) + continue; + setStackInSlot(compartment * STACKS_PER_COMPARTMENT + i, stackInSlot); + setStackInSlot(compartment * STACKS_PER_COMPARTMENT + j, ItemStack.EMPTY); + break; + } + } + } else { + for (int i = 0; i < STACKS_PER_COMPARTMENT; i++) { + ItemStack copy = totalCount <= 0 ? ItemStack.EMPTY + : ItemHandlerHelper.copyStackWithSize(sample, Math.min(totalCount, sample.getMaxStackSize())); + setStackInSlot(compartment * STACKS_PER_COMPARTMENT + i, copy); + totalCount -= copy.getCount(); + } + } + settling = false; + te.sendData(); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + if (AllItemTags.TOOLBOXES.matches(stack)) + return false; + if (slot < 0 || slot >= getSlots()) + return false; + int compartment = slot / STACKS_PER_COMPARTMENT; + ItemStack filter = filters.get(compartment); + if (limitedMode && filter.isEmpty()) + return false; + if (filter.isEmpty() || ToolboxInventory.canItemsShareCompartment(filter, stack)) + return super.isItemValid(slot, stack); + return false; + } + + @Override + public void setStackInSlot(int slot, ItemStack stack) { + super.setStackInSlot(slot, stack); + int compartment = slot / STACKS_PER_COMPARTMENT; + if (!stack.isEmpty() && filters.get(compartment) + .isEmpty()) { + filters.set(compartment, ItemHandlerHelper.copyStackWithSize(stack, 1)); + te.sendData(); + } + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + ItemStack insertItem = super.insertItem(slot, stack, simulate); + if (insertItem.getCount() != stack.getCount()) { + int compartment = slot / STACKS_PER_COMPARTMENT; + if (!stack.isEmpty() && filters.get(compartment) + .isEmpty()) { + filters.set(compartment, ItemHandlerHelper.copyStackWithSize(stack, 1)); + te.sendData(); + } + } + return insertItem; + } + + @Override + public CompoundNBT serializeNBT() { + CompoundNBT compound = super.serializeNBT(); + compound.put("Compartments", NBTHelper.writeItemList(filters)); + return compound; + } + + @Override + protected void onContentsChanged(int slot) { + if (!settling && !te.getWorld().isClientSide) + settle(slot / STACKS_PER_COMPARTMENT); + super.onContentsChanged(slot); + } + + @Override + public void deserializeNBT(CompoundNBT nbt) { + filters = NBTHelper.readItemList(nbt.getList("Compartments", NBT.TAG_COMPOUND)); + if (filters.size() != 8) { + filters.clear(); + for (int i = 0; i < 8; i++) + filters.add(ItemStack.EMPTY); + } + super.deserializeNBT(nbt); + } + + public ItemStack distributeToCompartment(@Nonnull ItemStack stack, int compartment, boolean simulate) { + if (stack.isEmpty()) + return stack; + if (filters.get(compartment) + .isEmpty()) + return stack; + + for (int i = STACKS_PER_COMPARTMENT - 1; i >= 0; i--) { + int slot = compartment * STACKS_PER_COMPARTMENT + i; + stack = insertItem(slot, stack, simulate); + if (stack.isEmpty()) + return ItemStack.EMPTY; + } + + return stack; + } + + public ItemStack takeFromCompartment(int amount, int compartment, boolean simulate) { + if (amount == 0) + return ItemStack.EMPTY; + + int remaining = amount; + ItemStack lastValid = ItemStack.EMPTY; + + for (int i = STACKS_PER_COMPARTMENT - 1; i >= 0; i--) { + int slot = compartment * STACKS_PER_COMPARTMENT + i; + ItemStack extracted = extractItem(slot, remaining, simulate); + remaining -= extracted.getCount(); + if (!extracted.isEmpty()) + lastValid = extracted; + if (remaining == 0) + return ItemHandlerHelper.copyStackWithSize(lastValid, amount); + } + + if (remaining == amount) + return ItemStack.EMPTY; + + return ItemHandlerHelper.copyStackWithSize(lastValid, amount - remaining); + } + + public static ItemStack cleanItemNBT(ItemStack stack) { + if (AllItems.BELT_CONNECTOR.isIn(stack)) + stack.removeTagKey("FirstPulley"); + return stack; + } + + public static boolean canItemsShareCompartment(ItemStack stack1, ItemStack stack2) { + if (!stack1.isStackable() && !stack2.isStackable() && stack1.isDamageableItem() && stack2.isDamageableItem()) + return stack1.getItem() == stack2.getItem(); + if (AllItems.BELT_CONNECTOR.isIn(stack1) && AllItems.BELT_CONNECTOR.isIn(stack2)) + return true; + return ItemHandlerHelper.canItemStacksStack(stack1, stack2); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxRenderer.java new file mode 100644 index 000000000..948470de1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxRenderer.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.curiosities.toolbox; + +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.tileEntity.renderer.SmartTileEntityRenderer; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.block.BlockState; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.util.Direction; + +public class ToolboxRenderer extends SmartTileEntityRenderer { + + public ToolboxRenderer(TileEntityRendererDispatcher dispatcher) { + super(dispatcher); + } + + @Override + protected void renderSafe(ToolboxTileEntity tileEntityIn, float partialTicks, MatrixStack ms, + IRenderTypeBuffer buffer, int light, int overlay) { + + BlockState blockState = tileEntityIn.getBlockState(); + Direction facing = blockState.getValue(ToolboxBlock.FACING) + .getOpposite(); + SuperByteBuffer lid = + PartialBufferer.get(AllBlockPartials.TOOLBOX_LIDS.get(tileEntityIn.getColor()), blockState); + SuperByteBuffer drawer = PartialBufferer.get(AllBlockPartials.TOOLBOX_DRAWER, blockState); + + float lidAngle = tileEntityIn.lid.getValue(partialTicks); + float drawerOffset = tileEntityIn.drawers.getValue(partialTicks); + + IVertexBuilder layer = buffer.getBuffer(RenderType.solid()); + lid.matrixStacker() + .centre() + .rotateY(-facing.toYRot()) + .unCentre() + .translate(0, 6 / 16f, 12 / 16f) + .rotateX(135 * lidAngle) + .translate(0, -6 / 16f, -12 / 16f); + lid.light(light) + .renderInto(ms, layer); + + for (int offset : Iterate.zeroAndOne) { + drawer.matrixStacker() + .centre() + .rotateY(-facing.toYRot()) + .unCentre(); + drawer.translate(0, offset * 1 / 8f, -drawerOffset * .175f * (2 - offset)) + .light(light) + .renderInto(ms, layer); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxScreen.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxScreen.java new file mode 100644 index 000000000..f2e3ab3ea --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxScreen.java @@ -0,0 +1,177 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import java.util.Collections; +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllBlocks; +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.Iterate; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.renderer.Rectangle2d; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.container.Slot; +import net.minecraft.item.DyeColor; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; + +public class ToolboxScreen extends AbstractSimiContainerScreen { + + AllGuiTextures BG = AllGuiTextures.TOOLBOX; + AllGuiTextures PLAYER = AllGuiTextures.PLAYER_INVENTORY; + protected Slot hoveredToolboxSlot; + private IconButton confirmButton; + private IconButton disposeButton; + private DyeColor color; + + private List extraAreas = Collections.emptyList(); + + public ToolboxScreen(ToolboxContainer container, PlayerInventory inv, ITextComponent title) { + super(container, inv, title); + init(); + } + + @Override + protected void init() { + super.init(); + widgets.clear(); + setWindowSize(BG.width, 256); + confirmButton = new IconButton(getGuiLeft() + BG.width - 23, getGuiTop() + BG.height - 24, AllIcons.I_CONFIRM); + disposeButton = new IconButton(getGuiLeft() + 91, getGuiTop() + 69, AllIcons.I_TOOLBOX); + disposeButton.setToolTip(Lang.translate("toolbox.depositBox")); + widgets.add(confirmButton); + widgets.add(disposeButton); + color = menu.contentHolder.getColor(); + + extraAreas = ImmutableList.of(new Rectangle2d(118, 155, 80, 100), new Rectangle2d(308, 125, 100, 70)); + } + + @Override + public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { + menu.renderPass = true; + super.render(matrixStack, mouseX, mouseY, partialTicks); + menu.renderPass = false; + } + + @Override + public void setBlitOffset(int p_230926_1_) { + super.setBlitOffset(p_230926_1_); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + BG.draw(ms, this, leftPos + 10, topPos); + PLAYER.draw(ms, this, leftPos + (BG.width - PLAYER.width) / 2 - 26, topPos + imageHeight - PLAYER.height); + font.draw(ms, title, leftPos + 24, topPos + 4, 0x442000); + font.draw(ms, inventory.getDisplayName(), leftPos - 13, topPos + 154, 0x404040); + + renderToolbox(ms, mouseX, mouseY, partialTicks); + + hoveredToolboxSlot = null; + for (int compartment = 0; compartment < 8; compartment++) { + int baseIndex = compartment * ToolboxInventory.STACKS_PER_COMPARTMENT; + Slot slot = menu.slots.get(baseIndex); + ItemStack itemstack = slot.getItem(); + int i = slot.x + leftPos; + int j = slot.y + topPos; + + if (itemstack.isEmpty()) + itemstack = menu.getFilter(compartment); + + if (!itemstack.isEmpty()) { + int count = menu.totalCountInCompartment(compartment); + String s = count + ""; + setBlitOffset(100); + itemRenderer.blitOffset = 100.0F; + RenderSystem.enableDepthTest(); + itemRenderer.renderAndDecorateItem(minecraft.player, itemstack, i, j); + itemRenderer.renderGuiItemDecorations(font, itemstack, i, j, s); + setBlitOffset(0); + itemRenderer.blitOffset = 0.0F; + } + + if (isHovering(slot.x, slot.y, 16, 16, mouseX, mouseY)) { + hoveredToolboxSlot = slot; + RenderSystem.disableDepthTest(); + RenderSystem.colorMask(true, true, true, false); + int slotColor = this.getSlotColor(baseIndex); + fillGradient(ms, i, j, i + 16, j + 16, slotColor, slotColor); + RenderSystem.colorMask(true, true, true, true); + RenderSystem.enableDepthTest(); + } + } + } + + private void renderToolbox(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + ms.pushPose(); + ms.translate(397, 190, 100); + MatrixTransformStack.of(ms) + .scale(50) + .rotateX(-22) + .rotateY(-202); + + GuiGameElement.of(AllBlocks.TOOLBOXES.get(color) + .getDefaultState()) + .render(ms); + + ms.pushPose(); + MatrixTransformStack.of(ms) + .translate(0, -6 / 16f, 12 / 16f) + .rotateX(-105 * menu.contentHolder.lid.getValue(partialTicks)) + .translate(0, 6 / 16f, -12 / 16f); + GuiGameElement.of(AllBlockPartials.TOOLBOX_LIDS.get(color)) + .render(ms); + ms.popPose(); + + for (int offset : Iterate.zeroAndOne) { + ms.pushPose(); + ms.translate(0, -offset * 1 / 8f, + menu.contentHolder.drawers.getValue(partialTicks) * -.175f * (2 - offset)); + GuiGameElement.of(AllBlockPartials.TOOLBOX_DRAWER) + .render(ms); + ms.popPose(); + } + ms.popPose(); + } + + @Override + protected void renderWindowForeground(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { + if (hoveredToolboxSlot != null) + hoveredSlot = hoveredToolboxSlot; + super.renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks); + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + boolean mouseClicked = super.mouseClicked(x, y, button); + + if (button == 0) { + if (confirmButton.isHovered()) { + minecraft.player.closeContainer(); + return true; + } + if (disposeButton.isHovered()) { + AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(menu.contentHolder.getBlockPos())); + return true; + } + } + + return mouseClicked; + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxSlot.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxSlot.java new file mode 100644 index 000000000..b14d0573f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxSlot.java @@ -0,0 +1,20 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class ToolboxSlot extends SlotItemHandler { + + private ToolboxContainer toolboxMenu; + + public ToolboxSlot(ToolboxContainer container, IItemHandler itemHandler, int index, int xPosition, int yPosition) { + super(itemHandler, index, xPosition, yPosition); + this.toolboxMenu = container; + } + + @Override + public boolean isActive() { + return !toolboxMenu.renderPass && super.isActive(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxTileEntity.java new file mode 100644 index 000000000..c3a13eb47 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxTileEntity.java @@ -0,0 +1,389 @@ +package com.simibubi.create.content.curiosities.toolbox; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.WeakHashMap; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.block.BlockState; +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.DyeColor; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.INameable; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ToolboxTileEntity extends SmartTileEntity implements INamedContainerProvider, INameable { + + public LerpedFloat lid = LerpedFloat.linear() + .startWithValue(0); + + public LerpedFloat drawers = LerpedFloat.linear() + .startWithValue(0); + + ToolboxInventory inventory; + LazyOptional inventoryProvider; + LazyOptional colorProvider; + protected int openCount; + + Map> connectedPlayers; + + private ITextComponent customName; + + public ToolboxTileEntity(TileEntityType tileEntityTypeIn) { + super(tileEntityTypeIn); + connectedPlayers = new HashMap<>(); + inventory = new ToolboxInventory(this); + inventoryProvider = LazyOptional.of(() -> inventory); + colorProvider = LazyOptional.of(() -> { + BlockState blockState = getBlockState(); + if (blockState != null && blockState.getBlock() instanceof ToolboxBlock) + return ((ToolboxBlock) blockState.getBlock()).getColor(); + return DyeColor.BROWN; + }); + setLazyTickRate(10); + } + + public DyeColor getColor() { + return colorProvider.orElse(DyeColor.BROWN); + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public void initialize() { + super.initialize(); + ToolboxHandler.onLoad(this); + } + + @Override + public void setRemoved() { + super.setRemoved(); + ToolboxHandler.onUnload(this); + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide) + tickAudio(); + if (!level.isClientSide) + tickPlayers(); + + lid.chase(openCount > 0 ? 1 : 0, 0.2f, Chaser.LINEAR); + drawers.chase(openCount > 0 ? 1 : 0, 0.2f, Chaser.EXP); + lid.tickChaser(); + drawers.tickChaser(); + } + + private void tickPlayers() { + boolean update = false; + + for (Iterator>> toolboxSlots = connectedPlayers.entrySet() + .iterator(); toolboxSlots.hasNext();) { + + Entry> toolboxSlotEntry = toolboxSlots.next(); + WeakHashMap set = toolboxSlotEntry.getValue(); + int slot = toolboxSlotEntry.getKey(); + + ItemStack referenceItem = inventory.filters.get(slot); + boolean clear = referenceItem.isEmpty(); + + for (Iterator> playerEntries = set.entrySet() + .iterator(); playerEntries.hasNext();) { + Entry playerEntry = playerEntries.next(); + + PlayerEntity player = playerEntry.getKey(); + int hotbarSlot = playerEntry.getValue(); + + if (!clear && !ToolboxHandler.withinRange(player, this)) + continue; + + ItemStack playerStack = player.inventory.getItem(hotbarSlot); + + if (clear || !playerStack.isEmpty() + && !ToolboxInventory.canItemsShareCompartment(playerStack, referenceItem)) { + player.getPersistentData() + .getCompound("CreateToolboxData") + .remove(String.valueOf(hotbarSlot)); + playerEntries.remove(); + if (player instanceof ServerPlayerEntity) + ToolboxHandler.syncData(player); + continue; + } + + int count = playerStack.getCount(); + int targetAmount = (referenceItem.getMaxStackSize() + 1) / 2; + + if (count < targetAmount) { + int amountToReplenish = targetAmount - count; + + if (isOpenInContainer(player)) { + ItemStack extracted = inventory.takeFromCompartment(amountToReplenish, slot, true); + if (!extracted.isEmpty()) { + ToolboxHandler.unequip(player, hotbarSlot, false); + ToolboxHandler.syncData(player); + continue; + } + } + + ItemStack extracted = inventory.takeFromCompartment(amountToReplenish, slot, false); + if (!extracted.isEmpty()) { + update = true; + ItemStack template = playerStack.isEmpty() ? extracted : playerStack; + player.inventory.setItem(hotbarSlot, + ItemHandlerHelper.copyStackWithSize(template, count + extracted.getCount())); + } + } + + if (count > targetAmount) { + int amountToDeposit = count - targetAmount; + ItemStack toDistribute = ItemHandlerHelper.copyStackWithSize(playerStack, amountToDeposit); + + if (isOpenInContainer(player)) { + int deposited = amountToDeposit - inventory.distributeToCompartment(toDistribute, slot, true) + .getCount(); + if (deposited > 0) { + ToolboxHandler.unequip(player, hotbarSlot, true); + ToolboxHandler.syncData(player); + continue; + } + } + + int deposited = amountToDeposit - inventory.distributeToCompartment(toDistribute, slot, false) + .getCount(); + if (deposited > 0) { + update = true; + player.inventory.setItem(hotbarSlot, + ItemHandlerHelper.copyStackWithSize(playerStack, count - deposited)); + } + } + } + + if (clear) + toolboxSlots.remove(); + } + + if (update) + + sendData(); + + } + + private boolean isOpenInContainer(PlayerEntity player) { + return player.containerMenu instanceof ToolboxContainer + && ((ToolboxContainer) player.containerMenu).contentHolder == this; + } + + public void unequipTracked() { + if (level.isClientSide) + return; + + Set affected = new HashSet<>(); + + for (Iterator>> toolboxSlots = connectedPlayers.entrySet() + .iterator(); toolboxSlots.hasNext();) { + + Entry> toolboxSlotEntry = toolboxSlots.next(); + WeakHashMap set = toolboxSlotEntry.getValue(); + + for (Iterator> playerEntries = set.entrySet() + .iterator(); playerEntries.hasNext();) { + Entry playerEntry = playerEntries.next(); + + PlayerEntity player = playerEntry.getKey(); + int hotbarSlot = playerEntry.getValue(); + + ToolboxHandler.unequip(player, hotbarSlot, false); + if (player instanceof ServerPlayerEntity) + affected.add((ServerPlayerEntity) player); + } + } + + for (ServerPlayerEntity player : affected) + ToolboxHandler.syncData(player); + connectedPlayers.clear(); + } + + public void unequip(int slot, PlayerEntity player, int hotbarSlot, boolean keepItems) { + if (!connectedPlayers.containsKey(slot)) + return; + connectedPlayers.get(slot) + .remove(player); + if (keepItems) + return; + + ItemStack playerStack = player.inventory.getItem(hotbarSlot); + ItemStack toInsert = ToolboxInventory.cleanItemNBT(playerStack.copy()); + ItemStack remainder = inventory.distributeToCompartment(toInsert, slot, false); + + if (remainder.getCount() != toInsert.getCount()) + player.inventory.setItem(hotbarSlot, remainder); + } + + private void tickAudio() { + Vector3d vec = VecHelper.getCenterOf(worldPosition); + if (lid.settled()) { + if (openCount > 0 && lid.getChaseTarget() == 0) { + level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.IRON_DOOR_OPEN, SoundCategory.BLOCKS, 0.25F, + level.random.nextFloat() * 0.1F + 1.2F, true); + level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.CHEST_OPEN, SoundCategory.BLOCKS, 0.1F, + level.random.nextFloat() * 0.1F + 1.1F, true); + } + if (openCount == 0 && lid.getChaseTarget() == 1) + level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.CHEST_CLOSE, SoundCategory.BLOCKS, 0.1F, + level.random.nextFloat() * 0.1F + 1.1F, true); + + } else if (openCount == 0 && lid.getChaseTarget() == 0 && lid.getValue(0) > 1 / 16f + && lid.getValue(1) < 1 / 16f) + level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.IRON_DOOR_CLOSE, SoundCategory.BLOCKS, 0.25F, + level.random.nextFloat() * 0.1F + 1.2F, true); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) + return inventoryProvider.cast(); + return super.getCapability(cap, side); + } + + @Override + protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { + inventory.deserializeNBT(compound.getCompound("Inventory")); + super.fromTag(state, compound, clientPacket); + if (compound.contains("CustomName", 8)) + this.customName = ITextComponent.Serializer.fromJson(compound.getString("CustomName")); + if (clientPacket) + openCount = compound.getInt("OpenCount"); + } + + @Override + protected void write(CompoundNBT compound, boolean clientPacket) { + compound.put("Inventory", inventory.serializeNBT()); + if (customName != null) + compound.putString("CustomName", ITextComponent.Serializer.toJson(customName)); + super.write(compound, clientPacket); + if (clientPacket) + compound.putInt("OpenCount", openCount); + } + + @Override + public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) { + return ToolboxContainer.create(id, inv, this); + } + + @Override + public void lazyTick() { + updateOpenCount(); + // keep re-advertising active TEs + ToolboxHandler.onLoad(this); + super.lazyTick(); + } + + void updateOpenCount() { + if (level.isClientSide) + return; + if (openCount == 0) + return; + + int prevOpenCount = openCount; + openCount = 0; + + for (PlayerEntity playerentity : level.getEntitiesOfClass(PlayerEntity.class, + new AxisAlignedBB(worldPosition).inflate(8))) + if (playerentity.containerMenu instanceof ToolboxContainer + && ((ToolboxContainer) playerentity.containerMenu).contentHolder == this) + openCount++; + + if (prevOpenCount != openCount) + sendData(); + } + + public void startOpen(PlayerEntity player) { + if (player.isSpectator()) + return; + if (openCount < 0) + openCount = 0; + openCount++; + sendData(); + } + + public void stopOpen(PlayerEntity player) { + if (player.isSpectator()) + return; + openCount--; + sendData(); + } + + public void connectPlayer(int slot, PlayerEntity player, int hotbarSlot) { + if (level.isClientSide) + return; + WeakHashMap map = connectedPlayers.computeIfAbsent(slot, WeakHashMap::new); + Integer previous = map.get(player); + if (previous != null) { + if (previous == hotbarSlot) + return; + ToolboxHandler.unequip(player, previous, false); + } + map.put(player, hotbarSlot); + } + + public void readInventory(CompoundNBT compound) { + inventory.deserializeNBT(compound); + } + + public void setCustomName(ITextComponent customName) { + this.customName = customName; + } + + @Override + public ITextComponent getDisplayName() { + return customName != null ? customName + : AllBlocks.TOOLBOXES.get(getColor()) + .get() + .getName(); + } + + @Override + public ITextComponent getCustomName() { + return customName; + } + + @Override + public boolean hasCustomName() { + return customName != null; + } + + @Override + public ITextComponent getName() { + return customName; + } + +} 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..eb5796c75 --- /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.containerMenu instanceof BlueprintContainer) { + BlueprintContainer c = (BlueprintContainer) player.containerMenu; + player.getLevel() + .getRecipeManager() + .byKey(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..966e65579 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintContainer.java @@ -0,0 +1,179 @@ +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 net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +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.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 { + + 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(8, 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().isClientSide) + return; + + ServerPlayerEntity serverplayerentity = (ServerPlayerEntity) player; + CraftingInventory craftingInventory = new BlueprintCraftingInventory(this, ghostInventory); + Optional optional = player.getServer() + .getRecipeManager() + .getRecipeFor(IRecipeType.CRAFTING, craftingInventory, player.getCommandSenderWorld()); + + if (!optional.isPresent()) { + if (ghostInventory.getStackInSlot(9) + .isEmpty()) + return; + if (!contentHolder.inferredIcon) + return; + + ghostInventory.setStackInSlot(9, ItemStack.EMPTY); + serverplayerentity.connection.send(new SSetSlotPacket(containerId, 36 + 9, ItemStack.EMPTY)); + contentHolder.inferredIcon = false; + return; + } + + ICraftingRecipe icraftingrecipe = optional.get(); + ItemStack itemstack = icraftingrecipe.assemble(craftingInventory); + ghostInventory.setStackInSlot(9, itemstack); + contentHolder.inferredIcon = true; + ItemStack toSend = itemstack.copy(); + toSend.getOrCreateTag() + .putBoolean("InferredFromRecipe", true); + serverplayerentity.connection.send(new SSetSlotPacket(containerId, 36 + 9, toSend)); + } + + @Override + public void setItem(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.setItem(p_75141_1_, p_75141_2_); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return contentHolder.getItems(); + } + + @Override + protected void initAndReadInventory(BlueprintSection contentHolder) { + super.initAndReadInventory(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().level.getEntity(entityID); + if (!(entityByID instanceof BlueprintEntity)) + return null; + BlueprintEntity blueprintEntity = (BlueprintEntity) entityByID; + BlueprintSection blueprintSection = blueprintEntity.getSection(section); + return blueprintSection; + } + + @Override + public boolean stillValid(PlayerEntity player) { + return contentHolder != null && contentHolder.canPlayerUse(player); + } + + 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); + setItem(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 setChanged() { + super.setChanged(); + if (index == 9 && hasItem() && !contentHolder.getBlueprintWorld().isClientSide) { + contentHolder.inferredIcon = false; + ServerPlayerEntity serverplayerentity = (ServerPlayerEntity) player; + serverplayerentity.connection.send(new SSetSlotPacket(containerId, 36 + 9, getItem())); + } + 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..e1fbc0f48 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java @@ -0,0 +1,584 @@ +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.gui.IInteractionChecker; +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, IInteractionChecker { + + 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.survives()) + break; + } + } + + public static EntityType.Builder build(EntityType.Builder builder) { + @SuppressWarnings("unchecked") + EntityType.Builder entityBuilder = (EntityType.Builder) builder; + return entityBuilder; + } + + @Override + public IPacket getAddEntityPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + public void addAdditionalSaveData(CompoundNBT p_213281_1_) { + p_213281_1_.putByte("Facing", (byte) this.direction.get3DDataValue()); + p_213281_1_.putByte("Orientation", (byte) this.verticalOrientation.get3DDataValue()); + p_213281_1_.putInt("Size", size); + super.addAdditionalSaveData(p_213281_1_); + } + + @Override + public void readAdditionalSaveData(CompoundNBT p_70037_1_) { + this.direction = Direction.from3DDataValue(p_70037_1_.getByte("Facing")); + this.verticalOrientation = Direction.from3DDataValue(p_70037_1_.getByte("Orientation")); + this.size = p_70037_1_.getInt("Size"); + super.readAdditionalSaveData(p_70037_1_); + this.updateFacingWithBoundingBox(this.direction, this.verticalOrientation); + } + + protected void updateFacingWithBoundingBox(Direction facing, Direction verticalOrientation) { + Validate.notNull(facing); + this.direction = facing; + this.verticalOrientation = verticalOrientation; + if (facing.getAxis() + .isHorizontal()) { + this.xRot = 0.0F; + this.yRot = (float) (this.direction.get2DDataValue() * 90); + } else { + this.xRot = (float) (-90 * facing.getAxisDirection() + .getStep()); + this.yRot = verticalOrientation.getAxis() + .isHorizontal() ? 180 + verticalOrientation.toYRot() : 0; + } + + this.xRotO = this.xRot; + this.yRotO = this.yRot; + this.recalculateBoundingBox(); + } + + @Override + protected float getEyeHeight(Pose p_213316_1_, EntitySize p_213316_2_) { + return 0; + } + + @Override + protected void recalculateBoundingBox() { + if (this.direction == null) + return; + if (this.verticalOrientation == null) + return; + + Vector3d pos = Vector3d.atLowerCornerOf(getPos()) + .add(.5, .5, .5) + .subtract(Vector3d.atLowerCornerOf(direction.getNormal()) + .scale(0.46875)); + double d1 = pos.x; + double d2 = pos.y; + double d3 = pos.z; + this.setPosRaw(d1, d2, d3); + + Axis axis = direction.getAxis(); + if (size == 2) + pos = pos.add(Vector3d.atLowerCornerOf(axis.isHorizontal() ? direction.getCounterClockWise() + .getNormal() + : verticalOrientation.getClockWise() + .getNormal()) + .scale(0.5)) + .add(Vector3d + .atLowerCornerOf(axis.isHorizontal() ? Direction.UP.getNormal() + : direction == Direction.UP ? verticalOrientation.getNormal() + : verticalOrientation.getOpposite() + .getNormal()) + .scale(0.5)); + + d1 = pos.x; + d2 = pos.y; + d3 = pos.z; + + double d4 = (double) this.getWidth(); + double d5 = (double) this.getHeight(); + double d6 = (double) this.getWidth(); + Direction.Axis direction$axis = this.direction.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)); + } + + @Override + public boolean survives() { + if (!level.noCollision(this)) + return false; + + int i = Math.max(1, this.getWidth() / 16); + int j = Math.max(1, this.getHeight() / 16); + BlockPos blockpos = this.pos.relative(this.direction.getOpposite()); + Direction upDirection = direction.getAxis() + .isHorizontal() ? Direction.UP + : direction == Direction.UP ? verticalOrientation : verticalOrientation.getOpposite(); + Direction newDirection = direction.getAxis() + .isVertical() ? verticalOrientation.getClockWise() : direction.getCounterClockWise(); + 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.set(blockpos) + .move(newDirection, k + i1) + .move(upDirection, l + j1); + BlockState blockstate = this.level.getBlockState(blockpos$mutable); + if (Block.canSupportCenter(this.level, blockpos$mutable, this.direction)) + continue; + if (!blockstate.getMaterial() + .isSolid() && !RedstoneDiodeBlock.isDiode(blockstate)) { + return false; + } + } + } + + return this.level.getEntities(this, this.getBoundingBox(), HANGING_ENTITY) + .isEmpty(); + } + + @Override + public int getWidth() { + return 16 * size; + } + + @Override + public int getHeight() { + return 16 * size; + } + + @Override + public boolean skipAttackInteraction(Entity source) { + if (!(source instanceof PlayerEntity) || level.isClientSide) + return super.skipAttackInteraction(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.getViewVector(1); + Vector3d target = eyePos.add(look.scale(attrib)); + + Optional rayTrace = getBoundingBox().clip(eyePos, target); + if (!rayTrace.isPresent()) + return super.skipAttackInteraction(source); + + Vector3d hitVec = rayTrace.get(); + BlueprintSection sectionAt = getSectionAt(hitVec.subtract(position())); + ItemStackHandler items = sectionAt.getItems(); + + if (items.getStackInSlot(9) + .isEmpty()) + return super.skipAttackInteraction(source); + for (int i = 0; i < items.getSlots(); i++) + items.setStackInSlot(i, ItemStack.EMPTY); + sectionAt.save(items); + return true; + } + + @Override + public void dropItem(@Nullable Entity p_110128_1_) { + if (!level.getGameRules() + .getBoolean(GameRules.RULE_DOENTITYDROPS)) + return; + + playSound(SoundEvents.PAINTING_BREAK, 1.0F, 1.0F); + if (p_110128_1_ instanceof PlayerEntity) { + PlayerEntity playerentity = (PlayerEntity) p_110128_1_; + if (playerentity.abilities.instabuild) { + return; + } + } + + spawnAtLocation(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 playPlacementSound() { + this.playSound(SoundEvents.PAINTING_PLACE, 1.0F, 1.0F); + } + + @Override + public void moveTo(double p_70012_1_, double p_70012_3_, double p_70012_5_, float p_70012_7_, + float p_70012_8_) { + this.setPos(p_70012_1_, p_70012_3_, p_70012_5_); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void lerpTo(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.pos.offset(p_180426_1_ - this.getX(), p_180426_3_ - this.getY(), p_180426_5_ - this.getZ()); + this.setPos((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); + } + + @Override + public void writeSpawnData(PacketBuffer buffer) { + CompoundNBT compound = new CompoundNBT(); + addAdditionalSaveData(compound); + buffer.writeNbt(compound); + buffer.writeNbt(getPersistentData()); + } + + @Override + public void readSpawnData(PacketBuffer additionalData) { + readAdditionalSaveData(additionalData.readNbt()); + getPersistentData().merge(additionalData.readNbt()); + } + + @Override + public ActionResultType interactAt(PlayerEntity player, Vector3d vec, Hand hand) { + if (player instanceof FakePlayer) + return ActionResultType.PASS; + + boolean holdingWrench = AllItems.WRENCH.isIn(player.getItemInHand(hand)); + BlueprintSection section = getSectionAt(vec); + ItemStackHandler items = section.getItems(); + + if (!holdingWrench && !level.isClientSide && !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(level, 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 = level.getRecipeManager() + .getRecipeFor(IRecipeType.CRAFTING, craftingInventory, level); + ItemStack result = recipe.filter(r -> r.matches(craftingInventory, level)) + .map(r -> r.assemble(craftingInventory)) + .orElse(ItemStack.EMPTY); + + if (result.isEmpty()) { + success = false; + } else if (result.getCount() + amountCrafted > 64) { + success = false; + } else { + amountCrafted += result.getCount(); + result.onCraftedBy(player.level, player, 1); + BasicEventHooks.firePlayerCraftingEvent(player, result, craftingInventory); + NonNullList nonnulllist = level.getRecipeManager() + .getRemainingItemsFor(IRecipeType.CRAFTING, craftingInventory, level); + + if (firstPass) + level.playSound(null, player.blockPosition(), SoundEvents.ITEM_PICKUP, + SoundCategory.PLAYERS, .2f, 1f + Create.RANDOM.nextFloat()); + player.inventory.placeItemBackInInventory(level, result); + for (ItemStack itemStack : nonnulllist) + player.inventory.placeItemBackInInventory(level, itemStack); + firstPass = false; + } + } + + if (!success) { + for (Entry entry : stacksTaken.entrySet()) + playerInv.insertItem(entry.getKey(), entry.getValue(), false); + break; + } + + } while (player.isShiftKeyDown()); + ForgeHooks.setCraftingPlayer(null); + return ActionResultType.SUCCESS; + } + + int i = section.index; + if (!level.isClientSide && player instanceof ServerPlayerEntity) { + NetworkHooks.openGui((ServerPlayerEntity) player, section, buf -> { + buf.writeVarInt(getId()); + buf.writeVarInt(i); + }); + } + + return ActionResultType.SUCCESS; + } + + public BlueprintSection getSectionAt(Vector3d vec) { + int index = 0; + if (size > 1) { + vec = VecHelper.rotate(vec, yRot, Axis.Y); + vec = VecHelper.rotate(vec, -xRot, 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 stillValid(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); + setItem(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, IInteractionChecker { + 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 (!level.isClientSide) + syncPersistentDataWithTracking(BlueprintEntity.this); + } + + public boolean isEntityAlive() { + return isAlive(); + } + + public World getBlueprintWorld() { + return level; + } + + @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() + .getDescriptionId()); + } + + @Override + public boolean canPlayerUse(PlayerEntity player) { + return BlueprintEntity.this.canPlayerUse(player); + } + + } + + @Override + public void onPersistentDataUpdated() { + sectionCache.clear(); + } + + @Override + public boolean canPlayerUse(PlayerEntity player) { + AxisAlignedBB box = getBoundingBox(); + + double dx = 0; + if (box.minX > player.getX()) { + dx = box.minX - player.getX(); + } else if (player.getX() > box.maxX) { + dx = player.getX() - box.maxX; + } + + double dy = 0; + if (box.minY > player.getY()) { + dy = box.minY - player.getY(); + } else if (player.getY() > box.maxY) { + dy = player.getY() - box.maxY; + } + + double dz = 0; + if (box.minZ > player.getZ()) { + dz = box.minZ - player.getZ(); + } else if (player.getZ() > box.maxZ) { + dz = player.getZ() - box.maxZ; + } + + return (dx * dx + dy * dy + dz * dz) <= 64.0D; + } + +} 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..7e3b069e1 --- /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 useOn(ItemUseContext ctx) { + Direction face = ctx.getClickedFace(); + PlayerEntity player = ctx.getPlayer(); + ItemStack stack = ctx.getItemInHand(); + BlockPos pos = ctx.getClickedPos() + .relative(face); + + if (player != null && !player.mayUseItemAt(pos, face, stack)) + return ActionResultType.FAIL; + + World world = ctx.getLevel(); + HangingEntity hangingentity = new BlueprintEntity(world, pos, face, face.getAxis() + .isHorizontal() ? Direction.DOWN : ctx.getHorizontalDirection()); + CompoundNBT compoundnbt = stack.getTag(); + + if (compoundnbt != null) + EntityType.updateCustomEntityTag(world, player, hangingentity, compoundnbt); + if (!hangingentity.survives()) + return ActionResultType.CONSUME; + if (!world.isClientSide) { + hangingentity.playPlacementSound(); + world.addFreshEntity(hangingentity); + } + + stack.shrink(1); + return ActionResultType.sidedSuccess(world.isClientSide); + } + + protected boolean canPlace(PlayerEntity p_200127_1_, Direction p_200127_2_, ItemStack p_200127_3_, + BlockPos p_200127_4_) { + return p_200127_1_.mayUseItemAt(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.getResultItem()); + + 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"); // values + 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.getItems(); + if (itemList instanceof SingleItemList) { + for (ItemStack itemStack : stacks) + return itemStack; + } + + if (itemList instanceof TagList) { + ResourceLocation resourcelocation = new ResourceLocation(JSONUtils.getAsString(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..f52ad6750 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java @@ -0,0 +1,295 @@ +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.hitResult; + BlueprintSection last = lastTargetedSection; + boolean sneak = mc.player.isShiftKeyDown(); + 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.getLocation() + .subtract(blueprintEntity.position())); + + 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.getContainerSize()); + for (int i = 0; i < playerInv.getSlots(); i++) + playerInv.setStackInSlot(i, mc.player.inventory.getItem(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.level, 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.level.getRecipeManager() + .getRecipeFor(IRecipeType.CRAFTING, craftingInventory, mc.level); + ItemStack resultFromRecipe = recipe.filter(r -> r.matches(craftingInventory, mc.level)) + .map(r -> r.assemble(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() + .getGuiScaledWidth() - w) / 2; + int y = (int) (mc.getWindow() + .getGuiScaledHeight() / 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() ? 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.level) / 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() + .renderGuiItemDecorations(mc.font, 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.getInstance() + .getItems() + .getTag(inTag.tagName); + if (itag != null) + return Ingredient.of(itag) + .getItems(); + } + } + } + + 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..02474015d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java @@ -0,0 +1,136 @@ +package com.simibubi.create.content.curiosities.tools; + +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +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 net.minecraft.block.Blocks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Atlases; +import net.minecraft.client.renderer.IRenderTypeBuffer; +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.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 manager) { + super(manager); + } + + @Override + public void render(BlueprintEntity entity, float yaw, float pt, MatrixStack ms, IRenderTypeBuffer buffer, + int light) { + 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.defaultBlockState()); + sbb.matrixStacker() + .rotateY(-yaw) + .rotateX(90.0F + entity.xRot) + .translate(-.5, -1 / 32f, -.5); + if (entity.size == 2) + sbb.translate(.5, 0, -.5); + + sbb.forEntityRender() + .light(light) + .renderInto(ms, buffer.getBuffer(Atlases.solidBlockSheet())); + super.render(entity, yaw, pt, ms, buffer, light); + + ms.pushPose(); + + float fakeNormalXRotation = -15; + int bl = light >> 4 & 0xf; + int sl = light >> 20 & 0xf; + boolean vertical = entity.xRot != 0; + if (entity.xRot == -90) + fakeNormalXRotation = -45; + else if (entity.xRot == 90 || yaw % 180 != 0) { + bl /= 1.35; + sl /= 1.35; + } + int itemLight = MathHelper.floor(sl + .5) << 20 | (MathHelper.floor(bl + .5) & 0xf) << 4; + + MatrixTransformStack.of(ms) + .rotateY(vertical ? 0 : -yaw) + .rotateX(fakeNormalXRotation); + Matrix3f copy = ms.last() + .normal() + .copy(); + + ms.popPose(); + ms.pushPose(); + + MatrixTransformStack.of(ms) + .rotateY(-yaw) + .rotateX(entity.xRot) + .translate(0, 0, 1 / 32f + .001); + + if (entity.size == 3) + ms.translate(-1, -1, 0); + + MatrixStack squashedMS = new MatrixStack(); + squashedMS.last() + .pose() + .multiply(ms.last() + .pose()); + + for (int x = 0; x < entity.size; x++) { + squashedMS.pushPose(); + for (int y = 0; y < entity.size; y++) { + BlueprintSection section = entity.getSection(x * entity.size + y); + Couple displayItems = section.getDisplayItems(); + squashedMS.pushPose(); + squashedMS.scale(.5f, .5f, 1 / 1024f); + displayItems.forEachWithContext((stack, primary) -> { + if (stack.isEmpty()) + return; + + squashedMS.pushPose(); + if (!primary) { + squashedMS.translate(0.325f, -0.325f, 1); + squashedMS.scale(.625f, .625f, 1); + } + + Matrix3f n = squashedMS.last() + .normal(); + n.m00 = copy.m00; + n.m01 = copy.m01; + n.m02 = copy.m02; + n.m10 = copy.m10; + n.m11 = copy.m11; + n.m12 = copy.m12; + n.m20 = copy.m20; + n.m21 = copy.m21; + n.m22 = copy.m22; + + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(stack, TransformType.GUI, itemLight, OverlayTexture.NO_OVERLAY, squashedMS, buffer); + squashedMS.popPose(); + }); + squashedMS.popPose(); + squashedMS.translate(1, 0, 0); + } + squashedMS.popPose(); + squashedMS.translate(0, 1, 0); + } + + ms.popPose(); + } + + @Override + public ResourceLocation getTextureLocation(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..5fba8bbbc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintScreen.java @@ -0,0 +1,192 @@ +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); + setWindowOffset(2 + (width % 2 == 0 ? 0 : -1), 0); + super.init(); + widgets.clear(); + + int x = leftPos; + int y = topPos; + + 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 - 36, 56, 44) + ); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int invX = getLeftOfCentered(PLAYER_INVENTORY.width); + int invY = topPos + background.height + 4; + renderPlayerInventory(ms, invX, invY); + + int x = leftPos; + int y = topPos; + + background.draw(ms, this, x, y); + font.draw(ms, title, x + 15, y + 4, 0xFFFFFF); + + GuiGameElement.of(AllBlockPartials.CRAFTING_BLUEPRINT_1x1) + .at(x + background.width + 20, y + background.height - 32, 0) + .rotate(45, -45, 22.5f) + .scale(40) + .render(ms); + } + + @Override + protected void renderTooltip(MatrixStack ms, int x, int y) { + if (!this.minecraft.player.inventory.getCarried() + .isEmpty() || this.hoveredSlot == null || this.hoveredSlot.hasItem() + || hoveredSlot.container == menu.playerInventory) { + super.renderTooltip(ms, x, y); + return; + } + renderWrappedToolTip(ms, addToTooltip(new LinkedList<>(), hoveredSlot.getSlotIndex(), true), x, y, + font); + } + + @Override + public List getTooltipFromItem(ItemStack stack) { + List list = super.getTooltipFromItem(stack); + if (hoveredSlot.container == menu.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") + .withStyle(TextFormatting.GOLD)); + if (isEmptySlot) + list.add(Lang.createTranslationTextComponent("crafting_blueprint.filter_items_viable") + .withStyle(TextFormatting.GRAY)); + + } else if (slot == 9) { + list.add(Lang.createTranslationTextComponent("crafting_blueprint.display_slot") + .withStyle(TextFormatting.GOLD)); + if (!isEmptySlot) + list.add(Lang + .createTranslationTextComponent("crafting_blueprint." + + (menu.contentHolder.inferredIcon ? "inferred" : "manually_assigned")) + .withStyle(TextFormatting.GRAY)); + + } else if (slot == 10) { + list.add(Lang.createTranslationTextComponent("crafting_blueprint.secondary_display_slot") + .withStyle(TextFormatting.GOLD)); + if (isEmptySlot) + list.add(Lang.createTranslationTextComponent("crafting_blueprint.optional") + .withStyle(TextFormatting.GRAY)); + } + + return list; + } + + @Override + public void tick() { +// handleTooltips(); + super.tick(); + + if (!menu.contentHolder.isEntityAlive()) + minecraft.player.closeContainer(); + } + +// 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()) { + minecraft.player.closeContainer(); + return true; + } + if (resetButton.isHovered()) { + menu.clearContents(); + contentsCleared(); + menu.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/ExtendoGripInteractionPacket.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java index a5f854031..9575cb268 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java @@ -29,7 +29,7 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase { public ExtendoGripInteractionPacket(Entity target, Hand hand, Vector3d specificPoint) { interactionHand = hand; this.specificPoint = specificPoint; - this.target = target.getEntityId(); + this.target = target.getId(); } public ExtendoGripInteractionPacket(PacketBuffer buffer) { @@ -58,22 +58,22 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase { ServerPlayerEntity sender = context.get().getSender(); if (sender == null) return; - Entity entityByID = sender.getServerWorld().getEntityByID(target); + Entity entityByID = sender.getLevel().getEntity(target); if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) { double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get()).getValue(); - if (!sender.canEntityBeSeen(entityByID)) + if (!sender.canSee(entityByID)) d -= 3; d *= d; - if (sender.getDistanceSq(entityByID) > d) { + if (sender.distanceToSqr(entityByID) > d) { // TODO log? return; } if (interactionHand == null) - sender.attackTargetEntityWithCurrentItem(entityByID); + sender.attack(entityByID); else if (specificPoint == null) sender.interactOn(entityByID, interactionHand); else - entityByID.applyPlayerInteraction(sender, specificPoint, interactionHand); + entityByID.interactAt(sender, specificPoint, interactionHand); } }); context.get().setPacketHandled(true); 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..4947f3636 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 @@ -5,7 +5,9 @@ import java.util.UUID; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; import com.simibubi.create.AllItems; +import com.simibubi.create.content.curiosities.armor.BackTankUtil; import com.simibubi.create.foundation.advancement.AllTriggers; +import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -20,9 +22,11 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.projectile.ProjectileHelper; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.item.Rarity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.DamageSource; +import net.minecraft.util.Hand; import net.minecraft.util.LazyValue; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockRayTraceResult; @@ -37,7 +41,11 @@ 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.event.world.BlockEvent.BreakEvent; +import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -45,83 +53,100 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; public class ExtendoGripItem extends Item { private static DamageSource lastActiveDamageSource; - public static final AttributeModifier singleRangeAttributeModifier = new AttributeModifier(UUID.fromString("7f7dbdb2-0d0d-458a-aa40-ac7633691f66"), "Range modifier", 3, AttributeModifier.Operation.ADDITION); - public static final AttributeModifier doubleRangeAttributeModifier = new AttributeModifier(UUID.fromString("8f7dbdb2-0d0d-458a-aa40-ac7633691f66"), "Range modifier", 5, AttributeModifier.Operation.ADDITION); + public static final int MAX_DAMAGE = 200; - static LazyValue> rangeModifier = - new LazyValue<>(() -> - // Holding an ExtendoGrip - ImmutableMultimap.of(ForgeMod.REACH_DISTANCE.get(), singleRangeAttributeModifier) - ); + public static final AttributeModifier singleRangeAttributeModifier = + new AttributeModifier(UUID.fromString("7f7dbdb2-0d0d-458a-aa40-ac7633691f66"), "Range modifier", 3, + AttributeModifier.Operation.ADDITION); + public static final AttributeModifier doubleRangeAttributeModifier = + new AttributeModifier(UUID.fromString("8f7dbdb2-0d0d-458a-aa40-ac7633691f66"), "Range modifier", 5, + AttributeModifier.Operation.ADDITION); - static LazyValue> doubleRangeModifier = - new LazyValue<>(() -> - // Holding two ExtendoGrips o.O - ImmutableMultimap.of(ForgeMod.REACH_DISTANCE.get(), doubleRangeAttributeModifier) - ); + static LazyValue> rangeModifier = new LazyValue<>(() -> + // Holding an ExtendoGrip + ImmutableMultimap.of(ForgeMod.REACH_DISTANCE.get(), singleRangeAttributeModifier)); + + static LazyValue> doubleRangeModifier = new LazyValue<>(() -> + // Holding two ExtendoGrips o.O + ImmutableMultimap.of(ForgeMod.REACH_DISTANCE.get(), doubleRangeAttributeModifier)); public ExtendoGripItem(Properties properties) { - super(properties.maxStackSize(1) + super(properties.stacksTo(1) .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()); - boolean inMain = AllItems.EXTENDO_GRIP.isIn(player.getHeldItemMainhand()); + boolean inOff = AllItems.EXTENDO_GRIP.isIn(player.getOffhandItem()); + boolean inMain = AllItems.EXTENDO_GRIP.isIn(player.getMainHandItem()); 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); + player.getAttributes() + .removeAttributeModifiers(rangeModifier.get()); + persistentData.remove(EXTENDO_MARKER); } else { if (player instanceof ServerPlayerEntity) AllTriggers.EXTENDO.trigger((ServerPlayerEntity) player); player.getAttributes() - .addTemporaryModifiers(rangeModifier.getValue()); - persistentData.putBoolean(marker, true); + .addTransientAttributeModifiers(rangeModifier.get()); + persistentData.putBoolean(EXTENDO_MARKER, true); } } if (holdingDualExtendo != wasHoldingDualExtendo) { if (!holdingDualExtendo) { player.getAttributes() - .removeModifiers(doubleRangeModifier.getValue()); - persistentData.remove(dualMarker); + .removeAttributeModifiers(doubleRangeModifier.get()); + 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); + .addTransientAttributeModifiers(doubleRangeModifier.get()); + 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() + .addTransientAttributeModifiers(doubleRangeModifier.get()); + else if (persistentData.contains(EXTENDO_MARKER)) + player.getAttributes() + .addTransientAttributeModifiers(rangeModifier.get()); + } + @SubscribeEvent @OnlyIn(Dist.CLIENT) public static void dontMissEntitiesWhenYouHaveHighReachDistance(ClickInputEvent event) { Minecraft mc = Minecraft.getInstance(); ClientPlayerEntity player = mc.player; - if (mc.world == null || player == null) + if (mc.level == null || player == null) return; if (!isHoldingExtendoGrip(player)) return; - if (mc.objectMouseOver instanceof BlockRayTraceResult && mc.objectMouseOver.getType() != Type.MISS) + if (mc.hitResult instanceof BlockRayTraceResult && mc.hitResult.getType() != Type.MISS) return; // Modified version of GameRenderer#getMouseOver @@ -130,38 +155,109 @@ public class ExtendoGripItem extends Item { if (!player.isCreative()) d0 -= 0.5f; Vector3d Vector3d = player.getEyePosition(AnimationTickHolder.getPartialTicks()); - Vector3d Vector3d1 = player.getLook(1.0F); + Vector3d Vector3d1 = player.getViewVector(1.0F); Vector3d Vector3d2 = Vector3d.add(Vector3d1.x * d0, Vector3d1.y * d0, Vector3d1.z * d0); AxisAlignedBB axisalignedbb = player.getBoundingBox() - .expand(Vector3d1.scale(d0)) - .grow(1.0D, 1.0D, 1.0D); + .expandTowards(Vector3d1.scale(d0)) + .inflate(1.0D, 1.0D, 1.0D); EntityRayTraceResult entityraytraceresult = - ProjectileHelper.rayTraceEntities(player, Vector3d, Vector3d2, axisalignedbb, (e) -> { - return !e.isSpectator() && e.canBeCollidedWith(); + ProjectileHelper.getEntityHitResult(player, Vector3d, Vector3d2, axisalignedbb, (e) -> { + return !e.isSpectator() && e.isPickable(); }, d0 * d0); if (entityraytraceresult != null) { Entity entity1 = entityraytraceresult.getEntity(); - Vector3d Vector3d3 = entityraytraceresult.getHitVec(); - double d2 = Vector3d.squareDistanceTo(Vector3d3); - if (d2 < d0 * d0 || mc.objectMouseOver == null || mc.objectMouseOver.getType() == Type.MISS) { - mc.objectMouseOver = entityraytraceresult; + Vector3d Vector3d3 = entityraytraceresult.getLocation(); + double d2 = Vector3d.distanceToSqr(Vector3d3); + if (d2 < d0 * d0 || mc.hitResult == null || mc.hitResult.getType() == Type.MISS) { + mc.hitResult = entityraytraceresult; if (entity1 instanceof LivingEntity || entity1 instanceof ItemFrameEntity) - mc.pointedEntity = entity1; + mc.crosshairPickEntity = entity1; } } } + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void consumeDurabilityOnBlockBreak(BreakEvent event) { + findAndDamageExtendoGrip(event.getPlayer()); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void consumeDurabilityOnPlace(EntityPlaceEvent event) { + Entity entity = event.getEntity(); + if (entity instanceof PlayerEntity) + findAndDamageExtendoGrip((PlayerEntity) entity); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void consumeDurabilityOnPlace(PlayerInteractEvent event) { +// findAndDamageExtendoGrip(event.getPlayer()); + } + + private static void findAndDamageExtendoGrip(PlayerEntity player) { + if (player == null) + return; + if (player.level.isClientSide) + return; + Hand hand = Hand.MAIN_HAND; + ItemStack extendo = player.getMainHandItem(); + if (!AllItems.EXTENDO_GRIP.isIn(extendo)) { + extendo = player.getOffhandItem(); + hand = Hand.OFF_HAND; + } + if (!AllItems.EXTENDO_GRIP.isIn(extendo)) + return; + final Hand h = hand; + if (!BackTankUtil.canAbsorbDamage(player, maxUses())) + extendo.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(h)); + } + + @Override + public int getRGBDurabilityForDisplay(ItemStack stack) { + return BackTankUtil.getRGBDurabilityForDisplay(stack, maxUses()); + } + + @Override + public double getDurabilityForDisplay(ItemStack stack) { + return BackTankUtil.getDurabilityForDisplay(stack, maxUses()); + } + + @Override + public boolean showDurabilityBar(ItemStack stack) { + return BackTankUtil.showDurabilityBar(stack, maxUses()); + } + + private static int maxUses() { + return AllConfigs.SERVER.curiosities.maxExtendoGripActions.get(); + } + + @Override + public boolean canBeDepleted() { + return true; + } + + @Override + public int getMaxDamage(ItemStack stack) { + return MAX_DAMAGE; + } + @SubscribeEvent public static void bufferLivingAttackEvent(LivingAttackEvent event) { - // Workaround for removed patch to get the attacking entity. Tbf this is a hack and a half, but it should work. + // Workaround for removed patch to get the attacking entity. lastActiveDamageSource = event.getSource(); + + DamageSource source = event.getSource(); + if (source == null) + return; + Entity trueSource = source.getEntity(); + if (trueSource instanceof PlayerEntity) + findAndDamageExtendoGrip((PlayerEntity) trueSource); } @SubscribeEvent public static void attacksByExtendoGripHaveMoreKnockback(LivingKnockBackEvent event) { if (lastActiveDamageSource == null) return; - Entity entity = lastActiveDamageSource.getImmediateSource(); + Entity entity = lastActiveDamageSource.getDirectEntity(); if (!(entity instanceof PlayerEntity)) return; PlayerEntity player = (PlayerEntity) entity; @@ -172,9 +268,9 @@ public class ExtendoGripItem extends Item { private static boolean isUncaughtClientInteraction(Entity entity, Entity target) { // Server ignores entity interaction further than 6m - if (entity.getDistanceSq(target) < 36) + if (entity.distanceToSqr(target) < 36) return false; - if (!entity.world.isRemote) + if (!entity.level.isClientSide) return false; if (!(entity instanceof PlayerEntity)) return false; @@ -219,8 +315,8 @@ public class ExtendoGripItem extends Item { } public static boolean isHoldingExtendoGrip(PlayerEntity player) { - boolean inOff = AllItems.EXTENDO_GRIP.isIn(player.getHeldItemOffhand()); - boolean inMain = AllItems.EXTENDO_GRIP.isIn(player.getHeldItemMainhand()); + boolean inOff = AllItems.EXTENDO_GRIP.isIn(player.getOffhandItem()); + boolean inMain = AllItems.EXTENDO_GRIP.isIn(player.getMainHandItem()); boolean holdingGrip = inOff || inMain; return holdingGrip; } 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..41b2bad89 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 @@ -1,13 +1,14 @@ package com.simibubi.create.content.curiosities.tools; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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; import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; @@ -21,7 +22,7 @@ public class ExtendoGripItemRenderer extends CustomRenderedItemModelRenderer mainHandAnimation && swingProgress > 0) @@ -86,7 +86,7 @@ public class ExtendoGripRenderHandler { ms.translate(flip * (0.64000005F - .1f), -0.4F + equipProgress * -0.6F, -0.71999997F + .3f); - ms.push(); + ms.pushPose(); msr.rotateY(flip * 75.0F); ms.translate(flip * -1.0F, 3.6F, 3.5F); msr.rotateZ(flip * 120) @@ -96,18 +96,18 @@ public class ExtendoGripRenderHandler { msr.rotateY(flip * 40.0F); ms.translate(flip * 0.05f, -0.3f, -0.3f); - PlayerRenderer playerrenderer = (PlayerRenderer) mc.getRenderManager() + PlayerRenderer playerrenderer = (PlayerRenderer) mc.getEntityRenderDispatcher() .getRenderer(player); if (rightHand) - playerrenderer.renderRightArm(event.getMatrixStack(), event.getBuffers(), event.getLight(), player); + playerrenderer.renderRightHand(event.getMatrixStack(), event.getBuffers(), event.getLight(), player); else - playerrenderer.renderLeftArm(event.getMatrixStack(), event.getBuffers(), event.getLight(), player); - ms.pop(); + playerrenderer.renderLeftHand(event.getMatrixStack(), event.getBuffers(), event.getLight(), player); + ms.popPose(); // Render gun - ms.push(); + ms.pushPose(); ms.translate(flip * -0.1f, 0, -0.3f); - FirstPersonRenderer firstPersonRenderer = mc.getFirstPersonRenderer(); + FirstPersonRenderer firstPersonRenderer = mc.getItemInHandRenderer(); TransformType transform = rightHand ? TransformType.FIRST_PERSON_RIGHT_HAND : TransformType.FIRST_PERSON_LEFT_HAND; firstPersonRenderer.renderItem(mc.player, notInOffhand ? heldItem : offhandItem, transform, !rightHand, @@ -115,11 +115,11 @@ public class ExtendoGripRenderHandler { if (!notInOffhand) { ForgeHooksClient.handleCameraTransforms(ms, mc.getItemRenderer() - .getItemModelWithOverrides(offhandItem, null, null), transform, !rightHand); + .getModel(offhandItem, null, null), transform, !rightHand); ms.translate(flip * -.05f, .15f, -1.2f); ms.translate(0, 0, -animation * 2.25f); if (blockItem && mc.getItemRenderer() - .getItemModelWithOverrides(heldItem, null, null) + .getModel(heldItem, null, null) .isGui3d()) { msr.rotateY(flip * 45); ms.translate(flip * 0.15f, -0.15f, -.05f); @@ -130,18 +130,18 @@ public class ExtendoGripRenderHandler { event.getBuffers(), event.getLight()); } - ms.pop(); + ms.popPose(); } - ms.pop(); + ms.popPose(); event.setCanceled(true); } private static ItemStack getRenderedMainHandStack() { - return Minecraft.getInstance().getFirstPersonRenderer().itemStackMainHand; + return Minecraft.getInstance().getItemInHandRenderer().mainHandItem; } private static ItemStack getRenderedOffHandStack() { - return Minecraft.getInstance().getFirstPersonRenderer().itemStackOffHand; + return Minecraft.getInstance().getItemInHandRenderer().offHandItem; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java b/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java index 676b36d80..5ee736091 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java @@ -32,55 +32,55 @@ import net.minecraftforge.common.util.FakePlayer; public class SandPaperItem extends Item { public SandPaperItem(Properties properties) { - super(properties.maxDamage(8)); + super(properties.durability(8)); } @Override - public UseAction getUseAction(ItemStack stack) { + public UseAction getUseAnimation(ItemStack stack) { return UseAction.EAT; } @Override - public ActionResultType onItemUse(ItemUseContext context) { + public ActionResultType useOn(ItemUseContext context) { return ActionResultType.PASS; } @Override - public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { - ItemStack itemstack = playerIn.getHeldItem(handIn); + public ActionResult use(World worldIn, PlayerEntity playerIn, Hand handIn) { + ItemStack itemstack = playerIn.getItemInHand(handIn); ActionResult FAIL = new ActionResult<>(ActionResultType.FAIL, itemstack); if (itemstack.getOrCreateTag() .contains("Polishing")) { - playerIn.setActiveHand(handIn); + playerIn.startUsingItem(handIn); return new ActionResult<>(ActionResultType.PASS, itemstack); } Hand otherHand = handIn == Hand.MAIN_HAND ? Hand.OFF_HAND : Hand.MAIN_HAND; - ItemStack itemInOtherHand = playerIn.getHeldItem(otherHand); + ItemStack itemInOtherHand = playerIn.getItemInHand(otherHand); if (SandPaperPolishingRecipe.canPolish(worldIn, itemInOtherHand)) { ItemStack item = itemInOtherHand.copy(); ItemStack toPolish = item.split(1); - playerIn.setActiveHand(handIn); + playerIn.startUsingItem(handIn); itemstack.getOrCreateTag() .put("Polishing", toPolish.serializeNBT()); - playerIn.setHeldItem(otherHand, item); + playerIn.setItemInHand(otherHand, item); return new ActionResult<>(ActionResultType.SUCCESS, itemstack); } - RayTraceResult raytraceresult = rayTrace(worldIn, playerIn, RayTraceContext.FluidMode.NONE); + RayTraceResult raytraceresult = getPlayerPOVHitResult(worldIn, playerIn, RayTraceContext.FluidMode.NONE); if (!(raytraceresult instanceof BlockRayTraceResult)) return FAIL; BlockRayTraceResult ray = (BlockRayTraceResult) raytraceresult; - Vector3d hitVec = ray.getHitVec(); + Vector3d hitVec = ray.getLocation(); - AxisAlignedBB bb = new AxisAlignedBB(hitVec, hitVec).grow(1f); + AxisAlignedBB bb = new AxisAlignedBB(hitVec, hitVec).inflate(1f); ItemEntity pickUp = null; - for (ItemEntity itemEntity : worldIn.getEntitiesWithinAABB(ItemEntity.class, bb)) { + for (ItemEntity itemEntity : worldIn.getEntitiesOfClass(ItemEntity.class, bb)) { if (!itemEntity.isAlive()) continue; - if (itemEntity.getPositionVec() - .distanceTo(playerIn.getPositionVec()) > 3) + if (itemEntity.position() + .distanceTo(playerIn.position()) > 3) continue; ItemStack stack = itemEntity.getItem(); if (!SandPaperPolishingRecipe.canPolish(worldIn, stack)) @@ -96,9 +96,9 @@ public class SandPaperItem extends Item { .copy(); ItemStack toPolish = item.split(1); - playerIn.setActiveHand(handIn); + playerIn.startUsingItem(handIn); - if (!worldIn.isRemote) { + if (!worldIn.isClientSide) { itemstack.getOrCreateTag() .put("Polishing", toPolish.serializeNBT()); if (item.isEmpty()) @@ -121,19 +121,19 @@ public class SandPaperItem extends Item { } @Override - public ItemStack onItemUseFinish(ItemStack stack, World worldIn, LivingEntity entityLiving) { + public ItemStack finishUsingItem(ItemStack stack, World worldIn, LivingEntity entityLiving) { if (!(entityLiving instanceof PlayerEntity)) return stack; PlayerEntity player = (PlayerEntity) entityLiving; CompoundNBT tag = stack.getOrCreateTag(); if (tag.contains("Polishing")) { - ItemStack toPolish = ItemStack.read(tag.getCompound("Polishing")); + ItemStack toPolish = ItemStack.of(tag.getCompound("Polishing")); ItemStack polished = - SandPaperPolishingRecipe.applyPolish(worldIn, entityLiving.getPositionVec(), toPolish, stack); + SandPaperPolishingRecipe.applyPolish(worldIn, entityLiving.position(), toPolish, stack); - if (worldIn.isRemote) { + if (worldIn.isClientSide) { spawnParticles(entityLiving.getEyePosition(1) - .add(entityLiving.getLookVec() + .add(entityLiving.getLookAngle() .scale(.5f)), toPolish, worldIn); return stack; @@ -141,13 +141,13 @@ public class SandPaperItem extends Item { if (!polished.isEmpty()) { if (player instanceof FakePlayer) { - player.dropItem(polished, false, false); + player.drop(polished, false, false); } else { player.inventory.placeItemBackInInventory(worldIn, polished); } } tag.remove("Polishing"); - stack.damageItem(1, entityLiving, p -> p.sendBreakAnimation(p.getActiveHand())); + stack.hurtAndBreak(1, entityLiving, p -> p.broadcastBreakEvent(p.getUsedItemHand())); } return stack; @@ -155,20 +155,20 @@ public class SandPaperItem extends Item { public static void spawnParticles(Vector3d location, ItemStack polishedStack, World world) { for (int i = 0; i < 20; i++) { - Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, world.rand, 1 / 8f); + Vector3d motion = VecHelper.offsetRandomly(Vector3d.ZERO, world.random, 1 / 8f); world.addParticle(new ItemParticleData(ParticleTypes.ITEM, polishedStack), location.x, location.y, location.z, motion.x, motion.y, motion.z); } } @Override - public void onPlayerStoppedUsing(ItemStack stack, World worldIn, LivingEntity entityLiving, int timeLeft) { + public void releaseUsing(ItemStack stack, World worldIn, LivingEntity entityLiving, int timeLeft) { if (!(entityLiving instanceof PlayerEntity)) return; PlayerEntity player = (PlayerEntity) entityLiving; CompoundNBT tag = stack.getOrCreateTag(); if (tag.contains("Polishing")) { - ItemStack toPolish = ItemStack.read(tag.getCompound("Polishing")); + ItemStack toPolish = ItemStack.of(tag.getCompound("Polishing")); player.inventory.placeItemBackInInventory(worldIn, toPolish); tag.remove("Polishing"); } @@ -180,7 +180,7 @@ public class SandPaperItem extends Item { } @Override - public int getItemEnchantability() { + public int getEnchantmentValue() { return 5; } 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..6a1524742 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,9 @@ 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.CreateCustomRenderedItemModel; +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.Minecraft; @@ -10,43 +12,41 @@ import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.ItemRenderer; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; -import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3f; -public class SandPaperItemRenderer extends ItemStackTileEntityRenderer { +public class SandPaperItemRenderer extends CustomRenderedItemModelRenderer { @Override - public void render(ItemStack stack, TransformType transformType, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + protected void render(ItemStack stack, SandPaperModel model, PartialItemModelRenderer renderer, + TransformType transformType, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer(); ClientPlayerEntity player = Minecraft.getInstance().player; - SandPaperModel mainModel = (SandPaperModel) itemRenderer.getItemModelWithOverrides(stack, Minecraft.getInstance().world, null); float partialTicks = AnimationTickHolder.getPartialTicks(); boolean leftHand = transformType == TransformType.FIRST_PERSON_LEFT_HAND; boolean firstPerson = leftHand || transformType == TransformType.FIRST_PERSON_RIGHT_HAND; - ms.push(); - ms.translate(.5f, .5f, .5f); - CompoundNBT tag = stack.getOrCreateTag(); boolean jeiMode = tag.contains("JEI"); + ms.pushPose(); + if (tag.contains("Polishing")) { - ms.push(); + ms.pushPose(); if (transformType == TransformType.GUI) { ms.translate(0.0F, .2f, 1.0F); ms.scale(.75f, .75f, .75f); } else { int modifier = leftHand ? -1 : 1; - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(modifier * 40)); + ms.mulPose(Vector3f.YP.rotationDegrees(modifier * 40)); } // Reverse bobbing - float time = (float) (!jeiMode ? player.getItemInUseCount() + float time = (float) (!jeiMode ? player.getUseItemRemainingTicks() : (-AnimationTickHolder.getTicks()) % stack.getUseDuration()) - partialTicks + 1.0F; if (time / (float) stack.getUseDuration() < 0.8F) { float bobbing = -MathHelper.abs(MathHelper.cos(time / 4.0F * (float) Math.PI) * 0.1F); @@ -57,39 +57,39 @@ public class SandPaperItemRenderer extends ItemStackTileEntityRenderer { ms.translate(0.0f, bobbing, 0.0F); } - ItemStack toPolish = ItemStack.read(tag.getCompound("Polishing")); - itemRenderer.renderItem(toPolish, TransformType.NONE, light, overlay, ms, buffer); + ItemStack toPolish = ItemStack.of(tag.getCompound("Polishing")); + itemRenderer.renderStatic(toPolish, TransformType.NONE, light, overlay, ms, buffer); - ms.pop(); + ms.popPose(); } if (firstPerson) { - int itemInUseCount = player.getItemInUseCount(); + int itemInUseCount = player.getUseItemRemainingTicks(); if (itemInUseCount > 0) { int modifier = leftHand ? -1 : 1; ms.translate(modifier * .5f, 0, -.25f); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(modifier * 40)); - ms.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(modifier * 10)); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(modifier * 90)); + ms.mulPose(Vector3f.ZP.rotationDegrees(modifier * 40)); + ms.mulPose(Vector3f.XP.rotationDegrees(modifier * 10)); + ms.mulPose(Vector3f.YP.rotationDegrees(modifier * 90)); } } - itemRenderer.renderItem(stack, TransformType.NONE, false, ms, buffer, light, overlay, mainModel.getOriginalModel()); + itemRenderer.render(stack, TransformType.NONE, false, ms, buffer, light, overlay, model.getOriginalModel()); - ms.pop(); + ms.popPose(); } - public static class SandPaperModel extends CustomRenderedItemModel { + @Override + public SandPaperModel createModel(IBakedModel originalModel) { + return new SandPaperModel(originalModel); + } + + public static class SandPaperModel extends CreateCustomRenderedItemModel { public SandPaperModel(IBakedModel template) { super(template, ""); } - @Override - public ItemStackTileEntityRenderer createRenderer() { - return new SandPaperItemRenderer(); - } - } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperPolishingRecipe.java b/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperPolishingRecipe.java index b949f1f94..8ef830a4f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperPolishingRecipe.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperPolishingRecipe.java @@ -26,7 +26,7 @@ public class SandPaperPolishingRecipe extends ProcessingRecipe { @Override public boolean matches(SandPaperInv inv, World worldIn) { return ingredients.get(0) - .test(inv.getStackInSlot(0)); + .test(inv.getItem(0)); } @Override @@ -47,14 +47,14 @@ public class SandPaperPolishingRecipe extends ProcessingRecipe { List> matchingRecipes = getMatchingRecipes(world, stack); if (!matchingRecipes.isEmpty()) return matchingRecipes.get(0) - .getCraftingResult(new SandPaperInv(stack)) + .assemble(new SandPaperInv(stack)) .copy(); return stack; } public static List> getMatchingRecipes(World world, ItemStack stack) { return world.getRecipeManager() - .getRecipes(AllRecipeTypes.SANDPAPER_POLISHING.getType(), new SandPaperInv(stack), world); + .getRecipesFor(AllRecipeTypes.SANDPAPER_POLISHING.getType(), new SandPaperInv(stack), world); } public static class SandPaperInv extends RecipeWrapper { diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java new file mode 100644 index 000000000..c3856616c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java @@ -0,0 +1,391 @@ +package com.simibubi.create.content.curiosities.weapons; + +import java.util.UUID; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +import com.mojang.authlib.GameProfile; +import com.mojang.datafixers.util.Pair; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.utility.WorldAttached; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.item.FallingBlockEntity; +import net.minecraft.entity.monster.ZombieVillagerEntity; +import net.minecraft.entity.passive.FoxEntity; +import net.minecraft.item.Food; +import net.minecraft.item.Foods; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.potion.Effect; +import net.minecraft.potion.EffectInstance; +import net.minecraft.potion.Effects; +import net.minecraft.util.Direction; +import net.minecraft.util.Hand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.EntityRayTraceResult; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.common.IPlantable; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.event.entity.living.EntityTeleportEvent; +import net.minecraftforge.registries.IRegistryDelegate; + +public class BuiltinPotatoProjectileTypes { + + private static final GameProfile ZOMBIE_CONVERTER_NAME = + new GameProfile(UUID.fromString("be12d3dc-27d3-4992-8c97-66be53fd49c5"), "Converter"); + private static final WorldAttached ZOMBIE_CONVERTERS = + new WorldAttached<>(w -> new FakePlayer((ServerWorld) w, ZOMBIE_CONVERTER_NAME)); + + public static final PotatoCannonProjectileType + + FALLBACK = create("fallback").damage(0) + .register(), + + POTATO = create("potato").damage(5) + .reloadTicks(15) + .velocity(1.25f) + .knockback(1.5f) + .renderTumbling() + .onBlockHit(plantCrop(Blocks.POTATOES.delegate)) + .registerAndAssign(Items.POTATO), + + BAKED_POTATO = create("baked_potato").damage(5) + .reloadTicks(15) + .velocity(1.25f) + .knockback(0.5f) + .renderTumbling() + .preEntityHit(setFire(3)) + .registerAndAssign(Items.BAKED_POTATO), + + CARROT = create("carrot").damage(4) + .reloadTicks(12) + .velocity(1.45f) + .knockback(0.3f) + .renderTowardMotion(140, 1) + .soundPitch(1.5f) + .onBlockHit(plantCrop(Blocks.CARROTS.delegate)) + .registerAndAssign(Items.CARROT), + + GOLDEN_CARROT = create("golden_carrot").damage(12) + .reloadTicks(15) + .velocity(1.45f) + .knockback(0.5f) + .renderTowardMotion(140, 2) + .soundPitch(1.5f) + .registerAndAssign(Items.GOLDEN_CARROT), + + SWEET_BERRIES = create("sweet_berry").damage(3) + .reloadTicks(10) + .knockback(0.1f) + .velocity(1.05f) + .renderTumbling() + .splitInto(3) + .soundPitch(1.25f) + .registerAndAssign(Items.SWEET_BERRIES), + + CHOCOLATE_BERRIES = create("chocolate_berry").damage(4) + .reloadTicks(10) + .knockback(0.2f) + .velocity(1.05f) + .renderTumbling() + .splitInto(3) + .soundPitch(1.25f) + .registerAndAssign(AllItems.CHOCOLATE_BERRIES.get()), + + POISON_POTATO = create("poison_potato").damage(5) + .reloadTicks(15) + .knockback(0.05f) + .velocity(1.25f) + .renderTumbling() + .onEntityHit(potion(Effects.POISON, 1,160, true)) + .registerAndAssign(Items.POISONOUS_POTATO), + + CHORUS_FRUIT = create("chorus_fruit").damage(3) + .reloadTicks(15) + .velocity(1.20f) + .knockback(0.05f) + .renderTumbling() + .onEntityHit(chorusTeleport(20)) + .registerAndAssign(Items.CHORUS_FRUIT), + + APPLE = create("apple").damage(5) + .reloadTicks(10) + .velocity(1.45f) + .knockback(0.5f) + .renderTumbling() + .soundPitch(1.1f) + .registerAndAssign(Items.APPLE), + + HONEYED_APPLE = create("honeyed_apple").damage(6) + .reloadTicks(15) + .velocity(1.35f) + .knockback(0.1f) + .renderTumbling() + .soundPitch(1.1f) + .onEntityHit(potion(Effects.MOVEMENT_SLOWDOWN, 2,160, true)) + .registerAndAssign(AllItems.HONEYED_APPLE.get()), + + GOLDEN_APPLE = create("golden_apple").damage(1) + .reloadTicks(100) + .velocity(1.45f) + .knockback(0.05f) + .renderTumbling() + .soundPitch(1.1f) + .onEntityHit(ray -> { + Entity entity = ray.getEntity(); + World world = entity.level; + + if (!(entity instanceof ZombieVillagerEntity) + || !((ZombieVillagerEntity) entity).hasEffect(Effects.WEAKNESS)) + return foodEffects(Foods.GOLDEN_APPLE, false).test(ray); + if (world.isClientSide) + return false; + + FakePlayer dummy = ZOMBIE_CONVERTERS.get(world); + dummy.setItemInHand(Hand.MAIN_HAND, new ItemStack(Items.GOLDEN_APPLE, 1)); + ((ZombieVillagerEntity) entity).mobInteract(dummy, Hand.MAIN_HAND); + return true; + }) + .registerAndAssign(Items.GOLDEN_APPLE), + + ENCHANTED_GOLDEN_APPLE = create("enchanted_golden_apple").damage(1) + .reloadTicks(100) + .velocity(1.45f) + .knockback(0.05f) + .renderTumbling() + .soundPitch(1.1f) + .onEntityHit(foodEffects(Foods.ENCHANTED_GOLDEN_APPLE, false)) + .registerAndAssign(Items.ENCHANTED_GOLDEN_APPLE), + + BEETROOT = create("beetroot").damage(2) + .reloadTicks(5) + .velocity(1.6f) + .knockback(0.1f) + .renderTowardMotion(140, 2) + .soundPitch(1.6f) + .registerAndAssign(Items.BEETROOT), + + MELON_SLICE = create("melon_slice").damage(3) + .reloadTicks(8) + .knockback(0.1f) + .velocity(1.45f) + .renderTumbling() + .soundPitch(1.5f) + .registerAndAssign(Items.MELON_SLICE), + + GLISTENING_MELON = create("glistening_melon").damage(5) + .reloadTicks(8) + .knockback(0.1f) + .velocity(1.45f) + .renderTumbling() + .soundPitch(1.5f) + .onEntityHit(potion(Effects.GLOWING, 1, 100, true)) + .registerAndAssign(Items.GLISTERING_MELON_SLICE), + + MELON_BLOCK = create("melon_block").damage(8) + .reloadTicks(20) + .knockback(2.0f) + .velocity(0.95f) + .renderTumbling() + .soundPitch(0.9f) + .onBlockHit(placeBlockOnGround(Blocks.MELON.delegate)) + .registerAndAssign(Blocks.MELON), + + PUMPKIN_BLOCK = create("pumpkin_block").damage(6) + .reloadTicks(15) + .knockback(2.0f) + .velocity(0.95f) + .renderTumbling() + .soundPitch(0.9f) + .onBlockHit(placeBlockOnGround(Blocks.PUMPKIN.delegate)) + .registerAndAssign(Blocks.PUMPKIN), + + PUMPKIN_PIE = create("pumpkin_pie").damage(7) + .reloadTicks(15) + .knockback(0.05f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .soundPitch(1.1f) + .registerAndAssign(Items.PUMPKIN_PIE), + + CAKE = create("cake").damage(8) + .reloadTicks(15) + .knockback(0.1f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .soundPitch(1.0f) + .registerAndAssign(Items.CAKE), + + BLAZE_CAKE = create("blaze_cake").damage(15) + .reloadTicks(20) + .knockback(0.3f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .preEntityHit(setFire(12)) + .soundPitch(1.0f) + .registerAndAssign(AllItems.BLAZE_CAKE.get()) + + ; + + private static PotatoCannonProjectileType.Builder create(String name) { + return new PotatoCannonProjectileType.Builder(Create.asResource(name)); + } + + private static Predicate setFire(int seconds) { + return ray -> { + ray.getEntity().setSecondsOnFire(seconds); + return false; + }; + } + + private static Predicate potion(Effect effect, int level, int ticks, boolean recoverable) { + return ray -> { + Entity entity = ray.getEntity(); + if (entity.level.isClientSide) + return true; + if (entity instanceof LivingEntity) + applyEffect((LivingEntity) entity, new EffectInstance(effect, ticks, level - 1)); + return !recoverable; + }; + } + + private static Predicate foodEffects(Food food, boolean recoverable) { + return ray -> { + Entity entity = ray.getEntity(); + if (entity.level.isClientSide) + return true; + + if (entity instanceof LivingEntity) { + for (Pair effect : food.getEffects()) { + if (Create.RANDOM.nextFloat() < effect.getSecond()) + applyEffect((LivingEntity) entity, new EffectInstance(effect.getFirst())); + } + } + return !recoverable; + }; + } + + public static void applyEffect(LivingEntity entity, EffectInstance effect) { + if (effect.getEffect().isInstantenous()) + effect.getEffect().applyInstantenousEffect(null, null, entity, effect.getDuration(), 1.0); + else + entity.addEffect(effect); + } + + private static BiPredicate plantCrop(IRegistryDelegate cropBlock) { + return (world, ray) -> { + if (world.isClientSide()) + return true; + + BlockPos hitPos = ray.getBlockPos(); + if (!world.isAreaLoaded(hitPos, 1)) + return true; + Direction face = ray.getDirection(); + BlockPos placePos = hitPos.relative(face); + if (!world.getBlockState(placePos) + .getMaterial() + .isReplaceable()) + return false; + if (!(cropBlock.get() instanceof IPlantable)) + return false; + BlockState blockState = world.getBlockState(hitPos); + if (!blockState.canSustainPlant(world, hitPos, face, (IPlantable) cropBlock.get())) + return false; + world.setBlock(placePos, cropBlock.get().defaultBlockState(), 3); + return true; + }; + } + + private static BiPredicate placeBlockOnGround(IRegistryDelegate block) { + return (world, ray) -> { + if (world.isClientSide()) + return true; + + BlockPos hitPos = ray.getBlockPos(); + if (!world.isAreaLoaded(hitPos, 1)) + return true; + Direction face = ray.getDirection(); + BlockPos placePos = hitPos.relative(face); + if (!world.getBlockState(placePos) + .getMaterial() + .isReplaceable()) + return false; + + if (face == Direction.UP) { + world.setBlock(placePos, block.get().defaultBlockState(), 3); + } else if (world instanceof World) { + double y = ray.getLocation().y - 0.5; + if (!world.isEmptyBlock(placePos.above())) + y = Math.min(y, placePos.getY()); + if (!world.isEmptyBlock(placePos.below())) + y = Math.max(y, placePos.getY()); + + FallingBlockEntity falling = new FallingBlockEntity((World) world, placePos.getX() + 0.5, y, + placePos.getZ() + 0.5, block.get().defaultBlockState()); + falling.time = 1; + world.addFreshEntity(falling); + } + + return true; + }; + } + + private static Predicate chorusTeleport(double teleportDiameter) { + return ray -> { + Entity entity = ray.getEntity(); + World world = entity.getCommandSenderWorld(); + if (world.isClientSide) + return true; + if (!(entity instanceof LivingEntity)) + return false; + LivingEntity livingEntity = (LivingEntity) entity; + + double entityX = livingEntity.getX(); + double entityY = livingEntity.getY(); + double entityZ = livingEntity.getZ(); + + for (int teleportTry = 0; teleportTry < 16; ++teleportTry) { + double teleportX = entityX + (livingEntity.getRandom().nextDouble() - 0.5D) * teleportDiameter; + double teleportY = MathHelper.clamp(entityY + (livingEntity.getRandom().nextInt((int) teleportDiameter) - (int) (teleportDiameter / 2)), 0.0D, world.getHeight() - 1); + double teleportZ = entityZ + (livingEntity.getRandom().nextDouble() - 0.5D) * teleportDiameter; + + EntityTeleportEvent.ChorusFruit event = ForgeEventFactory.onChorusFruitTeleport(livingEntity, teleportX, teleportY, teleportZ); + if (event.isCanceled()) + return false; + if (livingEntity.randomTeleport(event.getTargetX(), event.getTargetY(), event.getTargetZ(), true)) { + if (livingEntity.isPassenger()) + livingEntity.stopRiding(); + + SoundEvent soundevent = livingEntity instanceof FoxEntity ? SoundEvents.FOX_TELEPORT : SoundEvents.CHORUS_FRUIT_TELEPORT; + world.playSound(null, entityX, entityY, entityZ, soundevent, SoundCategory.PLAYERS, 1.0F, 1.0F); + livingEntity.playSound(soundevent, 1.0F, 1.0F); + livingEntity.setDeltaMovement(Vector3d.ZERO); + return true; + } + } + + return false; + }; + } + + public static void register() {} + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java new file mode 100644 index 000000000..46fb0767d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java @@ -0,0 +1,295 @@ +package com.simibubi.create.content.curiosities.weapons; + +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; + +import com.simibubi.create.AllEnchantments; +import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.Create; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.curiosities.armor.BackTankUtil; +import com.simibubi.create.content.curiosities.zapper.ShootableGadgetItemMethods; +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUseContext; +import net.minecraft.item.ShootableItem; +import net.minecraft.item.UseAction; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.text.IFormattableTextComponent; +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; + +public class PotatoCannonItem extends ShootableItem { + + public static ItemStack CLIENT_CURRENT_AMMO = ItemStack.EMPTY; + public static final int MAX_DAMAGE = 100; + + public PotatoCannonItem(Properties properties) { + super(properties); + } + + @Override + public boolean canAttackBlock(BlockState state, World world, BlockPos pos, PlayerEntity player) { + return false; + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + if (enchantment == Enchantments.POWER_ARROWS) + return true; + if (enchantment == Enchantments.PUNCH_ARROWS) + return true; + if (enchantment == Enchantments.FLAMING_ARROWS) + return true; + if (enchantment == Enchantments.MOB_LOOTING) + return true; + if (enchantment == AllEnchantments.POTATO_RECOVERY.get()) + return true; + return super.canApplyAtEnchantingTable(stack, enchantment); + } + + @Override + public ActionResultType useOn(ItemUseContext context) { + return use(context.getLevel(), context.getPlayer(), context.getHand()).getResult(); + } + + @Override + public int getItemStackLimit(ItemStack stack) { + return 1; + } + + @Override + public int getRGBDurabilityForDisplay(ItemStack stack) { + return BackTankUtil.getRGBDurabilityForDisplay(stack, maxUses()); + } + + @Override + public double getDurabilityForDisplay(ItemStack stack) { + return BackTankUtil.getDurabilityForDisplay(stack, maxUses()); + } + + @Override + public boolean showDurabilityBar(ItemStack stack) { + return BackTankUtil.showDurabilityBar(stack, maxUses()); + } + + private int maxUses() { + return AllConfigs.SERVER.curiosities.maxPotatoCannonShots.get(); + } + + @Override + public boolean canBeDepleted() { + return true; + } + + public boolean isCannon(ItemStack stack) { + return stack.getItem() instanceof PotatoCannonItem; + } + + @Override + public int getMaxDamage(ItemStack stack) { + return MAX_DAMAGE; + } + + @Override + public ActionResult use(World world, PlayerEntity player, Hand hand) { + ItemStack stack = player.getItemInHand(hand); + return findAmmoInInventory(world, player, stack).map(itemStack -> { + + if (ShootableGadgetItemMethods.shouldSwap(player, stack, hand, this::isCannon)) + return ActionResult.fail(stack); + + if (world.isClientSide) { + CreateClient.POTATO_CANNON_RENDER_HANDLER.dontAnimateItem(hand); + return ActionResult.success(stack); + } + + Vector3d barrelPos = ShootableGadgetItemMethods.getGunBarrelVec(player, hand == Hand.MAIN_HAND, + new Vector3d(.75f, -0.15f, 1.5f)); + Vector3d correction = + ShootableGadgetItemMethods.getGunBarrelVec(player, hand == Hand.MAIN_HAND, new Vector3d(-.05f, 0, 0)) + .subtract(player.position() + .add(0, player.getEyeHeight(), 0)); + + PotatoCannonProjectileType projectileType = PotatoProjectileTypeManager.getTypeForStack(itemStack) + .orElse(BuiltinPotatoProjectileTypes.FALLBACK); + Vector3d lookVec = player.getLookAngle(); + Vector3d motion = lookVec.add(correction) + .normalize() + .scale(projectileType.getVelocityMultiplier()); + + float soundPitch = projectileType.getSoundPitch() + (Create.RANDOM.nextFloat() - .5f) / 4f; + + boolean spray = projectileType.getSplit() > 1; + Vector3d sprayBase = VecHelper.rotate(new Vector3d(0, 0.1, 0), 360 * Create.RANDOM.nextFloat(), Axis.Z); + float sprayChange = 360f / projectileType.getSplit(); + + for (int i = 0; i < projectileType.getSplit(); i++) { + PotatoProjectileEntity projectile = AllEntityTypes.POTATO_PROJECTILE.create(world); + projectile.setItem(itemStack); + projectile.setEnchantmentEffectsFromCannon(stack); + + Vector3d splitMotion = motion; + if (spray) { + float imperfection = 40 * (Create.RANDOM.nextFloat() - 0.5f); + Vector3d sprayOffset = VecHelper.rotate(sprayBase, i * sprayChange + imperfection, Axis.Z); + splitMotion = splitMotion.add(VecHelper.lookAt(sprayOffset, motion)); + } + + if (i != 0) + projectile.recoveryChance = 0; + + projectile.setPos(barrelPos.x, barrelPos.y, barrelPos.z); + projectile.setDeltaMovement(splitMotion); + projectile.setOwner(player); + world.addFreshEntity(projectile); + } + + if (!player.isCreative()) { + itemStack.shrink(1); + if (itemStack.isEmpty()) + player.inventory.removeItem(itemStack); + } + + if (!BackTankUtil.canAbsorbDamage(player, maxUses())) + stack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand)); + + Integer cooldown = + findAmmoInInventory(world, player, stack).flatMap(PotatoProjectileTypeManager::getTypeForStack) + .map(PotatoCannonProjectileType::getReloadTicks) + .orElse(10); + + ShootableGadgetItemMethods.applyCooldown(player, stack, hand, this::isCannon, cooldown); + ShootableGadgetItemMethods.sendPackets(player, + b -> new PotatoCannonPacket(barrelPos, lookVec.normalize(), itemStack, hand, soundPitch, b)); + return ActionResult.success(stack); + }) + .orElse(ActionResult.pass(stack)); + } + + @Override + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { + return slotChanged || newStack.getItem() != oldStack.getItem(); + } + + private Optional findAmmoInInventory(World world, PlayerEntity player, ItemStack held) { + ItemStack findAmmo = player.getProjectile(held); + return PotatoProjectileTypeManager.getTypeForStack(findAmmo) + .map($ -> findAmmo); + } + + @OnlyIn(Dist.CLIENT) + public static Optional getAmmoforPreview(ItemStack cannon) { + if (AnimationTickHolder.getTicks() % 3 != 0) + return Optional.of(CLIENT_CURRENT_AMMO) + .filter(stack -> !stack.isEmpty()); + + ClientPlayerEntity player = Minecraft.getInstance().player; + CLIENT_CURRENT_AMMO = ItemStack.EMPTY; + if (player == null) + return Optional.empty(); + ItemStack findAmmo = player.getProjectile(cannon); + Optional found = PotatoProjectileTypeManager.getTypeForStack(findAmmo) + .map($ -> findAmmo); + found.ifPresent(stack -> CLIENT_CURRENT_AMMO = stack); + return found; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void appendHoverText(ItemStack stack, World world, List tooltip, ITooltipFlag flag) { + int power = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, stack); + int punch = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, stack); + final float additionalDamageMult = 1 + power * .2f; + final float additionalKnockback = punch * .5f; + + getAmmoforPreview(stack).ifPresent(ammo -> { + String _attack = "potato_cannon.ammo.attack_damage"; + String _reload = "potato_cannon.ammo.reload_ticks"; + String _knockback = "potato_cannon.ammo.knockback"; + + tooltip.add(new StringTextComponent("")); + tooltip.add(new TranslationTextComponent(ammo.getDescriptionId()).append(new StringTextComponent(":")) + .withStyle(TextFormatting.GRAY)); + PotatoCannonProjectileType type = PotatoProjectileTypeManager.getTypeForStack(ammo) + .get(); + StringTextComponent spacing = new StringTextComponent(" "); + TextFormatting green = TextFormatting.GREEN; + TextFormatting darkGreen = TextFormatting.DARK_GREEN; + + float damageF = type.getDamage() * additionalDamageMult; + IFormattableTextComponent damage = new StringTextComponent( + damageF == MathHelper.floor(damageF) ? "" + MathHelper.floor(damageF) : "" + damageF); + IFormattableTextComponent reloadTicks = new StringTextComponent("" + type.getReloadTicks()); + IFormattableTextComponent knockback = + new StringTextComponent("" + (type.getKnockback() + additionalKnockback)); + + damage = damage.withStyle(additionalDamageMult > 1 ? green : darkGreen); + knockback = knockback.withStyle(additionalKnockback > 0 ? green : darkGreen); + reloadTicks = reloadTicks.withStyle(darkGreen); + + tooltip.add(spacing.plainCopy() + .append(Lang.translate(_attack, damage) + .withStyle(darkGreen))); + tooltip.add(spacing.plainCopy() + .append(Lang.translate(_reload, reloadTicks) + .withStyle(darkGreen))); + tooltip.add(spacing.plainCopy() + .append(Lang.translate(_knockback, knockback) + .withStyle(darkGreen))); + }); + super.appendHoverText(stack, world, tooltip, flag); + } + + @Override + public Predicate getAllSupportedProjectiles() { + return stack -> PotatoProjectileTypeManager.getTypeForStack(stack) + .isPresent(); + } + + @Override + public int getEnchantmentValue() { + return 1; + } + + @Override + public boolean onEntitySwing(ItemStack stack, LivingEntity entity) { + return true; + } + + @Override + public UseAction getUseAnimation(ItemStack stack) { + return UseAction.NONE; + } + + @Override + public int getDefaultProjectileRange() { + return 15; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItemRenderer.java new file mode 100644 index 000000000..b4280d984 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItemRenderer.java @@ -0,0 +1,71 @@ +package com.simibubi.create.content.curiosities.weapons; + +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.CreateClient; +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.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.ItemRenderer; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.item.ItemStack; +import net.minecraft.util.HandSide; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Vector3f; + +public class PotatoCannonItemRenderer extends CustomRenderedItemModelRenderer { + + @Override + protected void render(ItemStack stack, PotatoCannonModel model, PartialItemModelRenderer renderer, + TransformType transformType, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + renderer.render(model.getOriginalModel(), light); + ClientPlayerEntity player = Minecraft.getInstance().player; + boolean mainHand = player.getMainHandItem() == stack; + boolean offHand = player.getOffhandItem() == stack; + boolean leftHanded = player.getMainArm() == HandSide.LEFT; + + float offset = .5f / 16; + float worldTime = AnimationTickHolder.getRenderTime() / 10; + float angle = worldTime * -25; + float speed = CreateClient.POTATO_CANNON_RENDER_HANDLER.getAnimation(mainHand ^ leftHanded, + AnimationTickHolder.getPartialTicks()); + + if (mainHand || offHand) + angle += 360 * MathHelper.clamp(speed * 5, 0, 1); + angle %= 360; + + ms.pushPose(); + ms.translate(0, offset, 0); + ms.mulPose(Vector3f.ZP.rotationDegrees(angle)); + ms.translate(0, -offset, 0); + renderer.render(model.getPartial("cog"), light); + ms.popPose(); + + if (transformType == TransformType.GUI) { + PotatoCannonItem.getAmmoforPreview(stack) + .ifPresent(ammo -> { + MatrixStack localMs = new MatrixStack(); + localMs.translate(-1 / 4f, -1 / 4f, 1); + localMs.scale(.5f, .5f, .5f); + MatrixTransformStack.of(localMs) + .rotateY(-34); + itemRenderer.renderStatic(ammo, TransformType.GUI, light, OverlayTexture.NO_OVERLAY, localMs, buffer); + }); + } + + } + + @Override + public PotatoCannonModel createModel(IBakedModel originalModel) { + return new PotatoCannonModel(originalModel); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonModel.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonModel.java new file mode 100644 index 000000000..f967d01ce --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonModel.java @@ -0,0 +1,14 @@ +package com.simibubi.create.content.curiosities.weapons; + +import com.simibubi.create.foundation.item.render.CreateCustomRenderedItemModel; + +import net.minecraft.client.renderer.model.IBakedModel; + +public class PotatoCannonModel extends CreateCustomRenderedItemModel { + + public PotatoCannonModel(IBakedModel template) { + super(template, "potato_cannon"); + addPartials("cog"); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonPacket.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonPacket.java new file mode 100644 index 000000000..f6d1a3b8f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonPacket.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.curiosities.weapons; + +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.curiosities.zapper.ShootGadgetPacket; +import com.simibubi.create.content.curiosities.zapper.ShootableGadgetRenderHandler; + +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.Hand; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class PotatoCannonPacket extends ShootGadgetPacket { + + private float pitch; + private Vector3d motion; + private ItemStack item; + + public PotatoCannonPacket(Vector3d location, Vector3d motion, ItemStack item, Hand hand, float pitch, boolean self) { + super(location, hand, self); + this.motion = motion; + this.item = item; + this.pitch = pitch; + } + + public PotatoCannonPacket(PacketBuffer buffer) { + super(buffer); + } + + @Override + protected void readAdditional(PacketBuffer buffer) { + pitch = buffer.readFloat(); + motion = new Vector3d(buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); + item = buffer.readItem(); + } + + @Override + protected void writeAdditional(PacketBuffer buffer) { + buffer.writeFloat(pitch); + buffer.writeFloat((float) motion.x); + buffer.writeFloat((float) motion.y); + buffer.writeFloat((float) motion.z); + buffer.writeItem(item); + } + + @Override + @OnlyIn(Dist.CLIENT) + protected void handleAdditional() { + CreateClient.POTATO_CANNON_RENDER_HANDLER.beforeShoot(pitch, location, motion, item); + } + + @Override + @OnlyIn(Dist.CLIENT) + protected ShootableGadgetRenderHandler getHandler() { + return CreateClient.POTATO_CANNON_RENDER_HANDLER; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileType.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileType.java new file mode 100644 index 000000000..303d83f7e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonProjectileType.java @@ -0,0 +1,295 @@ +package com.simibubi.create.content.curiosities.weapons; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import net.minecraft.item.Item; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.IItemProvider; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.ResourceLocationException; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.EntityRayTraceResult; +import net.minecraft.world.IWorld; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.IRegistryDelegate; + +public class PotatoCannonProjectileType { + + private Set> items = new HashSet<>(); + + private int reloadTicks = 10; + private int damage = 1; + private int split = 1; + private float knockback = 1; + private float drag = 0.99f; + private float velocityMultiplier = 1; + private float gravityMultiplier = 1; + private float soundPitch = 1; + private boolean sticky = false; + private PotatoProjectileRenderMode renderMode = PotatoProjectileRenderMode.Billboard.INSTANCE; + + private Predicate preEntityHit = e -> false; // True if hit should be canceled + private Predicate onEntityHit = e -> false; // True if shouldn't recover projectile + private BiPredicate onBlockHit = (w, ray) -> false; + + protected PotatoCannonProjectileType() { + } + + public Set> getItems() { + return items; + } + + public int getReloadTicks() { + return reloadTicks; + } + + public int getDamage() { + return damage; + } + + public int getSplit() { + return split; + } + + public float getKnockback() { + return knockback; + } + + public float getDrag() { + return drag; + } + + public float getVelocityMultiplier() { + return velocityMultiplier; + } + + public float getGravityMultiplier() { + return gravityMultiplier; + } + + public float getSoundPitch() { + return soundPitch; + } + + public boolean isSticky() { + return sticky; + } + + public PotatoProjectileRenderMode getRenderMode() { + return renderMode; + } + + public boolean preEntityHit(EntityRayTraceResult ray) { + return preEntityHit.test(ray); + } + + public boolean onEntityHit(EntityRayTraceResult ray) { + return onEntityHit.test(ray); + } + + public boolean onBlockHit(IWorld world, BlockRayTraceResult ray) { + return onBlockHit.test(world, ray); + } + + public static PotatoCannonProjectileType fromJson(JsonObject object) { + PotatoCannonProjectileType type = new PotatoCannonProjectileType(); + try { + JsonElement itemsElement = object.get("items"); + if (itemsElement != null && itemsElement.isJsonArray()) { + for (JsonElement element : itemsElement.getAsJsonArray()) { + if (element.isJsonPrimitive()) { + JsonPrimitive primitive = element.getAsJsonPrimitive(); + if (primitive.isString()) { + try { + Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(primitive.getAsString())); + if (item != null) { + type.items.add(item.delegate); + } + } catch (ResourceLocationException e) { + // + } + } + } + } + } + + parseJsonPrimitive(object, "reload_ticks", JsonPrimitive::isNumber, primitive -> type.reloadTicks = primitive.getAsInt()); + parseJsonPrimitive(object, "damage", JsonPrimitive::isNumber, primitive -> type.damage = primitive.getAsInt()); + parseJsonPrimitive(object, "split", JsonPrimitive::isNumber, primitive -> type.split = primitive.getAsInt()); + parseJsonPrimitive(object, "knockback", JsonPrimitive::isNumber, primitive -> type.knockback = primitive.getAsFloat()); + parseJsonPrimitive(object, "drag", JsonPrimitive::isNumber, primitive -> type.drag = primitive.getAsFloat()); + parseJsonPrimitive(object, "velocity_multiplier", JsonPrimitive::isNumber, primitive -> type.velocityMultiplier = primitive.getAsFloat()); + parseJsonPrimitive(object, "gravity_multiplier", JsonPrimitive::isNumber, primitive -> type.gravityMultiplier = primitive.getAsFloat()); + parseJsonPrimitive(object, "sound_pitch", JsonPrimitive::isNumber, primitive -> type.soundPitch = primitive.getAsFloat()); + parseJsonPrimitive(object, "sticky", JsonPrimitive::isBoolean, primitive -> type.sticky = primitive.getAsBoolean()); + } catch (Exception e) { + // + } + return type; + } + + private static void parseJsonPrimitive(JsonObject object, String key, Predicate predicate, Consumer consumer) { + JsonElement element = object.get(key); + if (element != null && element.isJsonPrimitive()) { + JsonPrimitive primitive = element.getAsJsonPrimitive(); + if (predicate.test(primitive)) { + consumer.accept(primitive); + } + } + } + + public static void toBuffer(PotatoCannonProjectileType type, PacketBuffer buffer) { + buffer.writeVarInt(type.items.size()); + for (IRegistryDelegate delegate : type.items) { + buffer.writeResourceLocation(delegate.name()); + } + buffer.writeInt(type.reloadTicks); + buffer.writeInt(type.damage); + buffer.writeInt(type.split); + buffer.writeFloat(type.knockback); + buffer.writeFloat(type.drag); + buffer.writeFloat(type.velocityMultiplier); + buffer.writeFloat(type.gravityMultiplier); + buffer.writeFloat(type.soundPitch); + buffer.writeBoolean(type.sticky); + } + + public static PotatoCannonProjectileType fromBuffer(PacketBuffer buffer) { + PotatoCannonProjectileType type = new PotatoCannonProjectileType(); + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { + Item item = ForgeRegistries.ITEMS.getValue(buffer.readResourceLocation()); + if (item != null) { + type.items.add(item.delegate); + } + } + type.reloadTicks = buffer.readInt(); + type.damage = buffer.readInt(); + type.split = buffer.readInt(); + type.knockback = buffer.readFloat(); + type.drag = buffer.readFloat(); + type.velocityMultiplier = buffer.readFloat(); + type.gravityMultiplier = buffer.readFloat(); + type.soundPitch = buffer.readFloat(); + type.sticky = buffer.readBoolean(); + return type; + } + + public static class Builder { + + protected ResourceLocation id; + protected PotatoCannonProjectileType result; + + public Builder(ResourceLocation id) { + this.id = id; + this.result = new PotatoCannonProjectileType(); + } + + public Builder reloadTicks(int reload) { + result.reloadTicks = reload; + return this; + } + + public Builder damage(int damage) { + result.damage = damage; + return this; + } + + public Builder splitInto(int split) { + result.split = split; + return this; + } + + public Builder knockback(float knockback) { + result.knockback = knockback; + return this; + } + + public Builder drag(float drag) { + result.drag = drag; + return this; + } + + public Builder velocity(float velocity) { + result.velocityMultiplier = velocity; + return this; + } + + public Builder gravity(float modifier) { + result.gravityMultiplier = modifier; + return this; + } + + public Builder soundPitch(float pitch) { + result.soundPitch = pitch; + return this; + } + + public Builder sticky() { + result.sticky = true; + return this; + } + + public Builder renderMode(PotatoProjectileRenderMode renderMode) { + result.renderMode = renderMode; + return this; + } + + public Builder renderBillboard() { + renderMode(PotatoProjectileRenderMode.Billboard.INSTANCE); + return this; + } + + public Builder renderTumbling() { + renderMode(PotatoProjectileRenderMode.Tumble.INSTANCE); + return this; + } + + public Builder renderTowardMotion(int spriteAngle, float spin) { + renderMode(new PotatoProjectileRenderMode.TowardMotion(spriteAngle, spin)); + return this; + } + + public Builder preEntityHit(Predicate callback) { + result.preEntityHit = callback; + return this; + } + + public Builder onEntityHit(Predicate callback) { + result.onEntityHit = callback; + return this; + } + + public Builder onBlockHit(BiPredicate callback) { + result.onBlockHit = callback; + return this; + } + + public Builder addItems(IItemProvider... items) { + for (IItemProvider provider : items) + result.items.add(provider.asItem().delegate); + return this; + } + + public PotatoCannonProjectileType register() { + PotatoProjectileTypeManager.registerBuiltinType(id, result); + return result; + } + + public PotatoCannonProjectileType registerAndAssign(IItemProvider... items) { + addItems(items); + register(); + return result; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonRenderHandler.java new file mode 100644 index 000000000..9f19f3ee6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonRenderHandler.java @@ -0,0 +1,64 @@ +package com.simibubi.create.content.curiosities.weapons; + +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.particle.AirParticleData; +import com.simibubi.create.content.curiosities.zapper.ShootableGadgetRenderHandler; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.item.ItemStack; +import net.minecraft.particles.ItemParticleData; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.Hand; +import net.minecraft.util.math.vector.Vector3d; + +public class PotatoCannonRenderHandler extends ShootableGadgetRenderHandler { + + private float nextPitch; + + @Override + protected void playSound(Hand hand, Vector3d position) { + PotatoProjectileEntity.playLaunchSound(Minecraft.getInstance().level, position, nextPitch); + } + + @Override + protected boolean appliesTo(ItemStack stack) { + return AllItems.POTATO_CANNON.get() + .isCannon(stack); + } + + public void beforeShoot(float nextPitch, Vector3d location, Vector3d motion, ItemStack stack) { + this.nextPitch = nextPitch; + if (stack.isEmpty()) + return; + ClientWorld world = Minecraft.getInstance().level; + for (int i = 0; i < 2; i++) { + Vector3d m = VecHelper.offsetRandomly(motion.scale(0.1f), Create.RANDOM, .025f); + world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), location.x, location.y, location.z, m.x, + m.y, m.z); + + Vector3d m2 = VecHelper.offsetRandomly(motion.scale(2f), Create.RANDOM, .5f); + world.addParticle(new AirParticleData(1, 1 / 4f), location.x, location.y, location.z, m2.x, m2.y, m2.z); + } + } + + @Override + protected void transformTool(MatrixStack ms, float flip, float equipProgress, float recoil, float pt) { + ms.translate(flip * -.1f, 0, .14f); + ms.scale(.75f, .75f, .75f); + MatrixTransformStack.of(ms) + .rotateX(recoil * 80); + } + + @Override + protected void transformHand(MatrixStack ms, float flip, float equipProgress, float recoil, float pt) { + ms.translate(flip * -.09, -.275, -.25); + MatrixTransformStack.of(ms) + .rotateZ(flip * -10); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java new file mode 100644 index 000000000..73c5d924d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileEntity.java @@ -0,0 +1,343 @@ +package com.simibubi.create.content.curiosities.weapons; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllEnchantments; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.particle.AirParticleData; +import com.simibubi.create.foundation.advancement.AllTriggers; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.boss.WitherEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.entity.projectile.DamagingProjectileEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.IPacket; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.SChangeGameStatePacket; +import net.minecraft.particles.IParticleData; +import net.minecraft.particles.ItemParticleData; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.DamageSource; +import net.minecraft.util.IndirectEntityDamageSource; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.EntityRayTraceResult; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; +import net.minecraftforge.fml.network.NetworkHooks; +import net.minecraftforge.items.ItemHandlerHelper; + +public class PotatoProjectileEntity extends DamagingProjectileEntity implements IEntityAdditionalSpawnData { + + protected PotatoCannonProjectileType type; + protected ItemStack stack = ItemStack.EMPTY; + + protected Entity stuckEntity; + protected Vector3d stuckOffset; + protected PotatoProjectileRenderMode stuckRenderer; + protected double stuckFallSpeed; + + protected float additionalDamageMult = 1; + protected float additionalKnockback = 0; + protected float recoveryChance = 0; + + public PotatoProjectileEntity(EntityType type, World world) { + super(type, world); + } + + public ItemStack getItem() { + return stack; + } + + public void setItem(ItemStack stack) { + this.stack = stack; + } + + public PotatoCannonProjectileType getProjectileType() { + if (type == null) + type = PotatoProjectileTypeManager.getTypeForStack(stack) + .orElse(BuiltinPotatoProjectileTypes.FALLBACK); + return type; + } + + public void setEnchantmentEffectsFromCannon(ItemStack cannon) { + int power = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, cannon); + int punch = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, cannon); + int flame = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, cannon); + int recovery = EnchantmentHelper.getItemEnchantmentLevel(AllEnchantments.POTATO_RECOVERY.get(), cannon); + + if (power > 0) + additionalDamageMult = 1 + power * .2f; + if (punch > 0) + additionalKnockback = punch * .5f; + if (flame > 0) + setSecondsOnFire(100); + if (recovery > 0) + recoveryChance = .125f + recovery * .125f; + } + + @Override + public void readAdditionalSaveData(CompoundNBT nbt) { + stack = ItemStack.of(nbt.getCompound("Item")); + additionalDamageMult = nbt.getFloat("AdditionalDamage"); + additionalKnockback = nbt.getFloat("AdditionalKnockback"); + recoveryChance = nbt.getFloat("Recovery"); + super.readAdditionalSaveData(nbt); + } + + @Override + public void addAdditionalSaveData(CompoundNBT nbt) { + nbt.put("Item", stack.serializeNBT()); + nbt.putFloat("AdditionalDamage", additionalDamageMult); + nbt.putFloat("AdditionalKnockback", additionalKnockback); + nbt.putFloat("Recovery", recoveryChance); + super.addAdditionalSaveData(nbt); + } + + public Entity getStuckEntity() { + if (stuckEntity == null) + return null; + if (!stuckEntity.isAlive()) + return null; + return stuckEntity; + } + + public void setStuckEntity(Entity stuckEntity) { + this.stuckEntity = stuckEntity; + this.stuckOffset = position().subtract(stuckEntity.position()); + this.stuckRenderer = new PotatoProjectileRenderMode.StuckToEntity(stuckOffset); + this.stuckFallSpeed = 0.0; + setDeltaMovement(Vector3d.ZERO); + } + + public PotatoProjectileRenderMode getRenderMode() { + if (getStuckEntity() != null) + return stuckRenderer; + + return getProjectileType().getRenderMode(); + } + + public void tick() { + PotatoCannonProjectileType projectileType = getProjectileType(); + + Entity stuckEntity = getStuckEntity(); + if (stuckEntity != null) { + if (getY() < stuckEntity.getY() - 0.1) { + pop(position()); + remove(); + } else { + stuckFallSpeed += 0.007 * projectileType.getGravityMultiplier(); + stuckOffset = stuckOffset.add(0, -stuckFallSpeed, 0); + Vector3d pos = stuckEntity.position() + .add(stuckOffset); + setPos(pos.x, pos.y, pos.z); + } + } else { + setDeltaMovement(getDeltaMovement().add(0, -0.05 * projectileType.getGravityMultiplier(), 0) + .scale(projectileType.getDrag())); + } + + super.tick(); + } + + @Override + protected float getInertia() { + return 1; + } + + @Override + protected IParticleData getTrailParticle() { + return new AirParticleData(1, 10); + } + + @Override + protected boolean shouldBurn() { + return false; + } + + @Override + protected void onHitEntity(EntityRayTraceResult ray) { + super.onHitEntity(ray); + + if (getStuckEntity() != null) + return; + + Vector3d hit = ray.getLocation(); + Entity target = ray.getEntity(); + PotatoCannonProjectileType projectileType = getProjectileType(); + float damage = projectileType.getDamage() * additionalDamageMult; + float knockback = projectileType.getKnockback() + additionalKnockback; + Entity owner = this.getOwner(); + + if (!target.isAlive()) + return; + if (owner instanceof LivingEntity) + ((LivingEntity) owner).setLastHurtMob(target); + if (target instanceof PotatoProjectileEntity && tickCount < 10 && target.tickCount < 10) + return; + + pop(hit); + + if (target instanceof WitherEntity && ((WitherEntity) target).isPowered()) + return; + if (projectileType.preEntityHit(ray)) + return; + + boolean targetIsEnderman = target.getType() == EntityType.ENDERMAN; + int k = target.getRemainingFireTicks(); + if (this.isOnFire() && !targetIsEnderman) + target.setSecondsOnFire(5); + + boolean onServer = !level.isClientSide; + if (onServer && !target.hurt(causePotatoDamage(), damage)) { + target.setRemainingFireTicks(k); + remove(); + return; + } + + if (targetIsEnderman) + return; + + if (!projectileType.onEntityHit(ray) && onServer) + if (random.nextDouble() <= recoveryChance) + recoverItem(); + + if (!(target instanceof LivingEntity)) { + playHitSound(level, position()); + remove(); + return; + } + + LivingEntity livingentity = (LivingEntity) target; + + if (type.getReloadTicks() < 10) + livingentity.invulnerableTime = type.getReloadTicks() + 10; + + if (onServer && knockback > 0) { + Vector3d appliedMotion = this.getDeltaMovement() + .multiply(1.0D, 0.0D, 1.0D) + .normalize() + .scale(knockback * 0.6); + if (appliedMotion.lengthSqr() > 0.0D) + livingentity.push(appliedMotion.x, 0.1D, appliedMotion.z); + } + + if (onServer && owner instanceof LivingEntity) { + EnchantmentHelper.doPostHurtEffects(livingentity, owner); + EnchantmentHelper.doPostDamageEffects((LivingEntity) owner, livingentity); + } + + if (livingentity != owner && livingentity instanceof PlayerEntity && owner instanceof ServerPlayerEntity + && !this.isSilent()) { + ((ServerPlayerEntity) owner).connection + .send(new SChangeGameStatePacket(SChangeGameStatePacket.ARROW_HIT_PLAYER, 0.0F)); + } + + if (onServer && owner instanceof ServerPlayerEntity) { + ServerPlayerEntity serverplayerentity = (ServerPlayerEntity) owner; + if (!target.isAlive() && target.getType() + .getCategory() == EntityClassification.MONSTER + || (target instanceof PlayerEntity && target != owner)) + AllTriggers.POTATO_KILL.trigger(serverplayerentity); + } + + if (type.isSticky() && target.isAlive()) { + setStuckEntity(target); + } else { + remove(); + } + + } + + private void recoverItem() { + if (!stack.isEmpty()) + spawnAtLocation(ItemHandlerHelper.copyStackWithSize(stack, 1)); + } + + public static void playHitSound(World world, Vector3d location) { + AllSoundEvents.POTATO_HIT.playOnServer(world, new BlockPos(location)); + } + + public static void playLaunchSound(World world, Vector3d location, float pitch) { + AllSoundEvents.FWOOMP.playAt(world, location, 1, pitch, true); + } + + @Override + protected void onHitBlock(BlockRayTraceResult ray) { + Vector3d hit = ray.getLocation(); + pop(hit); + if (!getProjectileType().onBlockHit(level, ray) && !level.isClientSide) + if (random.nextDouble() <= recoveryChance) + recoverItem(); + super.onHitBlock(ray); + remove(); + } + + @Override + public boolean hurt(DamageSource source, float amt) { + if (source == DamageSource.IN_FIRE || source == DamageSource.ON_FIRE) + return false; + if (this.isInvulnerableTo(source)) + return false; + pop(position()); + remove(); + return true; + } + + private void pop(Vector3d hit) { + if (!stack.isEmpty()) { + for (int i = 0; i < 7; i++) { + Vector3d m = VecHelper.offsetRandomly(Vector3d.ZERO, this.random, .25f); + level.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), hit.x, hit.y, hit.z, m.x, m.y, m.z); + } + } + if (!level.isClientSide) + playHitSound(level, position()); + } + + private DamageSource causePotatoDamage() { + return new PotatoDamageSource(this, getOwner()).setProjectile(); + } + + public static class PotatoDamageSource extends IndirectEntityDamageSource { + + public PotatoDamageSource(Entity source, @Nullable Entity trueSource) { + super("create.potato_cannon", source, trueSource); + } + + } + + @SuppressWarnings("unchecked") + public static EntityType.Builder build(EntityType.Builder builder) { + EntityType.Builder entityBuilder = (EntityType.Builder) builder; + return entityBuilder.sized(.25f, .25f); + } + + @Override + public IPacket getAddEntityPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + public void writeSpawnData(PacketBuffer buffer) { + CompoundNBT compound = new CompoundNBT(); + addAdditionalSaveData(compound); + buffer.writeNbt(compound); + } + + @Override + public void readSpawnData(PacketBuffer additionalData) { + readAdditionalSaveData(additionalData.readNbt()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java new file mode 100644 index 000000000..aa8111556 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderMode.java @@ -0,0 +1,103 @@ +package com.simibubi.create.content.curiosities.weapons; + +import static com.simibubi.create.content.curiosities.weapons.PotatoProjectileRenderMode.entityRandom; + +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public interface PotatoProjectileRenderMode { + + @OnlyIn(Dist.CLIENT) + void transform(MatrixStack ms, PotatoProjectileEntity entity, float pt); + + public static class Billboard implements PotatoProjectileRenderMode { + + public static final Billboard INSTANCE = new Billboard(); + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(MatrixStack ms, PotatoProjectileEntity entity, float pt) { + Minecraft mc = Minecraft.getInstance(); + Vector3d p1 = mc.getCameraEntity() + .getEyePosition(pt); + Vector3d diff = entity.getBoundingBox() + .getCenter() + .subtract(p1); + + MatrixTransformStack.of(ms) + .rotateY(AngleHelper.deg(MathHelper.atan2(diff.x, diff.z))) + .rotateX(180 + + AngleHelper.deg(MathHelper.atan2(diff.y, -MathHelper.sqrt(diff.x * diff.x + diff.z * diff.z)))); + } + + } + + public static class Tumble extends Billboard { + + public static final Tumble INSTANCE = new Tumble(); + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(MatrixStack ms, PotatoProjectileEntity entity, float pt) { + super.transform(ms, entity, pt); + MatrixTransformStack.of(ms) + .rotateZ((entity.tickCount + pt) * 2 * entityRandom(entity, 16)) + .rotateX((entity.tickCount + pt) * entityRandom(entity, 32)); + } + + } + + public static class TowardMotion implements PotatoProjectileRenderMode { + + private int spriteAngleOffset; + private float spin; + + public TowardMotion(int spriteAngleOffset, float spin) { + this.spriteAngleOffset = spriteAngleOffset; + this.spin = spin; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(MatrixStack ms, PotatoProjectileEntity entity, float pt) { + Vector3d diff = entity.getDeltaMovement(); + MatrixTransformStack.of(ms) + .rotateY(AngleHelper.deg(MathHelper.atan2(diff.x, diff.z))) + .rotateX(270 + + AngleHelper.deg(MathHelper.atan2(diff.y, -MathHelper.sqrt(diff.x * diff.x + diff.z * diff.z)))); + MatrixTransformStack.of(ms) + .rotateY((entity.tickCount + pt) * 20 * spin + entityRandom(entity, 360)) + .rotateZ(-spriteAngleOffset); + } + + } + + public static class StuckToEntity implements PotatoProjectileRenderMode { + + private Vector3d offset; + + public StuckToEntity(Vector3d offset) { + this.offset = offset; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(MatrixStack ms, PotatoProjectileEntity entity, float pt) { + MatrixTransformStack.of(ms).rotateY(AngleHelper.deg(MathHelper.atan2(offset.x, offset.z))); + } + + } + + public static int entityRandom(Entity entity, int maxValue) { + return (System.identityHashCode(entity) * 31) % maxValue; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderer.java new file mode 100644 index 000000000..48138d20b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileRenderer.java @@ -0,0 +1,43 @@ +package com.simibubi.create.content.curiosities.weapons; + +import com.mojang.blaze3d.matrix.MatrixStack; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.IRenderTypeBuffer; +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.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +public class PotatoProjectileRenderer extends EntityRenderer { + + public PotatoProjectileRenderer(EntityRendererManager p_i46179_1_) { + super(p_i46179_1_); + } + + @Override + public void render(PotatoProjectileEntity entity, float yaw, float pt, MatrixStack ms, IRenderTypeBuffer buffer, + int light) { + ItemStack item = entity.getItem(); + if (item.isEmpty()) + return; + ms.pushPose(); + ms.translate(0, entity.getBoundingBox() + .getYsize() / 2 - 1 / 8f, 0); + entity.getRenderMode() + .transform(ms, entity, pt); + + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(item, TransformType.GROUND, light, OverlayTexture.NO_OVERLAY, ms, buffer); + ms.popPose(); + } + + @Override + public ResourceLocation getTextureLocation(PotatoProjectileEntity p_110775_1_) { + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileTypeManager.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileTypeManager.java new file mode 100644 index 000000000..86539ef5e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoProjectileTypeManager.java @@ -0,0 +1,160 @@ +package com.simibubi.create.content.curiosities.weapons; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.resources.JsonReloadListener; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.profiler.IProfiler; +import net.minecraft.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.network.NetworkEvent.Context; +import net.minecraftforge.fml.network.PacketDistributor; +import net.minecraftforge.registries.IRegistryDelegate; + +public class PotatoProjectileTypeManager { + + private static final Map BUILTIN_TYPE_MAP = new HashMap<>(); + private static final Map CUSTOM_TYPE_MAP = new HashMap<>(); + private static final Map, PotatoCannonProjectileType> ITEM_TO_TYPE_MAP = new HashMap<>(); + + public static void registerBuiltinType(ResourceLocation id, PotatoCannonProjectileType type) { + synchronized (BUILTIN_TYPE_MAP) { + BUILTIN_TYPE_MAP.put(id, type); + } + } + + public static PotatoCannonProjectileType getBuiltinType(ResourceLocation id) { + return BUILTIN_TYPE_MAP.get(id); + } + + public static PotatoCannonProjectileType getCustomType(ResourceLocation id) { + return CUSTOM_TYPE_MAP.get(id); + } + + public static PotatoCannonProjectileType getTypeForItem(IRegistryDelegate item) { + return ITEM_TO_TYPE_MAP.get(item); + } + + public static Optional getTypeForStack(ItemStack item) { + if (item.isEmpty()) + return Optional.empty(); + return Optional.ofNullable(getTypeForItem(item.getItem().delegate)); + } + + public static void clear() { + CUSTOM_TYPE_MAP.clear(); + ITEM_TO_TYPE_MAP.clear(); + } + + public static void fillItemMap() { + for (Map.Entry entry : BUILTIN_TYPE_MAP.entrySet()) { + PotatoCannonProjectileType type = entry.getValue(); + for (IRegistryDelegate delegate : type.getItems()) { + ITEM_TO_TYPE_MAP.put(delegate, type); + } + } + for (Map.Entry entry : CUSTOM_TYPE_MAP.entrySet()) { + PotatoCannonProjectileType type = entry.getValue(); + for (IRegistryDelegate delegate : type.getItems()) { + ITEM_TO_TYPE_MAP.put(delegate, type); + } + } + ITEM_TO_TYPE_MAP.remove(AllItems.POTATO_CANNON.get().delegate); + } + + public static void toBuffer(PacketBuffer buffer) { + buffer.writeVarInt(CUSTOM_TYPE_MAP.size()); + for (Map.Entry entry : CUSTOM_TYPE_MAP.entrySet()) { + buffer.writeResourceLocation(entry.getKey()); + PotatoCannonProjectileType.toBuffer(entry.getValue(), buffer); + } + } + + public static void fromBuffer(PacketBuffer buffer) { + clear(); + + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { + CUSTOM_TYPE_MAP.put(buffer.readResourceLocation(), PotatoCannonProjectileType.fromBuffer(buffer)); + } + + fillItemMap(); + } + + public static void syncTo(ServerPlayerEntity player) { + AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SyncPacket()); + } + + public static void syncToAll() { + AllPackets.channel.send(PacketDistributor.ALL.noArg(), new SyncPacket()); + } + + public static class ReloadListener extends JsonReloadListener { + + private static final Gson GSON = new Gson(); + + public static final ReloadListener INSTANCE = new ReloadListener(); + + protected ReloadListener() { + super(GSON, "potato_cannon_projectile_types"); + } + + @Override + protected void apply(Map map, IResourceManager resourceManager, IProfiler profiler) { + clear(); + + for (Map.Entry entry : map.entrySet()) { + JsonElement element = entry.getValue(); + if (element.isJsonObject()) { + ResourceLocation id = entry.getKey(); + JsonObject object = element.getAsJsonObject(); + PotatoCannonProjectileType type = PotatoCannonProjectileType.fromJson(object); + CUSTOM_TYPE_MAP.put(id, type); + } + } + + fillItemMap(); + } + + } + + public static class SyncPacket extends SimplePacketBase { + + private PacketBuffer buffer; + + public SyncPacket() { + } + + public SyncPacket(PacketBuffer buffer) { + this.buffer = buffer; + } + + @Override + public void write(PacketBuffer buffer) { + toBuffer(buffer); + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + fromBuffer(buffer); + }); + context.get().setPacketHandled(true); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoRecoveryEnchantment.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoRecoveryEnchantment.java new file mode 100644 index 000000000..d6f770279 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoRecoveryEnchantment.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.curiosities.weapons; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentType; +import net.minecraft.inventory.EquipmentSlotType; +import net.minecraft.item.ItemStack; + +public class PotatoRecoveryEnchantment extends Enchantment { + + public PotatoRecoveryEnchantment(Rarity p_i46731_1_, EnchantmentType p_i46731_2_, EquipmentSlotType[] p_i46731_3_) { + super(p_i46731_1_, p_i46731_2_, p_i46731_3_); + } + + @Override + public int getMaxLevel() { + return 3; + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack) { + return stack.getItem() instanceof PotatoCannonItem; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ConfigureZapperPacket.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ConfigureZapperPacket.java new file mode 100644 index 000000000..ee0026820 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ConfigureZapperPacket.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.curiosities.zapper; + +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.minecraft.util.Hand; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public abstract class ConfigureZapperPacket extends SimplePacketBase { + + protected Hand hand; + protected PlacementPatterns pattern; + + public ConfigureZapperPacket(Hand hand, PlacementPatterns pattern) { + this.hand = hand; + this.pattern = pattern; + } + + public ConfigureZapperPacket(PacketBuffer buffer) { + hand = buffer.readEnum(Hand.class); + pattern = buffer.readEnum(PlacementPatterns.class); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeEnum(hand); + buffer.writeEnum(pattern); + } + + @Override + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + ServerPlayerEntity player = context.get().getSender(); + if (player == null) { + return; + } + ItemStack stack = player.getItemInHand(hand); + if (stack.getItem() instanceof ZapperItem) { + configureZapper(stack); + } + }); + context.get().setPacketHandled(true); + } + + public abstract void configureZapper(ItemStack stack); + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/PlacementPatterns.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/PlacementPatterns.java index 416400af0..9a8f85b9e 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/PlacementPatterns.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/PlacementPatterns.java @@ -21,8 +21,8 @@ public enum PlacementPatterns { Chance50(AllIcons.I_PATTERN_CHANCE_50), Chance75(AllIcons.I_PATTERN_CHANCE_75); - public String translationKey; - public AllIcons icon; + public final String translationKey; + public final AllIcons icon; private PlacementPatterns(AllIcons icon) { this.translationKey = Lang.asId(name()); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootGadgetPacket.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootGadgetPacket.java new file mode 100644 index 000000000..8226cc221 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootGadgetPacket.java @@ -0,0 +1,78 @@ +package com.simibubi.create.content.curiosities.zapper; + +import java.util.function.Supplier; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.Hand; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public abstract class ShootGadgetPacket extends SimplePacketBase { + + public Vector3d location; + public Hand hand; + public boolean self; + + public ShootGadgetPacket(Vector3d location, Hand hand, boolean self) { + this.location = location; + this.hand = hand; + this.self = self; + } + + public ShootGadgetPacket(PacketBuffer buffer) { + hand = buffer.readBoolean() ? Hand.MAIN_HAND : Hand.OFF_HAND; + self = buffer.readBoolean(); + location = new Vector3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); + readAdditional(buffer); + } + + public final void write(PacketBuffer buffer) { + buffer.writeBoolean(hand == Hand.MAIN_HAND); + buffer.writeBoolean(self); + buffer.writeDouble(location.x); + buffer.writeDouble(location.y); + buffer.writeDouble(location.z); + writeAdditional(buffer); + } + + protected abstract void readAdditional(PacketBuffer buffer); + + protected abstract void writeAdditional(PacketBuffer buffer); + + @OnlyIn(Dist.CLIENT) + protected abstract void handleAdditional(); + + @OnlyIn(Dist.CLIENT) + protected abstract ShootableGadgetRenderHandler getHandler(); + + @Override + @OnlyIn(Dist.CLIENT) + public final void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + Entity renderViewEntity = Minecraft.getInstance() + .getCameraEntity(); + if (renderViewEntity == null) + return; + if (renderViewEntity.position() + .distanceTo(location) > 100) + return; + + ShootableGadgetRenderHandler handler = getHandler(); + handleAdditional(); + if (self) + handler.shoot(hand, location); + else + handler.playSound(hand, location); + }); + context.get() + .setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetItemMethods.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetItemMethods.java new file mode 100644 index 000000000..a403f6ef0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetItemMethods.java @@ -0,0 +1,68 @@ +package com.simibubi.create.content.curiosities.zapper; + +import java.util.function.Function; +import java.util.function.Predicate; + +import com.simibubi.create.foundation.networking.AllPackets; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.HandSide; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.fml.network.PacketDistributor; + +public class ShootableGadgetItemMethods { + + public static void applyCooldown(PlayerEntity player, ItemStack item, Hand hand, Predicate predicate, + int cooldown) { + boolean gunInOtherHand = + predicate.test(player.getItemInHand(hand == Hand.MAIN_HAND ? Hand.OFF_HAND : Hand.MAIN_HAND)); + player.getCooldowns() + .addCooldown(item.getItem(), gunInOtherHand ? cooldown * 2 / 3 : cooldown); + } + + public static void sendPackets(PlayerEntity player, Function factory) { + if (!(player instanceof ServerPlayerEntity)) + return; + AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> player), factory.apply(false)); + AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), factory.apply(true)); + } + + public static boolean shouldSwap(PlayerEntity player, ItemStack item, Hand hand, Predicate predicate) { + boolean isSwap = item.getTag() + .contains("_Swap"); + boolean mainHand = hand == Hand.MAIN_HAND; + boolean gunInOtherHand = predicate.test(player.getItemInHand(mainHand ? Hand.OFF_HAND : Hand.MAIN_HAND)); + + // Pass To Offhand + if (mainHand && isSwap && gunInOtherHand) + return true; + if (mainHand && !isSwap && gunInOtherHand) + item.getTag() + .putBoolean("_Swap", true); + if (!mainHand && isSwap) + item.getTag() + .remove("_Swap"); + if (!mainHand && gunInOtherHand) + player.getItemInHand(Hand.MAIN_HAND) + .getTag() + .remove("_Swap"); + player.startUsingItem(hand); + return false; + } + + public static Vector3d getGunBarrelVec(PlayerEntity player, boolean mainHand, Vector3d rightHandForward) { + Vector3d start = player.position() + .add(0, player.getEyeHeight(), 0); + float yaw = (float) ((player.yRot) / -180 * Math.PI); + float pitch = (float) ((player.xRot) / -180 * Math.PI); + int flip = mainHand == (player.getMainArm() == HandSide.RIGHT) ? -1 : 1; + Vector3d barrelPosNoTransform = new Vector3d(flip * rightHandForward.x, rightHandForward.y, rightHandForward.z); + Vector3d barrelPos = start.add(barrelPosNoTransform.xRot(pitch) + .yRot(yaw)); + return barrelPos; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetRenderHandler.java new file mode 100644 index 000000000..e381b7be9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetRenderHandler.java @@ -0,0 +1,150 @@ +package com.simibubi.create.content.curiosities.zapper; + +import com.mojang.blaze3d.matrix.MatrixStack; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.AbstractClientPlayerEntity; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.renderer.FirstPersonRenderer; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.entity.PlayerRenderer; +import net.minecraft.client.renderer.model.ItemCameraTransforms; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.HandSide; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.vector.Vector3f; +import net.minecraftforge.client.event.RenderHandEvent; +import net.minecraftforge.eventbus.api.IEventBus; + +public abstract class ShootableGadgetRenderHandler { + + protected float leftHandAnimation; + protected float rightHandAnimation; + protected float lastLeftHandAnimation; + protected float lastRightHandAnimation; + protected boolean dontReequipLeft; + protected boolean dontReequipRight; + + public void tick() { + lastLeftHandAnimation = leftHandAnimation; + lastRightHandAnimation = rightHandAnimation; + leftHandAnimation *= animationDecay(); + rightHandAnimation *= animationDecay(); + } + + public float getAnimation(boolean rightHand, float partialTicks) { + return MathHelper.lerp(partialTicks, rightHand ? lastRightHandAnimation : lastLeftHandAnimation, + rightHand ? rightHandAnimation : leftHandAnimation); + } + + protected float animationDecay() { + return 0.8f; + } + + public void shoot(Hand hand, Vector3d location) { + ClientPlayerEntity player = Minecraft.getInstance().player; + boolean rightHand = hand == Hand.MAIN_HAND ^ player.getMainArm() == HandSide.LEFT; + if (rightHand) { + rightHandAnimation = .2f; + dontReequipRight = false; + } else { + leftHandAnimation = .2f; + dontReequipLeft = false; + } + playSound(hand, location); + } + + protected abstract void playSound(Hand hand, Vector3d position); + + protected abstract boolean appliesTo(ItemStack stack); + + protected abstract void transformTool(MatrixStack ms, float flip, float equipProgress, float recoil, float pt); + + protected abstract void transformHand(MatrixStack ms, float flip, float equipProgress, float recoil, float pt); + + public void registerListeners(IEventBus bus) { + bus.addListener(this::onRenderPlayerHand); + } + + protected void onRenderPlayerHand(RenderHandEvent event) { + ItemStack heldItem = event.getItemStack(); + if (!appliesTo(heldItem)) + return; + + Minecraft mc = Minecraft.getInstance(); + AbstractClientPlayerEntity player = mc.player; + TextureManager textureManager = mc.getTextureManager(); + PlayerRenderer playerrenderer = (PlayerRenderer) mc.getEntityRenderDispatcher() + .getRenderer(player); + FirstPersonRenderer firstPersonRenderer = mc.getItemInHandRenderer(); + + MatrixStack ms = event.getMatrixStack(); + IRenderTypeBuffer buffer = event.getBuffers(); + int light = event.getLight(); + float pt = event.getPartialTicks(); + + boolean rightHand = event.getHand() == Hand.MAIN_HAND ^ mc.player.getMainArm() == HandSide.LEFT; + float recoil = rightHand ? MathHelper.lerp(pt, lastRightHandAnimation, rightHandAnimation) + : MathHelper.lerp(pt, lastLeftHandAnimation, leftHandAnimation); + float equipProgress = event.getEquipProgress(); + + if (rightHand && (rightHandAnimation > .01f || dontReequipRight)) + equipProgress = 0; + if (!rightHand && (leftHandAnimation > .01f || dontReequipLeft)) + equipProgress = 0; + + // Render arm + ms.pushPose(); + textureManager.bind(player.getSkinTextureLocation()); + + float flip = rightHand ? 1.0F : -1.0F; + float f1 = MathHelper.sqrt(event.getSwingProgress()); + float f2 = -0.3F * MathHelper.sin(f1 * (float) Math.PI); + float f3 = 0.4F * MathHelper.sin(f1 * ((float) Math.PI * 2F)); + float f4 = -0.4F * MathHelper.sin(event.getSwingProgress() * (float) Math.PI); + float f5 = MathHelper.sin(event.getSwingProgress() * event.getSwingProgress() * (float) Math.PI); + float f6 = MathHelper.sin(f1 * (float) Math.PI); + + ms.translate(flip * (f2 + 0.64F - .1f), f3 + -0.4F + equipProgress * -0.6F, f4 + -0.72F + .3f + recoil); + ms.mulPose(Vector3f.YP.rotationDegrees(flip * 75.0F)); + ms.mulPose(Vector3f.YP.rotationDegrees(flip * f6 * 70.0F)); + ms.mulPose(Vector3f.ZP.rotationDegrees(flip * f5 * -20.0F)); + ms.translate(flip * -1.0F, 3.6F, 3.5F); + ms.mulPose(Vector3f.ZP.rotationDegrees(flip * 120.0F)); + ms.mulPose(Vector3f.XP.rotationDegrees(200.0F)); + ms.mulPose(Vector3f.YP.rotationDegrees(flip * -135.0F)); + ms.translate(flip * 5.6F, 0.0F, 0.0F); + ms.mulPose(Vector3f.YP.rotationDegrees(flip * 40.0F)); + transformHand(ms, flip, equipProgress, recoil, pt); + if (rightHand) + playerrenderer.renderRightHand(ms, buffer, light, player); + else + playerrenderer.renderLeftHand(ms, buffer, light, player); + ms.popPose(); + + // Render gadget + ms.pushPose(); + ms.translate(flip * (f2 + 0.64F - .1f), f3 + -0.4F + equipProgress * -0.6F, f4 + -0.72F - 0.1f + recoil); + ms.mulPose(Vector3f.YP.rotationDegrees(flip * f6 * 70.0F)); + ms.mulPose(Vector3f.ZP.rotationDegrees(flip * f5 * -20.0F)); + transformTool(ms, flip, equipProgress, recoil, pt); + firstPersonRenderer.renderItem(mc.player, heldItem, + rightHand ? ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND + : ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, + !rightHand, ms, buffer, light); + ms.popPose(); + + event.setCanceled(true); + } + + public void dontAnimateItem(Hand hand) { + ClientPlayerEntity player = Minecraft.getInstance().player; + boolean rightHand = hand == Hand.MAIN_HAND ^ player.getMainArm() == HandSide.LEFT; + dontReequipRight |= rightHand; + dontReequipLeft |= !rightHand; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java index a99ebf2cd..0bf447cbe 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java @@ -1,64 +1,49 @@ package com.simibubi.create.content.curiosities.zapper; -import java.util.function.Supplier; - +import com.simibubi.create.CreateClient; import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler.LaserBeam; -import com.simibubi.create.foundation.networking.SimplePacketBase; -import net.minecraft.client.Minecraft; import net.minecraft.network.PacketBuffer; import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.network.NetworkEvent.Context; +import net.minecraftforge.api.distmarker.OnlyIn; -public class ZapperBeamPacket extends SimplePacketBase { +public class ZapperBeamPacket extends ShootGadgetPacket { - public Vector3d start; public Vector3d target; - public Hand hand; - public boolean self; public ZapperBeamPacket(Vector3d start, Vector3d target, Hand hand, boolean self) { - this.start = start; + super(start, hand, self); this.target = target; - this.hand = hand; - this.self = self; - } - - public ZapperBeamPacket(PacketBuffer buffer) { - start = new Vector3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); - target = new Vector3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); - hand = buffer.readBoolean()? Hand.MAIN_HAND : Hand.OFF_HAND; - self = buffer.readBoolean(); } - public void write(PacketBuffer buffer) { - buffer.writeDouble(start.x); - buffer.writeDouble(start.y); - buffer.writeDouble(start.z); + public ZapperBeamPacket(PacketBuffer buffer) { + super(buffer); + } + + @Override + protected void readAdditional(PacketBuffer buffer) { + target = new Vector3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); + } + + @Override + protected void writeAdditional(PacketBuffer buffer) { buffer.writeDouble(target.x); buffer.writeDouble(target.y); buffer.writeDouble(target.z); - - buffer.writeBoolean(hand == Hand.MAIN_HAND); - buffer.writeBoolean(self); } - public void handle(Supplier context) { - context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - if (Minecraft.getInstance().player.getPositionVec().distanceTo(start) > 100) - return; - ZapperRenderHandler.addBeam(new LaserBeam(start, target).followPlayer(self, hand == Hand.MAIN_HAND)); - - if (self) - ZapperRenderHandler.shoot(hand); - else - ZapperRenderHandler.playSound(hand, new BlockPos(start)); - })); - context.get().setPacketHandled(true); + @Override + @OnlyIn(Dist.CLIENT) + protected ShootableGadgetRenderHandler getHandler() { + return CreateClient.ZAPPER_RENDER_HANDLER; + } + + @Override + @OnlyIn(Dist.CLIENT) + protected void handleAdditional() { + CreateClient.ZAPPER_RENDER_HANDLER.addBeam(new LaserBeam(location, target)); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperInteractionHandler.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperInteractionHandler.java index c56d86a0e..7a7ba0e59 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperInteractionHandler.java @@ -30,10 +30,10 @@ public class ZapperInteractionHandler { @SubscribeEvent public static void leftClickingBlocksWithTheZapperSelectsTheBlock(PlayerInteractEvent.LeftClickBlock event) { - if (event.getWorld().isRemote) + if (event.getWorld().isClientSide) return; ItemStack heldItem = event.getPlayer() - .getHeldItemMainhand(); + .getMainHandItem(); if (heldItem.getItem() instanceof ZapperItem && trySelect(heldItem, event.getPlayer())) { event.setCancellationResult(ActionResultType.FAIL); event.setCanceled(true); @@ -41,46 +41,46 @@ public class ZapperInteractionHandler { } public static boolean trySelect(ItemStack stack, PlayerEntity player) { - if (player.isSneaking()) + if (player.isShiftKeyDown()) return false; - Vector3d start = player.getPositionVec() + Vector3d start = player.position() .add(0, player.getEyeHeight(), 0); - Vector3d range = player.getLookVec() + Vector3d range = player.getLookAngle() .scale(getRange(stack)); - BlockRayTraceResult raytrace = player.world - .rayTraceBlocks(new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, player)); - BlockPos pos = raytrace.getPos(); + BlockRayTraceResult raytrace = player.level + .clip(new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, player)); + BlockPos pos = raytrace.getBlockPos(); if (pos == null) return false; - player.world.sendBlockBreakProgress(player.getEntityId(), pos, -1); - BlockState newState = player.world.getBlockState(pos); + player.level.destroyBlockProgress(player.getId(), pos, -1); + BlockState newState = player.level.getBlockState(pos); if (BlockHelper.getRequiredItem(newState) .isEmpty()) return false; if (newState.hasTileEntity() && !AllBlockTags.SAFE_NBT.matches(newState)) return false; - if (newState.contains(BlockStateProperties.DOUBLE_BLOCK_HALF)) + if (newState.hasProperty(BlockStateProperties.DOUBLE_BLOCK_HALF)) return false; - if (newState.contains(BlockStateProperties.ATTACHED)) + if (newState.hasProperty(BlockStateProperties.ATTACHED)) return false; - if (newState.contains(BlockStateProperties.HANGING)) + if (newState.hasProperty(BlockStateProperties.HANGING)) return false; - if (newState.contains(BlockStateProperties.BED_PART)) + if (newState.hasProperty(BlockStateProperties.BED_PART)) return false; - if (newState.contains(BlockStateProperties.STAIRS_SHAPE)) - newState = newState.with(BlockStateProperties.STAIRS_SHAPE, StairsShape.STRAIGHT); - if (newState.contains(BlockStateProperties.PERSISTENT)) - newState = newState.with(BlockStateProperties.PERSISTENT, true); - if (newState.contains(BlockStateProperties.WATERLOGGED)) - newState = newState.with(BlockStateProperties.WATERLOGGED, false); + if (newState.hasProperty(BlockStateProperties.STAIRS_SHAPE)) + newState = newState.setValue(BlockStateProperties.STAIRS_SHAPE, StairsShape.STRAIGHT); + if (newState.hasProperty(BlockStateProperties.PERSISTENT)) + newState = newState.setValue(BlockStateProperties.PERSISTENT, true); + if (newState.hasProperty(BlockStateProperties.WATERLOGGED)) + newState = newState.setValue(BlockStateProperties.WATERLOGGED, false); CompoundNBT data = null; - TileEntity tile = player.world.getTileEntity(pos); + TileEntity tile = player.level.getBlockEntity(pos); if (tile != null) { - data = tile.write(new CompoundNBT()); + data = tile.save(new CompoundNBT()); data.remove("x"); data.remove("y"); data.remove("z"); @@ -98,7 +98,7 @@ public class ZapperInteractionHandler { else tag.put("BlockData", data); - AllSoundEvents.CONFIRM.playOnServer(player.world, player.getBlockPos()); + AllSoundEvents.CONFIRM.playOnServer(player.level, player.blockPosition()); return true; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java index f6e573b8e..a42370581 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java @@ -6,10 +6,11 @@ import javax.annotation.Nonnull; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.item.ItemDescription; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTProcessors; import net.minecraft.block.BlockState; @@ -17,7 +18,6 @@ import net.minecraft.block.Blocks; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; @@ -28,7 +28,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; -import net.minecraft.util.HandSide; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.RayTraceContext; @@ -43,27 +42,26 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.network.PacketDistributor; public abstract class ZapperItem extends Item { public ZapperItem(Properties properties) { - super(properties.maxStackSize(1)); + super(properties.stacksTo(1)); } @Override @OnlyIn(Dist.CLIENT) - public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { if (stack.hasTag() && stack.getTag() .contains("BlockUsed")) { String usedblock = NBTUtil.readBlockState(stack.getTag() .getCompound("BlockUsed")) .getBlock() - .getTranslationKey(); + .getDescriptionId(); ItemDescription.add(tooltip, Lang.translate("terrainzapper.usingBlock", - new TranslationTextComponent(usedblock).formatted(TextFormatting.GRAY)) - .formatted(TextFormatting.DARK_GRAY)); + new TranslationTextComponent(usedblock).withStyle(TextFormatting.GRAY)) + .withStyle(TextFormatting.DARK_GRAY)); } } @@ -87,66 +85,55 @@ public abstract class ZapperItem extends Item { @Nonnull @Override - public ActionResultType onItemUse(ItemUseContext context) { + public ActionResultType useOn(ItemUseContext context) { // Shift -> open GUI if (context.getPlayer() != null && context.getPlayer() - .isSneaking()) { - if (context.getWorld().isRemote) { + .isShiftKeyDown()) { + if (context.getLevel().isClientSide) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - openHandgunGUI(context.getItem(), context.getHand() == Hand.OFF_HAND); + openHandgunGUI(context.getItemInHand(), context.getHand()); }); - applyCooldown(context.getPlayer(), context.getItem(), false); + context.getPlayer() + .getCooldowns() + .addCooldown(context.getItemInHand() + .getItem(), 10); } return ActionResultType.SUCCESS; } - return super.onItemUse(context); + return super.useOn(context); } @Override - public ActionResult onItemRightClick(World world, PlayerEntity player, Hand hand) { - ItemStack item = player.getHeldItem(hand); + public ActionResult use(World world, PlayerEntity player, Hand hand) { + ItemStack item = player.getItemInHand(hand); CompoundNBT nbt = item.getOrCreateTag(); + boolean mainHand = hand == Hand.MAIN_HAND; // Shift -> Open GUI - if (player.isSneaking()) { - if (world.isRemote) { + if (player.isShiftKeyDown()) { + if (world.isClientSide) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - openHandgunGUI(item, hand == Hand.OFF_HAND); + openHandgunGUI(item, hand); }); - applyCooldown(player, item, false); + player.getCooldowns() + .addCooldown(item.getItem(), 10); } return new ActionResult<>(ActionResultType.SUCCESS, item); } - boolean mainHand = hand == Hand.MAIN_HAND; - boolean isSwap = item.getTag() - .contains("_Swap"); - boolean gunInOtherHand = isZapper(player.getHeldItem(mainHand ? Hand.OFF_HAND : Hand.MAIN_HAND)); - - // Pass To Offhand - if (mainHand && isSwap && gunInOtherHand) + if (ShootableGadgetItemMethods.shouldSwap(player, item, hand, this::isZapper)) return new ActionResult<>(ActionResultType.FAIL, item); - if (mainHand && !isSwap && gunInOtherHand) - item.getTag() - .putBoolean("_Swap", true); - if (!mainHand && isSwap) - item.getTag() - .remove("_Swap"); - if (!mainHand && gunInOtherHand) - player.getHeldItem(Hand.MAIN_HAND) - .getTag() - .remove("_Swap"); - player.setActiveHand(hand); // Check if can be used ITextComponent msg = validateUsage(item); if (msg != null) { - AllSoundEvents.DENY.play(world, player, player.getBlockPos()); - player.sendStatusMessage(msg.copy().formatted(TextFormatting.RED), true); + AllSoundEvents.DENY.play(world, player, player.blockPosition()); + player.displayClientMessage(msg.plainCopy() + .withStyle(TextFormatting.RED), true); return new ActionResult<>(ActionResultType.FAIL, item); } - BlockState stateToUse = Blocks.AIR.getDefaultState(); + BlockState stateToUse = Blocks.AIR.defaultBlockState(); if (nbt.contains("BlockUsed")) stateToUse = NBTUtil.readBlockState(nbt.getCompound("BlockUsed")); stateToUse = BlockHelper.setZeroAge(stateToUse); @@ -156,42 +143,35 @@ public abstract class ZapperItem extends Item { } // Raytrace - Find the target - Vector3d start = player.getPositionVec() + Vector3d start = player.position() .add(0, player.getEyeHeight(), 0); - Vector3d range = player.getLookVec() + Vector3d range = player.getLookAngle() .scale(getZappingRange(item)); BlockRayTraceResult raytrace = world - .rayTraceBlocks(new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, player)); - BlockPos pos = raytrace.getPos(); + .clip(new RayTraceContext(start, start.add(range), BlockMode.OUTLINE, FluidMode.NONE, player)); + BlockPos pos = raytrace.getBlockPos(); BlockState stateReplaced = world.getBlockState(pos); // No target if (pos == null || stateReplaced.getBlock() == Blocks.AIR) { - applyCooldown(player, item, gunInOtherHand); + ShootableGadgetItemMethods.applyCooldown(player, item, hand, this::isZapper, getCooldownDelay(item)); return new ActionResult<>(ActionResultType.SUCCESS, item); } // Find exact position of gun barrel for VFX - float yaw = (float) ((player.rotationYaw) / -180 * Math.PI); - float pitch = (float) ((player.rotationPitch) / -180 * Math.PI); - Vector3d barrelPosNoTransform = - new Vector3d(mainHand == (player.getPrimaryHand() == HandSide.RIGHT) ? -.35f : .35f, -0.1f, 1); - Vector3d barrelPos = start.add(barrelPosNoTransform.rotatePitch(pitch) - .rotateYaw(yaw)); + Vector3d barrelPos = ShootableGadgetItemMethods.getGunBarrelVec(player, mainHand, new Vector3d(.35f, -0.1f, 1)); // Client side - if (world.isRemote) { - ZapperRenderHandler.dontAnimateItem(hand); + if (world.isClientSide) { + CreateClient.ZAPPER_RENDER_HANDLER.dontAnimateItem(hand); return new ActionResult<>(ActionResultType.SUCCESS, item); } // Server side if (activate(world, player, item, stateToUse, raytrace, data)) { - applyCooldown(player, item, gunInOtherHand); - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> player), - new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, false)); - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), - new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true)); + ShootableGadgetItemMethods.applyCooldown(player, item, hand, this::isZapper, getCooldownDelay(item)); + ShootableGadgetItemMethods.sendPackets(player, + b -> new ZapperBeamPacket(barrelPos, raytrace.getLocation(), hand, b)); } return new ActionResult<>(ActionResultType.SUCCESS, item); @@ -208,7 +188,7 @@ public abstract class ZapperItem extends Item { BlockRayTraceResult raytrace, CompoundNBT data); @OnlyIn(Dist.CLIENT) - protected abstract void openHandgunGUI(ItemStack item, boolean b); + protected abstract void openHandgunGUI(ItemStack item, Hand hand); protected abstract int getCooldownDelay(ItemStack item); @@ -218,30 +198,29 @@ public abstract class ZapperItem extends Item { return false; } - protected void applyCooldown(PlayerEntity playerIn, ItemStack item, boolean dual) { - int delay = getCooldownDelay(item); - playerIn.getCooldownTracker() - .setCooldown(item.getItem(), dual ? delay * 2 / 3 : delay); - } - @Override public boolean onEntitySwing(ItemStack stack, LivingEntity entity) { return true; } @Override - public boolean canPlayerBreakBlockWhileHolding(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) { + public boolean canAttackBlock(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) { return false; } @Override - public UseAction getUseAction(ItemStack stack) { + public UseAction getUseAnimation(ItemStack stack) { return UseAction.NONE; } + public static void configureSettings(ItemStack stack, PlacementPatterns pattern) { + CompoundNBT nbt = stack.getOrCreateTag(); + NBTHelper.writeEnum(nbt, "Pattern", pattern); + } + public static void setTileData(World world, BlockPos pos, BlockState state, CompoundNBT data, PlayerEntity player) { if (data != null && AllBlockTags.SAFE_NBT.matches(state)) { - TileEntity tile = world.getTileEntity(pos); + TileEntity tile = world.getBlockEntity(pos); if (tile != null) { data = NBTProcessors.process(tile, data, !player.isCreative()); if (data == null) @@ -249,7 +228,7 @@ public abstract class ZapperItem extends Item { data.putInt("x", pos.getX()); data.putInt("y", pos.getY()); data.putInt("z", pos.getZ()); - tile.fromTag(state, data); + tile.load(state, data); } } } 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..4b6aa2dcc 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,10 @@ 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.CreateClient; +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; @@ -30,32 +31,28 @@ public abstract class ZapperItemRenderer exte BlockState state = NBTUtil.readBlockState(stack.getTag() .getCompound("BlockUsed")); - ms.push(); + ms.pushPose(); ms.translate(-0.3F, -0.45F, -0.0F); ms.scale(0.25F, 0.25F, 0.25F); IBakedModel modelForState = Minecraft.getInstance() - .getBlockRendererDispatcher() - .getModelForState(state); + .getBlockRenderer() + .getBlockModel(state); if (state.getBlock() instanceof FourWayBlock) modelForState = Minecraft.getInstance() .getItemRenderer() - .getItemModelWithOverrides(new ItemStack(state.getBlock()), Minecraft.getInstance().world, null); + .getModel(new ItemStack(state.getBlock()), Minecraft.getInstance().level, null); Minecraft.getInstance() .getItemRenderer() - .renderItem(new ItemStack(state.getBlock()), TransformType.NONE, false, ms, buffer, light, overlay, + .render(new ItemStack(state.getBlock()), TransformType.NONE, false, ms, buffer, light, overlay, modelForState); - ms.pop(); + ms.popPose(); } protected float getAnimationProgress(float pt, boolean leftHanded, boolean mainHand) { - float last = mainHand ^ leftHanded ? ZapperRenderHandler.lastRightHandAnimation - : ZapperRenderHandler.lastLeftHandAnimation; - float current = - mainHand ^ leftHanded ? ZapperRenderHandler.rightHandAnimation : ZapperRenderHandler.leftHandAnimation; - float animation = MathHelper.clamp(MathHelper.lerp(pt, last, current) * 5, 0, 1); - return animation; + float animation = CreateClient.ZAPPER_RENDER_HANDLER.getAnimation(mainHand ^ leftHanded, pt); + return MathHelper.clamp(animation * 5, 0, 1); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperLog.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperLog.java index 99955c390..6aa5be7bc 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperLog.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperLog.java @@ -35,7 +35,7 @@ public class ZapperLog { activeWorld = world; List blocks = positions.stream().map(pos -> { - TileEntity tileEntity = world.getTileEntity(pos); + TileEntity tileEntity = world.getBlockEntity(pos); return new BlockInfo(pos, world.getBlockState(pos), tileEntity == null ? null : tileEntity.serializeNBT()); }).collect(Collectors.toList()); 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..d04acb1e4 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java @@ -8,79 +8,27 @@ import java.util.function.Supplier; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.player.AbstractClientPlayerEntity; -import net.minecraft.client.entity.player.ClientPlayerEntity; -import net.minecraft.client.renderer.FirstPersonRenderer; -import net.minecraft.client.renderer.entity.PlayerRenderer; -import net.minecraft.client.renderer.model.ItemCameraTransforms; import net.minecraft.client.world.ClientWorld; import net.minecraft.item.ItemStack; import net.minecraft.particles.ParticleTypes; import net.minecraft.util.Hand; -import net.minecraft.util.HandSide; -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.Vector3f; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.RenderHandEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -@EventBusSubscriber(value = Dist.CLIENT) -public class ZapperRenderHandler { +public class ZapperRenderHandler extends ShootableGadgetRenderHandler { - public static List cachedBeams; - public static float leftHandAnimation; - public static float rightHandAnimation; - public static float lastLeftHandAnimation; - public static float lastRightHandAnimation; + public List cachedBeams; - private static boolean dontReequipLeft; - private static boolean dontReequipRight; - - public static class LaserBeam { - float itensity; - Vector3d start; - Vector3d end; - boolean follow; - boolean mainHand; - - public LaserBeam(Vector3d start, Vector3d end) { - this.start = start; - this.end = end; - itensity = 1; - } - - public LaserBeam followPlayer(boolean follow, boolean mainHand) { - this.follow = follow; - this.mainHand = mainHand; - return this; - } + @Override + protected boolean appliesTo(ItemStack stack) { + return stack.getItem() instanceof ZapperItem; } - public static Vector3d getExactBarrelPos(boolean mainHand) { - float partialTicks = AnimationTickHolder.getPartialTicks(); - ClientPlayerEntity player = Minecraft.getInstance().player; - float yaw = (float) ((player.getYaw(partialTicks)) / -180 * Math.PI); - float pitch = (float) ((player.getPitch(partialTicks)) / -180 * Math.PI); - boolean rightHand = mainHand == (player.getPrimaryHand() == HandSide.RIGHT); - float zOffset = ((float) Minecraft.getInstance().gameSettings.fov - 70) / -100; - Vector3d barrelPosNoTransform = new Vector3d(rightHand ? -.35f : .35f, -0.115f, .75f + zOffset); - Vector3d barrelPos = player.getEyePosition(partialTicks) - .add(barrelPosNoTransform.rotatePitch(pitch) - .rotateYaw(yaw)); - return barrelPos; - } - - public static void tick() { - lastLeftHandAnimation = leftHandAnimation; - lastRightHandAnimation = rightHandAnimation; - leftHandAnimation *= 0.8f; - rightHandAnimation *= 0.8f; + @Override + public void tick() { + super.tick(); if (cachedBeams == null) cachedBeams = new LinkedList<>(); @@ -90,7 +38,7 @@ public class ZapperRenderHandler { return; cachedBeams.forEach(beam -> { - CreateClient.outliner.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity) + CreateClient.OUTLINER.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity) .disableNormals() .colored(0xffffff) .lineWidth(beam.itensity * 1 / 8f); @@ -99,31 +47,28 @@ public class ZapperRenderHandler { cachedBeams.forEach(b -> b.itensity *= .6f); } - public static void shoot(Hand hand) { - ClientPlayerEntity player = Minecraft.getInstance().player; - boolean rightHand = hand == Hand.MAIN_HAND ^ player.getPrimaryHand() == HandSide.LEFT; - if (rightHand) { - rightHandAnimation = .2f; - dontReequipRight = false; - } else { - leftHandAnimation = .2f; - dontReequipLeft = false; - } - playSound(hand, player.getBlockPos()); + @Override + protected void transformTool(MatrixStack ms, float flip, float equipProgress, float recoil, float pt) { + ms.translate(flip * -0.1f, 0.1f, -0.4f); + ms.mulPose(Vector3f.YP.rotationDegrees(flip * 5.0F)); } - public static void playSound(Hand hand, BlockPos position) { + @Override + protected void transformHand(MatrixStack ms, float flip, float equipProgress, float recoil, float pt) {} + + @Override + protected void playSound(Hand hand, Vector3d position) { float pitch = hand == Hand.MAIN_HAND ? 0.1f : 0.9f; Minecraft mc = Minecraft.getInstance(); - AllSoundEvents.WORLDSHAPER_PLACE.play(mc.world, mc.player, position, 0.1f, pitch); + AllSoundEvents.WORLDSHAPER_PLACE.play(mc.level, mc.player, position, 0.1f, pitch); } - public static void addBeam(LaserBeam beam) { + public void addBeam(LaserBeam beam) { Random r = new Random(); double x = beam.end.x; double y = beam.end.y; double z = beam.end.z; - ClientWorld world = Minecraft.getInstance().world; + ClientWorld world = Minecraft.getInstance().level; Supplier randomSpeed = () -> (r.nextDouble() - .5d) * .2f; Supplier randomOffset = () -> (r.nextDouble() - .5d) * .2f; for (int i = 0; i < 10; i++) { @@ -135,87 +80,16 @@ public class ZapperRenderHandler { cachedBeams.add(beam); } - @SubscribeEvent - public static void onRenderPlayerHand(RenderHandEvent event) { - ItemStack heldItem = event.getItemStack(); - if (!(heldItem.getItem() instanceof ZapperItem)) - return; + public static class LaserBeam { + float itensity; + Vector3d start; + Vector3d end; - Minecraft mc = Minecraft.getInstance(); - boolean rightHand = event.getHand() == Hand.MAIN_HAND ^ mc.player.getPrimaryHand() == HandSide.LEFT; - - MatrixStack ms = event.getMatrixStack(); - - ms.push(); - float recoil = rightHand ? MathHelper.lerp(event.getPartialTicks(), lastRightHandAnimation, rightHandAnimation) - : MathHelper.lerp(event.getPartialTicks(), lastLeftHandAnimation, leftHandAnimation); - - float equipProgress = event.getEquipProgress(); - - if (rightHand && (rightHandAnimation > .01f || dontReequipRight)) - equipProgress = 0; - if (!rightHand && (leftHandAnimation > .01f || dontReequipLeft)) - equipProgress = 0; - - // Render arm - float f = rightHand ? 1.0F : -1.0F; - float f1 = MathHelper.sqrt(event.getSwingProgress()); - float f2 = -0.3F * MathHelper.sin(f1 * (float) Math.PI); - float f3 = 0.4F * MathHelper.sin(f1 * ((float) Math.PI * 2F)); - float f4 = -0.4F * MathHelper.sin(event.getSwingProgress() * (float) Math.PI); - float f5 = MathHelper.sin(event.getSwingProgress() * event.getSwingProgress() * (float) Math.PI); - float f6 = MathHelper.sin(f1 * (float) Math.PI); - - ms.translate(f * (f2 + 0.64000005F - .1f), f3 + -0.4F + equipProgress * -0.6F, - f4 + -0.71999997F + .3f + recoil); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(f * 75.0F)); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(f * f6 * 70.0F)); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(f * f5 * -20.0F)); - AbstractClientPlayerEntity abstractclientplayerentity = mc.player; - mc.getTextureManager() - .bindTexture(abstractclientplayerentity.getLocationSkin()); - ms.translate(f * -1.0F, 3.6F, 3.5F); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(f * 120.0F)); - ms.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(200.0F)); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(f * -135.0F)); - ms.translate(f * 5.6F, 0.0F, 0.0F); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(f * 40.0F)); - - PlayerRenderer playerrenderer = (PlayerRenderer) mc.getRenderManager() - .getRenderer(abstractclientplayerentity); - if (rightHand) { - playerrenderer.renderRightArm(event.getMatrixStack(), event.getBuffers(), event.getLight(), - abstractclientplayerentity); - } else { - playerrenderer.renderLeftArm(event.getMatrixStack(), event.getBuffers(), event.getLight(), - abstractclientplayerentity); + public LaserBeam(Vector3d start, Vector3d end) { + this.start = start; + this.end = end; + itensity = 1; } - ms.pop(); - - // Render gun - ms.push(); - ms.translate(f * (f2 + 0.64000005F - .1f), f3 + -0.4F + equipProgress * -0.6F, - f4 + -0.71999997F - 0.1f + recoil); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(f * f6 * 70.0F)); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(f * f5 * -20.0F)); - - ms.translate(f * -0.1f, 0.1f, -0.4f); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(f * 5.0F)); - - FirstPersonRenderer firstPersonRenderer = mc.getFirstPersonRenderer(); - firstPersonRenderer.renderItem(mc.player, heldItem, - rightHand ? ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND - : ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, - !rightHand, event.getMatrixStack(), event.getBuffers(), event.getLight()); - ms.pop(); - - event.setCanceled(true); - } - - public static void dontAnimateItem(Hand hand) { - boolean rightHand = hand == Hand.MAIN_HAND ^ Minecraft.getInstance().player.getPrimaryHand() == HandSide.LEFT; - dontReequipRight |= rightHand; - dontReequipLeft |= !rightHand; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperScreen.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperScreen.java index b62d2039d..feaf0561e 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperScreen.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperScreen.java @@ -9,12 +9,11 @@ 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.networking.NbtPacket; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; -import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.NBTUtil; @@ -23,79 +22,83 @@ import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; -public class ZapperScreen extends AbstractSimiScreen { - - protected ItemStack zapper; - protected boolean offhand; - protected float animationProgress; - protected AllGuiTextures background; - private IconButton confirmButton; +public abstract class ZapperScreen extends AbstractSimiScreen { protected final ITextComponent patternSection = Lang.translate("gui.terrainzapper.patternSection"); + protected AllGuiTextures background; + protected ItemStack zapper; + protected Hand hand; + + protected float animationProgress; + protected ITextComponent title; - protected Vector patternButtons; + protected Vector patternButtons = new Vector<>(6); + private IconButton confirmButton; protected int brightColor; protected int fontColor; - public ZapperScreen(AllGuiTextures background, ItemStack zapper, boolean offhand) { - super(); + protected PlacementPatterns currentPattern; + + public ZapperScreen(AllGuiTextures background, ItemStack zapper, Hand hand) { this.background = background; this.zapper = zapper; - this.offhand = offhand; + this.hand = hand; title = StringTextComponent.EMPTY; - brightColor = 0xfefefe; + brightColor = 0xFEFEFE; fontColor = AllGuiTextures.FONT_COLOR; + + CompoundNBT nbt = zapper.getOrCreateTag(); + currentPattern = NBTHelper.readEnum(nbt, "Pattern", PlacementPatterns.class); } @Override protected void init() { - animationProgress = 0; setWindowSize(background.width, background.height); + setWindowOffset(-10, 0); super.init(); widgets.clear(); + animationProgress = 0; + + int x = guiLeft; + int y = guiTop; + confirmButton = - new IconButton(guiLeft + background.width - 43, guiTop + background.height - 24, AllIcons.I_CONFIRM); + new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); widgets.add(confirmButton); - int i = guiLeft - 10; - int j = guiTop; - CompoundNBT nbt = zapper.getOrCreateTag(); - - patternButtons = new Vector<>(6); + patternButtons.clear(); for (int row = 0; row <= 1; row++) { for (int col = 0; col <= 2; col++) { int id = patternButtons.size(); PlacementPatterns pattern = PlacementPatterns.values()[id]; patternButtons - .add(new IconButton(i + background.width - 76 + col * 18, j + 21 + row * 18, pattern.icon)); + .add(new IconButton(x + background.width - 76 + col * 18, y + 21 + row * 18, pattern.icon)); patternButtons.get(id) .setToolTip(Lang.translate("gui.terrainzapper.pattern." + pattern.translationKey)); } } - if (nbt.contains("Pattern")) - patternButtons.get(PlacementPatterns.valueOf(nbt.getString("Pattern")) - .ordinal()).active = false; + patternButtons.get(currentPattern.ordinal()).active = false; widgets.addAll(patternButtons); } @Override - protected void renderWindow(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { - int i = guiLeft - 10; - int j = guiTop; + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; - background.draw(matrixStack, this, i, j); - drawOnBackground(matrixStack, i, j); + background.draw(ms, this, x, y); + drawOnBackground(ms, x, y); - renderBlock(matrixStack); - renderZapper(matrixStack); + renderBlock(ms, x, y); + renderZapper(ms, x, y); } - protected void drawOnBackground(MatrixStack matrixStack, int i, int j) { - textRenderer.draw(matrixStack, title, i + 11, j + 4, 0x54214F); + protected void drawOnBackground(MatrixStack ms, int x, int y) { + font.draw(ms, title, x + 11, y + 4, 0x54214F); } @Override @@ -106,22 +109,19 @@ public class ZapperScreen extends AbstractSimiScreen { @Override public void removed() { - CompoundNBT nbt = zapper.getTag(); - writeAdditionalOptions(nbt); - AllPackets.channel.sendToServer(new NbtPacket(zapper, offhand ? Hand.OFF_HAND : Hand.MAIN_HAND)); + ConfigureZapperPacket packet = getConfigurationPacket(); + packet.configureZapper(zapper); + AllPackets.channel.sendToServer(packet); } @Override public boolean mouseClicked(double x, double y, int button) { - CompoundNBT nbt = zapper.getTag(); - for (IconButton patternButton : patternButtons) { if (patternButton.isHovered()) { patternButtons.forEach(b -> b.active = true); patternButton.active = false; - patternButton.playDownSound(Minecraft.getInstance() - .getSoundHandler()); - nbt.putString("Pattern", PlacementPatterns.values()[patternButtons.indexOf(patternButton)].name()); + patternButton.playDownSound(minecraft.getSoundManager()); + currentPattern = PlacementPatterns.values()[patternButtons.indexOf(patternButton)]; } } @@ -133,31 +133,31 @@ public class ZapperScreen extends AbstractSimiScreen { return super.mouseClicked(x, y, button); } - protected void renderZapper(MatrixStack matrixStack) { + protected void renderZapper(MatrixStack ms, int x, int y) { GuiGameElement.of(zapper) .scale(4) - .at((this.width - this.sWidth) / 2 + 220, this.height / 2 - this.sHeight / 4 + 27, -150) - .render(matrixStack); + .at(x + background.width, y + background.height - 48, -200) + .render(ms); } - protected void renderBlock(MatrixStack matrixStack) { - matrixStack.push(); - matrixStack.translate(guiLeft + 22f, guiTop + 42f, 120); - matrixStack.multiply(new Vector3f(1f, 0, 0).getDegreesQuaternion(-25f)); - matrixStack.multiply(new Vector3f(0, 1f, 0).getDegreesQuaternion(-45f)); - matrixStack.scale(20, 20, 20); + protected void renderBlock(MatrixStack ms, int x, int y) { + ms.pushPose(); + ms.translate(x + 32, y + 42, 120); + ms.mulPose(new Vector3f(1f, 0, 0).rotationDegrees(-25f)); + ms.mulPose(new Vector3f(0, 1f, 0).rotationDegrees(-45f)); + ms.scale(20, 20, 20); - BlockState state = Blocks.AIR.getDefaultState(); + BlockState state = Blocks.AIR.defaultBlockState(); if (zapper.hasTag() && zapper.getTag() .contains("BlockUsed")) state = NBTUtil.readBlockState(zapper.getTag() .getCompound("BlockUsed")); GuiGameElement.of(state) - .render(matrixStack); - matrixStack.pop(); + .render(ms); + ms.popPose(); } - protected void writeAdditionalOptions(CompoundNBT nbt) {} + protected abstract ConfigureZapperPacket getConfigurationPacket(); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ConfigureWorldshaperPacket.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ConfigureWorldshaperPacket.java new file mode 100644 index 000000000..a5b849c85 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ConfigureWorldshaperPacket.java @@ -0,0 +1,55 @@ +package com.simibubi.create.content.curiosities.zapper.terrainzapper; + +import com.simibubi.create.content.curiosities.zapper.ConfigureZapperPacket; +import com.simibubi.create.content.curiosities.zapper.PlacementPatterns; + +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.Hand; + +public class ConfigureWorldshaperPacket extends ConfigureZapperPacket { + + protected TerrainBrushes brush; + protected int brushParamX; + protected int brushParamY; + protected int brushParamZ; + protected TerrainTools tool; + protected PlacementOptions placement; + + public ConfigureWorldshaperPacket(Hand hand, PlacementPatterns pattern, TerrainBrushes brush, int brushParamX, int brushParamY, int brushParamZ, TerrainTools tool, PlacementOptions placement) { + super(hand, pattern); + this.brush = brush; + this.brushParamX = brushParamX; + this.brushParamY = brushParamY; + this.brushParamZ = brushParamZ; + this.tool = tool; + this.placement = placement; + } + + public ConfigureWorldshaperPacket(PacketBuffer buffer) { + super(buffer); + brush = buffer.readEnum(TerrainBrushes.class); + brushParamX = buffer.readVarInt(); + brushParamY = buffer.readVarInt(); + brushParamZ = buffer.readVarInt(); + tool = buffer.readEnum(TerrainTools.class); + placement = buffer.readEnum(PlacementOptions.class); + } + + @Override + public void write(PacketBuffer buffer) { + super.write(buffer); + buffer.writeEnum(brush); + buffer.writeVarInt(brushParamX); + buffer.writeVarInt(brushParamY); + buffer.writeVarInt(brushParamZ); + buffer.writeEnum(tool); + buffer.writeEnum(placement); + } + + @Override + public void configureZapper(ItemStack stack) { + WorldshaperItem.configureSettings(stack, pattern, brush, brushParamX, brushParamY, brushParamZ, tool, placement); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CuboidBrush.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CuboidBrush.java index af409cc5a..f7c5d7f45 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CuboidBrush.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CuboidBrush.java @@ -26,8 +26,8 @@ public class CuboidBrush extends ShapedBrush { if (updateShape) { BlockPos zero = BlockPos.ZERO; positions = BlockPos - .getAllInBox(zero.add((param0 - 1) / -2, (param1 - 1) / -2, (param2 - 1) / -2), - zero.add((param0) / 2, (param1) / 2, (param2) / 2)) + .betweenClosedStream(zero.offset((param0 - 1) / -2, (param1 - 1) / -2, (param2 - 1) / -2), + zero.offset((param0) / 2, (param1) / 2, (param2) / 2)) .map(BlockPos::new) .collect(Collectors.toList()); } @@ -54,8 +54,8 @@ public class CuboidBrush extends ShapedBrush { int y = (param1 + (param1 == 0 ? 0 : offset)) / 2; int z = (param2 + (param2 == 0 ? 0 : offset)) / 2; - return BlockPos.ZERO.offset(face, face.getAxis() - .getCoordinate(x, y, z) * (option == PlacementOptions.Attached ? 1 : -1)); + return BlockPos.ZERO.relative(face, face.getAxis() + .choose(x, y, z) * (option == PlacementOptions.Attached ? 1 : -1)); } @Override diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CylinderBrush.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CylinderBrush.java index 0ec8b4f99..9ca87ced9 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CylinderBrush.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CylinderBrush.java @@ -30,7 +30,7 @@ public class CylinderBrush extends ShapedBrush { for (int i = 0; i <= MAX_RADIUS; i++) { int radius = i; List positions = - BlockPos.getAllInBox(BlockPos.ZERO.add(-i - 1, 0, -i - 1), BlockPos.ZERO.add(i + 1, 0, i + 1)) + BlockPos.betweenClosedStream(BlockPos.ZERO.offset(-i - 1, 0, -i - 1), BlockPos.ZERO.offset(i + 1, 0, i + 1)) .map(BlockPos::new) .filter(p -> VecHelper.getCenterOf(p) .distanceTo(VecHelper.getCenterOf(BlockPos.ZERO)) < radius + .42f) @@ -40,7 +40,7 @@ public class CylinderBrush extends ShapedBrush { for (int layer = 0; layer < h; layer++) { int yOffset = layer - h / 2; for (BlockPos p : positions) - stackedPositions.add(p.up(yOffset)); + stackedPositions.add(p.above(yOffset)); } cachedBrushes.put(Pair.of(i, h), stackedPositions); } @@ -58,7 +58,7 @@ public class CylinderBrush extends ShapedBrush { int r = (param0 + 1 + offset); int y = (param1 + (param1 == 0 ? 0 : yOffset)) / 2; - return BlockPos.ZERO.offset(face, (face.getAxis() + return BlockPos.ZERO.relative(face, (face.getAxis() .isVertical() ? y : r) * (option == PlacementOptions.Attached ? 1 : -1)); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/DynamicBrush.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/DynamicBrush.java index 5305a65e5..7e262093d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/DynamicBrush.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/DynamicBrush.java @@ -83,10 +83,10 @@ public class DynamicBrush extends Brush { for (int z = -1; z <= 1; z++) if (Math.abs(x) + Math.abs(y) + Math.abs(z) < 2 || searchDiagonals) if (targetFace.getAxis() - .getCoordinate(x, y, z) == 0 || !surface) + .choose(x, y, z) == 0 || !surface) offsets.add(new BlockPos(x, y, z)); - BlockPos startPos = replace ? targetPos : targetPos.offset(targetFace); + BlockPos startPos = replace ? targetPos : targetPos.relative(targetFace); frontier.add(startPos); while (!frontier.isEmpty()) { @@ -94,36 +94,36 @@ public class DynamicBrush extends Brush { if (visited.contains(currentPos)) continue; visited.add(currentPos); - if (!currentPos.withinDistance(startPos, searchRange)) + if (!currentPos.closerThan(startPos, searchRange)) continue; // Replace Mode if (replace) { BlockState stateToReplace = world.getBlockState(currentPos); - BlockState stateAboveStateToReplace = world.getBlockState(currentPos.offset(targetFace)); + BlockState stateAboveStateToReplace = world.getBlockState(currentPos.relative(targetFace)); // Criteria - if (stateToReplace.getBlockHardness(world, currentPos) == -1) + if (stateToReplace.getDestroySpeed(world, currentPos) == -1) continue; if (stateToReplace.getBlock() != state.getBlock() && !fuzzy) continue; if (stateToReplace.getMaterial() .isReplaceable()) continue; - if (BlockHelper.hasBlockSolidSide(stateAboveStateToReplace, world, currentPos.offset(targetFace), + if (BlockHelper.hasBlockSolidSide(stateAboveStateToReplace, world, currentPos.relative(targetFace), targetFace.getOpposite()) && surface) continue; affectedPositions.add(currentPos); // Search adjacent spaces for (BlockPos offset : offsets) - frontier.add(currentPos.add(offset)); + frontier.add(currentPos.offset(offset)); continue; } // Place Mode BlockState stateToPlaceAt = world.getBlockState(currentPos); - BlockState stateToPlaceOn = world.getBlockState(currentPos.offset(targetFace.getOpposite())); + BlockState stateToPlaceOn = world.getBlockState(currentPos.relative(targetFace.getOpposite())); // Criteria if (stateToPlaceOn.getMaterial() @@ -138,7 +138,7 @@ public class DynamicBrush extends Brush { // Search adjacent spaces for (BlockPos offset : offsets) - frontier.add(currentPos.add(offset)); + frontier.add(currentPos.offset(offset)); continue; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/FlattenTool.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/FlattenTool.java index eb11bd942..fc7287ca7 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/FlattenTool.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/FlattenTool.java @@ -56,7 +56,7 @@ public class FlattenTool { public static void apply(World world, List targetPositions, Direction facing) { List surfaces = new ArrayList<>(); Map, Integer> heightMap = new HashMap<>(); - int offset = facing.getAxisDirection().getOffset(); + int offset = facing.getAxisDirection().getStep(); int minEntry = Integer.MAX_VALUE; int minCoord1 = Integer.MAX_VALUE; @@ -80,7 +80,7 @@ public class FlattenTool { continue; } - p = p.offset(facing); + p = p.relative(facing); BlockState surface = world.getBlockState(p); if (!TerrainTools.isReplaceable(surface)) { @@ -90,7 +90,7 @@ public class FlattenTool { } surfaces.add(p); - int coordinate = facing.getAxis().getCoordinate(p.getX(), p.getY(), p.getZ()); + int coordinate = facing.getAxis().choose(p.getX(), p.getY(), p.getZ()); if (!heightMap.containsKey(coords) || heightMap.get(coords).equals(Integer.MAX_VALUE) || heightMap.get(coords).equals(Integer.MIN_VALUE) || heightMap.get(coords) * offset < coordinate * offset) { @@ -130,7 +130,7 @@ public class FlattenTool { for (BlockPos p : surfaces) { Pair coords = getCoords(p, facing); - int surfaceCoord = facing.getAxis().getCoordinate(p.getX(), p.getY(), p.getZ()) * offset; + int surfaceCoord = facing.getAxis().choose(p.getX(), p.getY(), p.getZ()) * offset; int targetCoord = heightMapArray[coords.getKey() - minCoord1][coords.getValue() - minCoord2] * offset; // Keep surface @@ -141,10 +141,10 @@ public class FlattenTool { BlockState blockState = world.getBlockState(p); int timeOut = 1000; while (surfaceCoord > targetCoord) { - BlockPos below = p.offset(facing.getOpposite()); - world.setBlockState(below, blockState); - world.setBlockState(p, blockState.getFluidState().getBlockState()); - p = p.offset(facing.getOpposite()); + BlockPos below = p.relative(facing.getOpposite()); + world.setBlockAndUpdate(below, blockState); + world.setBlockAndUpdate(p, blockState.getFluidState().createLegacyBlock()); + p = p.relative(facing.getOpposite()); surfaceCoord--; if (timeOut-- <= 0) break; @@ -152,11 +152,11 @@ public class FlattenTool { // Raise surface while (surfaceCoord < targetCoord) { - BlockPos above = p.offset(facing); + BlockPos above = p.relative(facing); if (!(blockState.getBlock() instanceof FlowingFluidBlock)) - world.setBlockState(above, blockState); - world.setBlockState(p, world.getBlockState(p.offset(facing.getOpposite()))); - p = p.offset(facing); + world.setBlockAndUpdate(above, blockState); + world.setBlockAndUpdate(p, world.getBlockState(p.relative(facing.getOpposite()))); + p = p.relative(facing); surfaceCoord++; if (timeOut-- <= 0) break; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ShapedBrush.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ShapedBrush.java index f0e67f3c2..c89e5c7a3 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ShapedBrush.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ShapedBrush.java @@ -20,7 +20,7 @@ public abstract class ShapedBrush extends Brush { if (includedPositions == null) return affectedPositions; for (BlockPos blockPos : includedPositions) - affectedPositions.add(targetPos.add(blockPos)); + affectedPositions.add(targetPos.offset(blockPos)); return affectedPositions; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/SphereBrush.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/SphereBrush.java index be7657398..544e70d1d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/SphereBrush.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/SphereBrush.java @@ -25,7 +25,7 @@ public class SphereBrush extends ShapedBrush { for (int i = 0; i <= MAX_RADIUS; i++) { int radius = i; List positions = - BlockPos.getAllInBox(BlockPos.ZERO.add(-i - 1, -i - 1, -i - 1), BlockPos.ZERO.add(i + 1, i + 1, i + 1)) + BlockPos.betweenClosedStream(BlockPos.ZERO.offset(-i - 1, -i - 1, -i - 1), BlockPos.ZERO.offset(i + 1, i + 1, i + 1)) .map(BlockPos::new).filter(p -> VecHelper.getCenterOf(p) .distanceTo(VecHelper.getCenterOf(BlockPos.ZERO)) < radius + .5f) .collect(Collectors.toList()); @@ -41,7 +41,7 @@ public class SphereBrush extends ShapedBrush { int offset = option == PlacementOptions.Attached ? 0 : -1; int r = (param0 + 1 + offset); - return BlockPos.ZERO.offset(face, r * (option == PlacementOptions.Attached ? 1 : -1)); + return BlockPos.ZERO.relative(face, r * (option == PlacementOptions.Attached ? 1 : -1)); } @Override diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java index 43ba4e9f5..1c51a6883 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java @@ -42,14 +42,14 @@ public enum TerrainTools { public void run(World world, List targetPositions, Direction facing, @Nullable BlockState paintedState, @Nullable CompoundNBT data, PlayerEntity player) { switch (this) { case Clear: - targetPositions.forEach(p -> world.setBlockState(p, Blocks.AIR.getDefaultState())); + targetPositions.forEach(p -> world.setBlockAndUpdate(p, Blocks.AIR.defaultBlockState())); break; case Fill: targetPositions.forEach(p -> { BlockState toReplace = world.getBlockState(p); if (!isReplaceable(toReplace)) return; - world.setBlockState(p, paintedState); + world.setBlockAndUpdate(p, paintedState); ZapperItem.setTileData(world, p, paintedState, data, player); }); break; @@ -64,18 +64,18 @@ public enum TerrainTools { if (toOverlay == paintedState) return; - p = p.up(); + p = p.above(); BlockState toReplace = world.getBlockState(p); if (!isReplaceable(toReplace)) return; - world.setBlockState(p, paintedState); + world.setBlockAndUpdate(p, paintedState); ZapperItem.setTileData(world, p, paintedState, data, player); }); break; case Place: targetPositions.forEach(p -> { - world.setBlockState(p, paintedState); + world.setBlockAndUpdate(p, paintedState); ZapperItem.setTileData(world, p, paintedState, data, player); }); break; @@ -84,7 +84,7 @@ public enum TerrainTools { BlockState toReplace = world.getBlockState(p); if (isReplaceable(toReplace)) return; - world.setBlockState(p, paintedState); + world.setBlockAndUpdate(p, paintedState); ZapperItem.setTileData(world, p, paintedState, data, player); }); break; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java index 86d74a5c6..ddaf57ad8 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java @@ -14,6 +14,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.text.ITextComponent; @@ -29,8 +30,8 @@ public class WorldshaperItem extends ZapperItem { @Override @OnlyIn(value = Dist.CLIENT) - protected void openHandgunGUI(ItemStack item, boolean b) { - ScreenOpener.open(new WorldshaperScreen(item, b)); + protected void openHandgunGUI(ItemStack item, Hand hand) { + ScreenOpener.open(new WorldshaperScreen(item, hand)); } @Override @@ -62,7 +63,7 @@ public class WorldshaperItem extends ZapperItem { protected boolean activate(World world, PlayerEntity player, ItemStack stack, BlockState stateToUse, BlockRayTraceResult raytrace, CompoundNBT data) { - BlockPos targetPos = raytrace.getPos(); + BlockPos targetPos = raytrace.getBlockPos(); List affectedPositions = new ArrayList<>(); CompoundNBT tag = stack.getOrCreateTag(); @@ -73,13 +74,22 @@ public class WorldshaperItem extends ZapperItem { TerrainTools tool = NBTHelper.readEnum(tag, "Tool", TerrainTools.class); brush.set(params.getX(), params.getY(), params.getZ()); - targetPos = targetPos.add(brush.getOffset(player.getLookVec(), raytrace.getFace(), option)); - brush.addToGlobalPositions(world, targetPos, raytrace.getFace(), affectedPositions, tool); + targetPos = targetPos.offset(brush.getOffset(player.getLookAngle(), raytrace.getDirection(), option)); + brush.addToGlobalPositions(world, targetPos, raytrace.getDirection(), affectedPositions, tool); PlacementPatterns.applyPattern(affectedPositions, stack); brush.redirectTool(tool) - .run(world, affectedPositions, raytrace.getFace(), stateToUse, data, player); + .run(world, affectedPositions, raytrace.getDirection(), stateToUse, data, player); return true; } + public static void configureSettings(ItemStack stack, PlacementPatterns pattern, TerrainBrushes brush, int brushParamX, int brushParamY, int brushParamZ, TerrainTools tool, PlacementOptions placement) { + ZapperItem.configureSettings(stack, pattern); + CompoundNBT nbt = stack.getOrCreateTag(); + NBTHelper.writeEnum(nbt, "Brush", brush); + nbt.put("BrushParams", NBTUtil.writeBlockPos(new BlockPos(brushParamX, brushParamY, brushParamZ))); + NBTHelper.writeEnum(nbt, "Tool", tool); + NBTHelper.writeEnum(nbt, "Placement", placement); + } + } 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..810272fd5 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,13 +5,14 @@ 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; import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.ItemCameraTransforms; import net.minecraft.item.ItemStack; import net.minecraft.util.HandSide; @@ -31,9 +32,9 @@ public class WorldshaperItemRenderer extends ZapperItemRenderer brush.addToGlobalPositions(player.world, pos, raytrace.getFace(), new ArrayList<>(), tool); + () -> brush.addToGlobalPositions(player.level, pos, raytrace.getDirection(), new ArrayList<>(), tool); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperScreen.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperScreen.java index 6937f719d..cc970b875 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperScreen.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperScreen.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Vector; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.curiosities.zapper.ConfigureZapperPacket; import com.simibubi.create.content.curiosities.zapper.ZapperScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; @@ -16,13 +17,14 @@ import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; -import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.common.util.Constants; public class WorldshaperScreen extends ZapperScreen { @@ -36,90 +38,109 @@ public class WorldshaperScreen extends ZapperScreen { protected ScrollInput brushInput; protected Label brushLabel; - protected Vector brushParams; - protected Vector

NonNullUnaryOperator> oxidizedBlockstate() { return b -> b.blockstate((ctx, prov) -> prov.getVariantBuilder(ctx.getEntry()) .forAllStates(state -> { - String name = AssetLookup.getOxidizedModel(ctx.getName(), state.get(OxidizingBlock.OXIDIZATION)); + String name = AssetLookup.getOxidizedModel(ctx.getName(), state.getValue(OxidizingBlock.OXIDIZATION)); return ConfiguredModel.builder() .modelFile(prov.models() .cubeAll(name, prov.modLoc(name))) @@ -108,14 +108,14 @@ public class BlockStateGen { RegistrateBlockstateProvider prov, Function modelFunc) { prov.getVariantBuilder(ctx.getEntry()) .forAllStatesExcept(state -> { - Direction dir = state.get(BlockStateProperties.FACING); + Direction dir = state.getValue(BlockStateProperties.FACING); return ConfiguredModel.builder() .modelFile(modelFunc.apply(state)) .rotationX(dir == Direction.DOWN ? 180 : dir.getAxis() .isHorizontal() ? 90 : 0) .rotationY(dir.getAxis() - .isVertical() ? 0 : (((int) dir.getHorizontalAngle()) + 180) % 360) + .isVertical() ? 0 : (((int) dir.toYRot()) + 180) % 360) .build(); }, BlockStateProperties.WATERLOGGED); } @@ -129,7 +129,7 @@ public class BlockStateGen { Function modelFunc, boolean uvLock) { prov.getVariantBuilder(ctx.getEntry()) .forAllStatesExcept(state -> { - Axis axis = state.get(BlockStateProperties.AXIS); + Axis axis = state.getValue(BlockStateProperties.AXIS); return ConfiguredModel.builder() .modelFile(modelFunc.apply(state)) .uvLock(uvLock) @@ -153,7 +153,7 @@ public class BlockStateGen { RegistrateBlockstateProvider prov, Function modelFunc) { prov.getVariantBuilder(ctx.getEntry()) .forAllStates(state -> { - Axis axis = state.get(BlockStateProperties.HORIZONTAL_AXIS); + Axis axis = state.getValue(BlockStateProperties.HORIZONTAL_AXIS); return ConfiguredModel.builder() .modelFile(modelFunc.apply(state)) .rotationY(axis == Axis.X ? 90 : 0) @@ -166,13 +166,13 @@ public class BlockStateGen { prov.getVariantBuilder(ctx.getEntry()) .forAllStates(state -> { - boolean alongFirst = state.get(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE); - Direction direction = state.get(DirectionalAxisKineticBlock.FACING); + boolean alongFirst = state.getValue(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE); + Direction direction = state.getValue(DirectionalAxisKineticBlock.FACING); boolean vertical = direction.getAxis() .isHorizontal() && (direction.getAxis() == Axis.X) == alongFirst; int xRot = direction == Direction.DOWN ? 270 : direction == Direction.UP ? 90 : 0; int yRot = direction.getAxis() - .isVertical() ? alongFirst ? 0 : 90 : (int) direction.getHorizontalAngle(); + .isVertical() ? alongFirst ? 0 : 90 : (int) direction.toYRot(); return ConfiguredModel.builder() .modelFile(modelFunc.apply(state, vertical)) @@ -188,8 +188,8 @@ public class BlockStateGen { .forAllStates(state -> ConfiguredModel.builder() .modelFile(modelFunc.apply(state)) .rotationX(90) - .rotationY(((int) state.get(BlockStateProperties.HORIZONTAL_FACING) - .getHorizontalAngle() + 180) % 360) + .rotationY(((int) state.getValue(BlockStateProperties.HORIZONTAL_FACING) + .toYRot() + 180) % 360) .build()); } @@ -209,26 +209,26 @@ public class BlockStateGen { ModelFile top, ModelFile covered) { prov.getVariantBuilder(ctx.getEntry()) .forAllStates(state -> ConfiguredModel.builder() - .modelFile(state.get(PavedBlock.COVERED) ? covered : top) + .modelFile(state.getValue(PavedBlock.COVERED) ? covered : top) .build()); } public static NonNullBiConsumer, RegistrateBlockstateProvider> cartAssembler() { return (c, p) -> p.getVariantBuilder(c.get()) .forAllStates(state -> { - CartAssembleRailType type = state.get(CartAssemblerBlock.RAIL_TYPE); - Boolean powered = state.get(CartAssemblerBlock.POWERED); - RailShape shape = state.get(CartAssemblerBlock.RAIL_SHAPE); + CartAssembleRailType type = state.getValue(CartAssemblerBlock.RAIL_TYPE); + Boolean powered = state.getValue(CartAssemblerBlock.POWERED); + Boolean backwards = state.getValue(CartAssemblerBlock.BACKWARDS); + RailShape shape = state.getValue(CartAssemblerBlock.RAIL_SHAPE); + int yRotation = shape == RailShape.EAST_WEST ? 270 : 0; - if (type == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS) { + if (backwards) yRotation += 180; - type = CartAssembleRailType.CONTROLLER_RAIL; - } return ConfiguredModel.builder() .modelFile(p.models() .getExistingFile(p.modLoc( - "block/" + c.getName() + "/block_" + type.getString() + (powered ? "_powered" : "")))) + "block/" + c.getName() + "/block_" + type.getSerializedName() + (powered ? "_powered" : "")))) .rotationY(yRotation % 360) .build(); }); @@ -247,9 +247,9 @@ public class BlockStateGen { return ConfiguredModel.builder() .modelFile(p.models() .getExistingFile(p.modLoc( - "block/" + c.getName() + "/block" + (state.get(ReinforcedRailBlock.CONNECTS_S) ? "_s" : "") - + (state.get(ReinforcedRailBlock.CONNECTS_N) ? "_n" : "")))) - .rotationY(state.get(ReinforcedRailBlock.RAIL_SHAPE) == RailShape.EAST_WEST ? 90 : 0) + "block/" + c.getName() + "/block" + (state.getValue(ReinforcedRailBlock.CONNECTS_S) ? "_s" : "") + + (state.getValue(ReinforcedRailBlock.CONNECTS_N) ? "_n" : "")))) + .rotationY(state.getValue(ReinforcedRailBlock.RAIL_SHAPE) == RailShape.EAST_WEST ? 90 : 0) .build(); }); } @@ -272,8 +272,8 @@ public class BlockStateGen { .texture("top", isTopSticky ? top_sticky : top)); BiFunction modelFunc = (t, b) -> models.get((t ? 0 : 2) + (b ? 0 : 1)); - axisBlock(c, p, state -> modelFunc.apply(state.get(LinearChassisBlock.STICKY_TOP), - state.get(LinearChassisBlock.STICKY_BOTTOM))); + axisBlock(c, p, state -> modelFunc.apply(state.getValue(LinearChassisBlock.STICKY_TOP), + state.getValue(LinearChassisBlock.STICKY_BOTTOM))); }; } @@ -290,14 +290,14 @@ public class BlockStateGen { Vector stickyFaces = new Vector<>(3); for (Axis axis : Iterate.axes) { - String suffix = "side_" + axis.getString(); + String suffix = "side_" + axis.getSerializedName(); faces.add(p.models() .withExistingParent("block/" + c.getName() + "_" + suffix, p.modLoc(templateModelPath + "/" + suffix)) .texture("side", side)); } for (Axis axis : Iterate.axes) { - String suffix = "side_" + axis.getString(); + String suffix = "side_" + axis.getSerializedName(); stickyFaces.add(p.models() .withExistingParent("block/" + c.getName() + "_" + suffix + "_sticky", p.modLoc(templateModelPath + "/" + suffix)) @@ -306,8 +306,8 @@ public class BlockStateGen { MultiPartBlockStateBuilder builder = p.getMultipartBuilder(c.get()); BlockState propertyGetter = c.get() - .getDefaultState() - .with(RadialChassisBlock.AXIS, Axis.Y); + .defaultBlockState() + .setValue(RadialChassisBlock.AXIS, Axis.Y); for (Axis axis : Iterate.axes) builder.part() @@ -321,7 +321,7 @@ public class BlockStateGen { for (Direction face : Iterate.horizontalDirections) { for (boolean sticky : Iterate.trueAndFalse) { for (Axis axis : Iterate.axes) { - int horizontalAngle = (int) (face.getHorizontalAngle()); + int horizontalAngle = (int) (face.toYRot()); int index = axis.ordinal(); int xRot = 0; int yRot = 0; @@ -367,7 +367,7 @@ public class BlockStateGen { builder.part() .modelFile(flatPass ? flat : open) .rotationX(verticalAngle) - .rotationY((int) (d.getHorizontalAngle() + (d.getAxis() + .rotationY((int) (d.toYRot() + (d.getAxis() .isVertical() ? 90 : 0)) % 360) .addModel() .condition(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(d), !flatPass) @@ -403,22 +403,22 @@ public class BlockStateGen { Map, ModelFile> coreModels = new HashMap<>(); for (Axis axis : Iterate.axes) - coreTemplates.put(axis, p.modLoc(path + "/core_" + axis.getString())); + coreTemplates.put(axis, p.modLoc(path + "/core_" + axis.getSerializedName())); ModelFile end = AssetLookup.partialBaseModel(c, p, "end"); for (Axis axis : Iterate.axes) { ResourceLocation parent = coreTemplates.get(axis); for (String s : orientations) { Pair key = Pair.of(s, axis); - String modelName = path + "/" + s + "_" + axis.getString(); + String modelName = path + "/" + s + "_" + axis.getSerializedName(); coreModels.put(key, p.models() .withExistingParent(modelName, parent) .element() .from(4, 4, 4) .to(12, 12, 12) - .face(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis)) + .face(Direction.get(AxisDirection.POSITIVE, axis)) .end() - .face(Direction.getFacingFromAxis(AxisDirection.NEGATIVE, axis)) + .face(Direction.get(AxisDirection.NEGATIVE, axis)) .end() .faces((d, builder) -> { Pair pair = uvs.get(s); @@ -441,9 +441,9 @@ public class BlockStateGen { builder.part() .modelFile(end) .rotationX(d == Direction.UP ? 0 : d == Direction.DOWN ? 180 : 90) - .rotationY((int) (d.getHorizontalAngle() + 180) % 360) + .rotationY((int) (d.toYRot() + 180) % 360) .addModel() - .condition(FluidPipeBlock.FACING_TO_PROPERTY_MAP.get(d), true) + .condition(FluidPipeBlock.PROPERTY_BY_DIRECTION.get(d), true) .end(); for (Axis axis : Iterate.axes) { @@ -464,8 +464,8 @@ public class BlockStateGen { private static void putPart(Map, ModelFile> coreModels, MultiPartBlockStateBuilder builder, Axis axis, String s, boolean up, boolean down, boolean left, boolean right) { - Direction positiveAxis = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); - Map propertyMap = FluidPipeBlock.FACING_TO_PROPERTY_MAP; + Direction positiveAxis = Direction.get(AxisDirection.POSITIVE, axis); + Map propertyMap = FluidPipeBlock.PROPERTY_BY_DIRECTION; builder.part() .modelFile(coreModels.get(Pair.of(s, axis))) .addModel() 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..7f837a738 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java +++ b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java @@ -22,16 +22,19 @@ import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelItem; import com.simibubi.create.content.logistics.block.inventories.CrateBlock; +import com.simibubi.create.foundation.block.BlockStressDefaults; import com.simibubi.create.foundation.block.ItemUseOverrides; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; -import com.simibubi.create.foundation.config.StressConfigDefaults; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; +import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; +import net.minecraft.block.SoundType; import net.minecraft.client.renderer.RenderType; import net.minecraft.item.DyeColor; import net.minecraft.item.Rarity; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.PistonType; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -45,8 +48,8 @@ public class BuilderTransformers { return b -> b.initialProperties(SharedProperties::wooden) .blockstate((c, p) -> p.horizontalBlock(c.get(), p.models() .getExistingFile(p.modLoc("block/cuckoo_clock/block")))) - .addLayer(() -> RenderType::getCutoutMipped) - .transform(StressConfigDefaults.setImpact(1.0)) + .addLayer(() -> RenderType::cutoutMipped) + .transform(BlockStressDefaults.setImpact(1.0)) .item() .transform(ModelGen.customItemModel("cuckoo_clock", "item")); } @@ -54,14 +57,14 @@ public class BuilderTransformers { public static NonNullUnaryOperator> encasedShaft(String casing, CTSpriteShiftEntry casingShift) { return builder -> builder.initialProperties(SharedProperties::stone) - .properties(Block.Properties::nonOpaque) + .properties(AbstractBlock.Properties::noOcclusion) .onRegister(CreateRegistrate.connectedTextures(new EncasedCTBehaviour(casingShift))) .onRegister(CreateRegistrate.casingConnectivity( - (block, cc) -> cc.make(block, casingShift, (s, f) -> f.getAxis() != s.get(EncasedShaftBlock.AXIS)))) + (block, cc) -> cc.make(block, casingShift, (s, f) -> f.getAxis() != s.getValue(EncasedShaftBlock.AXIS)))) .blockstate((c, p) -> axisBlock(c, p, blockState -> p.models() .getExistingFile(p.modLoc("block/encased_shaft/block_" + casing)), true)) - .transform(StressConfigDefaults.setNoImpact()) - .loot((p, b) -> p.registerDropping(b, AllBlocks.SHAFT.get())) + .transform(BlockStressDefaults.setNoImpact()) + .loot((p, b) -> p.dropOther(b, AllBlocks.SHAFT.get())) .item() .model(AssetLookup.customBlockItemModel("encased_shaft", "item_" + casing)) .build(); @@ -71,7 +74,7 @@ public class BuilderTransformers { @Nullable DyeColor color) { return b -> b.initialProperties(SharedProperties::softMetal) .blockstate((c, p) -> { - String variant = color == null ? "copper" : color.getString(); + String variant = color == null ? "copper" : color.getSerializedName(); p.directionalBlock(c.get(), p.models() .withExistingParent(variant + "_valve_handle", p.modLoc("block/valve_handle")) .texture("3", p.modLoc("block/valve_handle/valve_handle_" + variant))); @@ -95,15 +98,15 @@ public class BuilderTransformers { public static NonNullUnaryOperator> beltTunnel( String type, ResourceLocation particleTexture) { return b -> b.initialProperties(SharedProperties::stone) - .addLayer(() -> RenderType::getCutoutMipped) - .properties(Block.Properties::nonOpaque) + .addLayer(() -> RenderType::cutoutMipped) + .properties(AbstractBlock.Properties::noOcclusion) .blockstate((c, p) -> p.getVariantBuilder(c.get()) .forAllStates(state -> { String id = "block/" + type + "_tunnel"; - Shape shape = state.get(BeltTunnelBlock.SHAPE); + Shape shape = state.getValue(BeltTunnelBlock.SHAPE); if (shape == BeltTunnelBlock.Shape.CLOSED) shape = BeltTunnelBlock.Shape.STRAIGHT; - String shapeName = shape.getString(); + String shapeName = shape.getSerializedName(); return ConfiguredModel.builder() .modelFile(p.models() .withExistingParent(id + "/" + shapeName, p.modLoc("block/belt_tunnel/" + shapeName)) @@ -111,7 +114,7 @@ public class BuilderTransformers { .texture("2", p.modLoc(id)) .texture("3", p.modLoc(id + "_top_window")) .texture("particle", particleTexture)) - .rotationY(state.get(BeltTunnelBlock.HORIZONTAL_AXIS) == Axis.X ? 0 : 90) + .rotationY(state.getValue(BeltTunnelBlock.HORIZONTAL_AXIS) == Axis.X ? 0 : 90) .build(); })) .item(BeltTunnelItem::new) @@ -127,12 +130,12 @@ public class BuilderTransformers { public static NonNullUnaryOperator> mechanicalPiston(PistonType type) { return b -> b.initialProperties(SharedProperties::stone) - .properties(p -> p.nonOpaque()) + .properties(p -> p.noOcclusion()) .blockstate(new MechanicalPistonGenerator(type)::generate) - .addLayer(() -> RenderType::getCutoutMipped) - .transform(StressConfigDefaults.setImpact(4.0)) + .addLayer(() -> RenderType::cutoutMipped) + .transform(BlockStressDefaults.setImpact(4.0)) .item() - .transform(ModelGen.customItemModel("mechanical_piston", type.getString(), "item")); + .transform(ModelGen.customItemModel("mechanical_piston", type.getSerializedName(), "item")); } public static NonNullUnaryOperator> bearing(String prefix, @@ -145,7 +148,7 @@ public class BuilderTransformers { ResourceLocation sideTextureLocation = Create.asResource("block/" + prefix + "_bearing_side"); ResourceLocation backTextureLocation = Create.asResource("block/" + backTexture); return b -> b.initialProperties(SharedProperties::stone) - .properties(p -> p.nonOpaque()) + .properties(p -> p.noOcclusion()) .blockstate((c, p) -> p.directionalBlock(c.get(), p.models() .withExistingParent(c.getName(), baseBlockModelLocation) .texture("side", sideTextureLocation) @@ -181,8 +184,8 @@ public class BuilderTransformers { String variant = "single"; int yRot = 0; - if (state.get(CrateBlock.DOUBLE)) { - Direction direction = state.get(CrateBlock.FACING); + if (state.getValue(CrateBlock.DOUBLE)) { + Direction direction = state.getValue(CrateBlock.FACING); if (direction.getAxis() == Axis.X) yRot = 90; @@ -212,8 +215,25 @@ 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")); } + public static NonNullUnaryOperator> bell() { + return b -> b.initialProperties(SharedProperties::softMetal) + .properties(p -> p.noOcclusion() + .sound(SoundType.ANVIL)) + .addLayer(() -> RenderType::cutoutMipped) + .tag(AllBlockTags.BRITTLE.tag) + .blockstate((c, p) -> p.horizontalBlock(c.getEntry(), state -> { + String variant = state.getValue(BlockStateProperties.BELL_ATTACHMENT) + .getSerializedName(); + return p.models() + .withExistingParent(c.getName() + "_" + variant, p.modLoc("block/bell_base/block_" + variant)); + })) + .item() + .model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/" + c.getName()))) + .build(); + } + } 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..ef35ef8f0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/CreateEntityBuilder.java @@ -0,0 +1,55 @@ +package com.simibubi.create.foundation.data; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.backend.instancing.entity.IEntityInstanceFactory; +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; + +@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..8f7490658 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java @@ -9,15 +9,17 @@ import java.util.function.BiFunction; import java.util.function.Supplier; import java.util.stream.Collectors; +import com.simibubi.create.AllTags; import com.simibubi.create.Create; 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.CustomRenderedItemModelRenderer; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.builders.Builder; @@ -33,16 +35,19 @@ 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.client.renderer.tileentity.ItemStackTileEntityRenderer; +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.tags.BlockTags; 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.common.Tags; import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.ForgeFlowingFluid; import net.minecraftforge.fml.DistExecutor; @@ -113,7 +118,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,19 +129,40 @@ 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, - NonNullFunction factory, NonNullSupplier propertiesFrom, boolean TFworldGen) { - return super.block(name, factory).initialProperties(propertiesFrom) + public BlockBuilder paletteStoneBlock(String name, + NonNullFunction factory, NonNullSupplier propertiesFrom, boolean worldGenStone) { + BlockBuilder builder = super.block(name, factory).initialProperties(propertiesFrom) .blockstate((c, p) -> { final String location = "block/palettes/" + c.getName() + "/plain"; p.simpleBlock(c.get(), p.models() .cubeAll(c.getName(), p.modLoc(location))); - // TODO tag with forge:stone; if TFWorldGen == true tag with forge:wg_stone - // aswell }) - .simpleItem(); + .tag(Tags.Blocks.STONE) + .item() + .tag(Tags.Items.STONE) + .build(); + if (worldGenStone) { + builder.tag(BlockTags.BASE_STONE_OVERWORLD, AllTags.AllBlockTags.WG_STONE.tag); + } + return builder; + } + + public BlockBuilder paletteStoneBlock(String name, + NonNullSupplier propertiesFrom, boolean worldGenStone) { + return paletteStoneBlock(name, Block::new, propertiesFrom, worldGenStone); } /* Fluids */ @@ -172,38 +198,33 @@ 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 blockModel( + Supplier> func) { + return entry -> onClient(() -> () -> registerBlockModel(entry, func)); + } + public static NonNullConsumer itemModel( - Supplier> func) { + Supplier> func) { return entry -> onClient(() -> () -> registerItemModel(entry, func)); } - public static NonNullConsumer itemColors(Supplier> colorFunc) { - return entry -> onClient(() -> () -> registerItemColor(entry, colorFunc)); - } - public static NonNullUnaryOperator> customRenderedItem( - Supplier> func) { - return b -> b.properties(p -> p.setISTER(() -> () -> func.get() - .apply(null) - .createRenderer())) - .onRegister(entry -> onClient(() -> () -> registerCustomRenderedItem(entry, func))); + Supplier>> supplier) { + return b -> b.properties(p -> p.setISTER(() -> () -> supplier.get().get())) + .onRegister(entry -> onClient(() -> () -> { + ItemStackTileEntityRenderer ister = entry.getItemStackTileEntityRenderer(); + if (ister instanceof CustomRenderedItemModelRenderer) { + registerCustomRenderedItem(entry, (CustomRenderedItemModelRenderer) ister); + } + })); } protected static void onClient(Supplier toRun) { @@ -212,55 +233,41 @@ 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)); + CreateClient.MODEL_SWAPPER.getCustomBlockModels() + .register(entry.delegate, model -> new CTModel(model, behavior)); } @OnlyIn(Dist.CLIENT) private static void registerCasingConnectivity(T entry, - BiConsumer consumer) { - consumer.accept(entry, CreateClient.getCasingConnectivity()); + BiConsumer consumer) { + consumer.accept(entry, CreateClient.CASING_CONNECTIVITY); + } + + @OnlyIn(Dist.CLIENT) + private static void registerBlockVertexColor(Block entry, IBlockVertexColor colorFunc) { + CreateClient.MODEL_SWAPPER.getCustomBlockModels() + .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()); + Supplier> func) { + CreateClient.MODEL_SWAPPER.getCustomBlockModels() + .register(entry.delegate, func.get()); } @OnlyIn(Dist.CLIENT) private static void registerItemModel(Item entry, Supplier> func) { - CreateClient.getCustomItemModels() + CreateClient.MODEL_SWAPPER.getCustomItemModels() .register(entry.delegate, func.get()); } @OnlyIn(Dist.CLIENT) private static void registerCustomRenderedItem(Item entry, - Supplier> func) { - CreateClient.getCustomRenderedItems() - .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()); + CustomRenderedItemModelRenderer renderer) { + CreateClient.MODEL_SWAPPER.getCustomRenderedItems() + .register(entry.delegate, renderer::createModel); } } 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/DirectionalAxisBlockStateGen.java b/src/main/java/com/simibubi/create/foundation/data/DirectionalAxisBlockStateGen.java index 64512db71..ec321bd6e 100644 --- a/src/main/java/com/simibubi/create/foundation/data/DirectionalAxisBlockStateGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/DirectionalAxisBlockStateGen.java @@ -14,8 +14,8 @@ public abstract class DirectionalAxisBlockStateGen extends SpecialBlockStateGen @Override protected int getXRotation(BlockState state) { - Direction direction = state.get(GaugeBlock.FACING); - boolean alongFirst = state.get(GaugeBlock.AXIS_ALONG_FIRST_COORDINATE); + Direction direction = state.getValue(GaugeBlock.FACING); + boolean alongFirst = state.getValue(GaugeBlock.AXIS_ALONG_FIRST_COORDINATE); if (direction == Direction.DOWN) return 180; @@ -29,8 +29,8 @@ public abstract class DirectionalAxisBlockStateGen extends SpecialBlockStateGen @Override protected int getYRotation(BlockState state) { - Direction direction = state.get(GaugeBlock.FACING); - boolean alongFirst = state.get(GaugeBlock.AXIS_ALONG_FIRST_COORDINATE); + Direction direction = state.getValue(GaugeBlock.FACING); + boolean alongFirst = state.getValue(GaugeBlock.AXIS_ALONG_FIRST_COORDINATE); if (direction.getAxis() .isVertical()) @@ -45,7 +45,7 @@ public abstract class DirectionalAxisBlockStateGen extends SpecialBlockStateGen @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - boolean vertical = state.get(GaugeBlock.FACING) + boolean vertical = state.getValue(GaugeBlock.FACING) .getAxis() .isVertical(); String partial = vertical ? "" : "_wall"; 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..0b71d5383 100644 --- a/src/main/java/com/simibubi/create/foundation/data/LangMerger.java +++ b/src/main/java/com/simibubi/create/foundation/data/LangMerger.java @@ -60,6 +60,7 @@ public class LangMerger implements IDataProvider { private void populateLangIgnore() { // Key prefixes added here will NOT be transferred to lang templates langIgnore.add("create.ponder.debug_"); // Ponder debug scene text + langIgnore.add("create.gui.chromatic_projector"); } private boolean shouldIgnore(String key) { @@ -75,7 +76,7 @@ public class LangMerger implements IDataProvider { } @Override - public void act(DirectoryCache cache) throws IOException { + public void run(DirectoryCache cache) throws IOException { Path path = this.gen.getOutputFolder() .resolve("assets/" + Create.ID + "/lang/" + "en_us.json"); @@ -119,7 +120,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; } @@ -231,19 +232,19 @@ public class LangMerger implements IDataProvider { String data = createString(dataIn, missingKeys); // data = JavaUnicodeEscaper.outsideOf(0, 0x7f) // .translate(data); - String hash = IDataProvider.HASH_FUNCTION.hashUnencodedChars(data) + String hash = IDataProvider.SHA1.hashUnencodedChars(data) .toString(); - if (!Objects.equals(cache.getPreviousHash(target), hash) || !Files.exists(target)) { + if (!Objects.equals(cache.getHash(target), hash) || !Files.exists(target)) { Files.createDirectories(target.getParent()); try (BufferedWriter bufferedwriter = Files.newBufferedWriter(target)) { - Create.logger.info(message); + Create.LOGGER.info(message); bufferedwriter.write(data); bufferedwriter.close(); } } - cache.recordHash(target, hash); + cache.putNew(target, hash); } protected String createString(List data, int missingKeys) { diff --git a/src/main/java/com/simibubi/create/foundation/data/ModelGen.java b/src/main/java/com/simibubi/create/foundation/data/ModelGen.java index ff8cf6679..b99a63bb1 100644 --- a/src/main/java/com/simibubi/create/foundation/data/ModelGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/ModelGen.java @@ -21,7 +21,7 @@ public class ModelGen { public static ModelFile createOvergrown(DataGenContext ctx, BlockStateProvider prov, ResourceLocation side, ResourceLocation top, ResourceLocation bottom, ResourceLocation overlay) { return prov.models() - .withExistingParent(ctx.getName(), new ResourceLocation(Create.ID, "block/overgrown")) + .withExistingParent(ctx.getName(), Create.asResource("block/overgrown")) .texture("particle", side) .texture("side", side) .texture("top", top) diff --git a/src/main/java/com/simibubi/create/foundation/data/NamedTag.java b/src/main/java/com/simibubi/create/foundation/data/NamedTag.java index 066552663..000ff1b05 100644 --- a/src/main/java/com/simibubi/create/foundation/data/NamedTag.java +++ b/src/main/java/com/simibubi/create/foundation/data/NamedTag.java @@ -22,7 +22,7 @@ public class NamedTag implements ITag.INamedTag { } @Override - public ResourceLocation getId() { + public ResourceLocation getName() { return id; } @@ -34,9 +34,9 @@ public class NamedTag implements ITag.INamedTag { } @Override - public List values() { + public List getValues() { if (tag == null) return Collections.emptyList(); - return tag.values(); + return tag.getValues(); } } diff --git a/src/main/java/com/simibubi/create/foundation/data/SharedProperties.java b/src/main/java/com/simibubi/create/foundation/data/SharedProperties.java index f685c4368..c65837850 100644 --- a/src/main/java/com/simibubi/create/foundation/data/SharedProperties.java +++ b/src/main/java/com/simibubi/create/foundation/data/SharedProperties.java @@ -10,7 +10,7 @@ import net.minecraft.block.material.PushReaction; @MethodsReturnNonnullByDefault public class SharedProperties { public static Material beltMaterial = - new Material(MaterialColor.GRAY, false, true, true, true, false, false, PushReaction.NORMAL); + new Material(MaterialColor.COLOR_GRAY, false, true, true, true, false, false, PushReaction.NORMAL); public static Block stone() { return Blocks.ANDESITE; diff --git a/src/main/java/com/simibubi/create/foundation/data/SpecialBlockStateGen.java b/src/main/java/com/simibubi/create/foundation/data/SpecialBlockStateGen.java index 98aea3c9c..1529eac07 100644 --- a/src/main/java/com/simibubi/create/foundation/data/SpecialBlockStateGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/SpecialBlockStateGen.java @@ -31,7 +31,7 @@ public abstract class SpecialBlockStateGen { if (direction.getAxis() .isVertical()) return 0; - return (int) direction.getHorizontalAngle(); + return (int) direction.toYRot(); } protected abstract int getXRotation(BlockState state); diff --git a/src/main/java/com/simibubi/create/foundation/data/WindowGen.java b/src/main/java/com/simibubi/create/foundation/data/WindowGen.java index 3aabbe3d3..2e3c6dbc6 100644 --- a/src/main/java/com/simibubi/create/foundation/data/WindowGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/WindowGen.java @@ -44,10 +44,10 @@ public class WindowGen { private static final CreateRegistrate REGISTRATE = Create.registrate(); private static Properties glassProperties(Properties p) { - return p.allowsSpawning(WindowGen::never) - .solidBlock(WindowGen::never) - .suffocates(WindowGen::never) - .blockVision(WindowGen::never); + return p.isValidSpawn(WindowGen::never) + .isRedstoneConductor(WindowGen::never) + .isSuffocating(WindowGen::never) + .isViewBlocking(WindowGen::never); } private static boolean never(BlockState p_235436_0_, IBlockReader p_235436_1_, BlockPos p_235436_2_) { @@ -60,7 +60,7 @@ public class WindowGen { } public static BlockEntry woodenWindowBlock(WoodType woodType, Block planksBlock) { - return woodenWindowBlock(woodType, planksBlock, () -> RenderType::getCutoutMipped); + return woodenWindowBlock(woodType, planksBlock, () -> RenderType::cutoutMipped); } public static BlockEntry customWindowBlock(String name, Supplier ingredient, @@ -72,7 +72,7 @@ public class WindowGen { public static BlockEntry woodenWindowBlock(WoodType woodType, Block planksBlock, Supplier> renderType) { - String woodName = woodType.getName(); + String woodName = woodType.name(); String name = woodName + "_window"; NonNullFunction end_texture = $ -> new ResourceLocation("block/" + woodName + "_planks"); @@ -87,16 +87,16 @@ public class WindowGen { return REGISTRATE.block(name, WindowBlock::new) .onRegister(connectedTextures(new HorizontalCTBehaviour(ct))) .addLayer(renderType) - .recipe((c, p) -> ShapedRecipeBuilder.shapedRecipe(c.get(), 2) - .patternLine(" # ") - .patternLine("#X#") - .key('#', ingredient.get()) - .key('X', DataIngredient.tag(Tags.Items.GLASS_COLORLESS)) - .addCriterion("has_ingredient", p.hasItem(ingredient.get())) - .build(p::accept)) + .recipe((c, p) -> ShapedRecipeBuilder.shaped(c.get(), 2) + .pattern(" # ") + .pattern("#X#") + .define('#', ingredient.get()) + .define('X', DataIngredient.tag(Tags.Items.GLASS_COLORLESS)) + .unlockedBy("has_ingredient", p.hasItem(ingredient.get())) + .save(p::accept)) .initialProperties(() -> Blocks.GLASS) .properties(WindowGen::glassProperties) - .loot((t, g) -> t.registerSilkTouch(g)) + .loot((t, g) -> t.dropWhenSilkTouch(g)) .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() .cubeColumn(c.getName(), sideTexture.apply(c.getName()), endTexture.apply(c.getName())))) .tag(BlockTags.IMPERMEABLE) @@ -107,10 +107,10 @@ public class WindowGen { public static BlockEntry framedGlass(String name, ConnectedTextureBehaviour behaviour) { return REGISTRATE.block(name, ConnectedGlassBlock::new) .onRegister(connectedTextures(behaviour)) - .addLayer(() -> RenderType::getTranslucent) + .addLayer(() -> RenderType::translucent) .initialProperties(() -> Blocks.GLASS) .properties(WindowGen::glassProperties) - .loot((t, g) -> t.registerSilkTouch(g)) + .loot((t, g) -> t.dropWhenSilkTouch(g)) .recipe((c, p) -> p.stonecutting(DataIngredient.tag(Tags.Items.GLASS_COLORLESS), c::get)) .blockstate((c, p) -> BlockStateGen.cubeAll(c, p, "palettes/", "framed_glass")) .tag(Tags.Blocks.GLASS_COLORLESS, BlockTags.IMPERMEABLE) @@ -127,7 +127,7 @@ public class WindowGen { ResourceLocation sideTexture = Create.asResource(palettesDir() + "framed_glass"); ResourceLocation itemSideTexture = Create.asResource(palettesDir() + name); ResourceLocation topTexture = Create.asResource(palettesDir() + "framed_glass_pane_top"); - Supplier> renderType = () -> RenderType::getTranslucent; + Supplier> renderType = () -> RenderType::translucent; return connectedGlassPane(name, parent, ctshift, sideTexture, itemSideTexture, topTexture, renderType); } @@ -140,12 +140,12 @@ public class WindowGen { public static BlockEntry woodenWindowPane(WoodType woodType, Supplier parent) { - return woodenWindowPane(woodType, parent, () -> RenderType::getCutoutMipped); + return woodenWindowPane(woodType, parent, () -> RenderType::cutoutMipped); } public static BlockEntry woodenWindowPane(WoodType woodType, Supplier parent, Supplier> renderType) { - String woodName = woodType.getName(); + String woodName = woodType.name(); String name = woodName + "_window"; ResourceLocation topTexture = new ResourceLocation("block/" + woodName + "_planks"); ResourceLocation sideTexture = Create.asResource(palettesDir() + name); @@ -203,17 +203,17 @@ public class WindowGen { .addLayer(renderType) .initialProperties(() -> Blocks.GLASS_PANE) .blockstate(stateProvider) - .recipe((c, p) -> ShapedRecipeBuilder.shapedRecipe(c.get(), 16) - .patternLine("###") - .patternLine("###") - .key('#', parent.get()) - .addCriterion("has_ingredient", p.hasItem(parent.get())) - .build(p::accept)) + .recipe((c, p) -> ShapedRecipeBuilder.shaped(c.get(), 16) + .pattern("###") + .pattern("###") + .define('#', parent.get()) + .unlockedBy("has_ingredient", p.hasItem(parent.get())) + .save(p::accept)) .tag(Tags.Blocks.GLASS_PANES) - .loot((t, g) -> t.registerSilkTouch(g)) + .loot((t, g) -> t.dropWhenSilkTouch(g)) .item() .tag(Tags.Items.GLASS_PANES) - .model((c, p) -> p.withExistingParent(c.getName(), new ResourceLocation(Create.ID, "item/pane")) + .model((c, p) -> p.withExistingParent(c.getName(), Create.asResource("item/pane")) .texture("pane", sideTexture) .texture("edge", topTexture)) .build() diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CompactingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CompactingRecipeGen.java index d71049704..ccf3125c5 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CompactingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CompactingRecipeGen.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.data.recipe; import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllTags.AllFluidTags; import com.simibubi.create.content.palettes.AllPaletteBlocks; import net.minecraft.block.Blocks; @@ -21,9 +22,6 @@ public class CompactingRecipeGen extends ProcessingRecipeGen { .require(Items.RED_SAND) .output(Blocks.GRANITE, 1)), - CHOCOLATE = create("chocolate", b -> b.require(AllFluids.CHOCOLATE.get(), 250) - .output(AllItems.BAR_OF_CHOCOLATE.get(), 1)), - DIORITE = create("diorite_from_flint", b -> b.require(Items.FLINT) .require(Items.FLINT) .require(Fluids.LAVA, 100) @@ -36,10 +34,16 @@ public class CompactingRecipeGen extends ProcessingRecipeGen { .require(Items.GRAVEL) .output(Blocks.ANDESITE, 1)), + CHOCOLATE = create("chocolate", b -> b.require(AllFluids.CHOCOLATE.get(), 250) + .output(AllItems.BAR_OF_CHOCOLATE.get(), 1)), + BLAZE_CAKE = create("blaze_cake", b -> b.require(Tags.Items.EGGS) .require(Items.SUGAR) .require(AllItems.CINDER_FLOUR.get()) - .output(AllItems.BLAZE_CAKE_BASE.get(), 1)) + .output(AllItems.BLAZE_CAKE_BASE.get(), 1)), + + HONEY = create("honey", b -> b.require(AllFluidTags.HONEY.tag, 1000) + .output(Items.HONEY_BLOCK, 1)) ; 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..2e4138cec 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 @@ -20,21 +20,16 @@ import net.minecraftforge.common.Tags; public abstract class CreateRecipeProvider extends RecipeProvider { - final List all = new ArrayList<>(); + protected final List all = new ArrayList<>(); - public CreateRecipeProvider(DataGenerator p_i48262_1_) { - super(p_i48262_1_); + public CreateRecipeProvider(DataGenerator generator) { + super(generator); } @Override - protected void registerRecipes(Consumer p_200404_1_) { + protected void buildShapelessRecipes(Consumer p_200404_1_) { all.forEach(c -> c.register(p_200404_1_)); - Create.logger.info(getName() + " registered " + all.size() + " recipe" + (all.size() == 1 ? "" : "s")); - } - - @FunctionalInterface - interface GeneratedRecipe { - void register(Consumer consumer); + Create.LOGGER.info(getName() + " registered " + all.size() + " recipe" + (all.size() == 1 ? "" : "s")); } protected GeneratedRecipe register(GeneratedRecipe recipe) { @@ -42,6 +37,11 @@ public abstract class CreateRecipeProvider extends RecipeProvider { return recipe; } + @FunctionalInterface + public interface GeneratedRecipe { + void register(Consumer consumer); + } + protected static class Marker { } @@ -50,11 +50,15 @@ public abstract class CreateRecipeProvider extends RecipeProvider { static ITag.INamedTag redstone() { return Tags.Items.DUSTS_REDSTONE; } - + static ITag.INamedTag planks() { return ItemTags.PLANKS; } + static ITag.INamedTag woodSlab() { + return ItemTags.WOODEN_SLABS; + } + static ITag.INamedTag gold() { return AllTags.forgeItemTag("ingots/gold"); } @@ -79,6 +83,10 @@ public abstract class CreateRecipeProvider extends RecipeProvider { return AllBlocks.COGWHEEL.get(); } + static IItemProvider largeCog() { + return AllBlocks.LARGE_COGWHEEL.get(); + } + static IItemProvider andesiteCasing() { return AllBlocks.ANDESITE_CASING.get(); } @@ -95,6 +103,10 @@ public abstract class CreateRecipeProvider extends RecipeProvider { return Tags.Items.INGOTS_IRON; } + static ITag.INamedTag ironNugget() { + return AllTags.forgeItemTag("nuggets/iron"); + } + static ITag.INamedTag zinc() { return AllTags.forgeItemTag("ingots/zinc"); } @@ -111,8 +123,8 @@ public abstract class CreateRecipeProvider extends RecipeProvider { return AllItems.ELECTRON_TUBE.get(); } - static IItemProvider circuit() { - return AllItems.INTEGRATED_CIRCUIT.get(); + static IItemProvider precisionMechanism() { + return AllItems.PRECISION_MECHANISM.get(); } static ITag.INamedTag copperBlock() { @@ -134,7 +146,7 @@ public abstract class CreateRecipeProvider extends RecipeProvider { static ITag.INamedTag copperSheet() { return AllTags.forgeItemTag("plates/copper"); } - + static ITag.INamedTag copperNugget() { return AllTags.forgeItemTag("nuggets/copper"); } diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java index 8955e0531..eac7c4424 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java @@ -37,8 +37,8 @@ public class CuttingRecipeGen extends ProcessingRecipeGen { GeneratedRecipe stripAndMakePlanks(Block wood, Block stripped, Block planks) { create(() -> wood, b -> b.duration(50) .output(stripped)); - return create(() -> stripped, b -> b.duration(100) - .output(planks, 5)); + return create(() -> stripped, b -> b.duration(50) + .output(planks, 6)); } public CuttingRecipeGen(DataGenerator p_i48262_1_) { diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/EmptyingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/EmptyingRecipeGen.java index 36baa02ff..21a31eecd 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/EmptyingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/EmptyingRecipeGen.java @@ -12,23 +12,18 @@ public class EmptyingRecipeGen extends ProcessingRecipeGen { /* * potion/water bottles are handled internally */ - + GeneratedRecipe - HONEY_BOTTLE = create("honey_bottle", b -> b - .require(Items.HONEY_BOTTLE) - .output(AllFluids.HONEY.get(), 250) - .output(Items.GLASS_BOTTLE)), - - BUILDERS_TEA = create("builders_tea", b -> b - .require(AllItems.BUILDERS_TEA.get()) - .output(AllFluids.TEA.get(), 250) - .output(Items.GLASS_BOTTLE)), - - MILK_BUCKET = create("milk_bucket", b -> b - .require(Items.MILK_BUCKET) - .output(AllFluids.MILK.get(), 1000) - .output(Items.BUCKET)) + HONEY_BOTTLE = create("honey_bottle", b -> b + .require(Items.HONEY_BOTTLE) + .output(AllFluids.HONEY.get(), 250) + .output(Items.GLASS_BOTTLE)), + + BUILDERS_TEA = create("builders_tea", b -> b + .require(AllItems.BUILDERS_TEA.get()) + .output(AllFluids.TEA.get(), 250) + .output(Items.GLASS_BOTTLE)) ; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java index b677d9fa7..5421db0b5 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java @@ -3,19 +3,20 @@ package com.simibubi.create.foundation.data.recipe; import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.AllTags; +import com.simibubi.create.AllTags.AllFluidTags; import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; import net.minecraft.data.DataGenerator; import net.minecraft.fluid.Fluids; import net.minecraft.item.Items; import net.minecraft.potion.Potions; +import net.minecraftforge.common.Tags; public class FillingRecipeGen extends ProcessingRecipeGen { GeneratedRecipe - HONEY_BOTTLE = create("honey_bottle", b -> b.require(AllTags.forgeFluidTag("honey"), 250) + HONEY_BOTTLE = create("honey_bottle", b -> b.require(AllFluidTags.HONEY.tag, 250) .require(Items.GLASS_BOTTLE) .output(Items.HONEY_BOTTLE)), @@ -27,11 +28,11 @@ public class FillingRecipeGen extends ProcessingRecipeGen { .require(AllItems.BLAZE_CAKE_BASE.get()) .output(AllItems.BLAZE_CAKE.get())), - HONEYED_APPLE = create("honeyed_apple", b -> b.require(AllTags.forgeFluidTag("honey"), 250) + HONEYED_APPLE = create("honeyed_apple", b -> b.require(AllFluidTags.HONEY.tag, 250) .require(Items.APPLE) .output(AllItems.HONEYED_APPLE.get())), - SWEET_ROLL = create("sweet_roll", b -> b.require(AllTags.forgeFluidTag("milk"), 250) + SWEET_ROLL = create("sweet_roll", b -> b.require(Tags.Fluids.MILK, 250) .require(Items.BREAD) .output(AllItems.SWEET_ROLL.get())), @@ -53,11 +54,7 @@ public class FillingRecipeGen extends ProcessingRecipeGen { GLOWSTONE = create("glowstone", b -> b.require(PotionFluidHandler.potionIngredient(Potions.NIGHT_VISION, 25)) .require(AllItems.CINDER_FLOUR.get()) - .output(Items.GLOWSTONE_DUST)), - - MILK_BUCKET = create("milk_bucket", b -> b.require(AllTags.forgeFluidTag("milk"), 1000) - .require(Items.BUCKET) - .output(Items.MILK_BUCKET)) + .output(Items.GLOWSTONE_DUST)) ; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeBuilder.java b/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeBuilder.java index 1bc1314c7..2b75c2f4a 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeBuilder.java @@ -30,10 +30,12 @@ public class MechanicalCraftingRecipeBuilder { private final int count; private final List pattern = Lists.newArrayList(); private final Map key = Maps.newLinkedHashMap(); + private boolean acceptMirrored; public MechanicalCraftingRecipeBuilder(IItemProvider p_i48261_1_, int p_i48261_2_) { result = p_i48261_1_.asItem(); count = p_i48261_2_; + acceptMirrored = true; } /** @@ -54,14 +56,14 @@ public class MechanicalCraftingRecipeBuilder { * Adds a key to the recipe pattern. */ public MechanicalCraftingRecipeBuilder key(Character p_200469_1_, Tag p_200469_2_) { - return this.key(p_200469_1_, Ingredient.fromTag(p_200469_2_)); + return this.key(p_200469_1_, Ingredient.of(p_200469_2_)); } /** * Adds a key to the recipe pattern. */ public MechanicalCraftingRecipeBuilder key(Character p_200462_1_, IItemProvider p_200462_2_) { - return this.key(p_200462_1_, Ingredient.fromItems(p_200462_2_)); + return this.key(p_200462_1_, Ingredient.of(p_200462_2_)); } /** @@ -91,6 +93,14 @@ public class MechanicalCraftingRecipeBuilder { } } + /** + * Prevents the crafters from matching a vertically flipped version of the recipe + */ + public MechanicalCraftingRecipeBuilder disallowMirrored() { + acceptMirrored = false; + return this; + } + /** * Builds this recipe into an {@link IFinishedRecipe}. */ @@ -116,7 +126,8 @@ public class MechanicalCraftingRecipeBuilder { */ public void build(Consumer p_200467_1_, ResourceLocation p_200467_2_) { validate(p_200467_2_); - p_200467_1_.accept(new MechanicalCraftingRecipeBuilder.Result(p_200467_2_, result, count, pattern, key)); + p_200467_1_ + .accept(new MechanicalCraftingRecipeBuilder.Result(p_200467_2_, result, count, pattern, key, acceptMirrored)); } /** @@ -151,17 +162,19 @@ public class MechanicalCraftingRecipeBuilder { private final int count; private final List pattern; private final Map key; + private final boolean acceptMirrored; public Result(ResourceLocation p_i48271_2_, Item p_i48271_3_, int p_i48271_4_, List p_i48271_6_, - Map p_i48271_7_) { + Map p_i48271_7_, boolean asymmetrical) { this.id = p_i48271_2_; this.result = p_i48271_3_; this.count = p_i48271_4_; this.pattern = p_i48271_6_; this.key = p_i48271_7_; + this.acceptMirrored = asymmetrical; } - public void serialize(JsonObject p_218610_1_) { + public void serializeRecipeData(JsonObject p_218610_1_) { JsonArray jsonarray = new JsonArray(); for (String s : this.pattern) jsonarray.add(s); @@ -170,7 +183,7 @@ public class MechanicalCraftingRecipeBuilder { JsonObject jsonobject = new JsonObject(); for (Entry entry : this.key.entrySet()) jsonobject.add(String.valueOf(entry.getKey()), entry.getValue() - .serialize()); + .toJson()); p_218610_1_.add("key", jsonobject); JsonObject jsonobject1 = new JsonObject(); @@ -180,23 +193,24 @@ public class MechanicalCraftingRecipeBuilder { jsonobject1.addProperty("count", this.count); p_218610_1_.add("result", jsonobject1); + p_218610_1_.addProperty("acceptMirrored", acceptMirrored); } - public IRecipeSerializer getSerializer() { - return AllRecipeTypes.MECHANICAL_CRAFTING.serializer; + public IRecipeSerializer getType() { + return AllRecipeTypes.MECHANICAL_CRAFTING.getSerializer(); } - public ResourceLocation getID() { + public ResourceLocation getId() { return this.id; } @Nullable - public JsonObject getAdvancementJson() { + public JsonObject serializeAdvancement() { return null; } @Nullable - public ResourceLocation getAdvancementID() { + public ResourceLocation getAdvancementId() { return null; } } diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeGen.java index 7a7956291..b15d1ac64 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeGen.java @@ -20,46 +20,47 @@ public class MechanicalCraftingRecipeGen extends CreateRecipeProvider { GeneratedRecipe CRUSHING_WHEEL = create(AllBlocks.CRUSHING_WHEEL::get).returns(2) - .recipe(b -> b.key('P', Ingredient.fromTag(ItemTags.PLANKS)) - .key('S', Ingredient.fromTag(I.stone())) + .recipe(b -> b.key('P', Ingredient.of(ItemTags.PLANKS)) + .key('S', Ingredient.of(I.stone())) .key('A', I.andesite()) .patternLine(" AAA ") .patternLine("AAPAA") .patternLine("APSPA") .patternLine("AAPAA") - .patternLine(" AAA ")), - - INTEGRATED_CIRCUIT = create(AllItems.INTEGRATED_CIRCUIT::get).returns(1) - .recipe(b -> b.key('L', AllItems.LAPIS_SHEET.get()) - .key('R', Ingredient.fromTag(I.redstone())) - .key('Q', AllItems.POLISHED_ROSE_QUARTZ.get()) - .key('C', Ingredient.fromTag(Tags.Items.NUGGETS_GOLD)) - .patternLine(" L ") - .patternLine("RRQRR") - .patternLine(" CCC ")), + .patternLine(" AAA ") + .disallowMirrored()), EXTENDO_GRIP = create(AllItems.EXTENDO_GRIP::get).returns(1) - .recipe(b -> b.key('L', Ingredient.fromTag(I.brass())) - .key('R', I.cog()) + .recipe(b -> b.key('L', Ingredient.of(I.brass())) + .key('R', I.precisionMechanism()) .key('H', AllItems.BRASS_HAND.get()) - .key('S', Ingredient.fromTag(Tags.Items.RODS_WOODEN)) + .key('S', Ingredient.of(Tags.Items.RODS_WOODEN)) .patternLine(" L ") .patternLine(" R ") .patternLine("SSS") .patternLine("SSS") - .patternLine(" H ")), + .patternLine(" H ") + .disallowMirrored()), + + POTATO_CANNON = create(AllItems.POTATO_CANNON::get).returns(1) + .recipe(b -> b.key('L', I.andesite()) + .key('R', I.precisionMechanism()) + .key('S', AllBlocks.FLUID_PIPE.get()) + .key('C', Ingredient.of(I.copper())) + .patternLine("LRSSS") + .patternLine("CC ")), FURNACE_ENGINE = create(AllBlocks.FURNACE_ENGINE::get).returns(1) - .recipe(b -> b.key('P', Ingredient.fromTag(I.brassSheet())) - .key('B', Ingredient.fromTag(I.brass())) - .key('I', Ingredient.fromItems(Blocks.PISTON, Blocks.STICKY_PISTON)) + .recipe(b -> b.key('P', Ingredient.of(I.brassSheet())) + .key('B', Ingredient.of(I.brass())) + .key('I', Ingredient.of(Blocks.PISTON, Blocks.STICKY_PISTON)) .key('C', I.brassCasing()) .patternLine("PPB") .patternLine("PCI") .patternLine("PPB")), FLYWHEEL = create(AllBlocks.FLYWHEEL::get).returns(1) - .recipe(b -> b.key('B', Ingredient.fromTag(I.brass())) + .recipe(b -> b.key('B', Ingredient.of(I.brass())) .key('C', I.brassCasing()) .patternLine(" BBB") .patternLine("CB B") diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/MillingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/MillingRecipeGen.java index 92480a848..5a939f2eb 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/MillingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/MillingRecipeGen.java @@ -74,6 +74,10 @@ public class MillingRecipeGen extends ProcessingRecipeGen { .output(.1f, Items.GREEN_DYE, 1) .whenModMissing("quark")), + SEA_PICKLE = create(() -> Blocks.SEA_PICKLE, b -> b.duration(50) + .output(Items.LIME_DYE, 2) + .output(.1f, Items.GREEN_DYE)), + BONE_MEAL = create(() -> Items.BONE_MEAL, b -> b.duration(70) .output(Items.WHITE_DYE, 2) .output(.1f, Items.LIGHT_GRAY_DYE, 1)), @@ -90,6 +94,10 @@ public class MillingRecipeGen extends ProcessingRecipeGen { .output(Items.SUGAR, 2) .output(.1f, Items.SUGAR)), + BEETROOT = create(() -> Items.BEETROOT, b -> b.duration(70) + .output(Items.RED_DYE, 2) + .output(.1f, Items.BEETROOT_SEEDS)), + INK_SAC = create(() -> Items.INK_SAC, b -> b.duration(100) .output(Items.BLACK_DYE, 2) .output(.1f, Items.GRAY_DYE)), diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java index 87ac41546..6e26a2e26 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java @@ -17,22 +17,34 @@ public class MixingRecipeGen extends ProcessingRecipeGen { GeneratedRecipe - TEMP_LAVA = create("lava_from_cobble", b -> b.require(Tags.Items.COBBLESTONE) - .output(Fluids.LAVA, 50) - .requiresHeat(HeatCondition.SUPERHEATED)), + TEMP_LAVA = create("lava_from_cobble", b -> b.require(Tags.Items.COBBLESTONE) + .output(Fluids.LAVA, 50) + .requiresHeat(HeatCondition.SUPERHEATED)), TEA = create("tea", b -> b.require(Fluids.WATER, 250) - .require(AllTags.forgeFluidTag("milk"), 250) + .require(Tags.Fluids.MILK, 250) .require(ItemTags.LEAVES) .output(AllFluids.TEA.get(), 500) .requiresHeat(HeatCondition.HEATED)), - CHOCOLATE = create("chocolate", b -> b.require(AllTags.forgeFluidTag("milk"), 250) + CHOCOLATE = create("chocolate", b -> b.require(Tags.Fluids.MILK, 250) .require(Items.SUGAR) .require(Items.COCOA_BEANS) .output(AllFluids.CHOCOLATE.get(), 250) .requiresHeat(HeatCondition.HEATED)), + CHOCOLATE_MELTING = create("chocolate_melting", b -> b.require(AllItems.BAR_OF_CHOCOLATE.get()) + .output(AllFluids.CHOCOLATE.get(), 250) + .requiresHeat(HeatCondition.HEATED)), + + HONEY = create("honey", b -> b.require(Items.HONEY_BLOCK) + .output(AllFluids.HONEY.get(), 1000) + .requiresHeat(HeatCondition.HEATED)), + + DOUGH = create("dough_by_mixing", b -> b.require(AllItems.WHEAT_FLOUR.get()) + .require(Fluids.WATER, 1000) + .output(AllItems.DOUGH.get(), 1)), + BRASS_INGOT = create("brass_ingot", b -> b.require(I.copper()) .require(I.zinc()) .output(AllItems.BRASS_INGOT.get(), 2) 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..847efae00 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 @@ -3,7 +3,6 @@ package com.simibubi.create.foundation.data.recipe; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; -import net.minecraft.block.Blocks; import net.minecraft.data.DataGenerator; import net.minecraft.item.Items; import net.minecraft.item.crafting.Ingredient; @@ -14,7 +13,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.of(Items.GRASS_BLOCK, Items.DIRT)) .output(Items.GRASS_PATH)), IRON = create("iron_ingot", b -> b.require(I.iron()) @@ -23,8 +22,6 @@ public class PressingRecipeGen extends ProcessingRecipeGen { .output(AllItems.GOLDEN_SHEET.get())), COPPER = create("copper_ingot", b -> b.require(I.copper()) .output(AllItems.COPPER_SHEET.get())), - LAPIS = create("lapis_block", b -> b.require(Blocks.LAPIS_BLOCK) - .output(AllItems.LAPIS_SHEET.get())), BRASS = create("brass_ingot", b -> b.require(I.brass()) .output(AllItems.BRASS_SHEET.get())) diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java index 920d5ef13..d9b9f2026 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java @@ -6,50 +6,51 @@ import java.util.List; import java.util.function.Supplier; import java.util.function.UnaryOperator; -import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeSerializer; +import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import net.minecraft.data.DataGenerator; import net.minecraft.data.DirectoryCache; import net.minecraft.data.IDataProvider; import net.minecraft.item.crafting.Ingredient; import net.minecraft.util.IItemProvider; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.FluidAttributes; public abstract class ProcessingRecipeGen extends CreateRecipeProvider { - protected static List generators = new ArrayList<>(); + protected static final List GENERATORS = new ArrayList<>(); protected static final int BUCKET = FluidAttributes.BUCKET_VOLUME; protected static final int BOTTLE = 250; public static void registerAll(DataGenerator gen) { - generators.add(new CrushingRecipeGen(gen)); - generators.add(new MillingRecipeGen(gen)); - generators.add(new CuttingRecipeGen(gen)); - generators.add(new WashingRecipeGen(gen)); - generators.add(new PolishingRecipeGen(gen)); - generators.add(new DeployingRecipeGen(gen)); - generators.add(new MixingRecipeGen(gen)); - generators.add(new CompactingRecipeGen(gen)); - generators.add(new PressingRecipeGen(gen)); - generators.add(new FillingRecipeGen(gen)); - generators.add(new EmptyingRecipeGen(gen)); - + GENERATORS.add(new CrushingRecipeGen(gen)); + GENERATORS.add(new MillingRecipeGen(gen)); + GENERATORS.add(new CuttingRecipeGen(gen)); + GENERATORS.add(new WashingRecipeGen(gen)); + GENERATORS.add(new PolishingRecipeGen(gen)); + GENERATORS.add(new DeployingRecipeGen(gen)); + GENERATORS.add(new MixingRecipeGen(gen)); + GENERATORS.add(new CompactingRecipeGen(gen)); + GENERATORS.add(new PressingRecipeGen(gen)); + GENERATORS.add(new FillingRecipeGen(gen)); + GENERATORS.add(new EmptyingRecipeGen(gen)); + gen.addProvider(new IDataProvider() { - + @Override public String getName() { return "Create's Processing Recipes"; } - + @Override - public void act(DirectoryCache dc) throws IOException { - generators.forEach(g -> { + public void run(DirectoryCache dc) throws IOException { + GENERATORS.forEach(g -> { try { - g.act(dc); + g.run(dc); } catch (IOException e) { e.printStackTrace(); } @@ -57,55 +58,71 @@ public abstract class ProcessingRecipeGen extends CreateRecipeProvider { } }); } - - public ProcessingRecipeGen(DataGenerator p_i48262_1_) { - super(p_i48262_1_); + + public ProcessingRecipeGen(DataGenerator generator) { + super(generator); } - + /** * Create a processing recipe with a single itemstack ingredient, using its id * as the name of the recipe */ - protected > GeneratedRecipe create(Supplier singleIngredient, + protected > GeneratedRecipe create(String namespace, Supplier singleIngredient, UnaryOperator> transform) { ProcessingRecipeSerializer serializer = getSerializer(); GeneratedRecipe generatedRecipe = c -> { IItemProvider iItemProvider = singleIngredient.get(); transform - .apply(new ProcessingRecipeBuilder<>(serializer.getFactory(), Create.asResource(iItemProvider.asItem() + .apply(new ProcessingRecipeBuilder<>(serializer.getFactory(), new ResourceLocation(namespace, iItemProvider.asItem() .getRegistryName() - .getPath())).withItemIngredients(Ingredient.fromItems(iItemProvider))) + .getPath())).withItemIngredients(Ingredient.of(iItemProvider))) .build(c); }; all.add(generatedRecipe); return generatedRecipe; } + /** + * Create a processing recipe with a single itemstack ingredient, using its id + * as the name of the recipe + */ + > GeneratedRecipe create(Supplier singleIngredient, + UnaryOperator> transform) { + return create(Create.ID, singleIngredient, transform); + } + + /** + * Create a new processing recipe, with recipe definitions provided by the + * function + */ + protected > GeneratedRecipe create(ResourceLocation name, + UnaryOperator> transform) { + ProcessingRecipeSerializer serializer = getSerializer(); + GeneratedRecipe generatedRecipe = + c -> transform.apply(new ProcessingRecipeBuilder<>(serializer.getFactory(), name)) + .build(c); + all.add(generatedRecipe); + return generatedRecipe; + } + /** * Create a new processing recipe, with recipe definitions provided by the * function */ - protected > GeneratedRecipe create(String name, - UnaryOperator> transform) { - ProcessingRecipeSerializer serializer = getSerializer(); - GeneratedRecipe generatedRecipe = - c -> transform.apply(new ProcessingRecipeBuilder<>(serializer.getFactory(), Create.asResource(name))) - .build(c); - all.add(generatedRecipe); - return generatedRecipe; + > GeneratedRecipe create(String name, + UnaryOperator> transform) { + return create(Create.asResource(name), transform); } - @SuppressWarnings("unchecked") - private > ProcessingRecipeSerializer getSerializer() { - ProcessingRecipeSerializer serializer = (ProcessingRecipeSerializer) getRecipeType().serializer; - return serializer; + protected abstract IRecipeTypeInfo getRecipeType(); + + protected > ProcessingRecipeSerializer getSerializer() { + return getRecipeType().getSerializer(); } @Override - public final String getName() { - return "Create's Processing Recipes: " + getRecipeType(); + public String getName() { + return "Create's Processing Recipes: " + getRecipeType().getId().getPath(); } - - protected abstract AllRecipeTypes getRecipeType(); } diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/SequencedAssemblyRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/SequencedAssemblyRecipeGen.java new file mode 100644 index 000000000..42b653da0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/SequencedAssemblyRecipeGen.java @@ -0,0 +1,98 @@ +package com.simibubi.create.foundation.data.recipe; + +import java.util.function.UnaryOperator; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; +import com.simibubi.create.content.contraptions.components.saw.CuttingRecipe; +import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipeBuilder; + +import net.minecraft.block.Blocks; +import net.minecraft.data.DataGenerator; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.tags.ItemTags; + +public class SequencedAssemblyRecipeGen extends CreateRecipeProvider { + + GeneratedRecipe + +// TEST = create("test", b -> b.require(I.goldSheet()) +// .transitionTo(AllItems.INCOMPLETE_CLOCKWORK_COMPONENT.get()) +// .addOutput(AllItems.CLOCKWORK_COMPONENT.get(), 10) +// .addOutput(AllItems.GOLDEN_SHEET.get(), 5) +// .addOutput(AllItems.ANDESITE_ALLOY.get(), 2) +// .addOutput(AllBlocks.COGWHEEL.get(), 1) +// .loops(5) +// .addStep(DeployerApplicationRecipe::new, rb -> rb.require(I.cog())) +// .addStep(PressingRecipe::new, rb -> rb) +// .addStep(FillingRecipe::new, rb -> rb.require(Fluids.LAVA, 500)) +// .addStep(CuttingRecipe::new, rb -> rb.averageProcessingDuration()) +// .addStep(FillingRecipe::new, rb -> rb.require(Fluids.WATER, 100)) +// ) + + PRECISION_MECHANISM = create("precision_mechanism", b -> b.require(I.goldSheet()) + .transitionTo(AllItems.INCOMPLETE_PRECISION_MECHANISM.get()) + .addOutput(AllItems.PRECISION_MECHANISM.get(), 120) + .addOutput(AllItems.GOLDEN_SHEET.get(), 8) + .addOutput(AllItems.ANDESITE_ALLOY.get(), 8) + .addOutput(AllBlocks.COGWHEEL.get(), 5) + .addOutput(AllBlocks.SHAFT.get(), 2) + .addOutput(AllItems.CRUSHED_GOLD.get(), 2) + .addOutput(Items.GOLD_NUGGET, 2) + .addOutput(Items.IRON_INGOT, 1) + .addOutput(Items.CLOCK, 1) + .loops(5) + .addStep(DeployerApplicationRecipe::new, rb -> rb.require(I.cog())) + .addStep(DeployerApplicationRecipe::new, rb -> rb.require(I.largeCog())) + .addStep(DeployerApplicationRecipe::new, rb -> rb.require(I.ironNugget())) + ), + + COGWHEEL = create("cogwheel", b -> b.require(I.andesite()) + .transitionTo(AllItems.INCOMPLETE_COGWHEEL.get()) + .addOutput(new ItemStack(AllBlocks.COGWHEEL.get(), 12), 32) + .addOutput(AllItems.ANDESITE_ALLOY.get(), 2) + .addOutput(Blocks.ANDESITE, 1) + .addOutput(AllBlocks.LARGE_COGWHEEL.get(), 1) + .addOutput(Items.STICK, 1) + .addOutput(Items.IRON_NUGGET, 1) + .loops(4) + .addStep(DeployerApplicationRecipe::new, rb -> rb.require(ItemTags.WOODEN_BUTTONS)) + .addStep(CuttingRecipe::new, rb -> rb.duration(50)) + ), + + LARGE_COGWHEEL = create("large_cogwheel", b -> b.require(I.andesite()) + .transitionTo(AllItems.INCOMPLETE_LARGE_COGWHEEL.get()) + .addOutput(new ItemStack(AllBlocks.LARGE_COGWHEEL.get(), 6), 32) + .addOutput(AllItems.ANDESITE_ALLOY.get(), 2) + .addOutput(Blocks.ANDESITE, 1) + .addOutput(AllBlocks.COGWHEEL.get(), 1) + .addOutput(Items.STICK, 1) + .addOutput(Items.IRON_NUGGET, 1) + .loops(3) + .addStep(DeployerApplicationRecipe::new, rb -> rb.require(I.planks())) + .addStep(DeployerApplicationRecipe::new, rb -> rb.require(ItemTags.WOODEN_BUTTONS)) + .addStep(CuttingRecipe::new, rb -> rb.duration(50)) + ) + ; + + public SequencedAssemblyRecipeGen(DataGenerator p_i48262_1_) { + super(p_i48262_1_); + } + + protected GeneratedRecipe create(String name, UnaryOperator transform) { + GeneratedRecipe generatedRecipe = + c -> transform.apply(new SequencedAssemblyRecipeBuilder(Create.asResource(name))) + .build(c); + all.add(generatedRecipe); + return generatedRecipe; + } + + @Override + public String getName() { + return "Create's Sequenced Assembly Recipes"; + } + +} 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..6a7c376f6 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 @@ -36,6 +36,7 @@ import net.minecraft.data.DataGenerator; import net.minecraft.data.IFinishedRecipe; import net.minecraft.data.ShapedRecipeBuilder; import net.minecraft.data.ShapelessRecipeBuilder; +import net.minecraft.item.DyeColor; import net.minecraft.item.Item; import net.minecraft.item.Items; import net.minecraft.item.crafting.CookingRecipeSerializer; @@ -56,7 +57,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { /* * Recipes are added through fields, so one can navigate to the right one easily - * + * * (Ctrl-o) in Eclipse */ @@ -77,694 +78,708 @@ public class StandardRecipeGen extends CreateRecipeProvider { ImmutableList.of(I::zincNugget, I::zinc, I::zincBlock)), ANDESITE_ALLOY = create(AllItems.ANDESITE_ALLOY).unlockedByTag(I::iron) - .viaShaped(b -> b.key('A', Blocks.ANDESITE) - .key('B', Tags.Items.NUGGETS_IRON) - .patternLine("BA") - .patternLine("AB")), + .viaShaped(b -> b.define('A', Blocks.ANDESITE) + .define('B', Tags.Items.NUGGETS_IRON) + .pattern("BA") + .pattern("AB")), ANDESITE_ALLOY_FROM_ZINC = create(AllItems.ANDESITE_ALLOY).withSuffix("_from_zinc") .unlockedByTag(I::zinc) - .viaShaped(b -> b.key('A', Blocks.ANDESITE) - .key('B', I.zincNugget()) - .patternLine("BA") - .patternLine("AB")), + .viaShaped(b -> b.define('A', Blocks.ANDESITE) + .define('B', I.zincNugget()) + .pattern("BA") + .pattern("AB")), ANDESITE_CASING = create(AllBlocks.ANDESITE_CASING).returns(4) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', ItemTags.PLANKS) - .key('C', I.andesite()) - .key('S', ItemTags.LOGS) - .patternLine("AAA") - .patternLine("CSC") - .patternLine("AAA")), + .viaShaped(b -> b.define('A', ItemTags.PLANKS) + .define('C', I.andesite()) + .define('S', ItemTags.LOGS) + .pattern("AAA") + .pattern("CSC") + .pattern("AAA")), BRASS_CASING = create(AllBlocks.BRASS_CASING).returns(4) .unlockedByTag(I::brass) - .viaShaped(b -> b.key('A', ItemTags.PLANKS) - .key('C', I.brassSheet()) - .key('S', ItemTags.LOGS) - .patternLine("AAA") - .patternLine("CSC") - .patternLine("AAA")), + .viaShaped(b -> b.define('A', ItemTags.PLANKS) + .define('C', I.brassSheet()) + .define('S', ItemTags.LOGS) + .pattern("AAA") + .pattern("CSC") + .pattern("AAA")), COPPER_CASING = create(AllBlocks.COPPER_CASING).returns(4) .unlockedByTag(I::copper) - .viaShaped(b -> b.key('A', ItemTags.PLANKS) - .key('C', I.copperSheet()) - .key('S', ItemTags.LOGS) - .patternLine("AAA") - .patternLine("CSC") - .patternLine("AAA")), + .viaShaped(b -> b.define('A', ItemTags.PLANKS) + .define('C', I.copperSheet()) + .define('S', ItemTags.LOGS) + .pattern("AAA") + .pattern("CSC") + .pattern("AAA")), RADIANT_CASING = create(AllBlocks.REFINED_RADIANCE_CASING).returns(4) .unlockedBy(I::refinedRadiance) - .viaShaped(b -> b.key('A', ItemTags.PLANKS) - .key('C', I.refinedRadiance()) - .key('S', Tags.Items.GLASS_COLORLESS) - .patternLine("AAA") - .patternLine("CSC") - .patternLine("AAA")), + .viaShaped(b -> b.define('A', ItemTags.PLANKS) + .define('C', I.refinedRadiance()) + .define('S', Tags.Items.GLASS_COLORLESS) + .pattern("AAA") + .pattern("CSC") + .pattern("AAA")), SHADOW_CASING = create(AllBlocks.SHADOW_STEEL_CASING).returns(4) .unlockedBy(I::shadowSteel) - .viaShaped(b -> b.key('A', ItemTags.PLANKS) - .key('C', I.shadowSteel()) - .key('S', Tags.Items.OBSIDIAN) - .patternLine("AAA") - .patternLine("CSC") - .patternLine("AAA")), + .viaShaped(b -> b.define('A', ItemTags.PLANKS) + .define('C', I.shadowSteel()) + .define('S', Tags.Items.OBSIDIAN) + .pattern("AAA") + .pattern("CSC") + .pattern("AAA")), ELECTRON_TUBE = create(AllItems.ELECTRON_TUBE).unlockedBy(AllItems.ROSE_QUARTZ::get) - .viaShaped(b -> b.key('L', AllItems.POLISHED_ROSE_QUARTZ.get()) - .key('R', Items.REDSTONE_TORCH) - .key('N', Tags.Items.NUGGETS_IRON) - .patternLine("L") - .patternLine("R") - .patternLine("N")), + .viaShaped(b -> b.define('L', AllItems.POLISHED_ROSE_QUARTZ.get()) + .define('R', Items.REDSTONE_TORCH) + .define('N', Tags.Items.NUGGETS_IRON) + .pattern("L") + .pattern("R") + .pattern("N")), ROSE_QUARTZ = create(AllItems.ROSE_QUARTZ).unlockedBy(() -> Items.REDSTONE) - .viaShapeless(b -> b.addIngredient(Tags.Items.GEMS_QUARTZ) - .addIngredient(Ingredient.fromTag(I.redstone()), 8)), + .viaShapeless(b -> b.requires(Tags.Items.GEMS_QUARTZ) + .requires(Ingredient.of(I.redstone()), 8)), SAND_PAPER = create(AllItems.SAND_PAPER).unlockedBy(() -> Items.PAPER) - .viaShapeless(b -> b.addIngredient(Items.PAPER) - .addIngredient(Tags.Items.SAND_COLORLESS)), + .viaShapeless(b -> b.requires(Items.PAPER) + .requires(Tags.Items.SAND_COLORLESS)), RED_SAND_PAPER = create(AllItems.RED_SAND_PAPER).unlockedBy(() -> Items.PAPER) - .viaShapeless(b -> b.addIngredient(Items.PAPER) - .addIngredient(Tags.Items.SAND_RED)) + .viaShapeless(b -> b.requires(Items.PAPER) + .requires(Tags.Items.SAND_RED)) ; private Marker CURIOSITIES = enterSection(AllSections.CURIOSITIES); GeneratedRecipe WAND_OF_SYMMETRY = create(AllItems.WAND_OF_SYMMETRY).unlockedBy(I::refinedRadiance) - .viaShaped(b -> b.key('E', I.refinedRadiance()) - .key('G', Tags.Items.GLASS_PANES_WHITE) - .key('O', Tags.Items.OBSIDIAN) - .key('L', I.brass()) - .patternLine(" GE") - .patternLine("LEG") - .patternLine("OL ")), + .viaShaped(b -> b.define('E', I.refinedRadiance()) + .define('G', Tags.Items.GLASS_PANES_WHITE) + .define('O', Tags.Items.OBSIDIAN) + .define('L', I.brass()) + .pattern(" GE") + .pattern("LEG") + .pattern("OL ")), + + TOOLBOX = create(AllBlocks.TOOLBOXES.get(DyeColor.BROWN)).unlockedByTag(I::goldSheet) + .viaShaped(b -> b.define('S', I.goldSheet()) + .define('C', I.cog()) + .define('W', Tags.Items.CHESTS_WOODEN) + .define('L', Tags.Items.LEATHER) + .pattern(" C ") + .pattern("SWS") + .pattern(" L ")), MINECART_COUPLING = create(AllItems.MINECART_COUPLING).unlockedBy(I::andesite) - .viaShaped(b -> b.key('E', I.andesite()) - .key('O', I.ironSheet()) - .patternLine(" E") - .patternLine(" O ") - .patternLine("E ")) + .viaShaped(b -> b.define('E', I.andesite()) + .define('O', I.ironSheet()) + .pattern(" E") + .pattern(" O ") + .pattern("E ")), + + PECULIAR_BELL = create(AllBlocks.PECULIAR_BELL).unlockedByTag(I::brass) + .viaShaped(b -> b.define('I', I.brassBlock()) + .define('P', I.brassSheet()) + .pattern("I") + .pattern("P")) ; private Marker KINETICS = enterSection(AllSections.KINETICS); GeneratedRecipe BASIN = create(AllBlocks.BASIN).unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', I.andesite()) - .patternLine("A A") - .patternLine("AAA")), + .viaShaped(b -> b.define('A', I.andesite()) + .pattern("A A") + .pattern("AAA")), GOGGLES = create(AllItems.GOGGLES).unlockedBy(I::andesite) - .viaShaped(b -> b.key('G', Tags.Items.GLASS) - .key('P', I.goldSheet()) - .key('S', Tags.Items.STRING) - .patternLine(" S ") - .patternLine("GPG")), + .viaShaped(b -> b.define('G', Tags.Items.GLASS) + .define('P', I.goldSheet()) + .define('S', Tags.Items.STRING) + .pattern(" S ") + .pattern("GPG")), WRENCH = create(AllItems.WRENCH).unlockedBy(I::andesite) - .viaShaped(b -> b.key('G', I.goldSheet()) - .key('P', I.cog()) - .key('S', Tags.Items.RODS_WOODEN) - .patternLine("GG") - .patternLine("GP") - .patternLine(" S")), + .viaShaped(b -> b.define('G', I.goldSheet()) + .define('P', I.cog()) + .define('S', Tags.Items.RODS_WOODEN) + .pattern("GG") + .pattern("GP") + .pattern(" S")), FILTER = create(AllItems.FILTER).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', ItemTags.WOOL) - .key('A', Tags.Items.NUGGETS_IRON) - .patternLine("ASA")), + .viaShaped(b -> b.define('S', ItemTags.WOOL) + .define('A', Tags.Items.NUGGETS_IRON) + .pattern("ASA")), ATTRIBUTE_FILTER = create(AllItems.ATTRIBUTE_FILTER).unlockedByTag(I::brass) - .viaShaped(b -> b.key('S', ItemTags.WOOL) - .key('A', I.brassNugget()) - .patternLine("ASA")), + .viaShaped(b -> b.define('S', ItemTags.WOOL) + .define('A', I.brassNugget()) + .pattern("ASA")), BRASS_HAND = create(AllItems.BRASS_HAND).unlockedByTag(I::brass) - .viaShaped(b -> b.key('A', I.andesite()) - .key('B', I.brassSheet()) - .patternLine(" A ") - .patternLine("BBB") - .patternLine(" B ")), + .viaShaped(b -> b.define('A', I.andesite()) + .define('B', I.brassSheet()) + .pattern(" A ") + .pattern("BBB") + .pattern(" B ")), SUPER_GLUE = create(AllItems.SUPER_GLUE).unlockedByTag(I::ironSheet) - .viaShaped(b -> b.key('A', Tags.Items.SLIMEBALLS) - .key('S', I.ironSheet()) - .key('N', Tags.Items.NUGGETS_IRON) - .patternLine("AS") - .patternLine("NA")), + .viaShaped(b -> b.define('A', Tags.Items.SLIMEBALLS) + .define('S', I.ironSheet()) + .define('N', Tags.Items.NUGGETS_IRON) + .pattern("AS") + .pattern("NA")), CRAFTER_SLOT_COVER = create(AllItems.CRAFTER_SLOT_COVER).unlockedBy(AllBlocks.MECHANICAL_CRAFTER::get) - .viaShaped(b -> b.key('A', I.brassNugget()) - .patternLine("AAA")), + .viaShaped(b -> b.define('A', I.brassNugget()) + .pattern("AAA")), COGWHEEL = create(AllBlocks.COGWHEEL).returns(8) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', ItemTags.WOODEN_BUTTONS) - .key('C', I.andesite()) - .patternLine("SSS") - .patternLine("SCS") - .patternLine("SSS")), + .viaShaped(b -> b.define('S', ItemTags.WOODEN_BUTTONS) + .define('C', I.andesite()) + .pattern("SSS") + .pattern("SCS") + .pattern("SSS")), LARGE_COGWHEEL = create(AllBlocks.LARGE_COGWHEEL).returns(2) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', ItemTags.WOODEN_BUTTONS) - .key('C', I.andesite()) - .key('D', ItemTags.PLANKS) - .patternLine("SDS") - .patternLine("DCD") - .patternLine("SDS")), + .viaShaped(b -> b.define('S', ItemTags.WOODEN_BUTTONS) + .define('C', I.andesite()) + .define('D', ItemTags.PLANKS) + .pattern("SDS") + .pattern("DCD") + .pattern("SDS")), WATER_WHEEL = create(AllBlocks.WATER_WHEEL).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', ItemTags.WOODEN_SLABS) - .key('C', AllBlocks.LARGE_COGWHEEL.get()) - .patternLine("SSS") - .patternLine("SCS") - .patternLine("SSS")), + .viaShaped(b -> b.define('S', ItemTags.WOODEN_SLABS) + .define('C', AllBlocks.LARGE_COGWHEEL.get()) + .pattern("SSS") + .pattern("SCS") + .pattern("SSS")), SHAFT = create(AllBlocks.SHAFT).returns(8) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', I.andesite()) - .patternLine("A") - .patternLine("A")), + .viaShaped(b -> b.define('A', I.andesite()) + .pattern("A") + .pattern("A")), MECHANICAL_PRESS = create(AllBlocks.MECHANICAL_PRESS).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('B', I.andesite()) - .key('S', I.cog()) - .key('C', I.andesiteCasing()) - .key('I', AllTags.forgeItemTag("storage_blocks/iron")) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")), + .viaShaped(b -> b.define('B', I.andesite()) + .define('S', I.cog()) + .define('C', I.andesiteCasing()) + .define('I', AllTags.forgeItemTag("storage_blocks/iron")) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")), MILLSTONE = create(AllBlocks.MILLSTONE).unlockedBy(I::andesite) - .viaShaped(b -> b.key('B', ItemTags.PLANKS) - .key('S', I.andesite()) - .key('C', I.cog()) - .key('I', I.stone()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")), + .viaShaped(b -> b.define('B', ItemTags.PLANKS) + .define('S', I.andesite()) + .define('C', I.cog()) + .define('I', I.stone()) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")), MECHANICAL_PISTON = create(AllBlocks.MECHANICAL_PISTON).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('B', ItemTags.PLANKS) - .key('S', I.cog()) - .key('C', I.andesiteCasing()) - .key('I', AllBlocks.PISTON_EXTENSION_POLE.get()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")), + .viaShaped(b -> b.define('B', ItemTags.PLANKS) + .define('S', I.cog()) + .define('C', I.andesiteCasing()) + .define('I', AllBlocks.PISTON_EXTENSION_POLE.get()) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")), STICKY_MECHANICAL_PISTON = create(AllBlocks.STICKY_MECHANICAL_PISTON).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', Tags.Items.SLIMEBALLS) - .key('P', AllBlocks.MECHANICAL_PISTON.get()) - .patternLine("S") - .patternLine("P")), + .viaShaped(b -> b.define('S', Tags.Items.SLIMEBALLS) + .define('P', AllBlocks.MECHANICAL_PISTON.get()) + .pattern("S") + .pattern("P")), TURNTABLE = create(AllBlocks.TURNTABLE).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', I.shaft()) - .key('P', ItemTags.WOODEN_SLABS) - .patternLine("P") - .patternLine("S")), + .viaShaped(b -> b.define('S', I.shaft()) + .define('P', ItemTags.WOODEN_SLABS) + .pattern("P") + .pattern("S")), PISTON_EXTENSION_POLE = create(AllBlocks.PISTON_EXTENSION_POLE).returns(8) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', I.andesite()) - .key('P', ItemTags.PLANKS) - .patternLine("P") - .patternLine("A") - .patternLine("P")), + .viaShaped(b -> b.define('A', I.andesite()) + .define('P', ItemTags.PLANKS) + .pattern("P") + .pattern("A") + .pattern("P")), GANTRY_PINION = create(AllBlocks.GANTRY_CARRIAGE).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('B', ItemTags.PLANKS) - .key('S', I.cog()) - .key('C', I.andesiteCasing()) - .key('I', I.shaft()) - .patternLine(" B ") - .patternLine("ICI") - .patternLine(" S ")), + .viaShaped(b -> b.define('B', ItemTags.PLANKS) + .define('S', I.cog()) + .define('C', I.andesiteCasing()) + .define('I', I.shaft()) + .pattern(" B ") + .pattern("ICI") + .pattern(" S ")), GANTRY_SHAFT = create(AllBlocks.GANTRY_SHAFT).returns(8) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', I.andesite()) - .key('R', I.redstone()) - .patternLine("A") - .patternLine("R") - .patternLine("A")), + .viaShaped(b -> b.define('A', I.andesite()) + .define('R', I.redstone()) + .pattern("A") + .pattern("R") + .pattern("A")), ANALOG_LEVER = create(AllBlocks.ANALOG_LEVER).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', I.andesiteCasing()) - .key('P', Tags.Items.RODS_WOODEN) - .patternLine("P") - .patternLine("S")), + .viaShaped(b -> b.define('S', I.andesiteCasing()) + .define('P', Tags.Items.RODS_WOODEN) + .pattern("P") + .pattern("S")), BELT_CONNECTOR = create(AllItems.BELT_CONNECTOR).unlockedBy(I::andesite) - .viaShaped(b -> b.key('D', Items.DRIED_KELP) - .patternLine("DDD") - .patternLine("DDD")), + .viaShaped(b -> b.define('D', Items.DRIED_KELP) + .pattern("DDD") + .pattern("DDD")), ADJUSTABLE_PULLEY = create(AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT).unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('A', I.electronTube()) - .key('B', AllBlocks.ENCASED_CHAIN_DRIVE.get()) - .key('C', AllBlocks.LARGE_COGWHEEL.get()) - .patternLine("A") - .patternLine("B") - .patternLine("C")), + .viaShaped(b -> b.define('A', I.electronTube()) + .define('B', AllBlocks.ENCASED_CHAIN_DRIVE.get()) + .define('C', AllBlocks.LARGE_COGWHEEL.get()) + .pattern("A") + .pattern("B") + .pattern("C")), CART_ASSEMBLER = create(AllBlocks.CART_ASSEMBLER).unlockedBy(I::andesite) - .viaShaped(b -> b.key('L', ItemTags.LOGS) - .key('R', I.redstone()) - .key('C', I.andesite()) - .patternLine(" L ") - .patternLine("CRC") - .patternLine("L L")), + .viaShaped(b -> b.define('L', ItemTags.LOGS) + .define('R', I.redstone()) + .define('C', I.andesite()) + .pattern(" L ") + .pattern("CRC") + .pattern("L L")), CONTROLLER_RAIL = create(AllBlocks.CONTROLLER_RAIL).returns(6) .unlockedBy(() -> Items.POWERED_RAIL) - .viaShaped(b -> b.key('A', I.gold()) - .key('E', I.electronTube()) - .key('S', Tags.Items.RODS_WOODEN) - .patternLine("A A") - .patternLine("ASA") - .patternLine("AEA")), + .viaShaped(b -> b.define('A', I.gold()) + .define('E', I.electronTube()) + .define('S', Tags.Items.RODS_WOODEN) + .pattern("A A") + .pattern("ASA") + .pattern("AEA")), HAND_CRANK = create(AllBlocks.HAND_CRANK).unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', I.andesite()) - .key('C', ItemTags.PLANKS) - .key('S', I.shaft()) - .patternLine(" S ") - .patternLine("CCC") - .patternLine(" A")), + .viaShaped(b -> b.define('A', I.andesite()) + .define('C', ItemTags.PLANKS) + .define('S', I.shaft()) + .pattern(" S ") + .pattern("CCC") + .pattern(" A")), COPPER_VALVE_HANDLE = create(AllBlocks.COPPER_VALVE_HANDLE).unlockedByTag(I::copper) - .viaShaped(b -> b.key('S', I.andesite()) - .key('C', I.copperSheet()) - .patternLine("CCC") - .patternLine(" S ")), + .viaShaped(b -> b.define('S', I.andesite()) + .define('C', I.copperSheet()) + .pattern("CCC") + .pattern(" S ")), COPPER_VALVE_HANDLE_FROM_OTHER_HANDLES = create(AllBlocks.COPPER_VALVE_HANDLE).withSuffix("_from_others") .unlockedByTag(I::copper) - .viaShapeless(b -> b.addIngredient(AllItemTags.VALVE_HANDLES.tag)), + .viaShapeless(b -> b.requires(AllItemTags.VALVE_HANDLES.tag)), NOZZLE = create(AllBlocks.NOZZLE).unlockedBy(AllBlocks.ENCASED_FAN::get) - .viaShaped(b -> b.key('S', I.andesite()) - .key('C', ItemTags.WOOL) - .patternLine(" S ") - .patternLine(" C ") - .patternLine("SSS")), + .viaShaped(b -> b.define('S', I.andesite()) + .define('C', ItemTags.WOOL) + .pattern(" S ") + .pattern(" C ") + .pattern("SSS")), PROPELLER = create(AllItems.PROPELLER).unlockedByTag(I::ironSheet) - .viaShaped(b -> b.key('S', I.ironSheet()) - .key('C', I.andesite()) - .patternLine(" S ") - .patternLine("SCS") - .patternLine(" S ")), + .viaShaped(b -> b.define('S', I.ironSheet()) + .define('C', I.andesite()) + .pattern(" S ") + .pattern("SCS") + .pattern(" S ")), WHISK = create(AllItems.WHISK).unlockedByTag(I::ironSheet) - .viaShaped(b -> b.key('S', I.ironSheet()) - .key('C', I.andesite()) - .patternLine(" C ") - .patternLine("SCS") - .patternLine("SSS")), + .viaShaped(b -> b.define('S', I.ironSheet()) + .define('C', I.andesite()) + .pattern(" C ") + .pattern("SCS") + .pattern("SSS")), ENCASED_FAN = create(AllBlocks.ENCASED_FAN).unlockedByTag(I::ironSheet) - .viaShaped(b -> b.key('S', I.shaft()) - .key('A', I.andesiteCasing()) - .key('R', I.cog()) - .key('P', AllItems.PROPELLER.get()) - .patternLine(" S ") - .patternLine("RAR") - .patternLine(" P ")), + .viaShaped(b -> b.define('S', I.shaft()) + .define('A', I.andesiteCasing()) + .define('R', I.cog()) + .define('P', AllItems.PROPELLER.get()) + .pattern(" S ") + .pattern("RAR") + .pattern(" P ")), CUCKOO_CLOCK = create(AllBlocks.CUCKOO_CLOCK).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', ItemTags.PLANKS) - .key('A', Items.CLOCK) - .key('B', ItemTags.LOGS) - .key('P', I.cog()) - .patternLine(" S ") - .patternLine("SAS") - .patternLine("BPB")), + .viaShaped(b -> b.define('S', ItemTags.PLANKS) + .define('A', Items.CLOCK) + .define('B', ItemTags.LOGS) + .define('P', I.cog()) + .pattern(" S ") + .pattern("SAS") + .pattern("BPB")), MECHANICAL_CRAFTER = create(AllBlocks.MECHANICAL_CRAFTER).returns(3) .unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('B', I.electronTube()) - .key('R', Blocks.CRAFTING_TABLE) - .key('C', I.brassCasing()) - .key('S', I.cog()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" R ")), + .viaShaped(b -> b.define('B', I.electronTube()) + .define('R', Blocks.CRAFTING_TABLE) + .define('C', I.brassCasing()) + .define('S', I.cog()) + .pattern(" B ") + .pattern("SCS") + .pattern(" R ")), WINDMILL_BEARING = create(AllBlocks.WINDMILL_BEARING).unlockedBy(I::andesite) - .viaShaped(b -> b.key('I', I.shaft()) - .key('B', AllBlocks.TURNTABLE.get()) - .key('C', I.stone()) - .patternLine(" B ") - .patternLine(" C ") - .patternLine(" I ")), + .viaShaped(b -> b.define('I', I.shaft()) + .define('B', AllBlocks.TURNTABLE.get()) + .define('C', I.stone()) + .pattern(" B ") + .pattern(" C ") + .pattern(" I ")), MECHANICAL_BEARING = create(AllBlocks.MECHANICAL_BEARING).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('I', I.shaft()) - .key('S', I.andesite()) - .key('B', AllBlocks.TURNTABLE.get()) - .key('C', I.andesiteCasing()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")), + .viaShaped(b -> b.define('I', I.shaft()) + .define('S', I.andesite()) + .define('B', AllBlocks.TURNTABLE.get()) + .define('C', I.andesiteCasing()) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")), CLOCKWORK_BEARING = create(AllBlocks.CLOCKWORK_BEARING).unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('I', I.shaft()) - .key('S', I.electronTube()) - .key('B', AllBlocks.TURNTABLE.get()) - .key('C', I.brassCasing()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")), + .viaShaped(b -> b.define('I', I.shaft()) + .define('S', I.electronTube()) + .define('B', AllBlocks.TURNTABLE.get()) + .define('C', I.brassCasing()) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")), WOODEN_BRACKET = create(AllBlocks.WOODEN_BRACKET).returns(4) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', Tags.Items.RODS_WOODEN) - .key('P', I.planks()) - .key('C', I.andesite()) - .patternLine("SSS") - .patternLine("PCP")), + .viaShaped(b -> b.define('S', Tags.Items.RODS_WOODEN) + .define('P', I.planks()) + .define('C', I.andesite()) + .pattern("SSS") + .pattern("PCP")), METAL_BRACKET = create(AllBlocks.METAL_BRACKET).returns(4) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', Tags.Items.NUGGETS_IRON) - .key('P', I.iron()) - .key('C', I.andesite()) - .patternLine("SSS") - .patternLine("PCP")), + .viaShaped(b -> b.define('S', Tags.Items.NUGGETS_IRON) + .define('P', I.iron()) + .define('C', I.andesite()) + .pattern("SSS") + .pattern("PCP")), FLUID_PIPE = create(AllBlocks.FLUID_PIPE).returns(8) .unlockedByTag(I::copper) - .viaShaped(b -> b.key('S', I.copperSheet()) - .key('C', I.copper()) - .patternLine("SCS")), + .viaShaped(b -> b.define('S', I.copperSheet()) + .define('C', I.copper()) + .pattern("SCS")), MECHANICAL_PUMP = create(AllBlocks.MECHANICAL_PUMP).unlockedByTag(I::copper) - .viaShaped(b -> b.key('P', I.cog()) - .key('S', AllBlocks.FLUID_PIPE.get()) - .patternLine("P") - .patternLine("S")), + .viaShaped(b -> b.define('P', I.cog()) + .define('S', AllBlocks.FLUID_PIPE.get()) + .pattern("P") + .pattern("S")), SMART_FLUID_PIPE = create(AllBlocks.SMART_FLUID_PIPE).unlockedByTag(I::copper) - .viaShaped(b -> b.key('P', I.electronTube()) - .key('S', AllBlocks.FLUID_PIPE.get()) - .key('I', I.brassSheet()) - .patternLine("I") - .patternLine("S") - .patternLine("P")), + .viaShaped(b -> b.define('P', I.electronTube()) + .define('S', AllBlocks.FLUID_PIPE.get()) + .define('I', I.brassSheet()) + .pattern("I") + .pattern("S") + .pattern("P")), FLUID_VALVE = create(AllBlocks.FLUID_VALVE).unlockedByTag(I::copper) - .viaShaped(b -> b.key('P', I.shaft()) - .key('S', AllBlocks.FLUID_PIPE.get()) - .key('I', I.ironSheet()) - .patternLine("I") - .patternLine("S") - .patternLine("P")), + .viaShaped(b -> b.define('P', I.shaft()) + .define('S', AllBlocks.FLUID_PIPE.get()) + .define('I', I.ironSheet()) + .pattern("I") + .pattern("S") + .pattern("P")), SPOUT = create(AllBlocks.SPOUT).unlockedBy(I::copperCasing) - .viaShaped(b -> b.key('T', AllBlocks.FLUID_TANK.get()) - .key('P', Items.DRIED_KELP) - .key('S', I.copperNugget()) - .patternLine("T") - .patternLine("P") - .patternLine("S")), + .viaShaped(b -> b.define('T', AllBlocks.FLUID_TANK.get()) + .define('P', Items.DRIED_KELP) + .define('S', I.copperNugget()) + .pattern("T") + .pattern("P") + .pattern("S")), ITEM_DRAIN = create(AllBlocks.ITEM_DRAIN).unlockedBy(I::copperCasing) - .viaShaped(b -> b.key('P', Blocks.IRON_BARS) - .key('S', I.copperCasing()) - .patternLine("P") - .patternLine("S")), + .viaShaped(b -> b.define('P', Blocks.IRON_BARS) + .define('S', I.copperCasing()) + .pattern("P") + .pattern("S")), FLUID_TANK = create(AllBlocks.FLUID_TANK).returns(2) .unlockedBy(I::copperCasing) - .viaShaped(b -> b.key('B', I.copperCasing()) - .key('S', I.copperNugget()) - .key('C', Tags.Items.GLASS) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" B ")), + .viaShaped(b -> b.define('B', I.copperCasing()) + .define('S', I.copperNugget()) + .define('C', Tags.Items.GLASS) + .pattern(" B ") + .pattern("SCS") + .pattern(" B ")), DEPLOYER = create(AllBlocks.DEPLOYER).unlockedBy(I::electronTube) - .viaShaped(b -> b.key('I', AllItems.BRASS_HAND.get()) - .key('B', I.electronTube()) - .key('S', I.cog()) - .key('C', I.andesiteCasing()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")), + .viaShaped(b -> b.define('I', AllItems.BRASS_HAND.get()) + .define('B', I.electronTube()) + .define('S', I.cog()) + .define('C', I.andesiteCasing()) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")), PORTABLE_STORAGE_INTERFACE = create(AllBlocks.PORTABLE_STORAGE_INTERFACE).unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('I', I.brassCasing()) - .key('B', AllBlocks.ANDESITE_FUNNEL.get()) - .patternLine(" B ") - .patternLine(" I ")), + .viaShaped(b -> b.define('I', I.brassCasing()) + .define('B', AllBlocks.ANDESITE_FUNNEL.get()) + .pattern(" B ") + .pattern(" I ")), PORTABLE_FLUID_INTERFACE = create(AllBlocks.PORTABLE_FLUID_INTERFACE).unlockedBy(I::copperCasing) - .viaShaped(b -> b.key('I', I.copperCasing()) - .key('B', AllBlocks.ANDESITE_FUNNEL.get()) - .patternLine(" B ") - .patternLine(" I ")), + .viaShaped(b -> b.define('I', I.copperCasing()) + .define('B', AllBlocks.ANDESITE_FUNNEL.get()) + .pattern(" B ") + .pattern(" I ")), ROPE_PULLEY = create(AllBlocks.ROPE_PULLEY).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', I.shaft()) - .key('B', I.andesiteCasing()) - .key('C', ItemTags.WOOL) - .key('I', I.ironSheet()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")), + .viaShaped(b -> b.define('S', I.shaft()) + .define('B', I.andesiteCasing()) + .define('C', ItemTags.WOOL) + .define('I', I.ironSheet()) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")), HOSE_PULLEY = create(AllBlocks.HOSE_PULLEY).unlockedByTag(I::copper) - .viaShaped(b -> b.key('S', I.shaft()) - .key('P', AllBlocks.FLUID_PIPE.get()) - .key('B', I.copperCasing()) - .key('C', Items.DRIED_KELP) - .key('I', I.copperSheet()) - .patternLine(" B ") - .patternLine("SCP") - .patternLine(" I ")), + .viaShaped(b -> b.define('S', I.shaft()) + .define('P', AllBlocks.FLUID_PIPE.get()) + .define('B', I.copperCasing()) + .define('C', Items.DRIED_KELP) + .define('I', I.copperSheet()) + .pattern(" B ") + .pattern("SCP") + .pattern(" I ")), EMPTY_BLAZE_BURNER = create(AllItems.EMPTY_BLAZE_BURNER).unlockedByTag(I::iron) - .viaShaped(b -> b.key('A', Blocks.IRON_BARS) - .key('I', I.ironSheet()) - .patternLine("II") - .patternLine("AA")), + .viaShaped(b -> b.define('A', Blocks.IRON_BARS) + .define('I', I.ironSheet()) + .pattern("II") + .pattern("AA")), CHUTE = create(AllBlocks.CHUTE).unlockedBy(I::andesite) .returns(4) - .viaShaped(b -> b.key('A', I.ironSheet()) - .key('I', I.andesite()) - .patternLine("II") - .patternLine("AA")), + .viaShaped(b -> b.define('A', I.ironSheet()) + .define('I', I.andesite()) + .pattern("II") + .pattern("AA")), SMART_CHUTE = create(AllBlocks.SMART_CHUTE).unlockedBy(AllBlocks.CHUTE::get) - .viaShaped(b -> b.key('P', I.electronTube()) - .key('S', AllBlocks.CHUTE.get()) - .key('I', I.brassSheet()) - .patternLine("I") - .patternLine("S") - .patternLine("P")), + .viaShaped(b -> b.define('P', I.electronTube()) + .define('S', AllBlocks.CHUTE.get()) + .define('I', I.brassSheet()) + .pattern("I") + .pattern("S") + .pattern("P")), DEPOT = create(AllBlocks.DEPOT).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('A', I.andesite()) - .key('I', I.andesiteCasing()) - .patternLine("A") - .patternLine("I")), + .viaShaped(b -> b.define('A', I.andesite()) + .define('I', I.andesiteCasing()) + .pattern("A") + .pattern("I")), WEIGHTED_EJECTOR = create(AllBlocks.WEIGHTED_EJECTOR).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('A', I.goldSheet()) - .key('D', AllBlocks.DEPOT.get()) - .key('I', I.cog()) - .patternLine("A") - .patternLine("D") - .patternLine("I")), + .viaShaped(b -> b.define('A', I.goldSheet()) + .define('D', AllBlocks.DEPOT.get()) + .define('I', I.cog()) + .pattern("A") + .pattern("D") + .pattern("I")), MECHANICAL_ARM = create(AllBlocks.MECHANICAL_ARM::get).unlockedBy(I::brassCasing) .returns(1) - .viaShaped(b -> b.key('L', I.brassSheet()) - .key('R', I.cog()) - .key('I', I.electronTube()) - .key('A', I.andesite()) - .key('C', I.brassCasing()) - .patternLine("LLA") - .patternLine("LR ") - .patternLine("ICI")), + .viaShaped(b -> b.define('L', I.brassSheet()) + .define('I', I.precisionMechanism()) + .define('A', I.andesite()) + .define('C', I.brassCasing()) + .pattern("LLA") + .pattern("L ") + .pattern("IC ")), MECHANICAL_MIXER = create(AllBlocks.MECHANICAL_MIXER).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', I.cog()) - .key('B', I.andesite()) - .key('C', I.andesiteCasing()) - .key('I', AllItems.WHISK.get()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")), + .viaShaped(b -> b.define('S', I.cog()) + .define('B', I.andesite()) + .define('C', I.andesiteCasing()) + .define('I', AllItems.WHISK.get()) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")), CLUTCH = create(AllBlocks.CLUTCH).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', I.shaft()) - .key('B', I.redstone()) - .key('C', I.andesiteCasing()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" B ")), + .viaShaped(b -> b.define('S', I.shaft()) + .define('B', I.redstone()) + .define('C', I.andesiteCasing()) + .pattern(" B ") + .pattern("SCS") + .pattern(" B ")), GEARSHIFT = create(AllBlocks.GEARSHIFT).unlockedBy(I::andesite) - .viaShaped(b -> b.key('S', I.cog()) - .key('B', I.redstone()) - .key('C', I.andesiteCasing()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" B ")), + .viaShaped(b -> b.define('S', I.cog()) + .define('B', I.redstone()) + .define('C', I.andesiteCasing()) + .pattern(" B ") + .pattern("SCS") + .pattern(" B ")), SAIL_FRAME = create(AllBlocks.SAIL_FRAME).returns(8) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', I.andesite()) - .key('S', Tags.Items.RODS_WOODEN) - .patternLine("SSS") - .patternLine("SAS") - .patternLine("SSS")), + .viaShaped(b -> b.define('A', I.andesite()) + .define('S', Tags.Items.RODS_WOODEN) + .pattern("SSS") + .pattern("SAS") + .pattern("SSS")), SAIL = create(AllBlocks.SAIL).returns(8) .unlockedBy(AllBlocks.SAIL_FRAME::get) - .viaShaped(b -> b.key('F', AllBlocks.SAIL_FRAME.get()) - .key('W', ItemTags.WOOL) - .patternLine("FFF") - .patternLine("FWF") - .patternLine("FFF")), + .viaShaped(b -> b.define('F', AllBlocks.SAIL_FRAME.get()) + .define('W', ItemTags.WOOL) + .pattern("FFF") + .pattern("FWF") + .pattern("FFF")), RADIAL_CHASIS = create(AllBlocks.RADIAL_CHASSIS).returns(3) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('P', I.andesite()) - .key('L', ItemTags.LOGS) - .patternLine(" L ") - .patternLine("PLP") - .patternLine(" L ")), + .viaShaped(b -> b.define('P', I.andesite()) + .define('L', ItemTags.LOGS) + .pattern(" L ") + .pattern("PLP") + .pattern(" L ")), LINEAR_CHASIS = create(AllBlocks.LINEAR_CHASSIS).returns(3) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('P', I.andesite()) - .key('L', ItemTags.LOGS) - .patternLine(" P ") - .patternLine("LLL") - .patternLine(" P ")), + .viaShaped(b -> b.define('P', I.andesite()) + .define('L', ItemTags.LOGS) + .pattern(" P ") + .pattern("LLL") + .pattern(" P ")), LINEAR_CHASSIS_CYCLE = conversionCycle(ImmutableList.of(AllBlocks.LINEAR_CHASSIS, AllBlocks.SECONDARY_LINEAR_CHASSIS)), STICKER = create(AllBlocks.STICKER).returns(1) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('I', I.andesite()) - .key('C', Tags.Items.COBBLESTONE) - .key('R', I.redstone()) - .key('S', Tags.Items.SLIMEBALLS) - .patternLine("ISI") - .patternLine("CRC")), + .viaShaped(b -> b.define('I', I.andesite()) + .define('C', Tags.Items.COBBLESTONE) + .define('R', I.redstone()) + .define('S', Tags.Items.SLIMEBALLS) + .pattern("ISI") + .pattern("CRC")), MINECART = create(() -> Items.MINECART).withSuffix("_from_contraption_cart") .unlockedBy(AllBlocks.CART_ASSEMBLER::get) - .viaShapeless(b -> b.addIngredient(AllItems.MINECART_CONTRAPTION.get())), + .viaShapeless(b -> b.requires(AllItems.MINECART_CONTRAPTION.get())), FURNACE_MINECART = create(() -> Items.FURNACE_MINECART).withSuffix("_from_contraption_cart") .unlockedBy(AllBlocks.CART_ASSEMBLER::get) - .viaShapeless(b -> b.addIngredient(AllItems.FURNACE_MINECART_CONTRAPTION.get())), + .viaShapeless(b -> b.requires(AllItems.FURNACE_MINECART_CONTRAPTION.get())), GEARBOX = create(AllBlocks.GEARBOX).unlockedBy(I::cog) - .viaShaped(b -> b.key('C', I.cog()) - .key('B', I.andesiteCasing()) - .patternLine(" C ") - .patternLine("CBC") - .patternLine(" C ")), + .viaShaped(b -> b.define('C', I.cog()) + .define('B', I.andesiteCasing()) + .pattern(" C ") + .pattern("CBC") + .pattern(" C ")), GEARBOX_CYCLE = conversionCycle(ImmutableList.of(AllBlocks.GEARBOX, AllItems.VERTICAL_GEARBOX)), MYSTERIOUS_CUCKOO_CLOCK = create(AllBlocks.MYSTERIOUS_CUCKOO_CLOCK).unlockedBy(AllBlocks.CUCKOO_CLOCK::get) - .viaShaped(b -> b.key('C', Tags.Items.GUNPOWDER) - .key('B', AllBlocks.CUCKOO_CLOCK.get()) - .patternLine(" C ") - .patternLine("CBC") - .patternLine(" C ")), + .viaShaped(b -> b.define('C', Tags.Items.GUNPOWDER) + .define('B', AllBlocks.CUCKOO_CLOCK.get()) + .pattern(" C ") + .pattern("CBC") + .pattern(" C ")), ENCASED_CHAIN_DRIVE = create(AllBlocks.ENCASED_CHAIN_DRIVE).returns(2) .unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('S', I.shaft()) - .key('B', Tags.Items.NUGGETS_IRON) - .key('C', I.andesiteCasing()) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" B ")), + .viaShaped(b -> b.define('S', I.shaft()) + .define('B', Tags.Items.NUGGETS_IRON) + .define('C', I.andesiteCasing()) + .pattern(" B ") + .pattern("SCS") + .pattern(" B ")), SPEEDOMETER = create(AllBlocks.SPEEDOMETER).unlockedBy(I::andesite) - .viaShaped(b -> b.key('C', Items.COMPASS) - .key('A', I.andesiteCasing()) - .key('S', I.shaft()) - .patternLine(" C ") - .patternLine("SAS")), + .viaShaped(b -> b.define('C', Items.COMPASS) + .define('A', I.andesiteCasing()) + .define('S', I.shaft()) + .pattern(" C ") + .pattern("SAS")), GAUGE_CYCLE = conversionCycle(ImmutableList.of(AllBlocks.SPEEDOMETER, AllBlocks.STRESSOMETER)), ROTATION_SPEED_CONTROLLER = create(AllBlocks.ROTATION_SPEED_CONTROLLER).unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('B', I.circuit()) - .key('C', I.brassCasing()) - .key('S', I.shaft()) - .patternLine(" B ") - .patternLine("SCS")), + .viaShaped(b -> b.define('B', I.precisionMechanism()) + .define('C', I.brassCasing()) + .define('S', I.shaft()) + .pattern(" B ") + .pattern("SCS")), - NIXIE_TUBE = create(AllBlocks.NIXIE_TUBE).unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('E', I.electronTube()) - .key('B', I.brassCasing()) - .patternLine("EBE")), + NIXIE_TUBE = create(AllBlocks.ORANGE_NIXIE_TUBE).unlockedBy(I::brassCasing) + .viaShaped(b -> b.define('E', I.electronTube()) + .define('B', I.brassCasing()) + .pattern("EBE")), MECHANICAL_SAW = create(AllBlocks.MECHANICAL_SAW).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('C', I.andesiteCasing()) - .key('A', I.ironSheet()) - .key('I', I.iron()) - .patternLine(" A ") - .patternLine("AIA") - .patternLine(" C ")), + .viaShaped(b -> b.define('C', I.andesiteCasing()) + .define('A', I.ironSheet()) + .define('I', I.iron()) + .pattern(" A ") + .pattern("AIA") + .pattern(" C ")), MECHANICAL_HARVESTER = create(AllBlocks.MECHANICAL_HARVESTER).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('C', I.andesiteCasing()) - .key('A', I.andesite()) - .key('I', I.ironSheet()) - .patternLine("AIA") - .patternLine("AIA") - .patternLine(" C ")), + .viaShaped(b -> b.define('C', I.andesiteCasing()) + .define('A', I.andesite()) + .define('I', I.ironSheet()) + .pattern("AIA") + .pattern("AIA") + .pattern(" C ")), MECHANICAL_PLOUGH = create(AllBlocks.MECHANICAL_PLOUGH).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('C', I.andesiteCasing()) - .key('A', I.andesite()) - .key('I', I.ironSheet()) - .patternLine("III") - .patternLine("AAA") - .patternLine(" C ")), + .viaShaped(b -> b.define('C', I.andesiteCasing()) + .define('A', I.andesite()) + .define('I', I.ironSheet()) + .pattern("III") + .pattern("AAA") + .pattern(" C ")), MECHANICAL_DRILL = create(AllBlocks.MECHANICAL_DRILL).unlockedBy(I::andesiteCasing) - .viaShaped(b -> b.key('C', I.andesiteCasing()) - .key('A', I.andesite()) - .key('I', I.iron()) - .patternLine(" A ") - .patternLine("AIA") - .patternLine(" C ")), + .viaShaped(b -> b.define('C', I.andesiteCasing()) + .define('A', I.andesite()) + .define('I', I.iron()) + .pattern(" A ") + .pattern("AIA") + .pattern(" C ")), SEQUENCED_GEARSHIFT = create(AllBlocks.SEQUENCED_GEARSHIFT).unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('B', I.electronTube()) - .key('S', I.cog()) - .key('C', I.brassCasing()) - .key('I', Items.CLOCK) - .patternLine(" B ") - .patternLine("SCS") - .patternLine(" I ")) + .viaShaped(b -> b.define('B', I.electronTube()) + .define('S', I.cog()) + .define('C', I.brassCasing()) + .define('I', Items.CLOCK) + .pattern(" B ") + .pattern("SCS") + .pattern(" I ")) ; @@ -774,111 +789,111 @@ public class StandardRecipeGen extends CreateRecipeProvider { REDSTONE_CONTACT = create(AllBlocks.REDSTONE_CONTACT).returns(2) .unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('W', I.redstone()) - .key('C', Blocks.COBBLESTONE) - .key('S', I.ironSheet()) - .patternLine(" S ") - .patternLine("CWC") - .patternLine("CCC")), + .viaShaped(b -> b.define('W', I.redstone()) + .define('C', Blocks.COBBLESTONE) + .define('S', I.ironSheet()) + .pattern(" S ") + .pattern("CWC") + .pattern("CCC")), ANDESITE_FUNNEL = create(AllBlocks.ANDESITE_FUNNEL).returns(2) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', I.andesite()) - .key('K', Items.DRIED_KELP) - .patternLine("AKA") - .patternLine(" K ")), + .viaShaped(b -> b.define('A', I.andesite()) + .define('K', Items.DRIED_KELP) + .pattern("AKA") + .pattern(" K ")), BRASS_FUNNEL = create(AllBlocks.BRASS_FUNNEL).returns(2) .unlockedByTag(I::brass) - .viaShaped(b -> b.key('A', I.brass()) - .key('K', Items.DRIED_KELP) - .key('E', I.electronTube()) - .patternLine("AEA") - .patternLine(" K ")), + .viaShaped(b -> b.define('A', I.brass()) + .define('K', Items.DRIED_KELP) + .define('E', I.electronTube()) + .pattern("AEA") + .pattern(" K ")), ANDESITE_TUNNEL = create(AllBlocks.ANDESITE_TUNNEL).returns(2) .unlockedBy(I::andesite) - .viaShaped(b -> b.key('A', I.andesite()) - .key('K', Items.DRIED_KELP) - .patternLine("AA") - .patternLine("KK")), + .viaShaped(b -> b.define('A', I.andesite()) + .define('K', Items.DRIED_KELP) + .pattern("AA") + .pattern("KK")), BRASS_TUNNEL = create(AllBlocks.BRASS_TUNNEL).returns(2) .unlockedByTag(I::brass) - .viaShaped(b -> b.key('A', I.brass()) - .key('K', Items.DRIED_KELP) - .key('E', I.electronTube()) - .patternLine("E ") - .patternLine("AA") - .patternLine("KK")), + .viaShaped(b -> b.define('A', I.brass()) + .define('K', Items.DRIED_KELP) + .define('E', I.electronTube()) + .pattern("E ") + .pattern("AA") + .pattern("KK")), ADJUSTABLE_CRATE = create(AllBlocks.ADJUSTABLE_CRATE).returns(4) .unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('B', I.brassCasing()) - .patternLine("BBB") - .patternLine("B B") - .patternLine("BBB")), + .viaShaped(b -> b.define('B', I.brassCasing()) + .pattern("BBB") + .pattern("B B") + .pattern("BBB")), BELT_OBSERVER = create(AllBlocks.CONTENT_OBSERVER).unlockedBy(AllItems.BELT_CONNECTOR::get) - .viaShaped(b -> b.key('B', I.brassCasing()) - .key('R', I.redstone()) - .key('I', I.iron()) - .key('C', Blocks.OBSERVER) - .patternLine("RCI") - .patternLine(" B ")), + .viaShaped(b -> b.define('B', I.brassCasing()) + .define('R', I.redstone()) + .define('I', I.iron()) + .define('C', Blocks.OBSERVER) + .pattern("RCI") + .pattern(" B ")), STOCKPILE_SWITCH = create(AllBlocks.STOCKPILE_SWITCH).unlockedBy(I::brassCasing) - .viaShaped(b -> b.key('B', I.brassCasing()) - .key('R', I.redstone()) - .key('I', I.iron()) - .key('C', Blocks.COMPARATOR) - .patternLine("RCI") - .patternLine(" B ")), + .viaShaped(b -> b.define('B', I.brassCasing()) + .define('R', I.redstone()) + .define('I', I.iron()) + .define('C', Blocks.COMPARATOR) + .pattern("RCI") + .pattern(" B ")), ADJUSTABLE_REPEATER = create(AllBlocks.ADJUSTABLE_REPEATER).unlockedByTag(I::redstone) - .viaShaped(b -> b.key('T', Blocks.REDSTONE_TORCH) - .key('C', Items.CLOCK) - .key('R', I.redstone()) - .key('S', I.stone()) - .patternLine("RCT") - .patternLine("SSS")), + .viaShaped(b -> b.define('T', Blocks.REDSTONE_TORCH) + .define('C', Items.CLOCK) + .define('R', I.redstone()) + .define('S', I.stone()) + .pattern("RCT") + .pattern("SSS")), ADJUSTABLE_PULSE_REPEATER = create(AllBlocks.ADJUSTABLE_PULSE_REPEATER).unlockedByTag(I::redstone) - .viaShaped(b -> b.key('S', AllBlocks.PULSE_REPEATER.get()) - .key('P', AllBlocks.ADJUSTABLE_REPEATER.get()) - .patternLine("SP")), + .viaShaped(b -> b.define('S', AllBlocks.PULSE_REPEATER.get()) + .define('P', AllBlocks.ADJUSTABLE_REPEATER.get()) + .pattern("SP")), PULSE_REPEATER = create(AllBlocks.PULSE_REPEATER).unlockedByTag(I::redstone) - .viaShaped(b -> b.key('T', Blocks.REDSTONE_TORCH) - .key('R', I.redstone()) - .key('S', I.stone()) - .patternLine("RRT") - .patternLine("SSS")), + .viaShaped(b -> b.define('T', Blocks.REDSTONE_TORCH) + .define('R', I.redstone()) + .define('S', I.stone()) + .pattern("RRT") + .pattern("SSS")), POWERED_TOGGLE_LATCH = create(AllBlocks.POWERED_TOGGLE_LATCH).unlockedByTag(I::redstone) - .viaShaped(b -> b.key('T', Blocks.REDSTONE_TORCH) - .key('C', Blocks.LEVER) - .key('S', I.stone()) - .patternLine(" T ") - .patternLine(" C ") - .patternLine("SSS")), + .viaShaped(b -> b.define('T', Blocks.REDSTONE_TORCH) + .define('C', Blocks.LEVER) + .define('S', I.stone()) + .pattern(" T ") + .pattern(" C ") + .pattern("SSS")), POWERED_LATCH = create(AllBlocks.POWERED_LATCH).unlockedByTag(I::redstone) - .viaShaped(b -> b.key('T', Blocks.REDSTONE_TORCH) - .key('C', Blocks.LEVER) - .key('R', I.redstone()) - .key('S', I.stone()) - .patternLine(" T ") - .patternLine("RCR") - .patternLine("SSS")), + .viaShaped(b -> b.define('T', Blocks.REDSTONE_TORCH) + .define('C', Blocks.LEVER) + .define('R', I.redstone()) + .define('S', I.stone()) + .pattern(" T ") + .pattern("RCR") + .pattern("SSS")), REDSTONE_LINK = create(AllBlocks.REDSTONE_LINK).returns(2) .unlockedByTag(I::brass) - .viaShaped(b -> b.key('C', Blocks.REDSTONE_TORCH) - .key('S', I.brassSheet()) - .key('I', ItemTags.PLANKS) - .patternLine(" C") - .patternLine("SIS")) + .viaShaped(b -> b.define('C', Blocks.REDSTONE_TORCH) + .define('S', I.brassSheet()) + .define('I', ItemTags.PLANKS) + .pattern(" C") + .pattern("SIS")) ; @@ -887,29 +902,29 @@ public class StandardRecipeGen extends CreateRecipeProvider { GeneratedRecipe SCHEMATIC_TABLE = create(AllBlocks.SCHEMATIC_TABLE).unlockedBy(AllItems.EMPTY_SCHEMATIC::get) - .viaShaped(b -> b.key('W', ItemTags.WOODEN_SLABS) - .key('S', Blocks.SMOOTH_STONE) - .patternLine("WWW") - .patternLine(" S ") - .patternLine(" S ")), + .viaShaped(b -> b.define('W', ItemTags.WOODEN_SLABS) + .define('S', Blocks.SMOOTH_STONE) + .pattern("WWW") + .pattern(" S ") + .pattern(" S ")), SCHEMATICANNON = create(AllBlocks.SCHEMATICANNON).unlockedBy(AllItems.EMPTY_SCHEMATIC::get) - .viaShaped(b -> b.key('L', ItemTags.LOGS) - .key('D', Blocks.DISPENSER) - .key('C', Blocks.CAULDRON) - .key('S', Blocks.SMOOTH_STONE) - .key('I', Blocks.IRON_BLOCK) - .patternLine(" C ") - .patternLine("LDL") - .patternLine("SIS")), + .viaShaped(b -> b.define('L', ItemTags.LOGS) + .define('D', Blocks.DISPENSER) + .define('C', Blocks.CAULDRON) + .define('S', Blocks.SMOOTH_STONE) + .define('I', Blocks.IRON_BLOCK) + .pattern(" C ") + .pattern("LDL") + .pattern("SIS")), EMPTY_SCHEMATIC = create(AllItems.EMPTY_SCHEMATIC).unlockedBy(() -> Items.PAPER) - .viaShapeless(b -> b.addIngredient(Items.PAPER) - .addIngredient(Tags.Items.DYES_LIGHT_BLUE)), + .viaShapeless(b -> b.requires(Items.PAPER) + .requires(Tags.Items.DYES_LIGHT_BLUE)), SCHEMATIC_AND_QUILL = create(AllItems.SCHEMATIC_AND_QUILL).unlockedBy(() -> Items.PAPER) - .viaShapeless(b -> b.addIngredient(AllItems.EMPTY_SCHEMATIC.get()) - .addIngredient(Tags.Items.FEATHERS)) + .viaShapeless(b -> b.requires(AllItems.EMPTY_SCHEMATIC.get()) + .requires(Tags.Items.FEATHERS)) ; @@ -919,24 +934,24 @@ public class StandardRecipeGen extends CreateRecipeProvider { DARK_SCORIA = create(AllPaletteBlocks.DARK_SCORIA).returns(8) .unlockedBy(() -> AllPaletteBlocks.SCORIA.get()) - .viaShaped(b -> b.key('#', AllPaletteBlocks.SCORIA.get()) - .key('D', Tags.Items.DYES_BLACK) - .patternLine("###") - .patternLine("#D#") - .patternLine("###")), + .viaShaped(b -> b.define('#', AllPaletteBlocks.SCORIA.get()) + .define('D', Tags.Items.DYES_BLACK) + .pattern("###") + .pattern("#D#") + .pattern("###")), COPPER_SHINGLES = create(AllBlocks.COPPER_SHINGLES).returns(16) .unlockedByTag(I::copperSheet) - .viaShaped(b -> b.key('#', I.copperSheet()) - .patternLine("##") - .patternLine("##")), + .viaShaped(b -> b.define('#', I.copperSheet()) + .pattern("##") + .pattern("##")), COPPER_SHINGLES_FROM_TILES = create(AllBlocks.COPPER_SHINGLES).withSuffix("_from_tiles") .unlockedByTag(I::copperSheet) - .viaShapeless(b -> b.addIngredient(AllBlocks.COPPER_TILES.get())), + .viaShapeless(b -> b.requires(AllBlocks.COPPER_TILES.get())), COPPER_TILES = create(AllBlocks.COPPER_TILES).unlockedByTag(I::copperSheet) - .viaShapeless(b -> b.addIngredient(AllBlocks.COPPER_SHINGLES.get())) + .viaShapeless(b -> b.requires(AllBlocks.COPPER_SHINGLES.get())) ; @@ -945,40 +960,52 @@ public class StandardRecipeGen extends CreateRecipeProvider { GeneratedRecipe DOUGH = create(AllItems.DOUGH).unlockedBy(AllItems.WHEAT_FLOUR::get) - .viaShapeless(b -> b.addIngredient(AllItems.WHEAT_FLOUR.get()) - .addIngredient(Items.WATER_BUCKET)), + .viaShapeless(b -> b.requires(AllItems.WHEAT_FLOUR.get()) + .requires(Items.WATER_BUCKET)), DIVING_HELMET = create(AllItems.DIVING_HELMET).unlockedByTag(I::copper) - .viaShaped(b -> b.key('G', Tags.Items.GLASS) - .key('P', I.copper()) - .patternLine("PPP") - .patternLine("PGP")), + .viaShaped(b -> b.define('G', Tags.Items.GLASS) + .define('P', I.copper()) + .pattern("PPP") + .pattern("PGP")), COPPER_BACKTANK = create(AllItems.COPPER_BACKTANK).unlockedByTag(I::copper) - .viaShaped(b -> b.key('G', I.shaft()) - .key('A', I.andesite()) - .key('P', I.copper()) - .patternLine("AGA") - .patternLine("PPP") - .patternLine(" P ")), + .viaShaped(b -> b.define('G', I.shaft()) + .define('A', I.andesite()) + .define('B', I.copperBlock()) + .define('P', I.copper()) + .pattern("AGA") + .pattern("PBP") + .pattern(" P ")), DIVING_BOOTS = create(AllItems.DIVING_BOOTS).unlockedByTag(I::copper) - .viaShaped(b -> b.key('G', I.andesite()) - .key('P', I.copper()) - .patternLine("P P") - .patternLine("P P") - .patternLine("G G")), + .viaShaped(b -> b.define('G', I.andesite()) + .define('P', I.copper()) + .pattern("P P") + .pattern("P P") + .pattern("G G")), + + LINKED_CONTROLLER = create(AllItems.LINKED_CONTROLLER).unlockedBy(AllBlocks.REDSTONE_LINK::get) + .viaShaped(b -> b.define('S', ItemTags.WOODEN_BUTTONS) + .define('P', AllBlocks.REDSTONE_LINK.get()) + .pattern("SSS") + .pattern(" P ") + .pattern("SSS")), + + CRAFTING_BLUEPRINT = create(AllItems.CRAFTING_BLUEPRINT).unlockedBy(() -> Items.CRAFTING_TABLE) + .viaShapeless(b -> b.requires(Items.PAINTING) + .requires(Items.CRAFTING_TABLE)), SLIME_BALL = create(() -> Items.SLIME_BALL).unlockedBy(AllItems.DOUGH::get) - .viaShapeless(b -> b.addIngredient(AllItems.DOUGH.get()) - .addIngredient(Tags.Items.DYES_LIME)), + .viaShapeless(b -> b.requires(AllItems.DOUGH.get()) + .requires(Tags.Items.DYES_LIME)), TREE_FERTILIZER = create(AllItems.TREE_FERTILIZER).returns(2) .unlockedBy(() -> Items.BONE_MEAL) - .viaShapeless(b -> b.addIngredient(Ingredient.fromTag(ItemTags.SMALL_FLOWERS), 2) - .addIngredient(Ingredient.fromItems(Items.HORN_CORAL, Items.BRAIN_CORAL, Items.TUBE_CORAL, - Items.BUBBLE_CORAL, Items.FIRE_CORAL)) - .addIngredient(Items.BONE_MEAL)) + .viaShapeless(b -> b.requires(Ingredient.of(ItemTags.SMALL_FLOWERS), 2) + .requires(Ingredient.of(Items.HORN_CORAL, Items.BRAIN_CORAL, Items.TUBE_CORAL, Items.BUBBLE_CORAL, + Items.FIRE_CORAL)) + .requires(Items.BONE_MEAL)) ; @@ -1113,15 +1140,15 @@ public class StandardRecipeGen extends CreateRecipeProvider { result = create(nextEntry).withSuffix("_from_compacting") .unlockedBy(currentEntry::get) - .viaShaped(b -> b.patternLine("###") - .patternLine("###") - .patternLine("###") - .key('#', currentIngredient.get())); + .viaShaped(b -> b.pattern("###") + .pattern("###") + .pattern("###") + .define('#', currentIngredient.get())); result = create(currentEntry).returns(9) .withSuffix("_from_decompacting") .unlockedBy(nextEntry::get) - .viaShapeless(b -> b.addIngredient(nextIngredient.get())); + .viaShapeless(b -> b.requires(nextIngredient.get())); } return result; } @@ -1133,7 +1160,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { ItemProviderEntry nextEntry = cycle.get((i + 1) % cycle.size()); result = create(nextEntry).withSuffix("from_conversion") .unlockedBy(currentEntry::get) - .viaShapeless(b -> b.addIngredient(currentEntry.get())); + .viaShapeless(b -> b.requires(currentEntry.get())); } return result; } @@ -1172,15 +1199,15 @@ public class StandardRecipeGen extends CreateRecipeProvider { } GeneratedRecipeBuilder unlockedBy(Supplier item) { - this.unlockedBy = () -> ItemPredicate.Builder.create() - .item(item.get()) + this.unlockedBy = () -> ItemPredicate.Builder.item() + .of(item.get()) .build(); return this; } GeneratedRecipeBuilder unlockedByTag(Supplier> tag) { - this.unlockedBy = () -> ItemPredicate.Builder.create() - .tag(tag.get()) + this.unlockedBy = () -> ItemPredicate.Builder.item() + .of(tag.get()) .build(); return this; } @@ -1205,19 +1232,19 @@ public class StandardRecipeGen extends CreateRecipeProvider { GeneratedRecipe viaShaped(UnaryOperator builder) { return register(consumer -> { - ShapedRecipeBuilder b = builder.apply(ShapedRecipeBuilder.shapedRecipe(result.get(), amount)); + ShapedRecipeBuilder b = builder.apply(ShapedRecipeBuilder.shaped(result.get(), amount)); if (unlockedBy != null) - b.addCriterion("has_item", hasItem(unlockedBy.get())); - b.build(consumer, createLocation("crafting")); + b.unlockedBy("has_item", inventoryTrigger(unlockedBy.get())); + b.save(consumer, createLocation("crafting")); }); } GeneratedRecipe viaShapeless(UnaryOperator builder) { return register(consumer -> { - ShapelessRecipeBuilder b = builder.apply(ShapelessRecipeBuilder.shapelessRecipe(result.get(), amount)); + ShapelessRecipeBuilder b = builder.apply(ShapelessRecipeBuilder.shapeless(result.get(), amount)); if (unlockedBy != null) - b.addCriterion("has_item", hasItem(unlockedBy.get())); - b.build(consumer, createLocation("crafting")); + b.unlockedBy("has_item", inventoryTrigger(unlockedBy.get())); + b.save(consumer, createLocation("crafting")); }); } @@ -1236,11 +1263,11 @@ public class StandardRecipeGen extends CreateRecipeProvider { } GeneratedCookingRecipeBuilder viaCooking(Supplier item) { - return unlockedBy(item).viaCookingIngredient(() -> Ingredient.fromItems(item.get())); + return unlockedBy(item).viaCookingIngredient(() -> Ingredient.of(item.get())); } GeneratedCookingRecipeBuilder viaCookingTag(Supplier> tag) { - return unlockedByTag(tag).viaCookingIngredient(() -> Ingredient.fromTag(tag.get())); + return unlockedByTag(tag).viaCookingIngredient(() -> Ingredient.of(tag.get())); } GeneratedCookingRecipeBuilder viaCookingIngredient(Supplier ingredient) { @@ -1253,9 +1280,9 @@ public class StandardRecipeGen extends CreateRecipeProvider { private float exp; private int cookingTime; - private final CookingRecipeSerializer FURNACE = IRecipeSerializer.SMELTING, - SMOKER = IRecipeSerializer.SMOKING, BLAST = IRecipeSerializer.BLASTING, - CAMPFIRE = IRecipeSerializer.CAMPFIRE_COOKING; + private final CookingRecipeSerializer FURNACE = IRecipeSerializer.SMELTING_RECIPE, + SMOKER = IRecipeSerializer.SMOKING_RECIPE, BLAST = IRecipeSerializer.BLASTING_RECIPE, + CAMPFIRE = IRecipeSerializer.CAMPFIRE_COOKING_RECIPE; GeneratedCookingRecipeBuilder(Supplier ingredient) { this.ingredient = ingredient; @@ -1305,12 +1332,12 @@ public class StandardRecipeGen extends CreateRecipeProvider { return register(consumer -> { boolean isOtherMod = compatDatagenOutput != null; - CookingRecipeBuilder b = builder.apply( - CookingRecipeBuilder.cookingRecipe(ingredient.get(), isOtherMod ? Items.DIRT : result.get(), + CookingRecipeBuilder b = builder + .apply(CookingRecipeBuilder.cooking(ingredient.get(), isOtherMod ? Items.DIRT : result.get(), exp, (int) (cookingTime * cookingTimeModifier), serializer)); if (unlockedBy != null) - b.addCriterion("has_item", hasItem(unlockedBy.get())); - b.build(result -> { + b.unlockedBy("has_item", inventoryTrigger(unlockedBy.get())); + b.save(result -> { consumer.accept( isOtherMod ? new ModdedCookingRecipeResult(result, compatDatagenOutput, recipeConditions) : result); @@ -1344,28 +1371,28 @@ public class StandardRecipeGen extends CreateRecipeProvider { } @Override - public ResourceLocation getID() { - return wrapped.getID(); + public ResourceLocation getId() { + return wrapped.getId(); } @Override - public IRecipeSerializer getSerializer() { - return wrapped.getSerializer(); + public IRecipeSerializer getType() { + return wrapped.getType(); } @Override - public JsonObject getAdvancementJson() { - return wrapped.getAdvancementJson(); + public JsonObject serializeAdvancement() { + return wrapped.serializeAdvancement(); } @Override - public ResourceLocation getAdvancementID() { - return wrapped.getAdvancementID(); + public ResourceLocation getAdvancementId() { + return wrapped.getAdvancementId(); } @Override - public void serialize(JsonObject object) { - wrapped.serialize(object); + public void serializeRecipeData(JsonObject object) { + wrapped.serializeRecipeData(object); object.addProperty("result", outputOverride.toString()); JsonArray conds = new JsonArray(); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java index 8f8bb2a0b..54acfecce 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java @@ -100,7 +100,7 @@ public class WashingRecipeGen extends ProcessingRecipeGen { ResourceLocation nugget = mod.nuggetOf(metalName); create(mod.getId() + "/" + crushed.getId() .getPath(), - b -> b.withItemIngredients(Ingredient.fromItems(crushed::get)) + b -> b.withItemIngredients(Ingredient.of(crushed::get)) .output(1, nugget, 10) .output(.5f, nugget, 5) .whenModLoaded(mod.getId())); diff --git a/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java b/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java index 96d61a412..744b45325 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java @@ -8,6 +8,7 @@ import com.google.gson.JsonSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling; +import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity; import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.utility.Pair; @@ -47,12 +48,14 @@ public class FluidHelper { } public static boolean hasBlockState(Fluid fluid) { - BlockState blockState = fluid.getDefaultState() - .getBlockState(); - return blockState != null && blockState != Blocks.AIR.getDefaultState(); + BlockState blockState = fluid.defaultFluidState() + .createLegacyBlock(); + return blockState != null && blockState != Blocks.AIR.defaultBlockState(); } public static FluidStack copyStackWithAmount(FluidStack fs, int amount) { + if (amount <= 0) + return FluidStack.EMPTY; if (fs.isEmpty()) return FluidStack.EMPTY; FluidStack copy = fs.copy(); @@ -66,7 +69,7 @@ public class FluidHelper { if (fluid == Fluids.LAVA) return Fluids.FLOWING_LAVA; if (fluid instanceof ForgeFlowingFluid) - return ((ForgeFlowingFluid) fluid).getFlowingFluid(); + return ((ForgeFlowingFluid) fluid).getFlowing(); return fluid; } @@ -76,7 +79,7 @@ public class FluidHelper { if (fluid == Fluids.FLOWING_LAVA) return Fluids.LAVA; if (fluid instanceof ForgeFlowingFluid) - return ((ForgeFlowingFluid) fluid).getStillFluid(); + return ((ForgeFlowingFluid) fluid).getSource(); return fluid; } @@ -93,11 +96,11 @@ public class FluidHelper { } public static FluidStack deserializeFluidStack(JsonObject json) { - ResourceLocation id = new ResourceLocation(JSONUtils.getString(json, "fluid")); + ResourceLocation id = new ResourceLocation(JSONUtils.getAsString(json, "fluid")); Fluid fluid = ForgeRegistries.FLUIDS.getValue(id); if (fluid == null) throw new JsonSyntaxException("Unknown fluid '" + id + "'"); - int amount = JSONUtils.getInt(json, "amount"); + int amount = JSONUtils.getAsInt(json, "amount"); FluidStack stack = new FluidStack(fluid, amount); if (!json.has("nbt")) @@ -105,8 +108,8 @@ public class FluidHelper { try { JsonElement element = json.get("nbt"); - stack.setTag(JsonToNBT.getTagFromJson( - element.isJsonObject() ? Create.GSON.toJson(element) : JSONUtils.getString(element, "nbt"))); + stack.setTag(JsonToNBT.parseTag( + element.isJsonObject() ? Create.GSON.toJson(element) : JSONUtils.convertToString(element, "nbt"))); } catch (CommandSyntaxException e) { e.printStackTrace(); @@ -127,18 +130,18 @@ public class FluidHelper { if (tank == null || fluidStack.getAmount() != tank.fill(fluidStack, FluidAction.SIMULATE)) return false; - if (worldIn.isRemote) + if (worldIn.isClientSide) return true; ItemStack copyOfHeld = heldItem.copy(); emptyingResult = EmptyingByBasin.emptyItem(worldIn, copyOfHeld, false); tank.fill(fluidStack, FluidAction.EXECUTE); - if (!player.isCreative()) { + if (!player.isCreative() && !(te instanceof CreativeFluidTankTileEntity)) { if (copyOfHeld.isEmpty()) - player.setHeldItem(handIn, emptyingResult.getSecond()); + player.setItemInHand(handIn, emptyingResult.getSecond()); else { - player.setHeldItem(handIn, copyOfHeld); + player.setItemInHand(handIn, copyOfHeld); player.inventory.placeItemBackInInventory(worldIn, emptyingResult.getSecond()); } } @@ -166,10 +169,10 @@ public class FluidHelper { if (requiredAmountForItem > fluid.getAmount()) continue; - if (world.isRemote) + if (world.isClientSide) return true; - if (player.isCreative()) + if (player.isCreative() || te instanceof CreativeFluidTankTileEntity) heldItem = heldItem.copy(); ItemStack out = GenericItemFilling.fillItem(world, requiredAmountForItem, heldItem, fluid.copy()); diff --git a/src/main/java/com/simibubi/create/foundation/fluid/FluidIngredient.java b/src/main/java/com/simibubi/create/foundation/fluid/FluidIngredient.java index 1082cb755..65e9d416a 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidIngredient.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidIngredient.java @@ -131,7 +131,7 @@ public abstract class FluidIngredient implements Predicate { if (!json.has("amount")) throw new JsonSyntaxException("Fluid ingredient has to define an amount"); - ingredient.amountRequired = JSONUtils.getInt(json, "amount"); + ingredient.amountRequired = JSONUtils.getAsInt(json, "amount"); return ingredient; } @@ -146,13 +146,13 @@ public abstract class FluidIngredient implements Predicate { void fixFlowing() { if (fluid instanceof FlowingFluid) - fluid = ((FlowingFluid) fluid).getStillFluid(); + fluid = ((FlowingFluid) fluid).getSource(); } @Override protected boolean testInternal(FluidStack t) { if (!t.getFluid() - .isEquivalentTo(fluid)) + .isSame(fluid)) return false; if (tagToMatch.isEmpty()) return true; @@ -165,13 +165,13 @@ public abstract class FluidIngredient implements Predicate { @Override protected void readInternal(PacketBuffer buffer) { fluid = buffer.readRegistryId(); - tagToMatch = buffer.readCompoundTag(); + tagToMatch = buffer.readNbt(); } @Override protected void writeInternal(PacketBuffer buffer) { buffer.writeRegistryId(fluid); - buffer.writeCompoundTag(tagToMatch); + buffer.writeNbt(tagToMatch); } @Override @@ -205,10 +205,10 @@ public abstract class FluidIngredient implements Predicate { if (tag == null) for (FluidStack accepted : getMatchingFluidStacks()) if (accepted.getFluid() - .isEquivalentTo(t.getFluid())) + .isSame(t.getFluid())) return true; return t.getFluid() - .isIn(tag); + .is(tag); } @Override @@ -230,10 +230,10 @@ public abstract class FluidIngredient implements Predicate { @Override protected void readInternal(JsonObject json) { - ResourceLocation id = new ResourceLocation(JSONUtils.getString(json, "fluidTag")); - Optional> optionalINamedTag = FluidTags.getRequiredTags() + ResourceLocation id = new ResourceLocation(JSONUtils.getAsString(json, "fluidTag")); + Optional> optionalINamedTag = FluidTags.getWrappers() .stream() - .filter(fluidINamedTag -> fluidINamedTag.getId() + .filter(fluidINamedTag -> fluidINamedTag.getName() .equals(id)) .findFirst(); // fixme if (!optionalINamedTag.isPresent()) @@ -243,17 +243,17 @@ public abstract class FluidIngredient implements Predicate { @Override protected void writeInternal(JsonObject json) { - json.addProperty("fluidTag", tag.getId() + json.addProperty("fluidTag", tag.getName() .toString()); } @Override protected List determineMatchingFluidStacks() { - return tag.values() + return tag.getValues() .stream() .map(f -> { if (f instanceof FlowingFluid) - return ((FlowingFluid) f).getStillFluid(); + return ((FlowingFluid) f).getSource(); return f; }) .distinct() 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..7fae09669 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java @@ -2,17 +2,18 @@ package com.simibubi.create.foundation.fluid; import java.util.function.Function; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack.Entry; import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.fluid.Fluid; import net.minecraft.inventory.container.PlayerContainer; @@ -23,31 +24,42 @@ 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.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.FluidStack; +@OnlyIn(Dist.CLIENT) public class FluidRenderer { + public static IVertexBuilder getFluidBuilder(IRenderTypeBuffer buffer) { + return buffer.getBuffer(RenderTypes.getFluid()); + } + public static void renderFluidStream(FluidStack fluidStack, Direction direction, float radius, float progress, boolean inbound, IRenderTypeBuffer buffer, MatrixStack ms, int light) { + renderFluidStream(fluidStack, direction, radius, progress, inbound, getFluidBuilder(buffer), ms, light); + } + + public static void renderFluidStream(FluidStack fluidStack, Direction direction, float radius, float progress, + boolean inbound, IVertexBuilder builder, MatrixStack ms, int light) { Fluid fluid = fluidStack.getFluid(); FluidAttributes fluidAttributes = fluid.getAttributes(); Function spriteAtlas = Minecraft.getInstance() - .getSpriteAtlas(PlayerContainer.BLOCK_ATLAS_TEXTURE); + .getTextureAtlas(PlayerContainer.BLOCK_ATLAS); TextureAtlasSprite flowTexture = spriteAtlas.apply(fluidAttributes.getFlowingTexture(fluidStack)); TextureAtlasSprite stillTexture = spriteAtlas.apply(fluidAttributes.getStillTexture(fluidStack)); int color = fluidAttributes.getColor(fluidStack); - IVertexBuilder builder = buffer.getBuffer(RenderType.getTranslucent()); - MatrixStacker msr = MatrixStacker.of(ms); - int blockLightIn = (light >> 4) & 0xf; + int blockLightIn = (light >> 4) & 0xF; int luminosity = Math.max(blockLightIn, fluidAttributes.getLuminosity(fluidStack)); - light = (light & 0xf00000) | luminosity << 4; + light = (light & 0xF00000) | luminosity << 4; if (inbound) direction = direction.getOpposite(); - ms.push(); + MatrixTransformStack msr = MatrixTransformStack.of(ms); + ms.pushPose(); msr.centre() .rotateY(AngleHelper.horizontalAngle(direction)) .rotateX(direction == Direction.UP ? 0 : direction == Direction.DOWN ? 180 : 90) @@ -62,10 +74,10 @@ public class FluidRenderer { float yMax = y + MathHelper.clamp(progress * .5f - 1e-6f, 0, 1); for (int i = 0; i < 4; i++) { - ms.push(); + ms.pushPose(); renderTiledHorizontalFace(h, Direction.SOUTH, hMin, yMin, hMax, yMax, builder, ms, light, color, flowTexture); - ms.pop(); + ms.popPose(); msr.rotateY(90); } @@ -73,32 +85,34 @@ public class FluidRenderer { renderTiledVerticalFace(yMax, Direction.UP, hMin, hMin, hMax, hMax, builder, ms, light, color, stillTexture); - ms.pop(); - + ms.popPose(); } public static void renderTiledFluidBB(FluidStack fluidStack, float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, IRenderTypeBuffer buffer, MatrixStack ms, int light, boolean renderBottom) { + renderTiledFluidBB(fluidStack, xMin, yMin, zMin, xMax, yMax, zMax, getFluidBuilder(buffer), ms, light, renderBottom); + } + + public static void renderTiledFluidBB(FluidStack fluidStack, float xMin, float yMin, float zMin, float xMax, + float yMax, float zMax, IVertexBuilder builder, MatrixStack ms, int light, boolean renderBottom) { Fluid fluid = fluidStack.getFluid(); FluidAttributes fluidAttributes = fluid.getAttributes(); TextureAtlasSprite fluidTexture = Minecraft.getInstance() - .getSpriteAtlas(PlayerContainer.BLOCK_ATLAS_TEXTURE) + .getTextureAtlas(PlayerContainer.BLOCK_ATLAS) .apply(fluidAttributes.getStillTexture(fluidStack)); int color = fluidAttributes.getColor(fluidStack); - IVertexBuilder builder = buffer.getBuffer(RenderType.getTranslucent()); - MatrixStacker msr = MatrixStacker.of(ms); - Vector3d center = new Vector3d(xMin + (xMax - xMin) / 2, yMin + (yMax - yMin) / 2, zMin + (zMax - zMin) / 2); - - int blockLightIn = (light >> 4) & 0xf; + int blockLightIn = (light >> 4) & 0xF; int luminosity = Math.max(blockLightIn, fluidAttributes.getLuminosity(fluidStack)); - light = (light & 0xf00000) | luminosity << 4; + light = (light & 0xF00000) | luminosity << 4; - ms.push(); + Vector3d center = new Vector3d(xMin + (xMax - xMin) / 2, yMin + (yMax - yMin) / 2, zMin + (zMax - zMin) / 2); + MatrixTransformStack msr = MatrixTransformStack.of(ms); + ms.pushPose(); if (fluidStack.getFluid() .getAttributes() .isLighterThanAir()) - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .translate(center) .rotateX(180) .translateBack(center); @@ -109,7 +123,7 @@ public class FluidRenderer { if (side.getAxis() .isHorizontal()) { - ms.push(); + ms.pushPose(); if (side.getAxisDirection() == AxisDirection.NEGATIVE) msr.translate(center) @@ -117,11 +131,11 @@ public class FluidRenderer { .translateBack(center); boolean X = side.getAxis() == Axis.X; - int darkColor = ColorHelper.mixColors(color, 0xff000011, 1 / 4f); + int darkColor = Color.mixColors(color, 0xff000011, 1 / 4f); renderTiledHorizontalFace(X ? xMax : zMax, side, X ? zMin : xMin, yMin, X ? zMax : xMax, yMax, builder, ms, light, darkColor, fluidTexture); - ms.pop(); + ms.popPose(); continue; } @@ -129,7 +143,7 @@ public class FluidRenderer { light, color, fluidTexture); } - ms.pop(); + ms.popPose(); } @@ -142,10 +156,10 @@ public class FluidRenderer { for (float z1 = zMin; z1 < zMax; z1 = z2) { z2 = Math.min((int) (z1 + 1), zMax); - float u1 = texture.getInterpolatedU(local(x1) * 16); - float v1 = texture.getInterpolatedV(local(z1) * 16); - float u2 = texture.getInterpolatedU(x2 == xMax ? local(x2) * 16 : 16); - float v2 = texture.getInterpolatedV(z2 == zMax ? local(z2) * 16 : 16); + float u1 = texture.getU(local(x1) * 16); + float v1 = texture.getV(local(z1) * 16); + float u2 = texture.getU(x2 == xMax ? local(x2) * 16 : 16); + float v2 = texture.getV(z2 == zMax ? local(z2) * 16 : 16); putVertex(builder, ms, x1, y, z2, color, u1, v2, face, light); putVertex(builder, ms, x2, y, z2, color, u2, v2, face, light); @@ -168,10 +182,10 @@ public class FluidRenderer { y2 = Math.min((int) (y1 + 1), yMax); int multiplier = texture.getWidth() == 32 ? 8 : 16; - float u1 = texture.getInterpolatedU(local(h1) * multiplier); - float v1 = texture.getInterpolatedV(local(y1) * multiplier); - float u2 = texture.getInterpolatedU(h2 == hMax ? local(h2) * multiplier : multiplier); - float v2 = texture.getInterpolatedV(y2 == yMax ? local(y2) * multiplier : multiplier); + float u1 = texture.getU(local(h1) * multiplier); + float v1 = texture.getV(local(y1) * multiplier); + float u2 = texture.getU(h2 == hMax ? local(h2) * multiplier : multiplier); + float v2 = texture.getV(y2 == yMax ? local(y2) * multiplier : multiplier); float x1 = X ? h : h1; float x2 = X ? h : h2; @@ -195,18 +209,19 @@ public class FluidRenderer { private static void putVertex(IVertexBuilder builder, MatrixStack ms, float x, float y, float z, int color, float u, float v, Direction face, int light) { - Vector3i n = face.getDirectionVec(); - Entry peek = ms.peek(); + Vector3i n = face.getNormal(); + Entry peek = ms.last(); int ff = 0xff; int a = color >> 24 & ff; int r = color >> 16 & ff; int g = color >> 8 & ff; int b = color & ff; - builder.vertex(peek.getModel(), x, y, z) + builder.vertex(peek.pose(), x, y, z) .color(r, g, b, a) - .texture(u, v) - .light(light) + .uv(u, v) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(light) .normal(n.getX(), n.getY(), n.getZ()) .endVertex(); } 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..acc765909 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java @@ -7,6 +7,8 @@ import java.util.List; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import org.lwjgl.opengl.GL11; + import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; @@ -33,6 +35,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); @@ -40,12 +44,24 @@ public abstract class AbstractSimiContainerScreen extends C } protected void setWindowSize(int width, int height) { - this.xSize = width; - this.ySize = height; + this.imageWidth = width; + this.imageHeight = height; + } + + protected void setWindowOffset(int xOffset, int yOffset) { + windowXOffset = xOffset; + windowYOffset = yOffset; } @Override - protected void drawForeground(MatrixStack p_230451_1_, int p_230451_2_, int p_230451_3_) { + protected void init() { + super.init(); + leftPos += windowXOffset; + topPos += windowYOffset; + } + + @Override + protected void renderLabels(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 // could also set this.titleX/Y and this.playerInventoryTitleX/Y to the proper values instead } @@ -53,7 +69,7 @@ public abstract class AbstractSimiContainerScreen extends C @Override public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { partialTicks = Minecraft.getInstance() - .getRenderPartialTicks(); + .getFrameTime(); renderBackground(matrixStack); renderWindow(matrixStack, mouseX, mouseY, partialTicks); @@ -65,7 +81,7 @@ public abstract class AbstractSimiContainerScreen extends C RenderSystem.enableAlphaTest(); RenderSystem.enableBlend(); RenderSystem.disableRescaleNormal(); - RenderHelper.disableStandardItemLighting(); + RenderHelper.turnOff(); RenderSystem.disableLighting(); RenderSystem.disableDepthTest(); renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks); @@ -91,8 +107,8 @@ public abstract class AbstractSimiContainerScreen extends C if (super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_)) return true; - InputMappings.Input mouseKey = InputMappings.getInputByCode(code, p_keyPressed_2_); - if (this.client.gameSettings.keyBindInventory.isActiveAndMatches(mouseKey)) { + InputMappings.Input mouseKey = InputMappings.getKey(code, p_keyPressed_2_); + if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) { this.onClose(); return true; } @@ -127,32 +143,21 @@ public abstract class AbstractSimiContainerScreen extends C return result | super.mouseReleased(x, y, button); } - @Override - public boolean shouldCloseOnEsc() { - return true; - } - - @Override - public boolean isPauseScreen() { - return false; - } - protected abstract void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks); @Override - protected void drawBackground(MatrixStack p_230450_1_, float p_230450_2_, int p_230450_3_, int p_230450_4_) { - + protected void renderBg(MatrixStack p_230450_1_, float p_230450_2_, int p_230450_3_, int p_230450_4_) { } protected void renderWindowForeground(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { - drawMouseoverTooltip(matrixStack, mouseX, mouseY); + renderTooltip(matrixStack, mouseX, mouseY); for (Widget widget : widgets) { if (!widget.isHovered()) continue; if (widget instanceof AbstractSimiWidget) { if (!((AbstractSimiWidget) widget).getToolTip().isEmpty()) - renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); + renderComponentTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); } else { widget.renderToolTip(matrixStack, mouseX, mouseY); @@ -160,62 +165,9 @@ public abstract class AbstractSimiContainerScreen extends C } } - protected void renderItemOverlayIntoGUI(MatrixStack matrixStack, FontRenderer fr, ItemStack stack, int xPosition, - int yPosition, @Nullable String text, int textColor) { - if (!stack.isEmpty()) { - if (stack.getItem() - .showDurabilityBar(stack)) { - RenderSystem.disableLighting(); - RenderSystem.disableDepthTest(); - RenderSystem.disableTexture(); - RenderSystem.disableAlphaTest(); - RenderSystem.disableBlend(); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferbuilder = tessellator.getBuffer(); - double health = stack.getItem() - .getDurabilityForDisplay(stack); - int i = Math.round(13.0F - (float) health * 13.0F); - int j = stack.getItem() - .getRGBDurabilityForDisplay(stack); - this.draw(bufferbuilder, xPosition + 2, yPosition + 13, 13, 2, 0, 0, 0, 255); - this.draw(bufferbuilder, xPosition + 2, yPosition + 13, i, 1, j >> 16 & 255, j >> 8 & 255, j & 255, - 255); - RenderSystem.enableBlend(); - RenderSystem.enableAlphaTest(); - RenderSystem.enableTexture(); - RenderSystem.enableLighting(); - RenderSystem.enableDepthTest(); - } - - if (stack.getCount() != 1 || text != null) { - String s = text == null ? String.valueOf(stack.getCount()) : text; - RenderSystem.disableLighting(); - RenderSystem.disableDepthTest(); - RenderSystem.disableBlend(); - matrixStack.push(); - - int guiScaleFactor = (int) client.getWindow() - .getGuiScaleFactor(); - matrixStack.translate(xPosition + 16.5f, yPosition + 16.5f, 0); - double scale = getItemCountTextScale(); - - matrixStack.scale((float) scale, (float) scale, 0); - matrixStack.translate(-fr.getStringWidth(s) - (guiScaleFactor > 1 ? 0 : -.5f), - -textRenderer.FONT_HEIGHT + (guiScaleFactor > 1 ? 1 : 1.75f), 0); - fr.drawWithShadow(matrixStack, s, 0, 0, textColor); - - matrixStack.pop(); - RenderSystem.enableBlend(); - RenderSystem.enableLighting(); - RenderSystem.enableDepthTest(); - RenderSystem.enableBlend(); - } - } - } - public double getItemCountTextScale() { - int guiScaleFactor = (int) client.getWindow() - .getGuiScaleFactor(); + int guiScaleFactor = (int) minecraft.getWindow() + .getGuiScale(); double scale = 1; switch (guiScaleFactor) { case 1: @@ -236,9 +188,85 @@ public abstract class AbstractSimiContainerScreen extends C return scale; } + public int getLeftOfCentered(int textureWidth) { + return (width - textureWidth) / 2; + } + + public void renderPlayerInventory(MatrixStack ms, int x, int y) { + AllGuiTextures.PLAYER_INVENTORY.draw(ms, this, x, y); + font.draw(ms, inventory.getDisplayName(), x + 8, y + 6, 0x404040); + } + + /** + * Used for moving JEI out of the way of extra things like Flexcrate renders. + * + *

This screen class must be bound to a SlotMover instance for this method to work. + * + * @return the space that the gui takes up besides the normal rectangle defined by {@link ContainerScreen}. + */ + public List getExtraAreas() { + return Collections.emptyList(); + } + + // Not up to date with ItemRenderer + @Deprecated + protected void renderItemOverlayIntoGUI(MatrixStack matrixStack, FontRenderer fr, ItemStack stack, int xPosition, + int yPosition, @Nullable String text, int textColor) { + if (!stack.isEmpty()) { + if (stack.getItem() + .showDurabilityBar(stack)) { + RenderSystem.disableLighting(); + RenderSystem.disableDepthTest(); + RenderSystem.disableTexture(); + RenderSystem.disableAlphaTest(); + RenderSystem.disableBlend(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuilder(); + double health = stack.getItem() + .getDurabilityForDisplay(stack); + int i = Math.round(13.0F - (float) health * 13.0F); + int j = stack.getItem() + .getRGBDurabilityForDisplay(stack); + this.draw(bufferbuilder, xPosition + 2, yPosition + 13, 13, 2, 0, 0, 0, 255); + this.draw(bufferbuilder, xPosition + 2, yPosition + 13, i, 1, j >> 16 & 255, j >> 8 & 255, j & 255, + 255); + RenderSystem.enableBlend(); + RenderSystem.enableAlphaTest(); + RenderSystem.enableTexture(); + RenderSystem.enableLighting(); + RenderSystem.enableDepthTest(); + } + + if (stack.getCount() != 1 || text != null) { + String s = text == null ? String.valueOf(stack.getCount()) : text; + RenderSystem.disableLighting(); + RenderSystem.disableDepthTest(); + RenderSystem.disableBlend(); + matrixStack.pushPose(); + + int guiScaleFactor = (int) minecraft.getWindow() + .getGuiScale(); + matrixStack.translate(xPosition + 16.5f, yPosition + 16.5f, 0); + double scale = getItemCountTextScale(); + + matrixStack.scale((float) scale, (float) scale, 0); + matrixStack.translate(-fr.width(s) - (guiScaleFactor > 1 ? 0 : -.5f), + -font.lineHeight + (guiScaleFactor > 1 ? 1 : 1.75f), 0); + fr.drawShadow(matrixStack, s, 0, 0, textColor); + + matrixStack.popPose(); + RenderSystem.enableBlend(); + RenderSystem.enableLighting(); + RenderSystem.enableDepthTest(); + RenderSystem.enableBlend(); + } + } + } + + @Deprecated private void draw(BufferBuilder renderer, int x, int y, int width, int height, int red, int green, int blue, int alpha) { - renderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + renderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); renderer.vertex((double) (x + 0), (double) (y + 0), 0.0D) .color(red, green, blue, alpha) .endVertex(); @@ -252,15 +280,19 @@ public abstract class AbstractSimiContainerScreen extends C .color(red, green, blue, alpha) .endVertex(); Tessellator.getInstance() - .draw(); + .end(); } - /** - * Used for moving JEI out of the way of extra things like Flexcrate renders - * - * @return the space that the gui takes up besides the normal rectangle defined by {@link ContainerScreen}. - */ - public List getExtraAreas() { - return Collections.emptyList(); + @Deprecated + protected void debugWindowArea(MatrixStack matrixStack) { + fill(matrixStack, leftPos + imageWidth, topPos + imageHeight, leftPos, topPos, 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..84689cf0b 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java @@ -10,6 +10,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.util.InputMappings; +import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -17,20 +18,37 @@ import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) public abstract class AbstractSimiScreen extends Screen { - protected int sWidth, sHeight; + protected int windowWidth, windowHeight; + protected int windowXOffset, windowYOffset; protected int guiLeft, guiTop; protected List widgets; - protected AbstractSimiScreen() { - super(new StringTextComponent("")); + protected AbstractSimiScreen(ITextComponent title) { + super(title); widgets = new ArrayList<>(); } + protected AbstractSimiScreen() { + this(new StringTextComponent("")); + } + protected void setWindowSize(int width, int height) { - sWidth = width; - sHeight = height; - guiLeft = (this.width - sWidth) / 2; - guiTop = (this.height - sHeight) / 2; + windowWidth = width; + windowHeight = height; + } + + protected void setWindowOffset(int xOffset, int yOffset) { + windowXOffset = xOffset; + windowYOffset = yOffset; + } + + @Override + protected void init() { + super.init(); + guiLeft = (width - windowWidth) / 2; + guiTop = (height - windowHeight) / 2; + guiLeft += windowXOffset; + guiTop += windowYOffset; } @Override @@ -43,10 +61,12 @@ public abstract class AbstractSimiScreen extends Screen { @Override public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { partialTicks = partialTicks == 10 ? 0 - : Minecraft.getInstance() - .getRenderPartialTicks(); + : Minecraft.getInstance() + .getFrameTime(); - ms.push(); + ms.pushPose(); + + prepareFrame(); renderWindowBackground(ms, mouseX, mouseY, partialTicks); renderWindow(ms, mouseX, mouseY, partialTicks); @@ -54,7 +74,15 @@ public abstract class AbstractSimiScreen extends Screen { widget.render(ms, mouseX, mouseY, partialTicks); renderWindowForeground(ms, mouseX, mouseY, partialTicks); - ms.pop(); + endFrame(); + + ms.popPose(); + } + + protected void prepareFrame() { + } + + protected void endFrame() { } protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { @@ -83,8 +111,8 @@ public abstract class AbstractSimiScreen extends Screen { if (super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_)) return true; - InputMappings.Input mouseKey = InputMappings.getInputByCode(code, p_keyPressed_2_); - if (this.client.gameSettings.keyBindInventory.isActiveAndMatches(mouseKey)) { + InputMappings.Input mouseKey = InputMappings.getKey(code, p_keyPressed_2_); + if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) { this.onClose(); return true; } @@ -138,7 +166,7 @@ public abstract class AbstractSimiScreen extends Screen { if (widget instanceof AbstractSimiWidget) { if (!((AbstractSimiWidget) widget).getToolTip().isEmpty()) - renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); + renderComponentTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); } else { widget.renderToolTip(ms, mouseX, mouseY); @@ -146,4 +174,13 @@ public abstract class AbstractSimiScreen extends Screen { } } + @Deprecated + protected void debugWindowArea(MatrixStack matrixStack) { + fill(matrixStack, guiLeft + windowWidth, guiTop + windowHeight, guiLeft, guiTop, 0xD3D3D3D3); + } + + public List getWidgets() { + return widgets; + } + } 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..67b52074c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -1,9 +1,8 @@ package com.simibubi.create.foundation.gui; -import java.awt.Color; - import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.Create; +import com.simibubi.create.foundation.utility.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.AbstractGui; @@ -20,6 +19,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), @@ -51,6 +52,18 @@ public enum AllGuiTextures implements IScreenRenderable { FILTER("filters.png", 214, 97), ATTRIBUTE_FILTER("filters.png", 0, 97, 241, 83), + TOOLBOX("toolbox.png", 188, 171), + TOOLBELT_SLOT("minecraft", "widgets.png", 24, 23, 22, 22), + TOOLBELT_SLOT_HIGHLIGHT("minecraft", "widgets.png", 0, 22, 24, 24), + TOOLBELT_MAIN_SLOT("widgets.png", 0, 97, 24, 24), + TOOLBELT_EMPTY_SLOT("widgets.png", 27, 98, 22, 22), + TOOLBELT_INACTIVE_SLOT("widgets.png", 52, 98, 22, 22), + + TOOLBELT_HOTBAR_OFF("widgets.png", 0, 130, 20, 24), + TOOLBELT_HOTBAR_ON("widgets.png", 20, 130, 20, 24), + TOOLBELT_SELECTED_OFF("widgets.png", 0, 155, 22, 22), + TOOLBELT_SELECTED_ON("widgets.png", 22, 155, 22, 22), + SEQUENCER("sequencer.png", 173, 159), SEQUENCER_INSTRUCTION("sequencer.png", 0, 14, 162, 22), SEQUENCER_DELAY("sequencer.png", 0, 58, 162, 22), @@ -58,6 +71,15 @@ public enum AllGuiTextures implements IScreenRenderable { SEQUENCER_EMPTY("sequencer.png", 0, 102, 162, 22), SEQUENCER_AWAIT("sequencer.png", 0, 160, 162, 22), + LINKED_CONTROLLER("curiosities_2.png", 179, 109), + BLUEPRINT("curiosities_2.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 +104,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), @@ -105,7 +132,11 @@ public enum AllGuiTextures implements IScreenRenderable { } private AllGuiTextures(String location, int startX, int startY, int width, int height) { - this.location = new ResourceLocation(Create.ID, "textures/gui/" + location); + this(Create.ID, location, startX, startY, width, height); + } + + private AllGuiTextures(String namespace, String location, int startX, int startY, int width, int height) { + this.location = new ResourceLocation(namespace, "textures/gui/" + location); this.width = width; this.height = height; this.startX = startX; @@ -116,18 +147,19 @@ public enum AllGuiTextures implements IScreenRenderable { public void bind() { Minecraft.getInstance() .getTextureManager() - .bindTexture(location); + .bind(location); } @Override @OnlyIn(Dist.CLIENT) public void draw(MatrixStack ms, AbstractGui screen, int x, int y) { bind(); - screen.drawTexture(ms, x, y, startX, startY, width, height); + screen.blit(ms, x, y, startX, startY, width, height); } public void draw(MatrixStack ms, int x, int y, Color c) { bind(); UIRenderHelper.drawColoredTexture(ms, c, x, y, startX, startY, width, height); } + } 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..6a07a5f57 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java @@ -4,7 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack.Entry; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.AbstractGui; @@ -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,8 @@ public class AllIcons implements IScreenRenderable { I_TUNNEL_PREFER_NEAREST = next(), I_TUNNEL_RANDOMIZE = next(), I_TUNNEL_SYNCHRONIZE = next(), - + I_TOOLBOX = next(), + I_TOOL_MOVE_XZ = newRow(), I_TOOL_MOVE_Y = next(), I_TOOL_ROTATE = next(), @@ -94,10 +95,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 +107,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 +137,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; @@ -155,25 +164,25 @@ public class AllIcons implements IScreenRenderable { public void bind() { Minecraft.getInstance() .getTextureManager() - .bindTexture(ICON_ATLAS); + .bind(ICON_ATLAS); } @Override @OnlyIn(Dist.CLIENT) public void draw(MatrixStack matrixStack, AbstractGui screen, int x, int y) { bind(); - screen.drawTexture(matrixStack, x, y, iconX, iconY, 16, 16); + screen.blit(matrixStack, x, y, iconX, iconY, 16, 16); } @OnlyIn(Dist.CLIENT) public void draw(MatrixStack ms, IRenderTypeBuffer buffer, int color) { - IVertexBuilder builder = buffer.getBuffer(RenderType.getTextSeeThrough(ICON_ATLAS)); + IVertexBuilder builder = buffer.getBuffer(RenderType.textSeeThrough(ICON_ATLAS)); float sheetSize = 256; int i = 15 << 20 | 15 << 4; int j = i >> 16 & '\uffff'; int k = i & '\uffff'; - Entry peek = ms.peek(); - Vector3d rgb = ColorHelper.getRGB(color); + Entry peek = ms.last(); + Vector3d rgb = Color.vectorFromRGB(color); Vector3d vec4 = new Vector3d(1, 1, 0); Vector3d vec3 = new Vector3d(0, 1, 0); @@ -198,10 +207,10 @@ public class AllIcons implements IScreenRenderable { @OnlyIn(Dist.CLIENT) private void vertex(Entry peek, IVertexBuilder builder, int j, int k, Vector3d rgb, Vector3d vec, float u, float v) { - builder.vertex(peek.getModel(), (float) vec.x, (float) vec.y, (float) vec.z) + builder.vertex(peek.pose(), (float) vec.x, (float) vec.y, (float) vec.z) .color((float) rgb.x, (float) rgb.y, (float) rgb.z, 1) - .texture(u, v) - .light(j, k) + .uv(u, v) + .uv2(j, k) .endVertex(); } diff --git a/src/main/java/com/simibubi/create/foundation/gui/BoxElement.java b/src/main/java/com/simibubi/create/foundation/gui/BoxElement.java index 673b057b6..61c46d231 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/BoxElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/BoxElement.java @@ -1,12 +1,10 @@ package com.simibubi.create.foundation.gui; -import java.awt.Color; - import org.lwjgl.opengl.GL11; 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.Color; import com.simibubi.create.foundation.utility.Couple; import net.minecraft.client.renderer.BufferBuilder; @@ -96,12 +94,12 @@ public class BoxElement extends RenderElement { RenderSystem.shadeModel(GL11.GL_SMOOTH); int f = borderOffset; - Color c1 = ColorHelper.applyAlpha(background, alpha); - Color c2 = ColorHelper.applyAlpha(borderTop, alpha); - Color c3 = ColorHelper.applyAlpha(borderBot, alpha); + Color c1 = background.copy().scaleAlpha(alpha); + Color c2 = borderTop.copy().scaleAlpha(alpha); + Color c3 = borderBot.copy().scaleAlpha(alpha); Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder b = tessellator.getBuffer(); - Matrix4f model = ms.peek().getModel(); + BufferBuilder b = tessellator.getBuilder(); + Matrix4f model = ms.last().pose(); b.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); //outer top b.vertex(model, x - f - 1 , y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); @@ -128,7 +126,7 @@ public class BoxElement extends RenderElement { b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - tessellator.draw(); + tessellator.end(); b.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); //inner top - includes corners b.vertex(model, x - f - 1 , y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); @@ -151,7 +149,7 @@ public class BoxElement extends RenderElement { b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - tessellator.draw(); + tessellator.end(); RenderSystem.shadeModel(GL11.GL_FLAT); RenderSystem.disableBlend(); 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..24b961302 --- /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.containerMenu instanceof IClearableContainer)) + return; + ((IClearableContainer) player.containerMenu).clearContents(); + }); + context.get() + .setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java index 374479c69..6382dce01 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/CombinedStencilElement.java @@ -44,16 +44,16 @@ public class CombinedStencilElement extends StencilElement { @Override protected void renderStencil(MatrixStack ms) { - ms.push(); + ms.pushPose(); element1.transform(ms); element1.withBounds(width, height); element1.renderStencil(ms); - ms.pop(); - ms.push(); + ms.popPose(); + ms.pushPose(); element2.transform(ms); element2.withBounds(width, height); element2.renderStencil(ms); - ms.pop(); + ms.popPose(); } @Override 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..849c1ff51 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java @@ -6,35 +6,47 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; +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.foundation.gui.widgets.BoxWidget; 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.text.ITextProperties; 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,15 +82,21 @@ 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; } public void open(@Nonnull Screen source) { this.source = source; Minecraft client = source.getMinecraft(); - this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight()); - this.client.currentScreen = this; + this.init(client, client.getWindow().getGuiScaledWidth(), client.getWindow().getGuiScaledHeight()); + this.minecraft.screen = this; } @Override @@ -94,11 +112,19 @@ public class ConfirmationScreen extends AbstractSimiScreen { ArrayList copy = new ArrayList<>(text); text.clear(); - copy.forEach(t -> text.addAll(client.fontRenderer.getTextHandler().wrapLines(t, 300, Style.EMPTY))); + copy.forEach(t -> text.addAll(minecraft.font.getSplitter().splitLines(t, 300, Style.EMPTY))); - textHeight = text.size() * (client.fontRenderer.FONT_HEIGHT + 1) + 4; + textHeight = text.size() * (minecraft.font.lineHeight + 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,38 +133,47 @@ 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(minecraft.font, 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(minecraft.font, "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)); + TextStencilElement cancelText = new TextStencilElement(minecraft.font, "Cancel").centered(true, true); + 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) { - client.currentScreen = source; + private void accept(Response success) { + minecraft.screen = source; action.accept(success); } @@ -146,49 +181,74 @@ public class ConfirmationScreen extends AbstractSimiScreen { protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { textBackground.render(ms); - int offset = client.fontRenderer.FONT_HEIGHT + 1; + int offset = minecraft.font.lineHeight + 1; int lineY = y - offset; - ms.push(); + ms.pushPose(); ms.translate(0, 0, 200); 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 - minecraft.font.width(line)) / 2; + minecraft.font.draw(ms, line.getString(), textX, lineY, 0xeaeaea); } - ms.pop(); + ms.popPose(); } @Override protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + endFrame(); - UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC); + source.render(ms, 0, 0, 10); // zero mouse coords to prevent further tooltips - ms.push(); - UIRenderHelper.framebuffer.bindFramebuffer(true); - source.render(ms, mouseX, mouseY, 10); - UIRenderHelper.framebuffer.unbindFramebuffer(); - Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer(); - ms.pop(); - - //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); - mainBuffer.bindFramebuffer(true); + prepareFrame(); this.fillGradient(ms, 0, 0, this.width, this.height, 0x70101010, 0x80101010); } + @Override + protected void prepareFrame() { + Framebuffer thisBuffer = UIRenderHelper.framebuffer; + Framebuffer mainBuffer = Minecraft.getInstance().getMainRenderTarget(); + + GlCompat functions = Backend.getInstance().compat; + functions.fbo.bindFramebuffer(GL30.GL_READ_FRAMEBUFFER, mainBuffer.frameBufferId); + functions.fbo.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, thisBuffer.frameBufferId); + functions.blit.blitFramebuffer(0, 0, mainBuffer.viewWidth, mainBuffer.viewHeight, 0, 0, mainBuffer.viewWidth, mainBuffer.viewHeight, GL30.GL_COLOR_BUFFER_BIT, GL20.GL_LINEAR); + + functions.fbo.bindFramebuffer(FramebufferConstants.GL_FRAMEBUFFER, thisBuffer.frameBufferId); + GL11.glClear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT); + + } + + @Override + protected void endFrame() { + + Framebuffer thisBuffer = UIRenderHelper.framebuffer; + Framebuffer mainBuffer = Minecraft.getInstance().getMainRenderTarget(); + + GlCompat functions = Backend.getInstance().compat; + functions.fbo.bindFramebuffer(GL30.GL_READ_FRAMEBUFFER, thisBuffer.frameBufferId); + functions.fbo.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, mainBuffer.frameBufferId); + functions.blit.blitFramebuffer(0, 0, mainBuffer.viewWidth, mainBuffer.viewHeight, 0, 0, mainBuffer.viewWidth, mainBuffer.viewHeight, GL30.GL_COLOR_BUFFER_BIT, GL20.GL_LINEAR); + + functions.fbo.bindFramebuffer(FramebufferConstants.GL_FRAMEBUFFER, mainBuffer.frameBufferId); + } + @Override public void resize(@Nonnull Minecraft client, int width, int height) { super.resize(client, width, height); source.resize(client, width, height); } + + @Override + public boolean isPauseScreen() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/ContainerBase.java b/src/main/java/com/simibubi/create/foundation/gui/ContainerBase.java new file mode 100644 index 000000000..fff1ae447 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/ContainerBase.java @@ -0,0 +1,69 @@ +package com.simibubi.create.foundation.gui; + +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.network.PacketBuffer; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class ContainerBase extends Container { + + public PlayerEntity player; + public PlayerInventory playerInventory; + public T contentHolder; + + protected ContainerBase(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id); + init(inv, createOnClient(extraData)); + } + + protected ContainerBase(ContainerType type, int id, PlayerInventory inv, T contentHolder) { + super(type, id); + init(inv, contentHolder); + } + + protected void init(PlayerInventory inv, T contentHolderIn) { + player = inv.player; + playerInventory = inv; + contentHolder = contentHolderIn; + initAndReadInventory(contentHolder); + addSlots(); + broadcastChanges(); + } + + @OnlyIn(Dist.CLIENT) + protected abstract T createOnClient(PacketBuffer extraData); + + protected abstract void addSlots(); + + protected abstract void initAndReadInventory(T contentHolder); + + protected abstract void saveData(T contentHolder); + + 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 void removed(PlayerEntity playerIn) { + super.removed(playerIn); + saveData(contentHolder); + } + + @Override + public boolean stillValid(PlayerEntity player) { + if (contentHolder == null) + return false; + if (contentHolder instanceof IInteractionChecker) + return ((IInteractionChecker) contentHolder).canPlayerUse(player); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/CustomLightingSettings.java b/src/main/java/com/simibubi/create/foundation/gui/CustomLightingSettings.java new file mode 100644 index 000000000..392dc76fa --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/CustomLightingSettings.java @@ -0,0 +1,83 @@ +package com.simibubi.create.foundation.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3f; + +public class CustomLightingSettings implements ILightingSettings { + + private Vector3f light1; + private Vector3f light2; + private Matrix4f lightMatrix; + + protected CustomLightingSettings(float yRot, float xRot) { + init(yRot, xRot, 0, 0, false); + } + + protected CustomLightingSettings(float yRot1, float xRot1, float yRot2, float xRot2) { + init(yRot1, xRot1, yRot2, xRot2, true); + } + + protected void init(float yRot1, float xRot1, float yRot2, float xRot2, boolean doubleLight) { + light1 = Vector3f.ZP.copy(); + light1.transform(Vector3f.YP.rotationDegrees(yRot1)); + light1.transform(Vector3f.XP.rotationDegrees(xRot1)); + + if (doubleLight) { + light2 = Vector3f.ZP.copy(); + light2.transform(Vector3f.YP.rotationDegrees(yRot2)); + light2.transform(Vector3f.XP.rotationDegrees(xRot2)); + } else { + light2 = VecHelper.ZERO_3F; + } + + lightMatrix = new Matrix4f(); + lightMatrix.setIdentity(); + } + + @Override + public void applyLighting() { + RenderSystem.setupLevelDiffuseLighting(light1, light2, lightMatrix); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private float yRot1, xRot1; + private float yRot2, xRot2; + private boolean doubleLight; + + public Builder firstLightRotation(float yRot, float xRot) { + yRot1 = yRot; + xRot1 = xRot; + return this; + } + + public Builder secondLightRotation(float yRot, float xRot) { + yRot2 = yRot; + xRot2 = xRot; + doubleLight = true; + return this; + } + + public Builder doubleLight() { + doubleLight = true; + return this; + } + + public CustomLightingSettings build() { + if (doubleLight) { + return new CustomLightingSettings(yRot1, xRot1, yRot2, xRot2); + } else { + return new CustomLightingSettings(yRot1, xRot1); + } + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java index 4b45ace4f..8093c9e7e 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/DelegatedStencilElement.java @@ -1,12 +1,12 @@ package com.simibubi.create.foundation.gui; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; public class DelegatedStencilElement extends StencilElement { protected static final ElementRenderer EMPTY_RENDERER = (ms, width, height, alpha) -> {}; - protected static final ElementRenderer DEFAULT_ELEMENT = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, -3, 5, height+4, width+6, ColorHelper.applyAlpha(0xff_10dd10, alpha), ColorHelper.applyAlpha(0xff_1010dd, alpha)); + protected static final ElementRenderer DEFAULT_ELEMENT = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, -3, 5, height+4, width+6, new Color(0xff_10dd10).scaleAlpha(alpha), new Color(0xff_1010dd).scaleAlpha(alpha)); protected ElementRenderer stencil; protected ElementRenderer element; 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..7b7f1903c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/GhostItemContainer.java @@ -0,0 +1,110 @@ +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.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; + +public abstract class GhostItemContainer extends ContainerBase implements IClearableContainer { + + public ItemStackHandler ghostInventory; + + protected GhostItemContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id, inv, extraData); + } + + protected GhostItemContainer(ContainerType type, int id, PlayerInventory inv, T contentHolder) { + super(type, id, inv, contentHolder); + } + + protected abstract ItemStackHandler createGhostInventory(); + + protected abstract boolean allowRepeats(); + + @Override + protected void initAndReadInventory(T contentHolder) { + ghostInventory = createGhostInventory(); + } + + @Override + public void clearContents() { + for (int i = 0; i < ghostInventory.getSlots(); i++) + ghostInventory.setStackInSlot(i, ItemStack.EMPTY); + } + + @Override + public boolean canTakeItemForPickAll(ItemStack stack, Slot slotIn) { + return slotIn.container == playerInventory; + } + + @Override + public boolean canDragTo(Slot slotIn) { + if (allowRepeats()) + return true; + return slotIn.container == playerInventory; + } + + @Override + public ItemStack clicked(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) { + ItemStack held = playerInventory.getCarried(); + if (slotId < 36) + return super.clicked(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.setCarried(stackInSlot); + return ItemStack.EMPTY; + } + return ItemStack.EMPTY; + } + + if (held.isEmpty()) { + ghostInventory.setStackInSlot(slot, ItemStack.EMPTY); + getSlot(slotId).setChanged(); + return ItemStack.EMPTY; + } + + ItemStack insert = held.copy(); + insert.setCount(1); + ghostInventory.setStackInSlot(slot, insert); + getSlot(slotId).setChanged(); + return held; + } + + @Override + public ItemStack quickMoveStack(PlayerEntity playerIn, int index) { + if (index < 36) { + ItemStack stackToInsert = playerInventory.getItem(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).setChanged(); + break; + } + } + } else { + ghostInventory.extractItem(index - 36, 1, false); + getSlot(index).setChanged(); + } + return ItemStack.EMPTY; + } + + + +} 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..3245586b6 --- /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.readItem(); + slot = buffer.readInt(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeItem(item); + buffer.writeInt(slot); + } + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + ServerPlayerEntity player = context.get() + .getSender(); + if (player == null) + return; + + if (player.containerMenu instanceof GhostItemContainer) { + GhostItemContainer c = (GhostItemContainer) player.containerMenu; + c.ghostInventory.setStackInSlot(slot, item); + c.getSlot(36 + slot).setChanged(); + } + + }); + 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..2f2563f97 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.Color; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.VirtualEmptyModelData; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -58,17 +58,18 @@ public class GuiGameElement { } public static GuiRenderBuilder of(Fluid fluid) { - return new GuiBlockStateRenderBuilder(fluid.getDefaultState() - .getBlockState() - .with(FlowingFluidBlock.LEVEL, 0)); + return new GuiBlockStateRenderBuilder(fluid.defaultFluidState() + .createLegacyBlock() + .setValue(FlowingFluidBlock.LEVEL, 0)); } 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 ILightingSettings customLighting = null; public GuiRenderBuilder atLocal(double x, double y, double z) { this.xLocal = x; @@ -104,33 +105,21 @@ public class GuiGameElement { return this; } - public abstract void render(MatrixStack matrixStack); - - @Deprecated - protected void prepare() {} - - 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); + public GuiRenderBuilder lighting(ILightingSettings lighting) { + customLighting = lighting; + return this; } - @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); + protected void prepareMatrix(MatrixStack matrixStack) { + matrixStack.pushPose(); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + 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) { @@ -139,30 +128,42 @@ public class GuiGameElement { matrixStack.translate(xLocal, yLocal, zLocal); matrixStack.scale(1, -1, 1); matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z); - matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion((float) zRot)); - matrixStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion((float) xRot)); - matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion((float) yRot)); + matrixStack.mulPose(Vector3f.ZP.rotationDegrees((float) zRot)); + matrixStack.mulPose(Vector3f.XP.rotationDegrees((float) xRot)); + matrixStack.mulPose(Vector3f.YP.rotationDegrees((float) yRot)); matrixStack.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z); } - @Deprecated - protected void cleanUp() {} - protected void cleanUpMatrix(MatrixStack matrixStack) { - matrixStack.pop(); - RenderSystem.disableAlphaTest(); + matrixStack.popPose(); RenderSystem.disableRescaleNormal(); + RenderSystem.disableAlphaTest(); + cleanUpLighting(matrixStack); + } + + protected void prepareLighting(MatrixStack matrixStack) { + if (customLighting != null) { + customLighting.applyLighting(); + } else { + RenderHelper.setupFor3DItems(); + } + } + + protected void cleanUpLighting(MatrixStack matrixStack) { + if (customLighting != null) { + RenderHelper.setupFor3DItems(); + } } } private static class GuiBlockModelRenderBuilder extends GuiRenderBuilder { - protected IBakedModel blockmodel; + protected IBakedModel blockModel; protected BlockState blockState; public GuiBlockModelRenderBuilder(IBakedModel blockmodel, @Nullable BlockState blockState) { - this.blockState = blockState == null ? Blocks.AIR.getDefaultState() : blockState; - this.blockmodel = blockmodel; + this.blockState = blockState == null ? Blocks.AIR.defaultBlockState() : blockState; + this.blockModel = blockmodel; } @Override @@ -170,17 +171,17 @@ public class GuiGameElement { prepareMatrix(matrixStack); Minecraft mc = Minecraft.getInstance(); - BlockRendererDispatcher blockRenderer = mc.getBlockRendererDispatcher(); - IRenderTypeBuffer.Impl buffer = mc.getBufferBuilders() - .getEntityVertexConsumers(); - RenderType renderType = blockState.getBlock() == Blocks.AIR ? Atlases.getEntityTranslucentCull() - : RenderTypeLookup.getEntityBlockLayer(blockState, true); + BlockRendererDispatcher blockRenderer = mc.getBlockRenderer(); + IRenderTypeBuffer.Impl buffer = mc.renderBuffers() + .bufferSource(); + RenderType renderType = blockState.getBlock() == Blocks.AIR ? Atlases.translucentCullBlockSheet() + : RenderTypeLookup.getRenderType(blockState, true); IVertexBuilder vb = buffer.getBuffer(renderType); transformMatrix(matrixStack); mc.getTextureManager() - .bindTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE); + .bind(PlayerContainer.BLOCK_ATLAS); renderModel(blockRenderer, buffer, renderType, vb, matrixStack); cleanUpMatrix(matrixStack); @@ -191,31 +192,32 @@ public class GuiGameElement { int color = Minecraft.getInstance() .getBlockColors() .getColor(blockState, null, null, 0); - Vector3d rgb = ColorHelper.getRGB(color == -1 ? this.color : color); - blockRenderer.getBlockModelRenderer() - .renderModel(ms.peek(), vb, blockState, blockmodel, (float) rgb.x, (float) rgb.y, (float) rgb.z, - 0xF000F0, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); - buffer.draw(); + Vector3d rgb = Color.vectorFromRGB(color == -1 ? this.color : color); + blockRenderer.getModelRenderer() + .renderModel(ms.last(), vb, blockState, blockModel, (float) rgb.x, (float) rgb.y, (float) rgb.z, + 0xF000F0, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); + buffer.endBatch(); } + } public static class GuiBlockStateRenderBuilder extends GuiBlockModelRenderBuilder { public GuiBlockStateRenderBuilder(BlockState blockstate) { super(Minecraft.getInstance() - .getBlockRendererDispatcher() - .getModelForState(blockstate), blockstate); + .getBlockRenderer() + .getBlockModel(blockstate), blockstate); } @Override protected void renderModel(BlockRendererDispatcher blockRenderer, IRenderTypeBuffer.Impl buffer, RenderType renderType, IVertexBuilder vb, MatrixStack ms) { if (blockState.getBlock() instanceof FireBlock) { - RenderHelper.disableGuiDepthLighting(); - blockRenderer.renderBlock(blockState, ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV, + RenderHelper.setupForFlatItems(); + blockRenderer.renderBlock(blockState, ms, buffer, 0xF000F0, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); - RenderHelper.enable(); - buffer.draw(); + buffer.endBatch(); + RenderHelper.setupFor3DItems(); return; } @@ -225,13 +227,9 @@ public class GuiGameElement { .isEmpty()) return; - ms.push(); - RenderHelper.disableStandardItemLighting(); FluidRenderer.renderTiledFluidBB(new FluidStack(blockState.getFluidState() - .getFluid(), 1000), 0, 0, 0, 1.0001f, 1.0001f, 1.0001f, buffer, ms, 0xf000f0, true); - buffer.draw(RenderType.getTranslucent()); - RenderHelper.enable(); - ms.pop(); + .getType(), 1000), 0, 0, 0, 1.0001f, 1.0001f, 1.0001f, buffer, ms, 0xF000F0, false); + buffer.endBatch(); } } @@ -259,48 +257,48 @@ public class GuiGameElement { public void render(MatrixStack matrixStack) { prepareMatrix(matrixStack); transformMatrix(matrixStack); - renderItemIntoGUI(matrixStack, stack); + renderItemIntoGUI(matrixStack, stack, customLighting == null); cleanUpMatrix(matrixStack); } - public static void renderItemIntoGUI(MatrixStack matrixStack, ItemStack stack) { - ItemRenderer renderer = Minecraft.getInstance() - .getItemRenderer(); - IBakedModel bakedModel = renderer.getItemModelWithOverrides(stack, null, null); - matrixStack.push(); - renderer.textureManager.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); - renderer.textureManager.getTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE) - .setBlurMipmapDirect(false, false); + public static void renderItemIntoGUI(MatrixStack matrixStack, ItemStack stack, boolean useDefaultLighting) { + ItemRenderer renderer = Minecraft.getInstance().getItemRenderer(); + IBakedModel bakedModel = renderer.getModel(stack, null, null); + + matrixStack.pushPose(); + renderer.textureManager.bind(AtlasTexture.LOCATION_BLOCKS); + renderer.textureManager.getTexture(AtlasTexture.LOCATION_BLOCKS).setFilter(false, false); RenderSystem.enableRescaleNormal(); RenderSystem.enableAlphaTest(); + RenderSystem.enableCull(); RenderSystem.defaultAlphaFunc(); RenderSystem.enableBlend(); - RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, - GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); - matrixStack.translate((float) 0, (float) 0, 100.0F + renderer.zLevel); + matrixStack.translate(0, 0, 100.0F + renderer.blitOffset); matrixStack.translate(8.0F, -8.0F, 0.0F); matrixStack.scale(16.0F, 16.0F, 16.0F); - IRenderTypeBuffer.Impl irendertypebuffer$impl = Minecraft.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - boolean flag = !bakedModel.isSideLit(); - if (flag) { - RenderHelper.disableGuiDepthLighting(); + IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().renderBuffers().bufferSource(); + boolean flatLighting = !bakedModel.usesBlockLight(); + if (useDefaultLighting) { + if (flatLighting) { + RenderHelper.setupForFlatItems(); + } } - renderer.renderItem(stack, ItemCameraTransforms.TransformType.GUI, false, matrixStack, - irendertypebuffer$impl, 15728880, OverlayTexture.DEFAULT_UV, bakedModel); - irendertypebuffer$impl.draw(); + renderer.render(stack, ItemCameraTransforms.TransformType.GUI, false, matrixStack, buffer, 0xF000F0, OverlayTexture.NO_OVERLAY, bakedModel); + buffer.endBatch(); RenderSystem.enableDepthTest(); - if (flag) { - RenderHelper.enableGuiDepthLighting(); + if (useDefaultLighting) { + if (flatLighting) { + RenderHelper.setupFor3DItems(); + } } RenderSystem.disableAlphaTest(); RenderSystem.disableRescaleNormal(); RenderSystem.enableCull(); - matrixStack.pop(); + matrixStack.popPose(); } } 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/IInteractionChecker.java b/src/main/java/com/simibubi/create/foundation/gui/IInteractionChecker.java new file mode 100644 index 000000000..9aca72ac4 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/IInteractionChecker.java @@ -0,0 +1,7 @@ +package com.simibubi.create.foundation.gui; + +import net.minecraft.entity.player.PlayerEntity; + +public interface IInteractionChecker { + boolean canPlayerUse(PlayerEntity player); +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/ILightingSettings.java b/src/main/java/com/simibubi/create/foundation/gui/ILightingSettings.java new file mode 100644 index 000000000..4248e4de2 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/ILightingSettings.java @@ -0,0 +1,12 @@ +package com.simibubi.create.foundation.gui; + +import net.minecraft.client.renderer.RenderHelper; + +public interface ILightingSettings { + + void applyLighting(); + + static final ILightingSettings DEFAULT_3D = () -> RenderHelper.setupFor3DItems(); + static final ILightingSettings DEFAULT_FLAT = () -> RenderHelper.setupForFlatItems(); + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/IScreenRenderable.java b/src/main/java/com/simibubi/create/foundation/gui/IScreenRenderable.java index 161bb01e2..ea8a9977c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/IScreenRenderable.java +++ b/src/main/java/com/simibubi/create/foundation/gui/IScreenRenderable.java @@ -1,10 +1,9 @@ package com.simibubi.create.foundation.gui; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.CreateClient; import net.minecraft.client.gui.AbstractGui; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.util.text.StringTextComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -15,7 +14,7 @@ public interface IScreenRenderable { @OnlyIn(Dist.CLIENT) default void draw(MatrixStack ms, int x, int y) { - draw(ms, new Screen(new StringTextComponent("")) { - }, x, y); + draw(ms, CreateClient.EMPTY_SCREEN, x, y); } + } diff --git a/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java b/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java index cfe1aa1d1..d28fa2eb4 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java @@ -20,7 +20,7 @@ public class ScreenOpener { private static Screen backSteppedFrom = null; public static void open(Screen screen) { - open(Minecraft.getInstance().currentScreen, screen); + open(Minecraft.getInstance().screen, screen); } public static void open(@Nullable Screen current, Screen toOpen) { @@ -70,7 +70,7 @@ public class ScreenOpener { if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen)) return false; - openPreviousScreen(Minecraft.getInstance().currentScreen, Optional.of(screen)); + openPreviousScreen(Minecraft.getInstance().screen, Optional.of(screen)); return true; } @@ -89,9 +89,9 @@ public class ScreenOpener { private static void openScreen(Screen screen) { Minecraft.getInstance() - .enqueue(() -> { + .tell(() -> { Minecraft.getInstance() - .displayGuiScreen(screen); + .setScreen(screen); Screen previouslyRenderedScreen = getPreviouslyRenderedScreen(); if (previouslyRenderedScreen != null && screen instanceof NavigatableSimiScreen) previouslyRenderedScreen.init(Minecraft.getInstance(), screen.width, screen.height); 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..6bbdeae75 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java @@ -11,14 +11,14 @@ public abstract class StencilElement extends RenderElement { @Override public void render(MatrixStack ms) { - ms.push(); + ms.pushPose(); transform(ms); prepareStencil(ms); renderStencil(ms); prepareElement(ms); renderElement(ms); cleanUp(ms); - ms.pop(); + ms.popPose(); } protected abstract void renderStencil(MatrixStack ms); @@ -32,7 +32,7 @@ public abstract class StencilElement extends RenderElement { protected void prepareStencil(MatrixStack ms) { GL11.glDisable(GL11.GL_STENCIL_TEST); RenderSystem.stencilMask(~0); - RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC); + RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX); GL11.glEnable(GL11.GL_STENCIL_TEST); RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP); RenderSystem.stencilMask(0xFF); @@ -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..9ede69764 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java @@ -50,10 +50,10 @@ public class TextStencilElement extends DelegatedStencilElement { float x = 0, y = 0; if (centerHorizontally) - x = width / 2f - font.getWidth(component) / 2f; + x = width / 2f - font.width(component) / 2f; if (centerVertically) - y = height / 2f - font.FONT_HEIGHT / 2f; + y = height / 2f - (font.lineHeight - 1) / 2f; font.draw(ms, component, x, y, 0xff_000000); } @@ -62,15 +62,15 @@ public class TextStencilElement extends DelegatedStencilElement { protected void renderElement(MatrixStack ms) { float x = 0, y = 0; if (centerHorizontally) - x = width / 2f - font.getWidth(component) / 2f; + x = width / 2f - font.width(component) / 2f; if (centerVertically) - y = height / 2f - font.FONT_HEIGHT / 2f; + y = height / 2f - (font.lineHeight - 1) / 2f; - ms.push(); + ms.pushPose(); ms.translate(x, y, 0); - element.render(ms, font.getWidth(component), font.FONT_HEIGHT + 2, alpha); - ms.pop(); + element.render(ms, font.width(component), font.lineHeight + 2, alpha); + ms.popPose(); } public IFormattableTextComponent getComponent() { 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..e61872984 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/Theme.java +++ b/src/main/java/com/simibubi/create/foundation/gui/Theme.java @@ -1,36 +1,45 @@ package com.simibubi.create.foundation.gui; -import java.awt.Color; +import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Couple; public class Theme { - private static final Theme base = new Theme(); - private static Theme custom = null; + private static final List themes = new ArrayList<>(); + private static final Theme base = addTheme(new Theme()); - public static void setTheme(@Nullable Theme theme) { - custom = theme; + public static Theme addTheme(@Nonnull Theme theme) { + themes.add(theme); + themes.sort(Comparator.comparingInt(Theme::getPriority).reversed()); + return theme; + } + + public static void removeTheme(Theme theme) { + themes.remove(theme); + } + + public static void reload() { + themes.forEach(Theme::init); } private static ColorHolder resolve(String key) { - ColorHolder h = null; - - if (custom != null) - h = custom.get(key); - - if (h == null) - h = base.get(key); - - if (h == null) - h = ColorHolder.missing; - - return h; + return themes + .stream() + .map(theme -> theme.get(key)) + .filter(Objects::nonNull) + .findFirst() + .map(holder -> holder.lookupKey == null ? holder : resolve(holder.lookupKey)) + .orElse(ColorHolder.missing); } @Nonnull public static Couple p(@Nonnull Key key) {return p(key.get());} @@ -51,35 +60,52 @@ public class Theme { //-----------// protected final Map colors; + private int priority = 0; protected Theme() { colors = new HashMap<>(); init(); } + /* + * Small note to addons: if you also want to make use of Theme, + * and add new Keys, please do not use mixins. Instead make a Theme + * subclass, override init and apply it via the static #addTheme + * + **/ + 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.VANILLA_TOOLTIP_BORDER, new Color(0x50_5000ff, true), new Color(0x50_28007f, true)); + put(Key.VANILLA_TOOLTIP_BACKGROUND, new Color(0xf0_100010, true)); + 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)); + //put(Key.PONDER_MISSING_VANILLA, new Color(0x50_5000ff, true), new Color(0x50_300077, true)); + lookup(Key.PONDER_MISSING_VANILLA, Key.VANILLA_TOOLTIP_BORDER); + put(Key.CONFIG_TITLE_A, new Color(0xffc69fbc, true), new Color(0xfff6b8bb, true)); + put(Key.CONFIG_TITLE_B, new Color(0xfff6b8bb, true), new Color(0xfffbf994, true)); //put(Key., new Color(0x, true), new Color(0x, true)); } @@ -99,10 +125,23 @@ public class Theme { put(key.get(), c1 , c2); } + protected void lookup(Key key, Key source) { + colors.put(key.get(), ColorHolder.lookup(source.get())); + } + @Nullable protected ColorHolder get(String key) { return colors.get(key); } + public int getPriority() { + return priority; + } + + public Theme setPriority(int priority) { + this.priority = priority; + return this; + } + public static class Key { public static Key BUTTON_IDLE = new Key(); @@ -118,6 +157,8 @@ public class Theme { public static Key TEXT_ACCENT_SLIGHT = new Key(); public static Key STREAK = new Key(); + public static Key VANILLA_TOOLTIP_BORDER = new Key(); + public static Key VANILLA_TOOLTIP_BACKGROUND = new Key(); public static Key PONDER_BACKGROUND_TRANSPARENT = new Key(); public static Key PONDER_BACKGROUND_FLAT = new Key(); @@ -130,6 +171,14 @@ 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(); + + public static Key CONFIG_TITLE_A = new Key(); + public static Key CONFIG_TITLE_B = new Key(); + private static int index = 0; private final String s; @@ -152,16 +201,23 @@ public class Theme { private static final ColorHolder missing = ColorHolder.single(Color.BLACK); private Couple colors; + private String lookupKey; private static ColorHolder single(Color c) { ColorHolder h = new ColorHolder(); - h.colors = Couple.create(c, c); + h.colors = Couple.create(c.setImmutable(), c.setImmutable()); return h; } private static ColorHolder pair(Color first, Color second) { ColorHolder h = new ColorHolder(); - h.colors = Couple.create(first, second); + h.colors = Couple.create(first.setImmutable(), second.setImmutable()); + return h; + } + + private static ColorHolder lookup(String key) { + ColorHolder h = new ColorHolder(); + h.lookupKey = key; return h; } 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..4748a8742 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java @@ -33,7 +33,7 @@ public class ToolSelectionScreen extends Screen { public ToolSelectionScreen(List tools, Consumer callback) { super(new StringTextComponent("Tool Selection")); - this.client = Minecraft.getInstance(); + this.minecraft = Minecraft.getInstance(); this.tools = tools; this.callback = callback; focused = false; @@ -62,12 +62,12 @@ public class ToolSelectionScreen extends Screen { Minecraft mc = Minecraft.getInstance(); MainWindow mainWindow = mc.getWindow(); if (!initialized) - init(mc, mainWindow.getScaledWidth(), mainWindow.getScaledHeight()); + init(mc, mainWindow.getGuiScaledWidth(), mainWindow.getGuiScaledHeight()); - int x = (mainWindow.getScaledWidth() - w) / 2 + 15; - int y = mainWindow.getScaledHeight() - h - 75; + int x = (mainWindow.getGuiScaledWidth() - w) / 2 + 15; + int y = mainWindow.getGuiScaledHeight() - h - 75; - matrixStack.push(); + matrixStack.pushPose(); matrixStack.translate(0, -yOffset, focused ? 100 : 0); AllGuiTextures gray = AllGuiTextures.HUD_BACKGROUND; @@ -76,8 +76,8 @@ public class ToolSelectionScreen extends Screen { Minecraft.getInstance() .getTextureManager() - .bindTexture(gray.location); - drawTexture(matrixStack, x - 15, y, gray.startX, gray.startY, w, h, gray.width, gray.height); + .bind(gray.location); + blit(matrixStack, x - 15, y, gray.startX, gray.startY, w, h, gray.width, gray.height); float toolTipAlpha = yOffset / 10; List toolTip = tools.get(selection) @@ -86,40 +86,40 @@ public class ToolSelectionScreen extends Screen { if (toolTipAlpha > 0.25f) { RenderSystem.color4f(.7f, .7f, .8f, toolTipAlpha); - drawTexture(matrixStack, x - 15, y + 33, gray.startX, gray.startY, w, h + 22, gray.width, gray.height); + blit(matrixStack, x - 15, y + 33, gray.startX, gray.startY, w, h + 22, gray.width, gray.height); RenderSystem.color4f(1, 1, 1, 1); if (toolTip.size() > 0) - textRenderer.draw(matrixStack, toolTip.get(0), x - 10, y + 38, 0xEEEEEE + stringAlphaComponent); + font.draw(matrixStack, toolTip.get(0), x - 10, y + 38, 0xEEEEEE + stringAlphaComponent); if (toolTip.size() > 1) - textRenderer.draw(matrixStack, toolTip.get(1), x - 10, y + 50, 0xCCDDFF + stringAlphaComponent); + font.draw(matrixStack, toolTip.get(1), x - 10, y + 50, 0xCCDDFF + stringAlphaComponent); if (toolTip.size() > 2) - textRenderer.draw(matrixStack, toolTip.get(2), x - 10, y + 60, 0xCCDDFF + stringAlphaComponent); + font.draw(matrixStack, toolTip.get(2), x - 10, y + 60, 0xCCDDFF + stringAlphaComponent); if (toolTip.size() > 3) - textRenderer.draw(matrixStack, toolTip.get(3), x - 10, y + 72, 0xCCCCDD + stringAlphaComponent); + font.draw(matrixStack, toolTip.get(3), x - 10, y + 72, 0xCCCCDD + stringAlphaComponent); } RenderSystem.color4f(1, 1, 1, 1); if (tools.size() > 1) { String keyName = AllKeys.TOOL_MENU.getBoundKey(); - int width = client.getWindow() - .getScaledWidth(); + int width = minecraft.getWindow() + .getGuiScaledWidth(); if (!focused) - drawCenteredText(matrixStack, client.fontRenderer, Lang.translate(holdToFocus, keyName), width / 2, + drawCenteredString(matrixStack, minecraft.font, Lang.translate(holdToFocus, keyName), width / 2, y - 10, 0xCCDDFF); else - drawCenteredString(matrixStack, client.fontRenderer, scrollToCycle, width / 2, y - 10, 0xCCDDFF); + drawCenteredString(matrixStack, minecraft.font, scrollToCycle, width / 2, y - 10, 0xCCDDFF); } else { x += 65; } for (int i = 0; i < tools.size(); i++) { - matrixStack.push(); + matrixStack.pushPose(); float alpha = focused ? 1 : .2f; if (i == selection) { matrixStack.translate(0, -10, 0); - drawCenteredString(matrixStack, client.fontRenderer, tools.get(i) + drawCenteredString(matrixStack, minecraft.font, tools.get(i) .getDisplayName() .getString(), x + i * 50 + 24, y + 28, 0xCCDDFF); alpha = 1; @@ -133,10 +133,11 @@ public class ToolSelectionScreen extends Screen { .getIcon() .draw(matrixStack, this, x + i * 50 + 16, y + 11); - matrixStack.pop(); + matrixStack.popPose(); } - matrixStack.pop(); + RenderSystem.enableBlend(); + matrixStack.popPose(); } public void update() { 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..fa35d9228 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java @@ -1,14 +1,12 @@ package com.simibubi.create.foundation.gui; -import java.awt.Color; - import javax.annotation.Nonnull; import org.lwjgl.opengl.GL11; 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.Color; import com.simibubi.create.foundation.utility.Couple; import net.minecraft.client.MainWindow; @@ -24,55 +22,65 @@ 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.resize(mainWindow.getWidth(), mainWindow.getHeight(), Minecraft.ON_OSX); + } + 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.getWidth(), mainWindow.getHeight(), true, + Minecraft.ON_OSX); + framebuffer.setClearColor(0, 0, 0, 0); + framebuffer.enableStencil(); + return framebuffer; + } + public static void drawFramebuffer(float alpha) { MainWindow window = Minecraft.getInstance() .getWindow(); - float vx = (float) window.getScaledWidth(); - float vy = (float) window.getScaledHeight(); - float tx = (float) framebuffer.framebufferWidth / (float) framebuffer.framebufferTextureWidth; - float ty = (float) framebuffer.framebufferHeight / (float) framebuffer.framebufferTextureHeight; + float vx = (float) window.getGuiScaledWidth(); + float vy = (float) window.getGuiScaledHeight(); + float tx = (float) framebuffer.viewWidth / (float) framebuffer.width; + float ty = (float) framebuffer.viewHeight / (float) framebuffer.height; RenderSystem.enableTexture(); RenderSystem.enableDepthTest(); - framebuffer.bindFramebufferTexture(); + framebuffer.bindRead(); Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferbuilder = tessellator.getBuffer(); - bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEXTURE); + BufferBuilder bufferbuilder = tessellator.getBuilder(); + bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX); - bufferbuilder.vertex(0, vy, 0).color(1, 1, 1, alpha).texture(0, 0).endVertex(); - bufferbuilder.vertex(vx, vy, 0).color(1, 1, 1, alpha).texture(tx, 0).endVertex(); - bufferbuilder.vertex(vx, 0, 0).color(1, 1, 1, alpha).texture(tx, ty).endVertex(); - bufferbuilder.vertex(0, 0, 0).color(1, 1, 1, alpha).texture(0, ty).endVertex(); + bufferbuilder.vertex(0, vy, 0).color(1, 1, 1, alpha).uv(0, 0).endVertex(); + bufferbuilder.vertex(vx, vy, 0).color(1, 1, 1, alpha).uv(tx, 0).endVertex(); + bufferbuilder.vertex(vx, 0, 0).color(1, 1, 1, alpha).uv(tx, ty).endVertex(); + bufferbuilder.vertex(0, 0, 0).color(1, 1, 1, alpha).uv(0, ty).endVertex(); - tessellator.draw(); - framebuffer.unbindFramebufferTexture(); + tessellator.end(); + framebuffer.unbindRead(); } 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; @@ -85,19 +93,35 @@ public class UIRenderHelper { int c3 = a3 | color; int c4 = a4 | color; - ms.push(); + ms.pushPose(); ms.translate(x, y, 0); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90)); + ms.mulPose(Vector3f.ZP.rotationDegrees(angle - 90)); streak(ms, breadth / 2, length, c1, c2, c3, c4); - ms.pop(); + ms.popPose(); + } + + public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length, Color c) { + Color color = c.copy().setImmutable(); + int c1 = color.scaleAlpha(0.625f).getRGB(); + int c2 = color.scaleAlpha(0.5f).getRGB(); + int c3 = color.scaleAlpha(0.0625f).getRGB(); + int c4 = color.scaleAlpha(0f).getRGB(); + + ms.pushPose(); + ms.translate(x, y, 0); + ms.mulPose(Vector3f.ZP.rotationDegrees(angle - 90)); + + streak(ms, breadth / 2, length, c1, c2, c3, c4); + + ms.popPose(); } private static void streak(MatrixStack ms, int width, int height, int c1, int c2, int c3, int c4) { double split1 = .5; double split2 = .75; - Matrix4f model = ms.peek().getModel(); + Matrix4f model = ms.last().pose(); RenderSystem.disableAlphaTest(); GuiUtils.drawGradientRect(model, 0, -width, 0, width, (int) (split1 * height), c1, c2); GuiUtils.drawGradientRect(model, 0, -width, (int) (split1 * height), width, (int) (split2 * height), c2, c3); @@ -106,23 +130,23 @@ public class UIRenderHelper { } /** - * @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int) + * @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color) */ public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int breadth, int length, Couple c) { angledGradient(ms, angle, x, y, 0, breadth, length, c); } /** - * @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int) + * @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color) */ public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int z, int breadth, int length, Couple c) { - angledGradient(ms, angle, x, y, z, breadth, length, c.getFirst().getRGB(), c.getSecond().getRGB()); + angledGradient(ms, angle, x, y, z, breadth, length, c.getFirst(), c.getSecond()); } /** - * @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int) + * @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color) */ - public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int breadth, int length, int color1, int color2) { + public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int breadth, int length, Color color1, Color color2) { angledGradient(ms, angle, x, y, 0, breadth, length, color1, color2); } @@ -134,31 +158,31 @@ public class UIRenderHelper { * @param color2 the color at the ending edge * @param breadth the total width of the gradient */ - public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int z, int breadth, int length, int color1, int color2) { - ms.push(); + public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int z, int breadth, int length, Color color1, Color color2) { + ms.pushPose(); ms.translate(x, y, z); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90)); + ms.mulPose(Vector3f.ZP.rotationDegrees(angle - 90)); - Matrix4f model = ms.peek().getModel(); + Matrix4f model = ms.last().pose(); int w = breadth / 2; - GuiUtils.drawGradientRect(model, 0, -w, 0, w, length, color1, color2); + GuiUtils.drawGradientRect(model, 0, -w, 0, w, length, color1.getRGB(), color2.getRGB()); - ms.pop(); + ms.popPose(); } - public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, Couple colors) {breadcrumbArrow(matrixStack, x, y, z, width, height, indent, colors.getFirst().getRGB(), colors.getSecond().getRGB());} + public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, Couple colors) {breadcrumbArrow(matrixStack, x, y, z, width, height, indent, colors.getFirst(), colors.getSecond());} // draws a wide chevron-style breadcrumb arrow pointing left - public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, int startColor, int endColor) { - matrixStack.push(); + public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, Color startColor, Color endColor) { + matrixStack.pushPose(); matrixStack.translate(x - indent, y, z); breadcrumbArrow(matrixStack, width, height, indent, startColor, endColor); - matrixStack.pop(); + matrixStack.popPose(); } - private static void breadcrumbArrow(MatrixStack ms, int width, int height, int indent, int c1, int c2) { + private static void breadcrumbArrow(MatrixStack ms, int width, int height, int indent, Color c1, Color c2) { /* * 0,0 x1,y1 ********************* x4,y4 ***** x7,y7 @@ -183,10 +207,10 @@ public class UIRenderHelper { indent = Math.abs(indent); width = Math.abs(width); - int fc1 = ColorHelper.mixAlphaColors(c1, c2, 0); - int fc2 = ColorHelper.mixAlphaColors(c1, c2, (indent) / (width + 2f * indent)); - int fc3 = ColorHelper.mixAlphaColors(c1, c2, (indent + width) / (width + 2f * indent)); - int fc4 = ColorHelper.mixAlphaColors(c1, c2, 1); + Color fc1 = Color.mixColors(c1, c2, 0); + Color fc2 = Color.mixColors(c1, c2, (indent) / (width + 2f * indent)); + Color fc3 = Color.mixColors(c1, c2, (indent + width) / (width + 2f * indent)); + Color fc4 = Color.mixColors(c1, c2, 1); RenderSystem.disableTexture(); RenderSystem.enableBlend(); @@ -196,35 +220,35 @@ public class UIRenderHelper { RenderSystem.shadeModel(GL11.GL_SMOOTH); Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferbuilder = tessellator.getBuffer(); - Matrix4f model = ms.peek().getModel(); + BufferBuilder bufferbuilder = tessellator.getBuilder(); + Matrix4f model = ms.last().pose(); bufferbuilder.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR); - bufferbuilder.vertex(model, x0, y0, 0).color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x1, y1, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x2, y2, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex(); + bufferbuilder.vertex(model, x0, y0, 0).color(fc1.getRed(), fc1.getGreen(), fc1.getBlue(), fc1.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x1, y1, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x2, y2, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x0, y0, 0).color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x2, y2, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x3, y3, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex(); + bufferbuilder.vertex(model, x0, y0, 0).color(fc1.getRed(), fc1.getGreen(), fc1.getBlue(), fc1.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x2, y2, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x3, y3, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x1, y1, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex(); + bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x1, y1, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x3, y3, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x6, y6, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex(); + bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x6, y6, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x5, y5, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x7, y7, 0).color(fc4 >> 16 & 0xFF, fc4 >> 8 & 0xFF, fc4 & 0xFF, fc4 >> 24 & 0xFF).endVertex(); + bufferbuilder.vertex(model, x5, y5, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x7, y7, 0).color(fc4.getRed(), fc4.getGreen(), fc4.getBlue(), fc4.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x6, y6, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x5, y5, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex(); - bufferbuilder.vertex(model, x8, y8, 0).color(fc4 >> 16 & 0xFF, fc4 >> 8 & 0xFF, fc4 & 0xFF, fc4 >> 24 & 0xFF).endVertex(); + bufferbuilder.vertex(model, x6, y6, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x5, y5, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); + bufferbuilder.vertex(model, x8, y8, 0).color(fc4.getRed(), fc4.getGreen(), fc4.getBlue(), fc4.getAlpha()).endVertex(); - tessellator.draw(); + tessellator.end(); RenderSystem.shadeModel(GL11.GL_FLAT); RenderSystem.disableBlend(); RenderSystem.enableCull(); @@ -242,19 +266,20 @@ public class UIRenderHelper { } private static void drawColoredTexture(MatrixStack ms, Color c, int left, int right, int top, int bot, int z, int tex_width, int tex_height, float tex_left, float tex_top, int sheet_width, int sheet_height) { - drawTexturedQuad(ms.peek().getModel(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float) sheet_width, (tex_left + (float) tex_width) / (float) sheet_width, (tex_top + 0.0F) / (float) sheet_height, (tex_top + (float) tex_height) / (float) sheet_height); + drawTexturedQuad(ms.last().pose(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float) sheet_width, (tex_left + (float) tex_width) / (float) sheet_width, (tex_top + 0.0F) / (float) sheet_height, (tex_top + (float) tex_height) / (float) sheet_height); } private static void drawTexturedQuad(Matrix4f m, Color c, int left, int right, int top, int bot, int z, float u1, float u2, float v1, float v2) { RenderSystem.enableBlend(); - BufferBuilder bufferbuilder = Tessellator.getInstance().getBuffer(); - bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEXTURE); - bufferbuilder.vertex(m, (float) left , (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u1, v2).endVertex(); - bufferbuilder.vertex(m, (float) right, (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u2, v2).endVertex(); - bufferbuilder.vertex(m, (float) right, (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u2, v1).endVertex(); - bufferbuilder.vertex(m, (float) left , (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u1, v1).endVertex(); - bufferbuilder.finishDrawing(); + BufferBuilder bufferbuilder = Tessellator.getInstance().getBuilder(); + bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX); + bufferbuilder.vertex(m, (float) left , (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v2).endVertex(); + bufferbuilder.vertex(m, (float) right, (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v2).endVertex(); + bufferbuilder.vertex(m, (float) right, (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v1).endVertex(); + bufferbuilder.vertex(m, (float) left , (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v1).endVertex(); + bufferbuilder.end(); RenderSystem.enableAlphaTest(); - WorldVertexBufferUploader.draw(bufferbuilder); + WorldVertexBufferUploader.end(bufferbuilder); } + } 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..43c25db2a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/mainMenu/CreateMainMenuScreen.java @@ -0,0 +1,207 @@ +package com.simibubi.create.foundation.gui.mainMenu; + +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; +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.item.TooltipHelper; +import com.simibubi.create.foundation.ponder.content.PonderTagIndexScreen; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; + +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; + + public static final RenderSkyboxCube PANORAMA_RESOURCES = + new RenderSkyboxCube(Create.asResource("textures/gui/title/background/panorama")); + public static final ResourceLocation PANORAMA_OVERLAY_TEXTURES = + new ResourceLocation("textures/gui/title/background/panorama_overlay.png"); + private RenderSkybox vanillaPanorama = new RenderSkybox(MainMenuScreen.CUBE_MAP); + public static RenderSkybox panorama = new RenderSkybox(PANORAMA_RESOURCES); + private long firstRenderTime; + private Button gettingStarted; + + 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.getMillis(); + super.render(ms, mouseX, mouseY, partialTicks); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + float f = (float) (Util.getMillis() - this.firstRenderTime) / 1000.0F; + float alpha = MathHelper.clamp(f, 0.0F, 1.0F); + float elapsedPartials = minecraft.getDeltaFrameTime(); + + if (parent instanceof MainMenuScreen) { + if (alpha < 1) + vanillaPanorama.render(elapsedPartials, 1); + panorama.render(elapsedPartials, alpha); + + minecraft.getTextureManager() + .bind(PANORAMA_OVERLAY_TEXTURES); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + blit(ms, 0, 0, this.width, this.height, 0.0F, 0.0F, 16, 128, 16, 128); + } + + RenderSystem.enableDepthTest(); + + for (int side : Iterate.positiveAndNegative) { + ms.pushPose(); + ms.translate(width / 2, 60, 200); + ms.scale(24 * side, 24 * side, 32); + ms.translate(-1.75 * ((alpha * alpha) / 2f + .5f), .25f, 0); + MatrixTransformStack.of(ms) + .rotateX(45); + GuiGameElement.of(AllBlocks.LARGE_COGWHEEL.getDefaultState()) + .rotateBlock(0, Util.getMillis() / 32f * side, 0) + .render(ms); + ms.translate(-1, 0, -1); + GuiGameElement.of(AllBlocks.COGWHEEL.getDefaultState()) + .rotateBlock(0, Util.getMillis() / -16f * side + 22.5f, 0) + .render(ms); + ms.popPose(); + } + + ms.pushPose(); + ms.translate(width / 2 - 32, 32, -10); + ms.pushPose(); + ms.scale(0.25f, 0.25f, 0.25f); + AllGuiTextures.LOGO.draw(ms, 0, 0); + ms.popPose(); + new BoxElement().withBackground(0x88_000000) + .flatBorder(new Color(0x01_000000)) + .at(-32, 56, 100) + .withBounds(128, 11) + .render(ms); + ms.popPose(); + + ms.pushPose(); + ms.translate(0, 0, 200); + drawCenteredString(ms, font, new StringTextComponent(Create.NAME).withStyle(TextFormatting.BOLD) + .append( + new StringTextComponent(" v" + Create.VERSION).withStyle(TextFormatting.BOLD, TextFormatting.WHITE)), + width / 2, 89, 0xff_E4BB67); + ms.popPose(); + + 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)))); + + gettingStarted = new Button(center + 2, yStart + 48 + -16, bShortWidth, bHeight, + Lang.translate("menu.ponder_index"), $ -> linkTo(new PonderTagIndexScreen())); + gettingStarted.active = !(parent instanceof MainMenuScreen); + 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)); + + if (parent instanceof MainMenuScreen) { + if (mouseX < gettingStarted.x || mouseX > gettingStarted.x + 98) + return; + if (mouseY < gettingStarted.y || mouseY > gettingStarted.y + 20) + return; + renderComponentTooltip(ms, TooltipHelper.cutTextComponent(Lang.translate("menu.only_ingame"), TextFormatting.GRAY, + TextFormatting.GRAY), mouseX, mouseY); + } + } + + 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.getPlatform() + .openUri(url); + this.minecraft.setScreen(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/AbstractSimiWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/AbstractSimiWidget.java index f8539a3d3..48e73d983 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/AbstractSimiWidget.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/AbstractSimiWidget.java @@ -56,7 +56,7 @@ public abstract class AbstractSimiWidget extends Widget { @Override public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { if (visible) { - hovered = isMouseOver(mouseX, mouseY); + isHovered = isMouseOver(mouseX, mouseY); beforeRender(ms, mouseX, mouseY, partialTicks); renderButton(ms, mouseX, mouseY, partialTicks); afterRender(ms, mouseX, mouseY, partialTicks); @@ -73,11 +73,11 @@ public abstract class AbstractSimiWidget extends Widget { } protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - ms.push(); + ms.pushPose(); } protected void afterRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - ms.pop(); + ms.popPose(); } public void runCallback(double mouseX, double mouseY) { 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..6c9a844f5 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,5 @@ package com.simibubi.create.foundation.gui.widgets; -import java.awt.Color; import java.util.function.Function; import javax.annotation.Nonnull; @@ -9,24 +8,28 @@ 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.Color; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.animation.LerpedFloat; public class BoxWidget extends ElementWidget { - public static final Function gradientFactory = (box) -> (ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, w/2, -2, w + 4, h + 4, box.gradientColor1.getRGB(), box.gradientColor2.getRGB()); + public static final Function gradientFactory = (box) -> (ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, w/2, -2, w + 4, h + 4, box.gradientColor1, box.gradientColor2); protected BoxElement box; protected Color customBorderTop; protected Color customBorderBot; + protected Color customBackground; 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).copy(); + private Color colorTarget2 = Theme.c(getIdleTheme(), false).copy(); public BoxWidget() { this(0, 0); @@ -68,6 +71,12 @@ public class BoxWidget extends ElementWidget { return (T) this; } + public T withCustomBackground(Color color) { + this.customBackground = color; + //noinspection unchecked + return (T) this; + } + public T animateColors(boolean b) { this.animateColors = b; //noinspection unchecked @@ -84,8 +93,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); } @@ -93,11 +102,11 @@ public class BoxWidget extends ElementWidget { protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { super.beforeRender(ms, mouseX, mouseY, partialTicks); - if (hovered != wasHovered) { + if (isHovered != wasHovered) { startGradientAnimation( getColorForState(true), getColorForState(false), - hovered + isHovered ); } @@ -106,8 +115,8 @@ public class BoxWidget extends ElementWidget { gradientColor2 = colorTarget2; } else { float animationValue = 1 - Math.abs(colorAnimation.getValue(partialTicks)); - gradientColor1 = ColorHelper.mixColors(previousColor1, colorTarget1, animationValue); - gradientColor2 = ColorHelper.mixColors(previousColor2, colorTarget2, animationValue); + gradientColor1 = Color.mixColors(previousColor1, colorTarget1, animationValue); + gradientColor2 = Color.mixColors(previousColor2, colorTarget2, animationValue); } } @@ -119,7 +128,7 @@ public class BoxWidget extends ElementWidget { return; box.withAlpha(fadeValue); - box.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_TRANSPARENT)) + box.withBackground(customBackground != null ? customBackground : Theme.c(Theme.Key.PONDER_BACKGROUND_TRANSPARENT)) .gradientBorder(gradientColor1, gradientColor2) .at(x, y, z) .withBounds(width, height) @@ -127,7 +136,7 @@ public class BoxWidget extends ElementWidget { super.renderButton(ms, mouseX, mouseY, partialTicks); - wasHovered = hovered; + wasHovered = isHovered; } @Override @@ -175,23 +184,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 (isHovered) { 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/ElementWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/ElementWidget.java index 499e81587..6bb91486d 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/ElementWidget.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/ElementWidget.java @@ -33,7 +33,7 @@ public class ElementWidget extends AbstractSimiWidget { public ElementWidget(int x, int y, int width, int height) { super(x, y, width, height); } - + public T showingElement(RenderElement element) { this.element = element; //noinspection unchecked @@ -91,6 +91,12 @@ public class ElementWidget extends AbstractSimiWidget { return (T) this; } + /** + * Rescaling and its effects aren't properly tested with most elements. + * Thought it should work fine when using a TextStencilElement. + * Check BaseConfigScreen's title for such an example. + */ + @Deprecated public T rescaleElement(float rescaleSizeX, float rescaleSizeY) { this.rescaleElement = true; this.rescaleSizeX = rescaleSizeX; @@ -124,18 +130,24 @@ public class ElementWidget extends AbstractSimiWidget { @Override public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - ms.push(); + ms.pushPose(); ms.translate(x + paddingX, y + paddingY, z); float innerWidth = width - 2 * paddingX; float innerHeight = height - 2 * paddingY; + float eX = element.getX(), eY = element.getY(); if (rescaleElement) { float xScale = innerWidth / rescaleSizeX; float yScale = innerHeight / rescaleSizeY; ms.scale(xScale, yScale, 1); - element.at(element.getX() / xScale, element.getY() / yScale); + element.at(eX / xScale, eY / yScale); + innerWidth /= xScale; + innerHeight /= yScale; } element.withBounds((int) innerWidth, (int) innerHeight).render(ms); - ms.pop(); + ms.popPose(); + if (rescaleElement) { + element.at(eX, eY); + } } public RenderElement getRenderElement() { 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..8209c907a 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 @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.gui.widgets; +import javax.annotation.Nonnull; + import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.foundation.gui.AllGuiTextures; @@ -7,8 +9,6 @@ import com.simibubi.create.foundation.gui.AllIcons; import net.minecraft.util.text.ITextComponent; -import javax.annotation.Nonnull; - public class IconButton extends AbstractSimiWidget { private AllIcons icon; @@ -22,15 +22,15 @@ public class IconButton extends AbstractSimiWidget { @Override public void renderButton(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { if (this.visible) { - this.hovered = + this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; AllGuiTextures button = (pressed || !active) ? button = AllGuiTextures.BUTTON_DOWN - : (hovered) ? AllGuiTextures.BUTTON_HOVER : AllGuiTextures.BUTTON; + : (isHovered) ? AllGuiTextures.BUTTON_HOVER : AllGuiTextures.BUTTON; RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); AllGuiTextures.BUTTON.bind(); - drawTexture(matrixStack, x, y, button.startX, button.startY, button.width, button.height); + blit(matrixStack, x, y, button.startX, button.startY, button.width, button.height); icon.draw(matrixStack, this, x + 1, y + 1); } } @@ -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/gui/widgets/Label.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/Label.java index 3c7d904ca..1fc0a881d 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/Label.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/Label.java @@ -20,8 +20,8 @@ public class Label extends AbstractSimiWidget { protected FontRenderer font; public Label(int x, int y, ITextComponent text) { - super(x, y, Minecraft.getInstance().fontRenderer.getWidth(text), 10); - font = Minecraft.getInstance().fontRenderer; + super(x, y, Minecraft.getInstance().font.width(text), 10); + font = Minecraft.getInstance().font; this.text = new StringTextComponent("Label"); color = 0xFFFFFF; hasShadow = false; @@ -44,15 +44,15 @@ public class Label extends AbstractSimiWidget { } public void setTextAndTrim(ITextComponent newText, boolean trimFront, int maxWidthPx) { - FontRenderer fontRenderer = Minecraft.getInstance().fontRenderer; + FontRenderer fontRenderer = Minecraft.getInstance().font; - if (fontRenderer.getWidth(newText) <= maxWidthPx) { + if (fontRenderer.width(newText) <= maxWidthPx) { text = newText; return; } String trim = "..."; - int trimWidth = fontRenderer.getStringWidth(trim); + int trimWidth = fontRenderer.width(trim); String raw = newText.getString(); StringBuilder builder = new StringBuilder(raw); @@ -62,7 +62,7 @@ public class Label extends AbstractSimiWidget { for (int i = startIndex; i != endIndex; i += step) { String sub = builder.substring(trimFront ? i : startIndex, trimFront ? endIndex + 1 : i + 1); - if (fontRenderer.getWidth(new StringTextComponent(sub).setStyle(newText.getStyle())) + trimWidth <= maxWidthPx) { + if (fontRenderer.width(new StringTextComponent(sub).setStyle(newText.getStyle())) + trimWidth <= maxWidthPx) { text = new StringTextComponent(trimFront ? trim + sub : sub + trim).setStyle(newText.getStyle()); return; } @@ -78,12 +78,12 @@ public class Label extends AbstractSimiWidget { return; RenderSystem.color4f(1, 1, 1, 1); - IFormattableTextComponent copy = text.copy(); + IFormattableTextComponent copy = text.plainCopy(); if (suffix != null && !suffix.isEmpty()) copy.append(suffix); if (hasShadow) - font.drawWithShadow(matrixStack, copy, x, y, color); + font.drawShadow(matrixStack, copy, x, y, color); else font.draw(matrixStack, copy, x, y, color); } diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/ScrollInput.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/ScrollInput.java index 146874bbf..8329c530c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/ScrollInput.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/ScrollInput.java @@ -91,7 +91,7 @@ public class ScrollInput extends AbstractSimiWidget { @Override public boolean mouseScrolled(double mouseX, double mouseY, double delta) { - if (!hovered) + if (!isHovered) return false; StepContext context = new StepContext(); @@ -137,9 +137,9 @@ public class ScrollInput extends AbstractSimiWidget { protected void updateTooltip() { toolTip.clear(); - toolTip.add(title.copy().formatted(TextFormatting.BLUE)); - toolTip.add(scrollToModify.copy().formatted(TextFormatting.ITALIC, TextFormatting.DARK_GRAY)); - toolTip.add(shiftScrollsFaster.copy().formatted(TextFormatting.ITALIC, TextFormatting.DARK_GRAY)); + toolTip.add(title.plainCopy().withStyle(TextFormatting.BLUE)); + toolTip.add(scrollToModify.plainCopy().withStyle(TextFormatting.ITALIC, TextFormatting.DARK_GRAY)); + toolTip.add(shiftScrollsFaster.plainCopy().withStyle(TextFormatting.ITALIC, TextFormatting.DARK_GRAY)); } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/SelectionScrollInput.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/SelectionScrollInput.java index c056984fe..4fb8329b7 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/SelectionScrollInput.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/SelectionScrollInput.java @@ -40,7 +40,7 @@ public class SelectionScrollInput extends ScrollInput { @Override protected void updateTooltip() { toolTip.clear(); - toolTip.add(title.copy().formatted(TextFormatting.BLUE)); + toolTip.add(title.plainCopy().withStyle(TextFormatting.BLUE)); int min = Math.min(this.max - 16, state - 7); int max = Math.max(this.min + 16, state + 8); min = Math.max(min, this.min); @@ -48,19 +48,19 @@ public class SelectionScrollInput extends ScrollInput { if (this.min + 1 == min) min--; if (min > this.min) - toolTip.add(new StringTextComponent("> ...").formatted(TextFormatting.GRAY)); + toolTip.add(new StringTextComponent("> ...").withStyle(TextFormatting.GRAY)); if (this.max - 1 == max) max++; for (int i = min; i < max; i++) { if (i == state) - toolTip.add(StringTextComponent.EMPTY.copy().append("-> ").append(options.get(i)).formatted(TextFormatting.WHITE)); + toolTip.add(StringTextComponent.EMPTY.plainCopy().append("-> ").append(options.get(i)).withStyle(TextFormatting.WHITE)); else - toolTip.add(StringTextComponent.EMPTY.copy().append("> ").append(options.get(i)).formatted(TextFormatting.GRAY)); + toolTip.add(StringTextComponent.EMPTY.plainCopy().append("> ").append(options.get(i)).withStyle(TextFormatting.GRAY)); } if (max < this.max) - toolTip.add(new StringTextComponent("> ...").formatted(TextFormatting.GRAY)); + toolTip.add(new StringTextComponent("> ...").withStyle(TextFormatting.GRAY)); - toolTip.add(scrollToSelect.copy().formatted(TextFormatting.DARK_GRAY, TextFormatting.ITALIC)); + toolTip.add(scrollToSelect.plainCopy().withStyle(TextFormatting.DARK_GRAY, TextFormatting.ITALIC)); } } diff --git a/src/main/java/com/simibubi/create/foundation/item/CreateItemGroupBase.java b/src/main/java/com/simibubi/create/foundation/item/CreateItemGroupBase.java index 379c84c76..1b354c712 100644 --- a/src/main/java/com/simibubi/create/foundation/item/CreateItemGroupBase.java +++ b/src/main/java/com/simibubi/create/foundation/item/CreateItemGroupBase.java @@ -30,7 +30,7 @@ public abstract class CreateItemGroupBase extends ItemGroup { @Override @OnlyIn(Dist.CLIENT) - public void fill(NonNullList items) { + public void fillItemList(NonNullList items) { addItems(items, true); addBlocks(items); addItems(items, false); @@ -42,7 +42,7 @@ public abstract class CreateItemGroupBase extends ItemGroup { Block def = entry.get(); Item item = def.asItem(); if (item != Items.AIR) - def.fillItemGroup(this, items); + def.fillItemCategory(this, items); } } @@ -50,20 +50,17 @@ public abstract class CreateItemGroupBase extends ItemGroup { public void addItems(NonNullList items, boolean specialItems) { Minecraft mc = Minecraft.getInstance(); ItemRenderer itemRenderer = mc.getItemRenderer(); - ClientWorld world = mc.world; + ClientWorld world = mc.level; for (RegistryEntry entry : getItems()) { Item item = entry.get(); if (item instanceof BlockItem) continue; ItemStack stack = new ItemStack(item); - IBakedModel model = itemRenderer.getItemModelWithOverrides(stack, world, null); - if (AllSections.of(stack) != AllSections.KINETICS) { - if (specialItems) - continue; - } else if (model.isGui3d() != specialItems) + IBakedModel model = itemRenderer.getModel(stack, world, null); + if (model.isGui3d() != specialItems) continue; - item.fillItemGroup(this, items); + item.fillItemCategory(this, items); } } diff --git a/src/main/java/com/simibubi/create/foundation/item/HiddenIngredientItem.java b/src/main/java/com/simibubi/create/foundation/item/HiddenIngredientItem.java index c565d81e9..899dcce8e 100644 --- a/src/main/java/com/simibubi/create/foundation/item/HiddenIngredientItem.java +++ b/src/main/java/com/simibubi/create/foundation/item/HiddenIngredientItem.java @@ -12,10 +12,10 @@ public class HiddenIngredientItem extends Item { } @Override - public void fillItemGroup(ItemGroup p_150895_1_, NonNullList p_150895_2_) { - if (p_150895_1_ != ItemGroup.SEARCH) + public void fillItemCategory(ItemGroup p_150895_1_, NonNullList p_150895_2_) { + if (p_150895_1_ != ItemGroup.TAB_SEARCH) return; - super.fillItemGroup(p_150895_1_, p_150895_2_); + super.fillItemCategory(p_150895_1_, p_150895_2_); } } diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java b/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java index 6c8a9afd0..2b8bac433 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java @@ -20,16 +20,15 @@ import static net.minecraft.util.text.TextFormatting.YELLOW; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; import com.simibubi.create.content.contraptions.base.IRotate.StressImpact; import com.simibubi.create.content.contraptions.components.fan.EncasedFanBlock; -import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineBlock; import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineBlock; import com.simibubi.create.content.contraptions.components.waterwheel.WaterWheelBlock; +import com.simibubi.create.foundation.block.BlockStressValues; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.CKinetics; import com.simibubi.create.foundation.utility.Lang; @@ -38,18 +37,16 @@ import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.inventory.EquipmentSlotType; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TextFormatting; -import net.minecraftforge.common.ForgeConfigSpec.ConfigValue; public class ItemDescription { public static final ItemDescription MISSING = new ItemDescription(null); public static ITextComponent trim = - new StringTextComponent(" ").formatted(WHITE, STRIKETHROUGH); + new StringTextComponent(" ").withStyle(WHITE, STRIKETHROUGH); public enum Palette { @@ -91,30 +88,34 @@ public class ItemDescription { public static List getKineticStats(Block block) { List list = new ArrayList<>(); - boolean isEngine = block instanceof EngineBlock; CKinetics config = AllConfigs.SERVER.kinetics; - SpeedLevel minimumRequiredSpeedLevel = - isEngine ? SpeedLevel.NONE : ((IRotate) block).getMinimumRequiredSpeedLevel(); - boolean hasSpeedRequirement = minimumRequiredSpeedLevel != SpeedLevel.NONE; - ResourceLocation id = block.getRegistryName(); - Map> impacts = config.stressValues.getImpacts(); - Map> capacities = config.stressValues.getCapacities(); - boolean hasStressImpact = impacts.containsKey(id) && impacts.get(id) - .get() > 0 && StressImpact.isEnabled(); - boolean hasStressCapacity = capacities.containsKey(id) && StressImpact.isEnabled(); - boolean hasGlasses = - AllItems.GOGGLES.get() == Minecraft.getInstance().player.getItemStackFromSlot(EquipmentSlotType.HEAD) - .getItem(); - ITextComponent rpmUnit = Lang.translate("generic.unit.rpm"); + + boolean hasGoggles = + AllItems.GOGGLES.isIn(Minecraft.getInstance().player.getItemBySlot(EquipmentSlotType.HEAD)); + + SpeedLevel minimumRequiredSpeedLevel; + boolean showStressImpact; + if (!(block instanceof IRotate)) { + minimumRequiredSpeedLevel = SpeedLevel.NONE; + showStressImpact = true; + } else { + minimumRequiredSpeedLevel = ((IRotate) block).getMinimumRequiredSpeedLevel(); + showStressImpact = !((IRotate) block).hideStressImpact(); + } + + boolean hasSpeedRequirement = minimumRequiredSpeedLevel != SpeedLevel.NONE; + boolean hasStressImpact = StressImpact.isEnabled() && showStressImpact && BlockStressValues.getImpact(block) > 0; + boolean hasStressCapacity = StressImpact.isEnabled() && BlockStressValues.hasCapacity(block); + if (hasSpeedRequirement) { List speedLevels = Lang.translatedOptions("tooltip.speedRequirement", "none", "medium", "high"); int index = minimumRequiredSpeedLevel.ordinal(); IFormattableTextComponent level = - new StringTextComponent(makeProgressBar(3, index)).formatted(minimumRequiredSpeedLevel.getTextColor()); + new StringTextComponent(makeProgressBar(3, index)).withStyle(minimumRequiredSpeedLevel.getTextColor()); - if (hasGlasses) + if (hasGoggles) level.append(String.valueOf(minimumRequiredSpeedLevel.getSpeedValue())) .append(rpmUnit) .append("+"); @@ -122,44 +123,41 @@ public class ItemDescription { level.append(speedLevels.get(index)); list.add(Lang.translate("tooltip.speedRequirement") - .formatted(GRAY)); + .withStyle(GRAY)); list.add(level); } - if (hasStressImpact && !(!isEngine && ((IRotate) block).hideStressImpact())) { + if (hasStressImpact) { List stressLevels = Lang.translatedOptions("tooltip.stressImpact", "low", "medium", "high"); - double impact = impacts.get(id) - .get(); + double impact = BlockStressValues.getImpact(block); StressImpact impactId = impact >= config.highStressImpact.get() ? StressImpact.HIGH : (impact >= config.mediumStressImpact.get() ? StressImpact.MEDIUM : StressImpact.LOW); int index = impactId.ordinal(); IFormattableTextComponent level = - new StringTextComponent(makeProgressBar(3, index)).formatted(impactId.getAbsoluteColor()); + new StringTextComponent(makeProgressBar(3, index)).withStyle(impactId.getAbsoluteColor()); - if (hasGlasses) - level.append(impacts.get(id) - .get() + "x ") + if (hasGoggles) + level.append(impact + "x ") .append(rpmUnit); else level.append(stressLevels.get(index)); list.add(Lang.translate("tooltip.stressImpact") - .formatted(GRAY)); + .withStyle(GRAY)); list.add(level); } if (hasStressCapacity) { List stressCapacityLevels = Lang.translatedOptions("tooltip.capacityProvided", "low", "medium", "high"); - double capacity = capacities.get(id) - .get(); + double capacity = BlockStressValues.getCapacity(block); StressImpact impactId = capacity >= config.highCapacity.get() ? StressImpact.LOW : (capacity >= config.mediumCapacity.get() ? StressImpact.MEDIUM : StressImpact.HIGH); int index = StressImpact.values().length - 2 - impactId.ordinal(); IFormattableTextComponent level = - new StringTextComponent(makeProgressBar(3, index)).formatted(impactId.getAbsoluteColor()); + new StringTextComponent(makeProgressBar(3, index)).withStyle(impactId.getAbsoluteColor()); - if (hasGlasses) + if (hasGoggles) level.append(capacity + "x ") .append(rpmUnit); else @@ -170,14 +168,14 @@ public class ItemDescription { // " " + DARK_GRAY + TextFormatting.ITALIC + Lang.translate("tooltip.capacityProvided.asGenerator"); list.add(Lang.translate("tooltip.capacityProvided") - .formatted(GRAY)); + .withStyle(GRAY)); list.add(level); IFormattableTextComponent genSpeed = generatorSpeed(block, rpmUnit); if (!genSpeed.getString() .isEmpty()) list.add(new StringTextComponent(" ").append(genSpeed) - .formatted(DARK_GRAY)); + .withStyle(DARK_GRAY)); } // if (hasSpeedRequirement || hasStressImpact || hasStressCapacity) @@ -196,13 +194,13 @@ public class ItemDescription { } public ItemDescription withBehaviour(String condition, String behaviour) { - add(linesOnShift, new StringTextComponent(condition).formatted(GRAY)); + add(linesOnShift, new StringTextComponent(condition).withStyle(GRAY)); addStrings(linesOnShift, cutStringTextComponent(behaviour, palette.color, palette.hColor, 1)); return this; } public ItemDescription withControl(String condition, String action) { - add(linesOnCtrl, new StringTextComponent(condition).formatted(GRAY)); + add(linesOnCtrl, new StringTextComponent(condition).withStyle(GRAY)); addStrings(linesOnCtrl, cutStringTextComponent(action, palette.color, palette.hColor, 1)); return this; } @@ -212,10 +210,8 @@ public class ItemDescription { boolean hasControls = !linesOnCtrl.isEmpty(); if (hasDescription || hasControls) { - String[] holdDesc = TooltipHelper.getUnformattedDeepText(Lang.translate("tooltip.holdForDescription", "$")) - .split("\\$"); - String[] holdCtrl = TooltipHelper.getUnformattedDeepText(Lang.translate("tooltip.holdForControls", "$")) - .split("\\$"); + String[] holdDesc = Lang.translate("tooltip.holdForDescription", "$").getString().split("\\$"); + String[] holdCtrl = Lang.translate("tooltip.holdForControls", "$").getString().split("\\$"); IFormattableTextComponent keyShift = Lang.translate("tooltip.keyShift"); IFormattableTextComponent keyCtrl = Lang.translate("tooltip.keyCtrl"); for (List list : Arrays.asList(lines, linesOnShift, linesOnCtrl)) { @@ -229,19 +225,19 @@ public class ItemDescription { if (hasControls) { IFormattableTextComponent tabBuilder = new StringTextComponent(""); - tabBuilder.append(new StringTextComponent(holdCtrl[0]).formatted(DARK_GRAY)); - tabBuilder.append(keyCtrl.copy() - .formatted(ctrl ? WHITE : GRAY)); - tabBuilder.append(new StringTextComponent(holdCtrl[1]).formatted(DARK_GRAY)); + tabBuilder.append(new StringTextComponent(holdCtrl[0]).withStyle(DARK_GRAY)); + tabBuilder.append(keyCtrl.plainCopy() + .withStyle(ctrl ? WHITE : GRAY)); + tabBuilder.append(new StringTextComponent(holdCtrl[1]).withStyle(DARK_GRAY)); list.add(0, tabBuilder); } if (hasDescription) { IFormattableTextComponent tabBuilder = new StringTextComponent(""); - tabBuilder.append(new StringTextComponent(holdDesc[0]).formatted(DARK_GRAY)); - tabBuilder.append(keyShift.copy() - .formatted(shift ? WHITE : GRAY)); - tabBuilder.append(new StringTextComponent(holdDesc[1]).formatted(DARK_GRAY)); + tabBuilder.append(new StringTextComponent(holdDesc[0]).withStyle(DARK_GRAY)); + tabBuilder.append(keyShift.plainCopy() + .withStyle(shift ? WHITE : GRAY)); + tabBuilder.append(new StringTextComponent(holdDesc[1]).withStyle(DARK_GRAY)); list.add(0, tabBuilder); } @@ -324,7 +320,7 @@ public class ItemDescription { } return !value.equals("") ? Lang.translate("tooltip.generationSpeed", value, unitRPM) - : StringTextComponent.EMPTY.copy(); + : StringTextComponent.EMPTY.plainCopy(); } } 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..fdcdbb801 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java @@ -26,7 +26,7 @@ public class ItemHelper { public static void dropContents(World world, BlockPos pos, IItemHandler inv) { for (int slot = 0; slot < inv.getSlots(); slot++) - InventoryHelper.spawnItemStack(world, pos.getX(), pos.getY(), pos.getZ(), inv.getStackInSlot(slot)); + InventoryHelper.dropItemStack(world, pos.getX(), pos.getY(), pos.getZ(), inv.getStackInSlot(slot)); } public static List multipliedOutput(ItemStack in, ItemStack out) { @@ -98,8 +98,8 @@ public class ItemHelper { Ingredients: for (Ingredient igd : recipeIngredients) { for (Pair pair : actualIngredients) { ItemStack[] stacks1 = pair.getFirst() - .getMatchingStacks(); - ItemStack[] stacks2 = igd.getMatchingStacks(); + .getItems(); + ItemStack[] stacks2 = igd.getItems(); if (stacks1.length != stacks2.length) continue; for (int i = 0; i <= stacks1.length; i++) { @@ -108,7 +108,7 @@ public class ItemHelper { .increment(); continue Ingredients; } - if (!ItemStack.areItemStacksEqual(stacks1[i], stacks2[i])) + if (!ItemStack.matches(stacks1[i], stacks2[i])) break; } } @@ -118,11 +118,11 @@ public class ItemHelper { } public static boolean matchIngredients(Ingredient i1, Ingredient i2) { - ItemStack[] stacks1 = i1.getMatchingStacks(); - ItemStack[] stacks2 = i2.getMatchingStacks(); + ItemStack[] stacks1 = i1.getItems(); + ItemStack[] stacks2 = i2.getItems(); if (stacks1.length == stacks2.length) { for (int i = 0; i < stacks1.length; i++) - if (!ItemStack.areItemsEqual(stacks1[i], stacks2[i])) + if (!ItemStack.isSame(stacks1[i], stacks2[i])) return false; return true; } @@ -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/SmartInventory.java b/src/main/java/com/simibubi/create/foundation/item/SmartInventory.java index 7be383918..f8ab9b2f7 100644 --- a/src/main/java/com/simibubi/create/foundation/item/SmartInventory.java +++ b/src/main/java/com/simibubi/create/foundation/item/SmartInventory.java @@ -105,8 +105,8 @@ public class SmartInventory extends RecipeWrapper } @Override - public ItemStack getStackInSlot(int slot) { - return super.getStackInSlot(slot); + public ItemStack getItem(int slot) { + return super.getItem(slot); } public int getStackLimit(int slot, @Nonnull ItemStack stack) { @@ -162,7 +162,7 @@ public class SmartInventory extends RecipeWrapper @Override public ItemStack getStackInSlotIntermediate(int slot) { - return getStackInSlot(slot); + return getItem(slot); } } diff --git a/src/main/java/com/simibubi/create/foundation/item/TagDependentIngredientItem.java b/src/main/java/com/simibubi/create/foundation/item/TagDependentIngredientItem.java index 55e6f5d8f..0b10e3196 100644 --- a/src/main/java/com/simibubi/create/foundation/item/TagDependentIngredientItem.java +++ b/src/main/java/com/simibubi/create/foundation/item/TagDependentIngredientItem.java @@ -18,15 +18,15 @@ public class TagDependentIngredientItem extends Item { } @Override - public void fillItemGroup(ItemGroup p_150895_1_, NonNullList p_150895_2_) { + public void fillItemCategory(ItemGroup p_150895_1_, NonNullList p_150895_2_) { if (!shouldHide()) - super.fillItemGroup(p_150895_1_, p_150895_2_); + super.fillItemCategory(p_150895_1_, p_150895_2_); } public boolean shouldHide() { - ITag tag = ItemTags.getCollection() - .get(this.tag); - return tag == null || tag.values() + ITag tag = ItemTags.getAllTags() + .getTag(this.tag); + return tag == null || tag.getValues() .isEmpty(); } 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..5b1704b5d 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 { @@ -48,26 +45,26 @@ public class TooltipHelper { public static IFormattableTextComponent holdShift(Palette color, boolean highlighted) { return Lang.translate("tooltip.holdForDescription", Lang.translate("tooltip.keyShift") - .formatted(TextFormatting.GRAY)) - .formatted(TextFormatting.DARK_GRAY); + .withStyle(TextFormatting.GRAY)) + .withStyle(TextFormatting.DARK_GRAY); } public static void addHint(List tooltip, String hintKey, Object... messageParams) { ITextComponent spacing = IHaveGoggleInformation.componentSpacing; - tooltip.add(spacing.copy() + tooltip.add(spacing.plainCopy() .append(Lang.translate(hintKey + ".title")) - .formatted(GOLD)); + .withStyle(GOLD)); ITextComponent hint = Lang.translate(hintKey); List cutComponent = TooltipHelper.cutTextComponent(hint, GRAY, TextFormatting.WHITE); for (ITextComponent component : cutComponent) - tooltip.add(spacing.copy() + tooltip.add(spacing.plainCopy() .append(component)); } public static void referTo(IItemProvider item, Supplier itemWithTooltip) { tooltipReferrals.put(item.asItem(), () -> itemWithTooltip.get() .asItem() - .getTranslationKey()); + .getDescriptionId()); } public static void referTo(IItemProvider item, String string) { @@ -76,7 +73,7 @@ public class TooltipHelper { @Deprecated public static List cutString(ITextComponent s, TextFormatting defaultColor, TextFormatting highlightColor) { - return cutString(s.getUnformattedComponentText(), defaultColor, highlightColor, 0); + return cutString(s.getContents(), defaultColor, highlightColor, 0); } @Deprecated @@ -95,7 +92,7 @@ public class TooltipHelper { words.add(word); } - FontRenderer font = Minecraft.getInstance().fontRenderer; + FontRenderer font = Minecraft.getInstance().font; List lines = FontHelper.cutString(font, markedUp, maxWidthPerLine); // Format @@ -127,7 +124,7 @@ public class TooltipHelper { public static List cutTextComponent(ITextComponent c, TextFormatting defaultColor, TextFormatting highlightColor, int indent) { - String s = getUnformattedDeepText(c); + String s = c.getString(); // Apply markup String markedUp = s;// .replaceAll("_([^_]+)_", highlightColor + "$1" + defaultColor); @@ -143,12 +140,12 @@ public class TooltipHelper { } // Apply hard wrap - FontRenderer font = Minecraft.getInstance().fontRenderer; + FontRenderer font = Minecraft.getInstance().font; List lines = new LinkedList<>(); StringBuilder currentLine = new StringBuilder(); int width = 0; for (String word : words) { - int newWidth = font.getStringWidth(word.replaceAll("_", "")); + int newWidth = font.width(word.replaceAll("_", "")); if (width + newWidth > maxWidthPerLine) { if (width > 0) { String line = currentLine.toString(); @@ -169,16 +166,16 @@ public class TooltipHelper { // Format IFormattableTextComponent lineStart = new StringTextComponent(Strings.repeat(" ", indent)); - lineStart.formatted(defaultColor); + lineStart.withStyle(defaultColor); List formattedLines = new ArrayList<>(lines.size()); Couple f = Couple.create(highlightColor, defaultColor); boolean currentlyHighlighted = false; for (String string : lines) { - IFormattableTextComponent currentComponent = lineStart.copy(); + IFormattableTextComponent currentComponent = lineStart.plainCopy(); String[] split = string.split("_"); for (String part : split) { - currentComponent.append(new StringTextComponent(part).formatted(f.get(currentlyHighlighted))); + currentComponent.append(new StringTextComponent(part).withStyle(f.get(currentlyHighlighted))); currentlyHighlighted = !currentlyHighlighted; } @@ -231,7 +228,7 @@ public class TooltipHelper { private static void checkLocale() { Language currentLanguage = Minecraft.getInstance() .getLanguageManager() - .getCurrentLanguage(); + .getSelected(); if (cachedLanguage != currentLanguage) { cachedTooltips.clear(); cachedLanguage = currentLanguage; @@ -241,7 +238,7 @@ public class TooltipHelper { public static boolean hasTooltip(ItemStack stack, PlayerEntity player) { checkLocale(); - boolean hasGlasses = AllItems.GOGGLES.isIn(player.getItemStackFromSlot(EquipmentSlotType.HEAD)); + boolean hasGlasses = AllItems.GOGGLES.isIn(player.getItemBySlot(EquipmentSlotType.HEAD)); if (hasGlasses != gogglesMode) { gogglesMode = hasGlasses; @@ -267,7 +264,7 @@ public class TooltipHelper { private static boolean findTooltip(ItemStack stack) { String key = getTooltipTranslationKey(stack); - if (I18n.hasKey(key)) { + if (I18n.exists(key)) { cachedTooltips.put(key, buildToolTip(key, stack)); return true; } @@ -277,16 +274,12 @@ 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"; // Summary - if (I18n.hasKey(summaryKey)) - tooltip = tooltip.withSummary(new StringTextComponent(I18n.format(summaryKey))); + if (I18n.exists(summaryKey)) + tooltip = tooltip.withSummary(new StringTextComponent(I18n.get(summaryKey))); // Requirements // if (stack.getItem() instanceof BlockItem) { @@ -300,21 +293,21 @@ public class TooltipHelper { for (int i = 1; i < 100; i++) { String conditionKey = translationKey + ".condition" + i; String behaviourKey = translationKey + ".behaviour" + i; - if (!I18n.hasKey(conditionKey)) + if (!I18n.exists(conditionKey)) break; if (i == 1) tooltip.getLinesOnShift() .add(new StringTextComponent("")); - tooltip.withBehaviour(I18n.format(conditionKey), I18n.format(behaviourKey)); + tooltip.withBehaviour(I18n.get(conditionKey), I18n.get(behaviourKey)); } // Controls for (int i = 1; i < 100; i++) { String controlKey = translationKey + ".control" + i; String actionKey = translationKey + ".action" + i; - if (!I18n.hasKey(controlKey)) + if (!I18n.exists(controlKey)) break; - tooltip.withControl(I18n.format(controlKey), I18n.format(actionKey)); + tooltip.withControl(I18n.get(controlKey), I18n.get(actionKey)); } return tooltip.createTabs(); @@ -325,24 +318,16 @@ public class TooltipHelper { if (tooltipReferrals.containsKey(item)) return tooltipReferrals.get(item) .get() + ".tooltip"; - return item.getTranslationKey(stack) + ".tooltip"; + return item.getDescriptionId(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(); - } - - public static String getUnformattedDeepText(ITextComponent component) { - StringBuilder b = new StringBuilder(); - b.append(component.getString()); - component.getSiblings() - .forEach(c -> b.append(getUnformattedDeepText(c))); - return b.toString(); - } +// 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(); +// } } 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/render/CreateCustomRenderedItemModel.java b/src/main/java/com/simibubi/create/foundation/item/render/CreateCustomRenderedItemModel.java new file mode 100644 index 000000000..e5e128ca6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/item/render/CreateCustomRenderedItemModel.java @@ -0,0 +1,13 @@ +package com.simibubi.create.foundation.item.render; + +import com.simibubi.create.Create; + +import net.minecraft.client.renderer.model.IBakedModel; + +public abstract class CreateCustomRenderedItemModel extends CustomRenderedItemModel { + + public CreateCustomRenderedItemModel(IBakedModel template, String basePath) { + super(template, Create.ID, basePath); + } + +} 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 91% 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..121bfa895 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; @@ -29,7 +29,7 @@ public class CustomItemModels { registered.add(Pair.of(entry, behaviour)); } - public void foreach(NonNullBiConsumer> consumer) { + public void forEach(NonNullBiConsumer> consumer) { loadEntriesIfMissing(); customModels.forEach(consumer); } 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 59% 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..fca2995ab 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; @@ -6,37 +6,36 @@ import java.util.Map; import java.util.stream.Collectors; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.Create; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.ItemCameraTransforms; import net.minecraft.client.renderer.model.ModelRotation; -import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.model.BakedModelWrapper; +import net.minecraftforge.client.model.ModelLoader; -@SuppressWarnings("deprecation") public abstract class CustomRenderedItemModel extends BakedModelWrapper { + protected String namespace; protected String basePath; protected Map partials = new HashMap<>(); - protected ItemStackTileEntityRenderer renderer; - public CustomRenderedItemModel(IBakedModel template, String basePath) { + public CustomRenderedItemModel(IBakedModel template, String namespace, String basePath) { super(template); + this.namespace = namespace; this.basePath = basePath; - this.renderer = createRenderer(); } @Override - public boolean isBuiltInRenderer() { + public boolean isCustomRenderer() { return true; } @Override public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat) { - // Super call returns originalModel, but we want to return this, else ISTER won't be used. + // Super call returns originalModel, but we want to return this, else ISTER + // won't be used. super.handlePerspective(cameraTransformType, mat); return this; } @@ -45,38 +44,32 @@ public abstract class CustomRenderedItemModel extends BakedModelWrapper getModelLocations() { return partials.keySet().stream().map(this::getPartialModelLocation).collect(Collectors.toList()); } protected void addPartials(String... partials) { - this.partials.clear(); for (String name : partials) this.partials.put(name, null); } - public CustomRenderedItemModel loadPartials(ModelBakeEvent event) { + public void loadPartials(ModelBakeEvent event) { + ModelLoader modelLoader = event.getModelLoader(); for (String name : partials.keySet()) - partials.put(name, loadModel(event, name)); - return this; + partials.put(name, loadPartial(modelLoader, name)); } - private IBakedModel loadModel(ModelBakeEvent event, String name) { - return event.getModelLoader().func_217845_a(getPartialModelLocation(name), ModelRotation.X0_Y0); + @SuppressWarnings("deprecation") + protected IBakedModel loadPartial(ModelLoader modelLoader, String name) { + return modelLoader.bake(getPartialModelLocation(name), ModelRotation.X0_Y0); } - private ResourceLocation getPartialModelLocation(String name) { - return new ResourceLocation(Create.ID, "item/" + basePath + "/" + name); - } - - public IBakedModel getPartial(String name) { - return partials.get(name); + protected ResourceLocation getPartialModelLocation(String name) { + return new ResourceLocation(namespace, "item/" + basePath + "/" + name); } } diff --git a/src/main/java/com/simibubi/create/foundation/block/render/CustomRenderedItemModelRenderer.java b/src/main/java/com/simibubi/create/foundation/item/render/CustomRenderedItemModelRenderer.java similarity index 68% rename from src/main/java/com/simibubi/create/foundation/block/render/CustomRenderedItemModelRenderer.java rename to src/main/java/com/simibubi/create/foundation/item/render/CustomRenderedItemModelRenderer.java index ee201c94c..09885f667 100644 --- a/src/main/java/com/simibubi/create/foundation/block/render/CustomRenderedItemModelRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/item/render/CustomRenderedItemModelRenderer.java @@ -1,10 +1,10 @@ -package com.simibubi.create.foundation.block.render; +package com.simibubi.create.foundation.item.render; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.item.PartialItemModelRenderer; 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.tileentity.ItemStackTileEntityRenderer; import net.minecraft.item.ItemStack; @@ -13,19 +13,21 @@ public abstract class CustomRenderedItemModelRenderer> consumer) { loadEntriesIfMissing(); customModels.forEach(consumer); diff --git a/src/main/java/com/simibubi/create/foundation/item/PartialItemModelRenderer.java b/src/main/java/com/simibubi/create/foundation/item/render/PartialItemModelRenderer.java similarity index 68% rename from src/main/java/com/simibubi/create/foundation/item/PartialItemModelRenderer.java rename to src/main/java/com/simibubi/create/foundation/item/render/PartialItemModelRenderer.java index 8e4d0a60d..32cf9b714 100644 --- a/src/main/java/com/simibubi/create/foundation/item/PartialItemModelRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/item/render/PartialItemModelRenderer.java @@ -1,10 +1,10 @@ -package com.simibubi.create.foundation.item; +package com.simibubi.create.foundation.item.render; import java.util.Random; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; -import com.simibubi.create.foundation.renderState.RenderTypes; +import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.client.Minecraft; @@ -20,27 +20,23 @@ import net.minecraftforge.client.model.data.IModelData; public class PartialItemModelRenderer { - static PartialItemModelRenderer instance; + private static final PartialItemModelRenderer INSTANCE = new PartialItemModelRenderer(); - ItemStack stack; - int overlay; - MatrixStack ms; - ItemCameraTransforms.TransformType transformType; - IRenderTypeBuffer buffer; + private final Random random = new Random(); - static PartialItemModelRenderer get() { - if (instance == null) - instance = new PartialItemModelRenderer(); - return instance; - } + private ItemStack stack; + private ItemCameraTransforms.TransformType transformType; + private MatrixStack ms; + private IRenderTypeBuffer buffer; + private int overlay; public static PartialItemModelRenderer of(ItemStack stack, ItemCameraTransforms.TransformType transformType, MatrixStack ms, IRenderTypeBuffer buffer, int overlay) { - PartialItemModelRenderer instance = get(); + PartialItemModelRenderer instance = INSTANCE; instance.stack = stack; - instance.buffer = buffer; - instance.ms = ms; instance.transformType = transformType; + instance.ms = ms; + instance.buffer = buffer; instance.overlay = overlay; return instance; } @@ -65,34 +61,33 @@ public class PartialItemModelRenderer { if (stack.isEmpty()) return; - ms.push(); + ms.pushPose(); ms.translate(-0.5D, -0.5D, -0.5D); - if (!model.isBuiltInRenderer()) + if (!model.isCustomRenderer()) renderBakedItemModel(model, light, ms, - ItemRenderer.getArmorVertexConsumer(buffer, type, true, stack.hasEffect())); + ItemRenderer.getFoilBufferDirect(buffer, type, true, stack.hasFoil())); else stack.getItem() .getItemStackTileEntityRenderer() - .render(stack, transformType, ms, buffer, light, overlay); + .renderByItem(stack, transformType, ms, buffer, light, overlay); - ms.pop(); + ms.popPose(); } - private void renderBakedItemModel(IBakedModel model, int light, MatrixStack ms, IVertexBuilder p_229114_6_) { + private void renderBakedItemModel(IBakedModel model, int light, MatrixStack ms, IVertexBuilder buffer) { ItemRenderer ir = Minecraft.getInstance() .getItemRenderer(); - Random random = new Random(); IModelData data = EmptyModelData.INSTANCE; for (Direction direction : Iterate.directions) { random.setSeed(42L); - ir.renderBakedItemQuads(ms, p_229114_6_, model.getQuads(null, direction, random, data), stack, light, + ir.renderQuadList(ms, buffer, model.getQuads(null, direction, random, data), stack, light, overlay); } random.setSeed(42L); - ir.renderBakedItemQuads(ms, p_229114_6_, model.getQuads(null, null, random, data), stack, light, overlay); + ir.renderQuadList(ms, buffer, model.getQuads(null, null, random, data), stack, light, overlay); } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/BreakProgressMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/BreakProgressMixin.java new file mode 100644 index 000000000..4ff137f5a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/BreakProgressMixin.java @@ -0,0 +1,27 @@ +package com.simibubi.create.foundation.mixin; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.simibubi.create.foundation.block.BreakProgressHook; + +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.BlockPos; + +@Mixin(ClientWorld.class) +public class BreakProgressMixin { + @Shadow + @Final + private WorldRenderer levelRenderer; // levelRenderer + private final ClientWorld self = (ClientWorld) (Object) this; + + @Inject(at = @At("HEAD"), method = "destroyBlockProgress") + private void onBreakProgress(int playerEntityId, BlockPos pos, int progress, CallbackInfo ci) { + BreakProgressHook.whenBreaking(self, this.levelRenderer, playerEntityId, pos, progress); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/CancelTileEntityRenderMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/CancelTileEntityRenderMixin.java deleted file mode 100644 index 79994972e..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/CancelTileEntityRenderMixin.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.simibubi.create.foundation.mixin; - -import java.util.List; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; - -import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; -import net.minecraft.tileentity.TileEntity; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@OnlyIn(Dist.CLIENT) -@Mixin(ChunkRenderDispatcher.CompiledChunk.class) -public class CancelTileEntityRenderMixin { - - /** - * JUSTIFICATION: when instanced rendering is enabled, many tile entities no longer need - * to be processed by the normal game renderer. This method is only called to retrieve the - * list of tile entities to render. By filtering the output here, we prevent the game from - * doing unnecessary light lookups and frustum checks. - */ - @Inject(at = @At("RETURN"), method = "getTileEntities", cancellable = true) - private void noRenderInstancedTiles(CallbackInfoReturnable> cir) { - if (FastRenderDispatcher.available()) { - List tiles = cir.getReturnValue(); - - tiles.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderAsTE()); - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/EntityContraptionInteractionMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/EntityContraptionInteractionMixin.java index 76122d409..ee082eac3 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/EntityContraptionInteractionMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/EntityContraptionInteractionMixin.java @@ -44,27 +44,27 @@ public abstract class EntityContraptionInteractionMixin extends CapabilityProvid @Final @Shadow - protected Random rand; + protected Random random; @Shadow - private float nextStepDistance; + private float nextStep; @Shadow - protected abstract float determineNextStepDistance(); + protected abstract float nextStep(); @Shadow protected abstract void playStepSound(BlockPos p_180429_1_, BlockState p_180429_2_); private Set getIntersectingContraptions() { - Set contraptions = ContraptionHandler.loadedContraptions.get(self.world) + Set contraptions = ContraptionHandler.loadedContraptions.get(self.level) .values() .stream() .map(Reference::get) .filter(cEntity -> cEntity != null && cEntity.collidingEntities.containsKey(self)) .collect(Collectors.toSet()); - contraptions.addAll(self.world.getEntitiesWithinAABB(AbstractContraptionEntity.class, self.getBoundingBox() - .grow(1f))); + contraptions.addAll(self.level.getEntitiesOfClass(AbstractContraptionEntity.class, self.getBoundingBox() + .inflate(1f))); return contraptions; } @@ -89,7 +89,7 @@ public abstract class EntityContraptionInteractionMixin extends CapabilityProvid @Inject(at = @At(value = "JUMP", opcode = 154, // IFNE line 587 injecting before `!blockstate.isAir(this.world, blockpos)` ordinal = 4), method = "move") private void movementMixin(MoverType mover, Vector3d movement, CallbackInfo ci) { - Vector3d worldPos = self.getPositionVec() + Vector3d worldPos = self.position() .add(0, -0.2, 0); AtomicBoolean stepped = new AtomicBoolean(false); @@ -101,22 +101,22 @@ public abstract class EntityContraptionInteractionMixin extends CapabilityProvid }); if (stepped.get()) - this.nextStepDistance = this.determineNextStepDistance(); + this.nextStep = this.nextStep(); } - @Inject(method = { "spawnSprintingParticles" }, at = @At(value = "TAIL")) + @Inject(method = { "spawnSprintParticle" }, at = @At(value = "TAIL")) private void createRunningParticlesMixin(CallbackInfo ci) { - Vector3d worldPos = self.getPositionVec() + Vector3d worldPos = self.position() .add(0, -0.2, 0); BlockPos pos = new BlockPos(worldPos); // pos where particles are spawned forCollision(worldPos, (contraption, blockstate, blockpos) -> { - if (!blockstate.addRunningEffects(self.world, blockpos, self) - && blockstate.getRenderType() != BlockRenderType.INVISIBLE) { - Vector3d vec3d = self.getMotion(); - self.world.addParticle(new BlockParticleData(ParticleTypes.BLOCK, blockstate).setPos(pos), - self.getX() + ((double) rand.nextFloat() - 0.5D) * (double) self.getWidth(), self.getY() + 0.1D, - self.getZ() + ((double) rand.nextFloat() - 0.5D) * (double) self.getWidth(), vec3d.x * -4.0D, 1.5D, + if (!blockstate.addRunningEffects(self.level, blockpos, self) + && blockstate.getRenderShape() != BlockRenderType.INVISIBLE) { + Vector3d vec3d = self.getDeltaMovement(); + self.level.addParticle(new BlockParticleData(ParticleTypes.BLOCK, blockstate).setPos(pos), + self.getX() + ((double) random.nextFloat() - 0.5D) * (double) self.getBbWidth(), self.getY() + 0.1D, + self.getZ() + ((double) random.nextFloat() - 0.5D) * (double) self.getBbWidth(), vec3d.x * -4.0D, 1.5D, vec3d.z * -4.0D); } }); @@ -132,7 +132,7 @@ public abstract class EntityContraptionInteractionMixin extends CapabilityProvid worldPos = worldPos.add(x, y, z); - self.world.playSound(null, worldPos.x + x, worldPos.y + y, worldPos.z + z, event, self.getSoundCategory(), + self.level.playSound(null, worldPos.x + x, worldPos.y + y, worldPos.z + z, event, self.getSoundSource(), pitch, volume); ci.cancel(); 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..b76f2ab3e --- /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;mul(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;fastInvCubeRoot(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/HeavyBootsOnEntityMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/HeavyBootsOnEntityMixin.java deleted file mode 100644 index d295d6fa4..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/HeavyBootsOnEntityMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.simibubi.create.foundation.mixin; - -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.CallbackInfoReturnable; - -import net.minecraft.entity.Entity; -import net.minecraft.nbt.CompoundNBT; -import net.minecraftforge.common.capabilities.CapabilityProvider; - -@Mixin(Entity.class) -public abstract class HeavyBootsOnEntityMixin extends CapabilityProvider { - - protected HeavyBootsOnEntityMixin(Class baseClass) { - super(baseClass); - } - - @Shadow - public abstract CompoundNBT getPersistentData(); - - @Inject(at = @At("HEAD"), method = "canSwim", cancellable = true) - public void noSwimmingWithHeavyBootsOn(CallbackInfoReturnable cir) { - CompoundNBT persistentData = getPersistentData(); - if (persistentData.contains("HeavyBoots")) - cir.setReturnValue(false); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/HeavyBootsOnPlayerMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/HeavyBootsOnPlayerMixin.java index 3ab84bb01..8561b404a 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/HeavyBootsOnPlayerMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/HeavyBootsOnPlayerMixin.java @@ -22,7 +22,7 @@ public abstract class HeavyBootsOnPlayerMixin extends AbstractClientPlayerEntity super(p_i50991_1_, p_i50991_2_); } - @Inject(at = @At("HEAD"), method = "canSwim", cancellable = true) + @Inject(at = @At("HEAD"), method = "isUnderWater", cancellable = true) public void noSwimmingWithHeavyBootsOn(CallbackInfoReturnable cir) { CompoundNBT persistentData = getPersistentData(); if (persistentData.contains("HeavyBoots")) 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..a7857c1b0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/ModelDataRefreshMixin.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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.simibubi.create.content.schematics.SchematicWorld; + +import net.minecraft.client.Minecraft; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.model.ModelDataManager; + +@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.getLevel(); + if (world != Minecraft.getInstance().level && 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/PlayerListMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/PlayerListMixin.java new file mode 100644 index 000000000..acc2a16dc --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/PlayerListMixin.java @@ -0,0 +1,25 @@ +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.content.curiosities.weapons.PotatoProjectileTypeManager; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.NetworkManager; +import net.minecraft.server.management.PlayerList; + +@Mixin(PlayerList.class) +public class PlayerListMixin { + @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/item/crafting/ServerRecipeBook;sendInitialRecipeBook(Lnet/minecraft/entity/player/ServerPlayerEntity;)V", shift = At.Shift.AFTER), method = "placeNewPlayer(Lnet/minecraft/network/NetworkManager;Lnet/minecraft/entity/player/ServerPlayerEntity;)V") + private void afterSendRecipeBookOnPlaceNewPlayer(NetworkManager networkManager, ServerPlayerEntity player, CallbackInfo ci) { + PotatoProjectileTypeManager.syncTo(player); + } + + @Inject(at = @At("TAIL"), method = "reloadResources()V") + private void onReloadResources(CallbackInfo ci) { + PotatoProjectileTypeManager.syncToAll(); + } +} 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..4af9f1243 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/WindowResizeMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/WindowResizeMixin.java @@ -18,12 +18,11 @@ import net.minecraftforge.api.distmarker.OnlyIn; @Mixin(Minecraft.class) public class WindowResizeMixin { - @Shadow @Final private MainWindow mainWindow; + @Shadow @Final private MainWindow window; - @Inject(at = @At("TAIL"), method = "updateWindowSize") + @Inject(at = @At("TAIL"), method = "resizeDisplay") 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(window); } } 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..47b63dbfc 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,24 @@ 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.bell.SoulPulseEffectPacket; +import com.simibubi.create.content.curiosities.symmetry.ConfigureSymmetryWandPacket; import com.simibubi.create.content.curiosities.symmetry.SymmetryEffectPacket; +import com.simibubi.create.content.curiosities.toolbox.ToolboxDisposeAllPacket; +import com.simibubi.create.content.curiosities.toolbox.ToolboxEquipPacket; +import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket; import com.simibubi.create.content.curiosities.tools.ExtendoGripInteractionPacket; +import com.simibubi.create.content.curiosities.weapons.PotatoCannonPacket; +import com.simibubi.create.content.curiosities.weapons.PotatoProjectileTypeManager; import com.simibubi.create.content.curiosities.zapper.ZapperBeamPacket; +import com.simibubi.create.content.curiosities.zapper.terrainzapper.ConfigureWorldshaperPacket; 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.LinkedControllerStopLecternPacket; 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 +49,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; @@ -59,14 +72,14 @@ import net.minecraftforge.fml.network.simple.SimpleChannel; public enum AllPackets { // Client to Server - NBT(NbtPacket.class, NbtPacket::new, PLAY_TO_SERVER), CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new, PLAY_TO_SERVER), 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), 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 +94,16 @@ 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), + LINKED_CONTROLLER_USE_LECTERN(LinkedControllerStopLecternPacket.class, LinkedControllerStopLecternPacket::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), + CONFIGURE_SYMMETRY_WAND(ConfigureSymmetryWandPacket.class, ConfigureSymmetryWandPacket::new, PLAY_TO_SERVER), + CONFIGURE_WORLDSHAPER(ConfigureWorldshaperPacket.class, ConfigureWorldshaperPacket::new, PLAY_TO_SERVER), + TOOLBOX_EQUIP(ToolboxEquipPacket.class, ToolboxEquipPacket::new, PLAY_TO_SERVER), + TOOLBOX_DISPOSE_ALL(ToolboxDisposeAllPacket.class, ToolboxDisposeAllPacket::new, PLAY_TO_SERVER), // Server to Client SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT), @@ -100,16 +122,20 @@ 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), + POTATO_CANNON(PotatoCannonPacket.class, PotatoCannonPacket::new, PLAY_TO_CLIENT), + SOUL_PULSE(SoulPulseEffectPacket.class, SoulPulseEffectPacket::new, PLAY_TO_CLIENT), + PERSISTENT_DATA(ISyncPersistentData.Packet.class, ISyncPersistentData.Packet::new, PLAY_TO_CLIENT), + SYNC_POTATO_PROJECTILE_TYPES(PotatoProjectileTypeManager.SyncPacket.class, PotatoProjectileTypeManager.SyncPacket::new, PLAY_TO_CLIENT), ; - public static final ResourceLocation CHANNEL_NAME = new ResourceLocation(Create.ID, "network"); - public static final String NETWORK_VERSION = new ResourceLocation(Create.ID, "1").toString(); + public static final ResourceLocation CHANNEL_NAME = Create.asResource("network"); + public static final String NETWORK_VERSION = Create.asResource("1").toString(); public static SimpleChannel channel; private LoadedPacket packet; - private AllPackets(Class type, Function factory, + AllPackets(Class type, Function factory, NetworkDirection direction) { packet = new LoadedPacket<>(type, factory, direction); } @@ -126,7 +152,7 @@ public enum AllPackets { public static void sendToNear(World world, BlockPos pos, int range, Object message) { channel.send(PacketDistributor.NEAR - .with(TargetPoint.p(pos.getX(), pos.getY(), pos.getZ(), range, world.getRegistryKey())), message); + .with(TargetPoint.p(pos.getX(), pos.getY(), pos.getZ(), range, world.dimension())), message); } private static class LoadedPacket { 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..1226eaabd --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/networking/ISyncPersistentData.java @@ -0,0 +1,61 @@ +package com.simibubi.create.foundation.networking; + +import java.util.HashSet; +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.getId(); + } + + public Packet(PacketBuffer buffer) { + entityId = buffer.readInt(); + readData = buffer.readNbt(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeInt(entityId); + buffer.writeNbt(entity.getPersistentData()); + } + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + Entity entityByID = Minecraft.getInstance().level.getEntity(entityId); + CompoundNBT data = entityByID.getPersistentData(); + new HashSet<>(data.getAllKeys()).forEach(data::remove); + data.merge(readData); + if (!(entityByID instanceof ISyncPersistentData)) + return; + ((ISyncPersistentData) entityByID).onPersistentDataUpdated(); + }); + context.get() + .setPacketHandled(true); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/networking/NbtPacket.java b/src/main/java/com/simibubi/create/foundation/networking/NbtPacket.java deleted file mode 100644 index b42262760..000000000 --- a/src/main/java/com/simibubi/create/foundation/networking/NbtPacket.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.simibubi.create.foundation.networking; - -import java.util.function.Supplier; - -import com.simibubi.create.content.curiosities.symmetry.SymmetryWandItem; -import com.simibubi.create.content.curiosities.zapper.ZapperItem; - -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.Hand; -import net.minecraftforge.fml.network.NetworkEvent.Context; - -@Deprecated -public class NbtPacket extends SimplePacketBase { - - public ItemStack stack; - public int slot; - public Hand hand; - - public NbtPacket(ItemStack stack, Hand hand) { - this(stack, -1); - this.hand = hand; - } - - public NbtPacket(ItemStack stack, int slot) { - this.stack = stack; - this.slot = slot; - this.hand = Hand.MAIN_HAND; - } - - public NbtPacket(PacketBuffer buffer) { - stack = buffer.readItemStack(); - slot = buffer.readInt(); - hand = Hand.values()[buffer.readInt()]; - } - - public void write(PacketBuffer buffer) { - buffer.writeItemStack(stack); - buffer.writeInt(slot); - buffer.writeInt(hand.ordinal()); - } - - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayerEntity player = context.get() - .getSender(); - if (player == null) - return; - if (!(stack.getItem() instanceof SymmetryWandItem || stack.getItem() instanceof ZapperItem)) { - return; - } - stack.removeChildTag("AttributeModifiers"); - if (slot == -1) { - ItemStack heldItem = player.getHeldItem(hand); - if (heldItem.getItem() == stack.getItem()) { - heldItem.setTag(stack.getTag()); - } - return; - } - - ItemStack heldInSlot = player.inventory.getStackInSlot(slot); - if (heldInSlot.getItem() == stack.getItem()) { - heldInSlot.setTag(stack.getTag()); - } - - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/networking/TileEntityConfigurationPacket.java b/src/main/java/com/simibubi/create/foundation/networking/TileEntityConfigurationPacket.java index 4bb198dcc..9f0ca903d 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/TileEntityConfigurationPacket.java +++ b/src/main/java/com/simibubi/create/foundation/networking/TileEntityConfigurationPacket.java @@ -39,15 +39,15 @@ public abstract class TileEntityConfigurationPacket .getSender(); if (player == null) return; - World world = player.world; + World world = player.level; - if (world == null || !world.isBlockPresent(pos)) + if (world == null || !world.isLoaded(pos)) return; - TileEntity tileEntity = world.getTileEntity(pos); + TileEntity tileEntity = world.getBlockEntity(pos); if (tileEntity instanceof SyncedTileEntity) { applySettings((TE) tileEntity); ((SyncedTileEntity) tileEntity).sendData(); - tileEntity.markDirty(); + tileEntity.setChanged(); } }); context.get() diff --git a/src/main/java/com/simibubi/create/foundation/networking/TileEntityDataPacket.java b/src/main/java/com/simibubi/create/foundation/networking/TileEntityDataPacket.java index 0be7edd6d..4e8acd5f7 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/TileEntityDataPacket.java +++ b/src/main/java/com/simibubi/create/foundation/networking/TileEntityDataPacket.java @@ -38,12 +38,12 @@ public abstract class TileEntityDataPacket extends public void handle(Supplier context) { NetworkEvent.Context ctx = context.get(); ctx.enqueueWork(() -> { - ClientWorld world = Minecraft.getInstance().world; + ClientWorld world = Minecraft.getInstance().level; if (world == null) return; - TileEntity tile = world.getTileEntity(tilePos); + TileEntity tile = world.getBlockEntity(tilePos); if (tile instanceof SyncedTileEntity) { handlePacket((TE) tile); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java b/src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java index 59d350155..0e334bed3 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/NavigatableSimiScreen.java @@ -10,13 +10,16 @@ import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllItems; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.IScreenRenderable; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.ponder.content.PonderTagIndexScreen; import com.simibubi.create.foundation.ponder.content.PonderTagScreen; import com.simibubi.create.foundation.ponder.ui.PonderButton; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.animation.LerpedFloat; @@ -25,6 +28,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.TranslationTextComponent; public abstract class NavigatableSimiScreen extends AbstractSimiScreen { @@ -42,8 +46,8 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { public NavigatableSimiScreen() { MainWindow window = Minecraft.getInstance() .getWindow(); - depthPointX = window.getScaledWidth() / 2; - depthPointY = window.getScaledHeight() / 2; + depthPointX = window.getGuiScaledWidth() / 2; + depthPointY = window.getGuiScaledHeight() / 2; } @Override @@ -73,14 +77,15 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { IScreenRenderable icon = null; ItemStack altIcon = null; + if (screen instanceof PonderTagIndexScreen) + altIcon = AllItems.WRENCH.asStack(); if (screen instanceof PonderUI) altIcon = ((PonderUI) screen).stack; if (screen instanceof PonderTagScreen) icon = ((PonderTagScreen) screen).getTag(); - widgets.add(backTrack = new PonderButton(31, height - 31 - 20) - .enableFade(0, 5) - .withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty()))); + widgets.add(backTrack = new PonderButton(31, height - 31 - 20).enableFade(0, 5) + .withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty()))); backTrack.fade(1); if (icon != null) @@ -96,16 +101,22 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { if (backTrack == null) return; - ms.push(); + ms.pushPose(); ms.translate(0, 0, 500); if (backTrack.isHovered()) { - textRenderer.draw(ms, Lang.translate(THINK_BACK), 15, height - 16, Theme.i(Theme.Key.TEXT_DARKER)); - if (MathHelper.epsilonEquals(arrowAnimation.getValue(), arrowAnimation.getChaseTarget())) { + TranslationTextComponent translate = Lang.translate(backTrackingLangKey()); + font.draw(ms, translate, 41 - font.width(translate) / 2, height - 16, + Theme.i(Theme.Key.TEXT_DARKER)); + if (MathHelper.equal(arrowAnimation.getValue(), arrowAnimation.getChaseTarget())) { arrowAnimation.setValue(1); arrowAnimation.setValue(1);// called twice to also set the previous value to 1 } } - ms.pop(); + ms.popPose(); + } + + protected String backTrackingLangKey() { + return THINK_BACK; } @Override @@ -115,7 +126,8 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { int maxX = backTrack.x + backTrack.getWidth(); if (x + 30 < backTrack.x) - UIRenderHelper.breadcrumbArrow(ms, x + 30, height - 51, 0, maxX - (x + 30), 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW)); + UIRenderHelper.breadcrumbArrow(ms, x + 30, height - 51, 0, maxX - (x + 30), 20, 5, + Theme.p(Theme.Key.PONDER_BACK_ARROW)); UIRenderHelper.breadcrumbArrow(ms, x, height - 51, 0, 30, 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW)); UIRenderHelper.breadcrumbArrow(ms, x - 30, height - 51, 0, 30, 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW)); @@ -134,24 +146,24 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { // draw last screen into buffer if (lastScreen != null && lastScreen != this && !transition.settled()) { - ms.push(); - UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC); + ms.pushPose(); + UIRenderHelper.framebuffer.clear(Minecraft.ON_OSX); ms.translate(0, 0, -1000); - UIRenderHelper.framebuffer.bindFramebuffer(true); + UIRenderHelper.framebuffer.bindWrite(true); lastScreen.render(ms, mouseX, mouseY, partialTicks); - ms.pop(); - ms.push(); + ms.popPose(); + ms.pushPose(); // use the buffer texture Minecraft.getInstance() - .getFramebuffer() - .bindFramebuffer(true); + .getMainRenderTarget() + .bindWrite(true); MainWindow window = Minecraft.getInstance() .getWindow(); - int dpx = window.getScaledWidth() / 2; - int dpy = window.getScaledHeight() / 2; + int dpx = window.getGuiScaledWidth() / 2; + int dpy = window.getGuiScaledHeight() / 2; if (lastScreen instanceof AbstractSimiScreen) { dpx = ((NavigatableSimiScreen) lastScreen).depthPointX; dpy = ((NavigatableSimiScreen) lastScreen).depthPointY; @@ -166,7 +178,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { UIRenderHelper.drawFramebuffer(1f - Math.abs(transitionValue)); RenderSystem.disableBlend(); RenderSystem.enableAlphaTest(); - ms.pop(); + ms.popPose(); } // modify current screen as well @@ -191,9 +203,9 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { } public void centerScalingOnMouse() { - MainWindow w = client.getWindow(); - double mouseX = client.mouseHelper.getMouseX() * w.getScaledWidth() / w.getWidth(); - double mouseY = client.mouseHelper.getMouseY() * w.getScaledHeight() / w.getHeight(); + MainWindow w = minecraft.getWindow(); + double mouseX = minecraft.mouseHandler.xpos() * w.getGuiScaledWidth() / w.getScreenWidth(); + double mouseY = minecraft.mouseHandler.ypos() * w.getGuiScaledHeight() / w.getScreenHeight(); centerScalingOn((int) mouseX, (int) mouseY); } @@ -208,7 +220,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { if (history.isEmpty()) return; - history.add(0, Minecraft.getInstance().currentScreen); + history.add(0, Minecraft.getInstance().screen); int spacing = 20; List names = history.stream() @@ -216,7 +228,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { .collect(Collectors.toList()); int bWidth = names.stream() - .mapToInt(s -> textRenderer.getStringWidth(s) + spacing) + .mapToInt(s -> font.width(s) + spacing) .sum(); MutableInt x = new MutableInt(width - bWidth); @@ -226,18 +238,18 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen { if (x.getValue() < 25) x.setValue(25); - ms.push(); + ms.pushPose(); ms.translate(0, 0, 600); names.forEach(s -> { - int sWidth = textRenderer.getStringWidth(s); + int sWidth = font.width(s); UIRenderHelper.breadcrumbArrow(ms, x.getValue(), y.getValue(), 0, sWidth + spacing, 14, spacing / 2, - 0xdd101010, 0x44101010); - textRenderer.draw(ms, s, x.getValue() + 5, y.getValue() + 3, first.getValue() ? 0xffeeffee : 0xffddeeff); + new Color(0xdd101010), new Color(0x44101010)); + font.draw(ms, s, x.getValue() + 5, y.getValue() + 3, first.getValue() ? 0xffeeffee : 0xffddeeff); first.setFalse(); x.add(sWidth + spacing); }); - ms.pop(); + ms.popPose(); } private static String screenTitle(Screen screen) { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderLocalization.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderLocalization.java index 64d61230b..9201555e2 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderLocalization.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderLocalization.java @@ -7,71 +7,116 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.simibubi.create.Create; import com.simibubi.create.foundation.ponder.content.PonderIndex; +import com.simibubi.create.foundation.ponder.content.PonderTag; +import com.simibubi.create.foundation.ponder.content.PonderTagIndexScreen; import com.simibubi.create.foundation.ponder.content.PonderTagScreen; +import com.simibubi.create.foundation.ponder.content.SharedText; import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; +import com.tterrag.registrate.AbstractRegistrate; + +import net.minecraft.client.resources.I18n; +import net.minecraft.util.ResourceLocation; public class PonderLocalization { - static Map shared = new HashMap<>(); - static Map> tag = new HashMap<>(); - static Map> specific = new HashMap<>(); + static final Map SHARED = new HashMap<>(); + static final Map> TAG = new HashMap<>(); + static final Map CHAPTER = new HashMap<>(); + static final Map> SPECIFIC = new HashMap<>(); // - public static void registerTag(String key, String enUS, String description) { - tag.put(key, Couple.create(enUS, description)); + public static void registerShared(ResourceLocation key, String enUS) { + SHARED.put(key, enUS); } - public static void registerShared(String key, String enUS) { - shared.put(key, enUS); + public static void registerTag(ResourceLocation key, String enUS, String description) { + TAG.put(key, Couple.create(enUS, description)); } - public static void registerSpecific(String sceneId, String key, String enUS) { - specific.computeIfAbsent(sceneId, $ -> new HashMap<>()) + public static void registerChapter(ResourceLocation key, String enUS) { + CHAPTER.put(key, enUS); + } + + public static void registerSpecific(ResourceLocation sceneId, String key, String enUS) { + SPECIFIC.computeIfAbsent(sceneId, $ -> new HashMap<>()) .put(key, enUS); } // - public static String getShared(String key) { + public static String getShared(ResourceLocation key) { if (PonderIndex.EDITOR_MODE) - return shared.containsKey(key) ? shared.get(key) : ("unregistered shared entry:" + key); - return Lang.translate(langKeyForShared(key)) - .getString(); + return SHARED.containsKey(key) ? SHARED.get(key) : ("unregistered shared entry: " + key); + return I18n.get(langKeyForShared(key)); } - public static String getSpecific(String sceneId, String k) { + public static String getTag(ResourceLocation key) { if (PonderIndex.EDITOR_MODE) - return specific.get(sceneId) + return TAG.containsKey(key) ? TAG.get(key) + .getFirst() : ("unregistered tag entry: " + key); + return I18n.get(langKeyForTag(key)); + } + + public static String getTagDescription(ResourceLocation key) { + if (PonderIndex.EDITOR_MODE) + return TAG.containsKey(key) ? TAG.get(key) + .getSecond() : ("unregistered tag entry: " + key); + return I18n.get(langKeyForTagDescription(key)); + } + + public static String getChapter(ResourceLocation key) { + if (PonderIndex.EDITOR_MODE) + return CHAPTER.containsKey(key) ? CHAPTER.get(key) : ("unregistered chapter entry: " + key); + return I18n.get(langKeyForChapter(key)); + } + + public static String getSpecific(ResourceLocation sceneId, String k) { + if (PonderIndex.EDITOR_MODE) + return SPECIFIC.get(sceneId) .get(k); - return Lang.translate(langKeyForSpecific(sceneId, k)) - .getString(); - } - - public static String getTag(String key) { - if (PonderIndex.EDITOR_MODE) - return tag.containsKey(key) ? tag.get(key) - .getFirst() : ("unregistered tag entry:" + key); - return Lang.translate(langKeyForTag(key)) - .getString(); - } - - public static String getTagDescription(String key) { - if (PonderIndex.EDITOR_MODE) - return tag.containsKey(key) ? tag.get(key) - .getSecond() : ("unregistered tag entry:" + key); - return Lang.translate(langKeyForTagDescription(key)) - .getString(); + return I18n.get(langKeyForSpecific(sceneId, k)); } // public static final String LANG_PREFIX = "ponder."; - public static JsonElement record() { - JsonObject object = new JsonObject(); + public static void record(String namespace, JsonObject object) { + SHARED.forEach((k, v) -> { + if (k.getNamespace().equals(namespace)) { + object.addProperty(langKeyForShared(k), v); + } + }); + TAG.forEach((k, v) -> { + if (k.getNamespace().equals(namespace)) { + object.addProperty(langKeyForTag(k), v.getFirst()); + object.addProperty(langKeyForTagDescription(k), v.getSecond()); + } + }); + + CHAPTER.forEach((k, v) -> { + if (k.getNamespace().equals(namespace)) { + object.addProperty(langKeyForChapter(k), v); + } + }); + + SPECIFIC.entrySet() + .stream() + .filter(entry -> entry.getKey().getNamespace().equals(namespace)) + .sorted(Map.Entry.comparingByKey()) + .forEach(entry -> { + entry.getValue() + .entrySet() + .stream() + .sorted(Map.Entry.comparingByKey()) + .forEach(subEntry -> object.addProperty( + langKeyForSpecific(entry.getKey(), subEntry.getKey()), subEntry.getValue())); + }); + } + + private static void recordGeneral(JsonObject object) { addGeneral(object, PonderTooltipHandler.HOLD_TO_PONDER, "Hold [%1$s] to Ponder"); addGeneral(object, PonderTooltipHandler.SUBJECT, "Subject of this scene"); addGeneral(object, PonderUI.PONDERING, "Pondering about..."); @@ -86,44 +131,72 @@ public class PonderLocalization { addGeneral(object, PonderUI.THINK_BACK, "Think Back"); addGeneral(object, PonderUI.SLOW_TEXT, "Comfy Reading"); - shared.forEach((k, v) -> object.addProperty(Create.ID + "." + langKeyForShared(k), v)); - tag.forEach((k, v) -> { - object.addProperty(Create.ID + "." + langKeyForTag(k), v.getFirst()); - object.addProperty(Create.ID + "." + langKeyForTagDescription(k), v.getSecond()); - }); - - specific.entrySet() - .stream() - .sorted(Map.Entry.comparingByKey()) - .forEach(entry -> { - entry.getValue() - .entrySet() - .stream() - .sorted(Map.Entry.comparingByKey()) - .forEach(subEntry -> object.addProperty( - Create.ID + "." + langKeyForSpecific(entry.getKey(), subEntry.getKey()), subEntry.getValue())); - }); - return object; + addGeneral(object, PonderTagIndexScreen.EXIT, "Exit"); + addGeneral(object, PonderTagIndexScreen.WELCOME, "Welcome to Ponder"); + addGeneral(object, PonderTagIndexScreen.CATEGORIES, "Available Categories in Create"); + addGeneral(object, PonderTagIndexScreen.DESCRIPTION, + "Click one of the icons to learn about its associated Items and Blocks"); + addGeneral(object, PonderTagIndexScreen.TITLE, "Ponder Index"); } private static void addGeneral(JsonObject json, String key, String enUS) { json.addProperty(Create.ID + "." + key, enUS); } - protected static String langKeyForSpecific(String sceneId, String k) { - return LANG_PREFIX + sceneId + "." + k; + public static void generateSceneLang() { + PonderRegistry.ALL.forEach((id, list) -> { + for (int i = 0; i < list.size(); i++) + PonderRegistry.compileScene(i, list.get(i), null); + }); } - protected static String langKeyForShared(String k) { - return LANG_PREFIX + "shared." + k; + /** + * Internal use only. + */ + public static JsonObject provideLangEntries() { + SharedText.gatherText(); + PonderTag.register(); + PonderIndex.register(); + + generateSceneLang(); + + JsonObject object = new JsonObject(); + recordGeneral(object); + record(Create.ID, object); + return object; } - protected static String langKeyForTag(String k) { - return LANG_PREFIX + "tag." + k; + public static void provideRegistrateLang(AbstractRegistrate registrate) { + generateSceneLang(); + + JsonObject object = new JsonObject(); + record(registrate.getModid(), object); + + for (Map.Entry entry : object.entrySet()) { + registrate.addRawLang(entry.getKey(), entry.getValue().getAsString()); + } } - protected static String langKeyForTagDescription(String k) { - return LANG_PREFIX + "tag." + k + ".description"; + // + + protected static String langKeyForShared(ResourceLocation k) { + return k.getNamespace() + "." + LANG_PREFIX + "shared." + k.getPath(); + } + + protected static String langKeyForTag(ResourceLocation k) { + return k.getNamespace() + "." + LANG_PREFIX + "tag." + k.getPath(); + } + + protected static String langKeyForTagDescription(ResourceLocation k) { + return k.getNamespace() + "." + LANG_PREFIX + "tag." + k.getPath() + ".description"; + } + + protected static String langKeyForChapter(ResourceLocation k) { + return k.getNamespace() + "." + LANG_PREFIX + "chapter." + k.getPath(); + } + + protected static String langKeyForSpecific(ResourceLocation sceneId, String k) { + return sceneId.getNamespace() + "." + LANG_PREFIX + sceneId.getPath() + "." + k; } } 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..b85cbb1db 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java @@ -90,29 +90,29 @@ public class PonderProgressBar extends AbstractSimiWidget { @Override public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - hovered = clicked(mouseX, mouseY); + isHovered = clicked(mouseX, mouseY); 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.pushPose(); + ms.translate(x - 2, y - 2, 200); - ms.push(); + ms.pushPose(); ms.scale((width + 4) * progress.getValue(partialTicks), 1, 1); int c1 = Theme.i(Theme.Key.PONDER_PROGRESSBAR, true); int c2 = Theme.i(Theme.Key.PONDER_PROGRESSBAR, false); - GuiUtils.drawGradientRect(ms.peek().getModel(), 110, 0, 3, 1, 4, c1, c1); - GuiUtils.drawGradientRect(ms.peek().getModel(), 110, 0, 4, 1, 5, c2, c2); - ms.pop(); + GuiUtils.drawGradientRect(ms.last().pose(), 110, 0, 3, 1, 4, c1, c1); + GuiUtils.drawGradientRect(ms.last().pose(), 110, 0, 4, 1, 5, c2, c2); + ms.popPose(); renderKeyframes(ms, mouseX, partialTicks); - ms.pop(); + ms.popPose(); } private void renderKeyframes(MatrixStack ms, int mouseX, float partialTicks) { @@ -124,7 +124,7 @@ public class PonderProgressBar extends AbstractSimiWidget { int idleEndColor = Theme.i(Theme.Key.PONDER_IDLE, false) | 0x40_000000; int hoverIndex; - if (hovered) { + if (isHovered) { hoverIndex = getHoveredKeyframeIndex(activeScene, mouseX); } else { hoverIndex = -2; @@ -152,26 +152,26 @@ public class PonderProgressBar extends AbstractSimiWidget { private void drawKeyframe(MatrixStack ms, PonderScene activeScene, boolean selected, int keyframeTime, int keyframePos, int startColor, int endColor, int height) { if (selected) { - FontRenderer font = Minecraft.getInstance().fontRenderer; - GuiUtils.drawGradientRect(ms.peek() - .getModel(), 100, keyframePos, 10, keyframePos + 1, 10 + height, endColor, startColor); - ms.push(); + FontRenderer font = Minecraft.getInstance().font; + GuiUtils.drawGradientRect(ms.last() + .pose(), 100, keyframePos, 10, keyframePos + 1, 10 + height, endColor, startColor); + ms.pushPose(); ms.translate(0, 0, 100); String text; int offset; if (activeScene.currentTime < keyframeTime) { text = ">"; - offset = -1 - font.getStringWidth(text); + offset = -1 - font.width(text); } else { text = "<"; offset = 3; } font.draw(ms, text, keyframePos + offset, 10, endColor); - ms.pop(); + ms.popPose(); } - GuiUtils.drawGradientRect(ms.peek() - .getModel(), 500, keyframePos, -1, keyframePos + 1, 2 + height, startColor, endColor); + GuiUtils.drawGradientRect(ms.last() + .pose(), 500, keyframePos, -1, keyframePos + 1, 2 + height, startColor, endColor); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistrationHelper.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistrationHelper.java new file mode 100644 index 000000000..39b97dc8c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistrationHelper.java @@ -0,0 +1,110 @@ +package com.simibubi.create.foundation.ponder; + +import java.util.Arrays; +import java.util.function.Consumer; + +import com.simibubi.create.foundation.ponder.PonderStoryBoardEntry.PonderStoryBoard; +import com.simibubi.create.foundation.ponder.content.PonderChapter; +import com.simibubi.create.foundation.ponder.content.PonderTag; +import com.tterrag.registrate.util.entry.ItemProviderEntry; + +import net.minecraft.util.ResourceLocation; + +public class PonderRegistrationHelper { + + protected String namespace; + + public PonderRegistrationHelper(String namespace) { + this.namespace = namespace; + } + + public PonderStoryBoardEntry addStoryBoard(ResourceLocation component, + ResourceLocation schematicLocation, PonderStoryBoard storyBoard, PonderTag... tags) { + PonderStoryBoardEntry entry = this.createStoryBoardEntry(storyBoard, schematicLocation, component); + entry.highlightTags(tags); + PonderRegistry.addStoryBoard(entry); + return entry; + } + + public PonderStoryBoardEntry addStoryBoard(ResourceLocation component, + String schematicPath, PonderStoryBoard storyBoard, PonderTag... tags) { + return addStoryBoard(component, asLocation(schematicPath), storyBoard, tags); + } + + public PonderStoryBoardEntry addStoryBoard(ItemProviderEntry component, + ResourceLocation schematicLocation, PonderStoryBoard storyBoard, PonderTag... tags) { + return addStoryBoard(component.getId(), schematicLocation, storyBoard, tags); + } + + public PonderStoryBoardEntry addStoryBoard(ItemProviderEntry component, + String schematicPath, PonderStoryBoard storyBoard, PonderTag... tags) { + return addStoryBoard(component, asLocation(schematicPath), storyBoard, tags); + } + + public MultiSceneBuilder forComponents(ItemProviderEntry... components) { + return new MultiSceneBuilder(Arrays.asList(components)); + } + + public MultiSceneBuilder forComponents(Iterable> components) { + return new MultiSceneBuilder(components); + } + + public PonderStoryBoardEntry createStoryBoardEntry(PonderStoryBoard storyBoard, ResourceLocation schematicLocation, ResourceLocation component) { + return new PonderStoryBoardEntry(storyBoard, namespace, schematicLocation, component); + } + + public PonderStoryBoardEntry createStoryBoardEntry(PonderStoryBoard storyBoard, String schematicPath, ResourceLocation component) { + return createStoryBoardEntry(storyBoard, asLocation(schematicPath), component); + } + + public PonderTag createTag(String name) { + return new PonderTag(asLocation(name)); + } + + public PonderChapter getOrCreateChapter(String name) { + return PonderChapter.of(asLocation(name)); + } + + public ResourceLocation asLocation(String path) { + return new ResourceLocation(namespace, path); + } + + public class MultiSceneBuilder { + + protected Iterable> components; + + protected MultiSceneBuilder(Iterable> components) { + this.components = components; + } + + public MultiSceneBuilder addStoryBoard(ResourceLocation schematicLocation, PonderStoryBoard storyBoard) { + return addStoryBoard(schematicLocation, storyBoard, $ -> { + }); + } + + public MultiSceneBuilder addStoryBoard(ResourceLocation schematicLocation, PonderStoryBoard storyBoard, PonderTag... tags) { + return addStoryBoard(schematicLocation, storyBoard, sb -> sb.highlightTags(tags)); + } + + public MultiSceneBuilder addStoryBoard(ResourceLocation schematicLocation, PonderStoryBoard storyBoard, + Consumer extras) { + components.forEach(c -> extras.accept(PonderRegistrationHelper.this.addStoryBoard(c, schematicLocation, storyBoard))); + return this; + } + + public MultiSceneBuilder addStoryBoard(String schematicPath, PonderStoryBoard storyBoard) { + return addStoryBoard(asLocation(schematicPath), storyBoard); + } + + public MultiSceneBuilder addStoryBoard(String schematicPath, PonderStoryBoard storyBoard, PonderTag... tags) { + return addStoryBoard(asLocation(schematicPath), storyBoard, tags); + } + + public MultiSceneBuilder addStoryBoard(String schematicPath, PonderStoryBoard storyBoard, + Consumer extras) { + return addStoryBoard(asLocation(schematicPath), storyBoard, extras); + } + + } + +} 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..9864d53f0 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistry.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistry.java @@ -2,31 +2,29 @@ package com.simibubi.create.foundation.ponder; import java.io.BufferedInputStream; import java.io.DataInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Consumer; import java.util.zip.GZIPInputStream; -import com.google.gson.JsonElement; import com.simibubi.create.Create; -import com.simibubi.create.foundation.ponder.PonderStoryBoardEntry.PonderStoryBoard; import com.simibubi.create.foundation.ponder.content.PonderChapter; import com.simibubi.create.foundation.ponder.content.PonderChapterRegistry; import com.simibubi.create.foundation.ponder.content.PonderIndex; -import com.simibubi.create.foundation.ponder.content.PonderTag; import com.simibubi.create.foundation.ponder.content.PonderTagRegistry; import com.simibubi.create.foundation.ponder.content.SharedText; -import com.tterrag.registrate.util.entry.ItemProviderEntry; import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTSizeTracker; +import net.minecraft.resources.IResource; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.gen.feature.template.PlacementSettings; @@ -34,52 +32,39 @@ import net.minecraft.world.gen.feature.template.Template; public class PonderRegistry { - public static final PonderTagRegistry tags = new PonderTagRegistry(); - public static final PonderChapterRegistry chapters = new PonderChapterRegistry(); - public static Map> all = new HashMap<>(); + public static final PonderTagRegistry TAGS = new PonderTagRegistry(); + public static final PonderChapterRegistry CHAPTERS = new PonderChapterRegistry(); + // Map from item IDs to storyboard entries + public static final Map> ALL = new HashMap<>(); - public static PonderSceneBuilder addStoryBoard(ItemProviderEntry component, String schematic, - PonderStoryBoard storyBoard, PonderTag... tags) { - ResourceLocation id = component.getId(); - PonderStoryBoardEntry entry = new PonderStoryBoardEntry(storyBoard, schematic, id); - PonderSceneBuilder builder = new PonderSceneBuilder(entry); - if (tags.length > 0) - builder.highlightTags(tags); - all.computeIfAbsent(id, _$ -> new ArrayList<>()) - .add(entry); - return builder; - } - - public static PonderSceneBuilder addStoryBoard(PonderChapter chapter, ResourceLocation component, String schematic, - PonderStoryBoard storyBoard) { - if (component == null) - component = new ResourceLocation("minecraft", "stick"); - - PonderStoryBoardEntry entry = new PonderStoryBoardEntry(storyBoard, schematic, component); - PonderSceneBuilder builder = new PonderSceneBuilder(entry); - chapters.addStoriesToChapter(chapter, entry); - return builder; - } - - public static MultiSceneBuilder forComponents(ItemProviderEntry... components) { - return new MultiSceneBuilder(Arrays.asList(components)); - } - - public static MultiSceneBuilder forComponents(Iterable> components) { - return new MultiSceneBuilder(components); + public static void addStoryBoard(PonderStoryBoardEntry entry) { + synchronized (ALL) { + List list = ALL.computeIfAbsent(entry.getComponent(), $ -> new ArrayList<>()); + synchronized (list) { + list.add(entry); + } + } } public static List compile(ResourceLocation id) { - return compile(all.get(id)); + List list = ALL.get(id); + if (list == null) { + return Collections.emptyList(); + } + return compile(list); } public static List compile(PonderChapter chapter) { - return compile(chapters.getStories(chapter)); + List list = CHAPTERS.getStories(chapter); + if (list == null) { + return Collections.emptyList(); + } + return compile(list); } public static List compile(List entries) { if (PonderIndex.EDITOR_MODE) { - PonderLocalization.shared.clear(); + PonderLocalization.SHARED.clear(); SharedText.gatherText(); } @@ -87,9 +72,9 @@ public class PonderRegistry { for (int i = 0; i < entries.size(); i++) { PonderStoryBoardEntry sb = entries.get(i); - Template activeTemplate = loadSchematic(sb.getSchematicName()); - PonderWorld world = new PonderWorld(BlockPos.ZERO, Minecraft.getInstance().world); - activeTemplate.placeAndNotifyListeners(world, BlockPos.ZERO, new PlacementSettings(), world.rand); + Template activeTemplate = loadSchematic(sb.getSchematicLocation()); + PonderWorld world = new PonderWorld(BlockPos.ZERO, Minecraft.getInstance().level); + activeTemplate.placeInWorld(world, BlockPos.ZERO, new PlacementSettings(), world.random); world.createBackup(); PonderScene scene = compileScene(i, sb, world); scene.begin(); @@ -100,98 +85,39 @@ public class PonderRegistry { } public static PonderScene compileScene(int i, PonderStoryBoardEntry sb, PonderWorld world) { - PonderScene scene = new PonderScene(world, sb.getComponent(), sb.getTags()); + PonderScene scene = new PonderScene(world, sb.getNamespace(), sb.getComponent(), sb.getTags()); SceneBuilder builder = scene.builder(); sb.getBoard() .program(builder, scene.getSceneBuildingUtil()); return scene; } - public static Template loadSchematic(String path) { - Template t = new Template(); - String filepath = "ponder/" + path + ".nbt"; - InputStream resourceAsStream = Create.class.getClassLoader() - .getResourceAsStream(filepath); - if (resourceAsStream == null) { - Create.logger.error("Ponder schematic missing: " + path); - return t; - } - try (DataInputStream stream = - new DataInputStream(new BufferedInputStream(new GZIPInputStream(resourceAsStream)))) { - CompoundNBT nbt = CompressedStreamTools.read(stream, new NBTSizeTracker(0x20000000L)); - t.read(nbt); + public static Template loadSchematic(ResourceLocation location) { + return loadSchematic(Minecraft.getInstance().getResourceManager(), location); + } + + public static Template loadSchematic(IResourceManager resourceManager, ResourceLocation location) { + String namespace = location.getNamespace(); + String path = "ponder/" + location.getPath() + ".nbt"; + ResourceLocation location1 = new ResourceLocation(namespace, path); + + try (IResource resource = resourceManager.getResource(location1)) { + return loadSchematic(resource.getInputStream()); + } catch (FileNotFoundException e) { + Create.LOGGER.error("Ponder schematic missing: " + location1, e); } catch (IOException e) { - Create.logger.warn("Failed to read ponder schematic", e); + Create.LOGGER.error("Failed to read ponder schematic: " + location1, e); } + return new Template(); + } + + public static Template loadSchematic(InputStream resourceStream) throws IOException { + Template t = new Template(); + DataInputStream stream = + new DataInputStream(new BufferedInputStream(new GZIPInputStream(resourceStream))); + CompoundNBT nbt = CompressedStreamTools.read(stream, new NBTSizeTracker(0x20000000L)); + t.load(nbt); return t; } - public static JsonElement provideLangEntries() { - PonderIndex.register(); - PonderTag.register(); - SharedText.gatherText(); - all.forEach((id, list) -> { - for (int i = 0; i < list.size(); i++) - compileScene(i, list.get(i), null); - }); - return PonderLocalization.record(); - } - - public static class MultiSceneBuilder { - - private final Iterable> components; - - MultiSceneBuilder(Iterable> components) { - this.components = components; - } - - public MultiSceneBuilder addStoryBoard(String schematicPath, PonderStoryBoard storyBoard) { - return addStoryBoard(schematicPath, storyBoard, $ -> { - }); - } - - public MultiSceneBuilder addStoryBoard(String schematicPath, PonderStoryBoard storyBoard, PonderTag... tags) { - return addStoryBoard(schematicPath, storyBoard, sb -> sb.highlightTags(tags)); - } - - public MultiSceneBuilder addStoryBoard(String schematicPath, PonderStoryBoard storyBoard, - Consumer extras) { - components.forEach(c -> extras.accept(PonderRegistry.addStoryBoard(c, schematicPath, storyBoard))); - return this; - } - - } - - public static class PonderSceneBuilder { - - private final PonderStoryBoardEntry entry; - - PonderSceneBuilder(PonderStoryBoardEntry entry) { - this.entry = entry; - } - - public PonderSceneBuilder highlightAllTags() { - entry.getTags() - .add(PonderTag.Highlight.ALL); - return this; - } - - public PonderSceneBuilder highlightTags(PonderTag... tags) { - entry.getTags() - .addAll(Arrays.asList(tags)); - return this; - } - - public PonderSceneBuilder chapter(PonderChapter chapter) { - PonderRegistry.chapters.addStoriesToChapter(chapter, entry); - return this; - } - - public PonderSceneBuilder chapters(PonderChapter... chapters) { - for (PonderChapter c : chapters) - chapter(c); - return this; - } - } - } 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..4f2ab9a83 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java @@ -13,9 +13,12 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import javax.annotation.Nullable; + import org.apache.commons.lang3.mutable.MutableDouble; import org.apache.commons.lang3.mutable.MutableObject; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.ponder.content.PonderIndex; import com.simibubi.create.foundation.ponder.content.PonderTag; @@ -23,9 +26,8 @@ import com.simibubi.create.foundation.ponder.elements.PonderOverlayElement; import com.simibubi.create.foundation.ponder.elements.PonderSceneElement; import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; import com.simibubi.create.foundation.ponder.instructions.HideAllInstruction; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.animation.LerpedFloat; @@ -59,7 +61,7 @@ public class PonderScene { boolean finished; int sceneIndex; int textIndex; - String sceneId; + ResourceLocation sceneId; IntList keyframeTimes; @@ -69,6 +71,7 @@ public class PonderScene { List tags; PonderWorld world; + String namespace; ResourceLocation component; SceneTransform transform; SceneRenderInfo info; @@ -78,6 +81,7 @@ public class PonderScene { Vector3d pointOfInterest; Vector3d chasingPointOfInterest; WorldSectionElement baseWorldSection; + @Nullable Entity renderViewEntity; int basePlateOffsetX; @@ -90,7 +94,7 @@ public class PonderScene { int totalTime; int currentTime; - public PonderScene(PonderWorld world, ResourceLocation component, Collection tags) { + public PonderScene(PonderWorld world, String namespace, ResourceLocation component, Collection tags) { if (world != null) world.scene = this; @@ -98,6 +102,7 @@ public class PonderScene { textIndex = 1; this.world = world; + this.namespace = namespace; this.component = component; outliner = new Outliner(); @@ -107,10 +112,10 @@ public class PonderScene { schedule = new ArrayList<>(); activeSchedule = new ArrayList<>(); transform = new SceneTransform(); - basePlateSize = getBounds().getXSize(); + basePlateSize = getBounds().getXSpan(); info = new SceneRenderInfo(); baseWorldSection = new WorldSectionElement(); - renderViewEntity = new ArmorStandEntity(world, 0, 0, 0); + renderViewEntity = world != null ? new ArmorStandEntity(world, 0, 0, 0) : null; keyframeTimes = new IntArrayList(4); scaleFactor = 1; yOffset = 0; @@ -150,10 +155,10 @@ public class PonderScene { BlockPos origin = new BlockPos(basePlateOffsetX, 0, basePlateOffsetZ); if (!world.getBounds() - .isVecInside(selectedPos)) + .isInside(selectedPos)) return Pair.of(ItemStack.EMPTY, null); - if (new MutableBoundingBox(origin, origin.add(new Vector3i(basePlateSize - 1, 0, basePlateSize - 1))) - .isVecInside(selectedPos)) { + if (new MutableBoundingBox(origin, origin.offset(new Vector3i(basePlateSize - 1, 0, basePlateSize - 1))) + .isInside(selectedPos)) { if (PonderIndex.EDITOR_MODE) nearestHit.getValue() .getFirst() @@ -223,29 +228,30 @@ public class PonderScene { } public void renderScene(SuperRenderTypeBuffer buffer, MatrixStack ms, float pt) { - ms.push(); + ms.pushPose(); Minecraft mc = Minecraft.getInstance(); - Entity prevRVE = mc.renderViewEntity; + Entity prevRVE = mc.cameraEntity; - mc.renderViewEntity = this.renderViewEntity; + mc.cameraEntity = this.renderViewEntity; forEachVisible(PonderSceneElement.class, e -> e.renderFirst(world, buffer, ms, pt)); - mc.renderViewEntity = prevRVE; + mc.cameraEntity = prevRVE; - for (RenderType type : RenderType.getBlockLayers()) + for (RenderType type : RenderType.chunkBufferLayers()) 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); - ms.pop(); + ms.popPose(); } public void renderOverlay(PonderUI screen, MatrixStack ms, float partialTicks) { - ms.push(); + ms.pushPose(); forEachVisible(PonderOverlayElement.class, e -> e.render(this, screen, ms, partialTicks)); - ms.pop(); + ms.popPose(); } public void setPointOfInterest(Vector3d poi) { @@ -391,10 +397,30 @@ public class PonderScene { return new SceneBuildingUtil(getBounds()); } + public String getNamespace() { + return namespace; + } + + public ResourceLocation getId() { + return sceneId; + } + public SceneTransform getTransform() { return transform; } + public Outliner getOutliner() { + return outliner; + } + + public boolean isFinished() { + return finished; + } + + public void setFinished(boolean finished) { + this.finished = finished; + } + public class SceneTransform { public LerpedFloat xRotation, yRotation; @@ -430,14 +456,14 @@ public class PonderScene { public MatrixStack apply(MatrixStack ms, float pt, boolean overlayCompatible) { ms.translate(width / 2, height / 2, 200 + offset); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .rotateX(-35) .rotateY(55); ms.translate(offset, 0, 0); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .rotateY(-55) .rotateX(35); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .rotateX(xRotation.getValue(pt)) .rotateY(yRotation.getValue(pt)); @@ -463,7 +489,8 @@ public class PonderScene { public void updateSceneRVE(float pt) { Vector3d v = screenToScene(width / 2, height / 2, 500, pt); - renderViewEntity.setPosition(v.x, v.y, v.z); + if (renderViewEntity != null) + renderViewEntity.setPos(v.x, v.y, v.z); } public Vector3d screenToScene(double x, double y, int depth, float pt) { @@ -481,7 +508,7 @@ public class PonderScene { float f = 1f / (30 * scaleFactor); - vec = vec.mul(f, -f, f); + vec = vec.multiply(f, -f, f); vec = vec.subtract((basePlateSize + basePlateOffsetX) / -2f, -1f + yOffset, (basePlateSize + basePlateOffsetZ) / -2f); @@ -492,14 +519,14 @@ public class PonderScene { refreshMatrix(pt); Vector4f vec4 = new Vector4f((float) vec.x, (float) vec.y, (float) vec.z, 1); vec4.transform(cachedMat); - return new Vector2f(vec4.getX(), vec4.getY()); + return new Vector2f(vec4.x(), vec4.y()); } protected void refreshMatrix(float pt) { if (cachedMat != null) return; - cachedMat = apply(new MatrixStack(), pt, false).peek() - .getModel(); + cachedMat = apply(new MatrixStack(), pt, false).last() + .pose(); } } @@ -507,21 +534,9 @@ public class PonderScene { public class SceneRenderInfo extends ActiveRenderInfo { public void set(float xRotation, float yRotation) { - setDirection(yRotation, xRotation); + setRotation(yRotation, xRotation); } } - public Outliner getOutliner() { - return outliner; - } - - public boolean isFinished() { - return finished; - } - - public void setFinished(boolean finished) { - this.finished = finished; - } - -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderStoryBoardEntry.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderStoryBoardEntry.java index 6d6ab1c98..aa6ec545e 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderStoryBoardEntry.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderStoryBoardEntry.java @@ -1,44 +1,87 @@ package com.simibubi.create.foundation.ponder; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import com.simibubi.create.foundation.ponder.content.PonderChapter; import com.simibubi.create.foundation.ponder.content.PonderTag; import net.minecraft.util.ResourceLocation; public class PonderStoryBoardEntry { - private final String schematicName; private final PonderStoryBoard board; - private final List tags; + private final String namespace; + private final ResourceLocation schematicLocation; private final ResourceLocation component; + private final List tags; - public PonderStoryBoardEntry(PonderStoryBoard board, String schematicName, ResourceLocation component) { + public PonderStoryBoardEntry(PonderStoryBoard board, String namespace, ResourceLocation schematicLocation, ResourceLocation component) { this.board = board; - this.schematicName = schematicName; - this.tags = new ArrayList<>(); + this.namespace = namespace; + this.schematicLocation = schematicLocation; this.component = component; + this.tags = new ArrayList<>(); } - public interface PonderStoryBoard { - void program(SceneBuilder scene, SceneBuildingUtil util); - } - - public String getSchematicName() { - return schematicName; + public PonderStoryBoardEntry(PonderStoryBoard board, String namespace, String schematicPath, ResourceLocation component) { + this(board, namespace, new ResourceLocation(namespace, schematicPath), component); } public PonderStoryBoard getBoard() { return board; } - public List getTags() { - return tags; + public String getNamespace() { + return namespace; + } + + public ResourceLocation getSchematicLocation() { + return schematicLocation; } public ResourceLocation getComponent() { return component; } + public List getTags() { + return tags; + } + + // Builder start + + public PonderStoryBoardEntry highlightTag(PonderTag tag) { + tags.add(tag); + return this; + } + + public PonderStoryBoardEntry highlightTags(PonderTag... tags) { + Collections.addAll(this.tags, tags); + return this; + } + + public PonderStoryBoardEntry highlightAllTags() { + tags.add(PonderTag.Highlight.ALL); + return this; + } + + public PonderStoryBoardEntry chapter(PonderChapter chapter) { + PonderRegistry.CHAPTERS.addStoriesToChapter(chapter, this); + return this; + } + + public PonderStoryBoardEntry chapters(PonderChapter... chapters) { + for (PonderChapter c : chapters) + chapter(c); + return this; + } + + // Builder end + + @FunctionalInterface + public interface PonderStoryBoard { + void program(SceneBuilder scene, SceneBuildingUtil util); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderTooltipHandler.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderTooltipHandler.java index 0cb380252..1177ffdc9 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderTooltipHandler.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderTooltipHandler.java @@ -4,7 +4,7 @@ import java.util.List; import com.google.common.base.Strings; import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.animation.LerpedFloat; @@ -45,12 +45,12 @@ public class PonderTooltipHandler { } Minecraft instance = Minecraft.getInstance(); - Screen currentScreen = instance.currentScreen; + Screen currentScreen = instance.screen; float value = holdWProgress.getValue(); int keyCode = ponderKeybind().getKey() - .getKeyCode(); + .getValue(); long window = instance.getWindow() - .getHandle(); + .getWindow(); if (!subject && InputMappings.isKeyDown(window, keyCode)) { if (value >= 1) { @@ -77,9 +77,9 @@ public class PonderTooltipHandler { return; float renderPartialTicks = Minecraft.getInstance() - .getRenderPartialTicks(); + .getFrameTime(); ITextComponent component = subject ? Lang.createTranslationTextComponent(SUBJECT) - .formatted(TextFormatting.GREEN) + .withStyle(TextFormatting.GREEN) : makeProgressBar(Math.min(1, holdWProgress.getValue(renderPartialTicks) * 8 / 7f)); if (toolTip.size() < 2) toolTip.add(component); @@ -89,24 +89,24 @@ public class PonderTooltipHandler { protected static void updateHovered(ItemStack stack) { Minecraft instance = Minecraft.getInstance(); - Screen currentScreen = instance.currentScreen; + Screen currentScreen = instance.screen; ItemStack prevStack = trackingStack; hoveredStack = ItemStack.EMPTY; subject = false; if (currentScreen instanceof PonderUI) { PonderUI ponderUI = (PonderUI) currentScreen; - if (stack.isItemEqual(ponderUI.getSubject())) + if (stack.sameItem(ponderUI.getSubject())) subject = true; } if (stack.isEmpty()) return; - if (!PonderRegistry.all.containsKey(stack.getItem() + if (!PonderRegistry.ALL.containsKey(stack.getItem() .getRegistryName())) return; - if (prevStack.isEmpty() || !prevStack.isItemEqual(stack)) + if (prevStack.isEmpty() || !prevStack.sameItem(stack)) holdWProgress.startWithValue(0); hoveredStack = stack; @@ -119,7 +119,7 @@ public class PonderTooltipHandler { if (holdWProgress.getValue() == 0) return; float renderPartialTicks = Minecraft.getInstance() - .getRenderPartialTicks(); + .getFrameTime(); int start = event.getOriginalBorderStart(); int end = event.getOriginalBorderEnd(); float progress = Math.min(1, holdWProgress.getValue(renderPartialTicks) * 8 / 7f); @@ -133,19 +133,19 @@ public class PonderTooltipHandler { private static int getSmoothColorForProgress(float progress) { if (progress < .5f) - return ColorHelper.mixColors(0x5000FF, 5592575, progress * 2); - return ColorHelper.mixColors(5592575, 0xffffff, (progress - .5f) * 2); + return Color.mixColors(0x5000FF, 5592575, progress * 2); + return Color.mixColors(5592575, 0xffffff, (progress - .5f) * 2); } private static ITextComponent makeProgressBar(float progress) { IFormattableTextComponent holdW = Lang .translate(HOLD_TO_PONDER, - ((IFormattableTextComponent) ponderKeybind().getBoundKeyLocalizedText()).formatted(TextFormatting.GRAY)) - .formatted(TextFormatting.DARK_GRAY); + ((IFormattableTextComponent) ponderKeybind().getTranslatedKeyMessage()).withStyle(TextFormatting.GRAY)) + .withStyle(TextFormatting.DARK_GRAY); - FontRenderer fontRenderer = Minecraft.getInstance().fontRenderer; - float charWidth = fontRenderer.getStringWidth("|"); - float tipWidth = fontRenderer.getWidth(holdW); + FontRenderer fontRenderer = Minecraft.getInstance().font; + float charWidth = fontRenderer.width("|"); + float tipWidth = fontRenderer.width(holdW); int total = (int) (tipWidth / charWidth); int current = (int) (progress * total); @@ -162,7 +162,7 @@ public class PonderTooltipHandler { } protected static KeyBinding ponderKeybind() { - return Minecraft.getInstance().gameSettings.keyBindForward; + return Minecraft.getInstance().options.keyUp; } } 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..248104947 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,6 @@ package com.simibubi.create.foundation.ponder; import static com.simibubi.create.foundation.ponder.PonderLocalization.LANG_PREFIX; -import java.awt.Color; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -13,6 +12,7 @@ import org.lwjgl.opengl.GL11; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.Create; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; @@ -29,8 +29,8 @@ import com.simibubi.create.foundation.ponder.content.PonderTag; import com.simibubi.create.foundation.ponder.content.PonderTagScreen; import com.simibubi.create.foundation.ponder.elements.TextWindowElement; import com.simibubi.create.foundation.ponder.ui.PonderButton; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.FontHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -137,11 +137,11 @@ public class PonderUI extends NavigatableSimiScreen { else stack = new ItemStack(ForgeRegistries.BLOCKS.getValue(component)); - tags = new ArrayList<>(PonderRegistry.tags.getTags(component)); + tags = new ArrayList<>(PonderRegistry.TAGS.getTags(component)); this.scenes = scenes; if (scenes.isEmpty()) { List l = Collections.singletonList(new PonderStoryBoardEntry(DebugScenes::empty, - "debug/scene_1", new ResourceLocation("minecraft", "stick"))); + Create.ID, "debug/scene_1", new ResourceLocation("minecraft", "stick"))); scenes.addAll(PonderRegistry.compile(l)); } lazyIndex = LerpedFloat.linear() @@ -190,7 +190,7 @@ public class PonderUI extends NavigatableSimiScreen { }).showing(chapter)); }*/ - GameSettings bindings = client.gameSettings; + GameSettings bindings = minecraft.options; int spacing = 8; int bX = (width - 20) / 2 - (70 + 2 * spacing); int bY = height - 20 - 31; @@ -203,7 +203,7 @@ public class PonderUI extends NavigatableSimiScreen { } widgets.add(scan = new PonderButton(bX, bY) - .withShortcut(bindings.keyBindDrop) + .withShortcut(bindings.keyDrop) .showing(AllIcons.I_MTD_SCAN) .enableFade(0, 5) .withCallback(() -> { @@ -212,7 +212,7 @@ public class PonderUI extends NavigatableSimiScreen { scenes.get(index) .deselect(); else - ponderPartialTicksPaused = client.getRenderPartialTicks(); + ponderPartialTicksPaused = minecraft.getFrameTime(); })); widgets.add(slowMode = new PonderButton(width - 20 - 31, bY) @@ -229,28 +229,28 @@ public class PonderUI extends NavigatableSimiScreen { bX += 50 + spacing; widgets.add(left = new PonderButton(bX, bY) - .withShortcut(bindings.keyBindLeft) + .withShortcut(bindings.keyLeft) .showing(AllIcons.I_MTD_LEFT) .enableFade(0, 5) .withCallback(() -> this.scroll(false))); bX += 20 + spacing; widgets.add(close = new PonderButton(bX, bY) - .withShortcut(bindings.keyBindInventory) + .withShortcut(bindings.keyInventory) .showing(AllIcons.I_MTD_CLOSE) .enableFade(0, 5) .withCallback(this::onClose)); bX += 20 + spacing; widgets.add(right = new PonderButton(bX, bY) - .withShortcut(bindings.keyBindRight) + .withShortcut(bindings.keyRight) .showing(AllIcons.I_MTD_RIGHT) .enableFade(0, 5) .withCallback(() -> this.scroll(true))); bX += 50 + spacing; widgets.add(replay = new PonderButton(bX, bY) - .withShortcut(bindings.keyBindBack) + .withShortcut(bindings.keyDown) .showing(AllIcons.I_MTD_REPLAY) .enableFade(0, 5) .withCallback(this::replay)); @@ -342,9 +342,9 @@ public class PonderUI extends NavigatableSimiScreen { if (!identifyMode) return; - MainWindow w = client.getWindow(); - double mouseX = client.mouseHelper.getMouseX() * w.getScaledWidth() / w.getWidth(); - double mouseY = client.mouseHelper.getMouseY() * w.getScaledHeight() / w.getHeight(); + MainWindow w = minecraft.getWindow(); + double mouseX = minecraft.mouseHandler.xpos() * w.getGuiScaledWidth() / w.getScreenWidth(); + double mouseY = minecraft.mouseHandler.ypos() * w.getGuiScaledHeight() / w.getScreenHeight(); SceneTransform t = activeScene.getTransform(); Vector3d vec1 = t.screenToScene(mouseX, mouseY, 1000, 0); Vector3d vec2 = t.screenToScene(mouseX, mouseY, -100, 0); @@ -365,11 +365,11 @@ public class PonderUI extends NavigatableSimiScreen { PonderScene scene = scenes.get(index); if (hasShiftDown()) { - List list = PonderRegistry.all.get(scene.component); + List list = PonderRegistry.ALL.get(scene.component); PonderStoryBoardEntry sb = list.get(index); - Template activeTemplate = PonderRegistry.loadSchematic(sb.getSchematicName()); - PonderWorld world = new PonderWorld(BlockPos.ZERO, Minecraft.getInstance().world); - activeTemplate.placeAndNotifyListeners(world, BlockPos.ZERO, new PlacementSettings(), new Random()); + Template activeTemplate = PonderRegistry.loadSchematic(sb.getSchematicLocation()); + PonderWorld world = new PonderWorld(BlockPos.ZERO, Minecraft.getInstance().level); + activeTemplate.placeInWorld(world, BlockPos.ZERO, new PlacementSettings(), new Random()); world.createBackup(); scene = PonderRegistry.compileScene(index, sb, world); scene.begin(); @@ -420,7 +420,7 @@ public class PonderUI extends NavigatableSimiScreen { protected void renderScene(MatrixStack ms, int mouseX, int mouseY, int i, float partialTicks) { SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); PonderScene story = scenes.get(i); - double value = lazyIndex.getValue(client.getRenderPartialTicks()); + double value = lazyIndex.getValue(minecraft.getFrameTime()); double diff = i - value; double slide = MathHelper.lerp(diff * diff, 200, 600) * diff; @@ -433,7 +433,7 @@ public class PonderUI extends NavigatableSimiScreen { // has to be outside of MS transforms, important for vertex sorting RenderSystem.translated(0, 0, 800); - ms.push(); + ms.pushPose(); ms.translate(0, 0, -800); story.transform.updateScreenParams(width, height, slide); story.transform.apply(ms, partialTicks, false); @@ -442,13 +442,13 @@ public class PonderUI extends NavigatableSimiScreen { buffer.draw(); MutableBoundingBox bounds = story.getBounds(); - ms.push(); + ms.pushPose(); // kool shadow fx { RenderSystem.enableCull(); RenderSystem.enableDepthTest(); - ms.push(); + ms.pushPose(); ms.translate(story.basePlateOffsetX, 0, story.basePlateOffsetZ); ms.scale(1, -1, 1); @@ -461,23 +461,23 @@ public class PonderUI extends NavigatableSimiScreen { for (int f = 0; f < 4; f++) { ms.translate(story.basePlateSize, 0, 0); - ms.push(); + ms.pushPose(); ms.translate(0, 0, -1 / 1024f); if (flash > 0) { - ms.push(); + ms.pushPose(); ms.scale(1, .5f + flash * .75f, 1); - GuiUtils.drawGradientRect(ms.peek() - .getModel(), 0, 0, -1, -story.basePlateSize, 0, 0x00_c6ffc9, - ColorHelper.applyAlpha(0xaa_c6ffc9, alpha)); - ms.pop(); + GuiUtils.drawGradientRect(ms.last() + .pose(), 0, 0, -1, -story.basePlateSize, 0, 0x00_c6ffc9, + new Color(0xaa_c6ffc9).scaleAlpha(alpha).getRGB()); + ms.popPose(); } ms.translate(0, 0, 2 / 1024f); - GuiUtils.drawGradientRect(ms.peek() - .getModel(), 0, 0, 0, -story.basePlateSize, 4, 0x66_000000, 0x00_000000); - ms.pop(); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(-90)); + GuiUtils.drawGradientRect(ms.last() + .pose(), 0, 0, 0, -story.basePlateSize, 4, 0x66_000000, 0x00_000000); + ms.popPose(); + ms.mulPose(Vector3f.YP.rotationDegrees(-90)); } - ms.pop(); + ms.popPose(); RenderSystem.disableCull(); RenderSystem.disableDepthTest(); } @@ -490,52 +490,54 @@ public class PonderUI extends NavigatableSimiScreen { ms.translate(1, -8, -1 / 64f); // X AXIS - ms.push(); + ms.pushPose(); ms.translate(4, -3, 0); ms.translate(0, 0, -2 / 1024f); - for (int x = 0; x <= bounds.getXSize(); x++) { + for (int x = 0; x <= bounds.getXSpan(); x++) { ms.translate(-16, 0, 0); - textRenderer.draw(ms, x == bounds.getXSize() ? "x" : "" + x, 0, 0, 0xFFFFFFFF); + font.draw(ms, x == bounds.getXSpan() ? "x" : "" + x, 0, 0, 0xFFFFFFFF); } - ms.pop(); + ms.popPose(); // Z AXIS - ms.push(); + ms.pushPose(); ms.scale(-1, 1, 1); ms.translate(0, -3, -4); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(-90)); + ms.mulPose(Vector3f.YP.rotationDegrees(-90)); ms.translate(-8, -2, 2 / 64f); - for (int z = 0; z <= bounds.getZSize(); z++) { + for (int z = 0; z <= bounds.getZSpan(); z++) { ms.translate(16, 0, 0); - textRenderer.draw(ms, z == bounds.getZSize() ? "z" : "" + z, 0, 0, 0xFFFFFFFF); + font.draw(ms, z == bounds.getZSpan() ? "z" : "" + z, 0, 0, 0xFFFFFFFF); } - ms.pop(); + ms.popPose(); // DIRECTIONS - ms.push(); - ms.translate(bounds.getXSize() * -8, 0, bounds.getZSize() * 8); - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(-90)); + ms.pushPose(); + ms.translate(bounds.getXSpan() * -8, 0, bounds.getZSpan() * 8); + ms.mulPose(Vector3f.YP.rotationDegrees(-90)); for (Direction d : Iterate.horizontalDirections) { - ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(90)); - ms.push(); - ms.translate(0, 0, bounds.getZSize() * 16); - ms.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-90)); - textRenderer.draw(ms, d.name() + ms.mulPose(Vector3f.YP.rotationDegrees(90)); + ms.pushPose(); + ms.translate(0, 0, bounds.getZSpan() * 16); + ms.mulPose(Vector3f.XP.rotationDegrees(-90)); + font.draw(ms, d.name() .substring(0, 1), 0, 0, 0x66FFFFFF); - textRenderer.draw(ms, "|", 2, 10, 0x44FFFFFF); - textRenderer.draw(ms, ".", 2, 14, 0x22FFFFFF); - ms.pop(); + font.draw(ms, "|", 2, 10, 0x44FFFFFF); + font.draw(ms, ".", 2, 14, 0x22FFFFFF); + ms.popPose(); } - ms.pop(); + ms.popPose(); buffer.draw(); } - ms.pop(); - ms.pop(); + ms.popPose(); + ms.popPose(); RenderSystem.popMatrix(); } 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); @@ -548,13 +550,13 @@ public class PonderUI extends NavigatableSimiScreen { int tooltipColor = Theme.i(Theme.Key.TEXT_DARKER); { // Chapter title - ms.push(); - ms.translate(0, 0, 100); + ms.pushPose(); + ms.translate(0, 0, 400); int x = 31 + 20 + 8; int y = 31; String title = activeScene.getTitle(); - int wordWrappedHeight = textRenderer.getWordWrappedHeight(title, left.x - 51); + int wordWrappedHeight = font.wordWrapHeight(title, left.x - 51); int streakHeight = 35 - 9 + wordWrappedHeight; UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade)); @@ -572,47 +574,49 @@ public class PonderUI extends NavigatableSimiScreen { .at(x - 39, y - 11) .render(ms); - textRenderer.draw(ms, Lang.translate(PONDERING), x, y - 6, tooltipColor); + font.draw(ms, Lang.translate(PONDERING), x, y - 6, tooltipColor); y += 8; x += 0; ms.translate(x, y, 0); - ms.multiply(Vector3f.NEGATIVE_X.getDegreesQuaternion(indexDiff * -75)); + ms.mulPose(Vector3f.XN.rotationDegrees(indexDiff * -75)); ms.translate(0, 0, 5); - FontHelper.drawSplitString(ms, textRenderer, title, 0, 0, left.x - 51, - ColorHelper.applyAlpha(Theme.i(Theme.Key.TEXT), 1 - indexDiff)); - ms.pop(); + FontHelper.drawSplitString(ms, font, title, 0, 0, left.x - 51, + Theme.c(Theme.Key.TEXT).scaleAlpha(1 - indexDiff).getRGB()); + ms.popPose(); if (chapter != null) { - ms.push(); + ms.pushPose(); ms.translate(chap.x - 4 - 4, chap.y, 0); UIRenderHelper.streak(ms, 180, 4, 10, 26, (int) (150 * fade)); - drawRightAlignedString(textRenderer, ms, Lang.translate(IN_CHAPTER).getString(), 0, 0, tooltipColor); - drawRightAlignedString(textRenderer, ms, - Lang.translate(LANG_PREFIX + "chapter." + chapter.getId()).getString(), 0, 12, Theme.i(Theme.Key.TEXT)); + drawRightAlignedString(font, ms, Lang.translate(IN_CHAPTER).getString(), 0, 0, tooltipColor); + drawRightAlignedString(font, ms, chapter.getTitle(), 0, 12, Theme.i(Theme.Key.TEXT)); - ms.pop(); + ms.popPose(); } - UIRenderHelper.breadcrumbArrow(ms, width / 2 - 20, height - 51, 0, 20, 20, 5, 0x40aa9999, 0x20aa9999); - UIRenderHelper.breadcrumbArrow(ms, width / 2 + 20, height - 51, 0, -20, 20, -5, 0x40aa9999, 0x20aa9999); - UIRenderHelper.breadcrumbArrow(ms, width / 2 - 90, height - 51, 0, 70, 20, 5, 0x40aa9999, 0x10aa9999); - UIRenderHelper.breadcrumbArrow(ms, width / 2 + 90, height - 51, 0, -70, 20, -5, 0x40aa9999, 0x10aa9999); + Color c1 = Theme.c(Theme.Key.PONDER_BACK_ARROW).setAlpha(0x40); + Color c2 = Theme.c(Theme.Key.PONDER_BACK_ARROW).setAlpha(0x20); + Color c3 = Theme.c(Theme.Key.PONDER_BACK_ARROW).setAlpha(0x10); + UIRenderHelper.breadcrumbArrow(ms, width / 2 - 20, height - 51, 0, 20, 20, 5, c1, c2); + UIRenderHelper.breadcrumbArrow(ms, width / 2 + 20, height - 51, 0, -20, 20, -5, c1, c2); + UIRenderHelper.breadcrumbArrow(ms, width / 2 - 90, height - 51, 0, 70, 20, 5, c1, c3); + UIRenderHelper.breadcrumbArrow(ms, width / 2 + 90, height - 51, 0, -70, 20, -5, c1, c3); } if (identifyMode) { if (noWidgetsHovered && mouseY < height - 80) { - ms.push(); + ms.pushPose(); ms.translate(mouseX, mouseY, 100); if (hoveredTooltipItem.isEmpty()) { IFormattableTextComponent text = Lang.translate( IDENTIFY_MODE, - ((IFormattableTextComponent) client.gameSettings.keyBindDrop.getBoundKeyLocalizedText()).formatted(TextFormatting.WHITE) - ).formatted(TextFormatting.GRAY); + ((IFormattableTextComponent) minecraft.options.keyDrop.getTranslatedKeyMessage()).withStyle(TextFormatting.WHITE) + ).withStyle(TextFormatting.GRAY); //renderOrderedTooltip(ms, textRenderer.wrapLines(text, width / 3), 0, 0); - renderWrappedToolTip(ms, textRenderer.getTextHandler().wrapLines(text, width / 3, Style.EMPTY), 0, 0, textRenderer); + renderWrappedToolTip(ms, font.getSplitter().splitLines(text, width / 3, Style.EMPTY), 0, 0, font); /*String tooltip = Lang .createTranslationTextComponent(IDENTIFY_MODE, client.gameSettings.keyBindDrop.getBoundKeyLocalizedText().applyTextStyle(TextFormatting.WHITE)) .applyTextStyle(TextFormatting.GRAY) @@ -624,10 +628,10 @@ public class PonderUI extends NavigatableSimiScreen { ms.translate(0, -15, 0); boolean copied = copiedBlockPos != null && hoveredBlockPos.equals(copiedBlockPos); IFormattableTextComponent coords = new StringTextComponent(hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ()) - .formatted(copied ? TextFormatting.GREEN : TextFormatting.GOLD); + .withStyle(copied ? TextFormatting.GREEN : TextFormatting.GOLD); renderTooltip(ms, coords, 0, 0); } - ms.pop(); + ms.popPose(); } scan.flash(); } else { @@ -649,12 +653,12 @@ public class PonderUI extends NavigatableSimiScreen { { // Scene overlay float scenePT = skipCooling > 0 ? 0 : partialTicks; - ms.push(); + ms.pushPose(); ms.translate(0, 0, 100); renderOverlay(ms, index, scenePT); if (indexDiff > 1 / 512f) renderOverlay(ms, lazyIndexValue < index ? index - 1 : index + 1, scenePT); - ms.pop(); + ms.popPose(); } // Widgets @@ -680,10 +684,10 @@ public class PonderUI extends NavigatableSimiScreen { boolean highlightAll = sceneTags.contains(PonderTag.Highlight.ALL); double s = Minecraft.getInstance() .getWindow() - .getGuiScaleFactor(); + .getGuiScale(); IntStream.range(0, tagButtons.size()) .forEach(i -> { - ms.push(); + ms.pushPose(); LerpedFloat chase = tagFades.get(i); PonderButton button = tagButtons.get(i); if (button.isMouseOver(mouseX, mouseY)) { @@ -693,7 +697,7 @@ public class PonderUI extends NavigatableSimiScreen { chase.tickChaser(); - if (highlightAll || sceneTags.contains(this.tags.get(i))) + if (highlightAll) button.flash(); else button.dim(); @@ -710,49 +714,51 @@ public class PonderUI extends NavigatableSimiScreen { String tagName = this.tags.get(i) .getTitle(); - textRenderer.draw(ms, tagName, 3, 8, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT)); + font.draw(ms, tagName, 3, 8, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT)); GL11.glDisable(GL11.GL_SCISSOR_TEST); - ms.pop(); + ms.popPose(); }); - ms.push(); + ms.pushPose(); ms.translate(0, 0, 500); int tooltipY = height - 16; if (scan.isHovered()) - drawCenteredText(ms, textRenderer, Lang.translate(IDENTIFY), scan.x + 10, tooltipY, tooltipColor); + drawCenteredString(ms, font, Lang.translate(IDENTIFY), scan.x + 10, tooltipY, tooltipColor); if (index != 0 && left.isHovered()) - drawCenteredText(ms, textRenderer, Lang.translate(PREVIOUS), left.x + 10, tooltipY, tooltipColor); + drawCenteredString(ms, font, Lang.translate(PREVIOUS), left.x + 10, tooltipY, tooltipColor); if (close.isHovered()) - drawCenteredText(ms, textRenderer, Lang.translate(CLOSE), close.x + 10, tooltipY, tooltipColor); + drawCenteredString(ms, font, Lang.translate(CLOSE), close.x + 10, tooltipY, tooltipColor); if (index != scenes.size() - 1 && right.isHovered()) - drawCenteredText(ms, textRenderer, Lang.translate(NEXT), right.x + 10, tooltipY, tooltipColor); + drawCenteredString(ms, font, Lang.translate(NEXT), right.x + 10, tooltipY, tooltipColor); if (replay.isHovered()) - drawCenteredText(ms, textRenderer, Lang.translate(REPLAY), replay.x + 10, tooltipY, tooltipColor); + drawCenteredString(ms, font, Lang.translate(REPLAY), replay.x + 10, tooltipY, tooltipColor); if (slowMode.isHovered()) - drawCenteredText(ms, textRenderer, Lang.translate(SLOW_TEXT), slowMode.x + 5, tooltipY, tooltipColor); + drawCenteredString(ms, font, Lang.translate(SLOW_TEXT), slowMode.x + 5, tooltipY, tooltipColor); if (PonderIndex.EDITOR_MODE && userMode.isHovered()) - drawCenteredString(ms, textRenderer, "Editor View", userMode.x + 10, tooltipY, tooltipColor); - ms.pop(); + drawCenteredString(ms, font, "Editor View", userMode.x + 10, tooltipY, tooltipColor); + ms.popPose(); + + RenderSystem.enableDepthTest(); } private void renderOverlay(MatrixStack ms, int i, float partialTicks) { if (identifyMode) return; - ms.push(); + ms.pushPose(); PonderScene story = scenes.get(i); story.renderOverlay(this, ms, skipCooling > 0 ? 0 : identifyMode ? ponderPartialTicksPaused : partialTicks); - ms.pop(); + ms.popPose(); } @Override public boolean mouseClicked(double x, double y, int button) { if (identifyMode && hoveredBlockPos != null && PonderIndex.EDITOR_MODE) { - long handle = client.getWindow() - .getHandle(); + long handle = minecraft.getWindow() + .getWindow(); if (copiedBlockPos != null && button == 1) { - clipboardHelper.setClipboardString(handle, + clipboardHelper.setClipboard(handle, "util.select.fromTo(" + copiedBlockPos.getX() + ", " + copiedBlockPos.getY() + ", " + copiedBlockPos.getZ() + ", " + hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")"); @@ -761,10 +767,10 @@ public class PonderUI extends NavigatableSimiScreen { } if (hasShiftDown()) - clipboardHelper.setClipboardString(handle, "util.select.position(" + hoveredBlockPos.getX() + ", " + clipboardHelper.setClipboard(handle, "util.select.position(" + hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")"); else - clipboardHelper.setClipboardString(handle, "util.grid.at(" + hoveredBlockPos.getX() + ", " + clipboardHelper.setClipboard(handle, "util.grid.at(" + hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")"); copiedBlockPos = hoveredBlockPos; return true; @@ -775,15 +781,15 @@ public class PonderUI extends NavigatableSimiScreen { @Override public boolean keyPressed(int code, int p_keyPressed_2_, int p_keyPressed_3_) { - GameSettings settings = Minecraft.getInstance().gameSettings; - int sCode = settings.keyBindBack.getKey() - .getKeyCode(); - int aCode = settings.keyBindLeft.getKey() - .getKeyCode(); - int dCode = settings.keyBindRight.getKey() - .getKeyCode(); - int qCode = settings.keyBindDrop.getKey() - .getKeyCode(); + GameSettings settings = Minecraft.getInstance().options; + int sCode = settings.keyDown.getKey() + .getValue(); + int aCode = settings.keyLeft.getKey() + .getValue(); + int dCode = settings.keyRight.getKey() + .getValue(); + int qCode = settings.keyDrop.getKey() + .getValue(); if (code == sCode) { replay(); @@ -814,16 +820,15 @@ public class PonderUI extends NavigatableSimiScreen { @Override protected String getBreadcrumbTitle() { if (chapter != null) - return Lang.translate(LANG_PREFIX + "chapter." + chapter.getId()) - .getString(); + return chapter.getTitle(); return stack.getItem() - .getName() + .getDescription() .getString(); } public FontRenderer getFontRenderer() { - return textRenderer; + return font; } protected boolean isMouseOver(double mouseX, double mouseY, int x, int y, int w, int h) { @@ -835,7 +840,7 @@ public class PonderUI extends NavigatableSimiScreen { public static void renderSpeechBox(MatrixStack ms, int x, int y, int w, int h, boolean highlighted, Pointing pointing, boolean returnWithLocalTransform) { if (!returnWithLocalTransform) - ms.push(); + ms.pushPose(); int boxX = x; int boxY = y; @@ -864,7 +869,7 @@ public class PonderUI extends NavigatableSimiScreen { boxY -= h / 2; divotX += distance; divotY -= divotRadius; - c = ColorHelper.mixColors(borderColors, 0.5f); + c = Color.mixColors(borderColors, 0.5f); break; case RIGHT: divotRotation = 270; @@ -872,7 +877,7 @@ public class PonderUI extends NavigatableSimiScreen { boxY -= h / 2; divotX -= divotSize + distance; divotY -= divotRadius; - c = ColorHelper.mixColors(borderColors, 0.5f); + c = Color.mixColors(borderColors, 0.5f); break; case UP: divotRotation = 180; @@ -891,20 +896,20 @@ public class PonderUI extends NavigatableSimiScreen { .withBounds(w, h) .render(ms); - ms.push(); + ms.pushPose(); ms.translate(divotX + divotRadius, divotY + divotRadius, 10); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(divotRotation)); + ms.mulPose(Vector3f.ZP.rotationDegrees(divotRotation)); ms.translate(-divotRadius, -divotRadius, 0); AllGuiTextures.SPEECH_TOOLTIP_BACKGROUND.draw(ms, 0, 0); AllGuiTextures.SPEECH_TOOLTIP_COLOR.draw(ms, 0, 0, c); - ms.pop(); + ms.popPose(); if (returnWithLocalTransform) { ms.translate(boxX, boxY, 0); return; } - ms.pop(); + ms.popPose(); } @@ -919,7 +924,7 @@ public class PonderUI extends NavigatableSimiScreen { @Override public boolean isEquivalentTo(NavigatableSimiScreen other) { if (other instanceof PonderUI) - return stack.isItemEqual(((PonderUI) other).stack); + return stack.sameItem(((PonderUI) other).stack); return super.isEquivalentTo(other); } @@ -933,10 +938,10 @@ public class PonderUI extends NavigatableSimiScreen { public static float getPartialTicks() { float renderPartialTicks = Minecraft.getInstance() - .getRenderPartialTicks(); + .getFrameTime(); - if (Minecraft.getInstance().currentScreen instanceof PonderUI) { - PonderUI ui = (PonderUI) Minecraft.getInstance().currentScreen; + if (Minecraft.getInstance().screen instanceof PonderUI) { + PonderUI ui = (PonderUI) Minecraft.getInstance().screen; if (ui.identifyMode) return ponderPartialTicksPaused; @@ -963,7 +968,7 @@ public class PonderUI extends NavigatableSimiScreen { public void drawRightAlignedString(FontRenderer fontRenderer, MatrixStack ms, String string, int x, int y, int color) { - fontRenderer.draw(ms, string, (float) (x - fontRenderer.getStringWidth(string)), (float) y, color); + fontRenderer.draw(ms, string, (float) (x - fontRenderer.width(string)), (float) y, color); } public boolean isComfyReadingEnabled() { 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..b3b1e7bd1 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java @@ -9,11 +9,12 @@ 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; import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.utility.worldWrappers.WrappedClientWorld; @@ -75,7 +76,7 @@ public class PonderWorld extends SchematicWorld { // ParticleManager.factories - ATs don't seem to like this one particleFactories = ObfuscationReflectionHelper.getPrivateValue(ParticleManager.class, - Minecraft.getInstance().particles, "field_178932_g"); + Minecraft.getInstance().particleEngine, "field_178932_g"); } public void createBackup() { @@ -83,8 +84,8 @@ public class PonderWorld extends SchematicWorld { originalTileEntities.clear(); blocks.forEach((k, v) -> originalBlocks.put(k, v)); tileEntities.forEach( - (k, v) -> originalTileEntities.put(k, TileEntity.createFromTag(blocks.get(k), v.write(new CompoundNBT())))); - entities.forEach(e -> EntityType.loadEntityUnchecked(e.serializeNBT(), this) + (k, v) -> originalTileEntities.put(k, TileEntity.loadStatic(blocks.get(k), v.save(new CompoundNBT())))); + entities.forEach(e -> EntityType.create(e.serializeNBT(), this) .ifPresent(originalEntities::add)); } @@ -96,23 +97,34 @@ public class PonderWorld extends SchematicWorld { renderedTileEntities.clear(); originalBlocks.forEach((k, v) -> blocks.put(k, v)); originalTileEntities.forEach((k, v) -> { - TileEntity te = TileEntity.createFromTag(originalBlocks.get(k), v.write(new CompoundNBT())); - onTEadded(te, te.getPos()); + TileEntity te = TileEntity.loadStatic(originalBlocks.get(k), v.save(new CompoundNBT())); + onTEadded(te, te.getBlockPos()); tileEntities.put(k, te); renderedTileEntities.add(te); }); - originalEntities.forEach(e -> EntityType.loadEntityUnchecked(e.serializeNBT(), this) + originalEntities.forEach(e -> EntityType.create(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.loadStatic(originalBlocks.get(p), originalTileEntities.get(p) + .save(new CompoundNBT())); + onTEadded(te, te.getBlockPos()); + 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) { @@ -124,7 +136,7 @@ public class PonderWorld extends SchematicWorld { } @Override - public int getLightLevel(LightType p_226658_1_, BlockPos p_226658_2_) { + public int getBrightness(LightType p_226658_1_, BlockPos p_226658_2_) { return overrideLight == -1 ? 15 : overrideLight; } @@ -139,46 +151,46 @@ public class PonderWorld extends SchematicWorld { @Override public BlockState getBlockState(BlockPos globalPos) { if (mask != null && !mask.test(globalPos.subtract(anchor))) - return Blocks.AIR.getDefaultState(); + return Blocks.AIR.defaultBlockState(); return super.getBlockState(globalPos); } @Override // For particle collision - public IBlockReader getExistingChunk(int p_225522_1_, int p_225522_2_) { + public IBlockReader getChunkForCollisions(int p_225522_1_, int p_225522_2_) { return this; } public void renderEntities(MatrixStack ms, SuperRenderTypeBuffer buffer, ActiveRenderInfo ari, float pt) { - Vector3d Vector3d = ari.getProjectedView(); - double d0 = Vector3d.getX(); - double d1 = Vector3d.getY(); - double d2 = Vector3d.getZ(); + Vector3d Vector3d = ari.getPosition(); + double d0 = Vector3d.x(); + double d1 = Vector3d.y(); + double d2 = Vector3d.z(); for (Entity entity : entities) { - if (entity.ticksExisted == 0) { - entity.lastTickPosX = entity.getX(); - entity.lastTickPosY = entity.getY(); - entity.lastTickPosZ = entity.getZ(); + if (entity.tickCount == 0) { + entity.xOld = entity.getX(); + entity.yOld = entity.getY(); + entity.zOld = entity.getZ(); } renderEntity(entity, d0, d1, d2, pt, ms, buffer); } - buffer.draw(RenderType.getEntitySolid(PlayerContainer.BLOCK_ATLAS_TEXTURE)); - buffer.draw(RenderType.getEntityCutout(PlayerContainer.BLOCK_ATLAS_TEXTURE)); - buffer.draw(RenderType.getEntityCutoutNoCull(PlayerContainer.BLOCK_ATLAS_TEXTURE)); - buffer.draw(RenderType.getEntitySmoothCutout(PlayerContainer.BLOCK_ATLAS_TEXTURE)); + buffer.draw(RenderType.entitySolid(PlayerContainer.BLOCK_ATLAS)); + buffer.draw(RenderType.entityCutout(PlayerContainer.BLOCK_ATLAS)); + buffer.draw(RenderType.entityCutoutNoCull(PlayerContainer.BLOCK_ATLAS)); + buffer.draw(RenderType.entitySmoothCutout(PlayerContainer.BLOCK_ATLAS)); } private void renderEntity(Entity entity, double x, double y, double z, float pt, MatrixStack ms, IRenderTypeBuffer buffer) { - double d0 = MathHelper.lerp((double) pt, entity.lastTickPosX, entity.getX()); - double d1 = MathHelper.lerp((double) pt, entity.lastTickPosY, entity.getY()); - double d2 = MathHelper.lerp((double) pt, entity.lastTickPosZ, entity.getZ()); - float f = MathHelper.lerp(pt, entity.prevRotationYaw, entity.rotationYaw); + double d0 = MathHelper.lerp((double) pt, entity.xOld, entity.getX()); + double d1 = MathHelper.lerp((double) pt, entity.yOld, entity.getY()); + double d2 = MathHelper.lerp((double) pt, entity.zOld, entity.getZ()); + float f = MathHelper.lerp(pt, entity.yRotO, entity.yRot); EntityRendererManager renderManager = Minecraft.getInstance() - .getRenderManager(); + .getEntityRenderDispatcher(); int light = renderManager.getRenderer(entity) - .getLight(entity, pt); + .getPackedLightCoords(entity, pt); renderManager.render(entity, d0 - x, d1 - y, d2 - z, f, pt, ms, buffer, light); } @@ -192,10 +204,10 @@ public class PonderWorld extends SchematicWorld { for (Iterator iterator = entities.iterator(); iterator.hasNext();) { Entity entity = iterator.next(); - entity.ticksExisted++; - entity.lastTickPosX = entity.getX(); - entity.lastTickPosY = entity.getY(); - entity.lastTickPosZ = entity.getZ(); + entity.tickCount++; + entity.xOld = entity.getX(); + entity.yOld = entity.getY(); + entity.zOld = entity.getZ(); entity.tick(); if (entity.getY() <= -.5f) @@ -212,7 +224,7 @@ public class PonderWorld extends SchematicWorld { } @Override - public void addOptionalParticle(IParticleData data, double x, double y, double z, double mx, double my, double mz) { + public void addAlwaysVisibleParticle(IParticleData data, double x, double y, double z, double mx, double my, double mz) { addParticle(data, x, y, z, mx, my, mz); } @@ -223,7 +235,12 @@ public class PonderWorld extends SchematicWorld { ResourceLocation key = ForgeRegistries.PARTICLE_TYPES.getKey(data.getType()); IParticleFactory iparticlefactory = (IParticleFactory) particleFactories.get(key); return iparticlefactory == null ? null - : iparticlefactory.makeParticle(data, asClientWorld.getValue(), x, y, z, mx, my, mz); + : iparticlefactory.createParticle(data, asClientWorld.get(), x, y, z, mx, my, mz); + } + + @Override + public boolean setBlock(BlockPos pos, BlockState arg1, int arg2) { + return super.setBlock(pos, arg1, arg2); } public void addParticle(Particle 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.getBlockPos(); + for (BlockPos blockPos : BeltBlock.getBeltChain(this, controllerPos)) { + TileEntity tileEntity2 = getBlockEntity(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.getBlockPos(); + if (lastKnown == null || current == null) + continue; + if (fluidTankTileEntity.isController()) + continue; + if (!lastKnown.equals(current)) { + BlockPos newControllerPos = fluidTankTileEntity.getController() + .offset(current.subtract(lastKnown)); + fluidTankTileEntity.setController(newControllerPos); + } } } } @@ -274,7 +305,7 @@ public class PonderWorld extends SchematicWorld { if (voxelshape.isEmpty()) return; - AxisAlignedBB bb = voxelshape.getBoundingBox(); + AxisAlignedBB bb = voxelshape.bounds(); double d1 = Math.min(1.0D, bb.maxX - bb.minX); double d2 = Math.min(1.0D, bb.maxY - bb.minY); double d3 = Math.min(1.0D, bb.maxZ - bb.minZ); @@ -304,17 +335,22 @@ public class PonderWorld extends SchematicWorld { } @Override - public boolean chunkExists(int x, int y) { + public boolean hasChunkAt(BlockPos pos) { return true; // fix particle lighting } @Override - public boolean isBlockPresent(BlockPos pos) { + public boolean hasChunk(int x, int y) { return true; // fix particle lighting } @Override - public boolean isPlayerWithin(double p_217358_1_, double p_217358_3_, double p_217358_5_, double p_217358_7_) { + public boolean isLoaded(BlockPos pos) { + return true; // fix particle lighting + } + + @Override + public boolean hasNearbyAlivePlayer(double p_217358_1_, double p_217358_3_, double p_217358_5_, double p_217358_7_) { return true; // always enable spawner animations } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorldParticles.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorldParticles.java index 3ff9774bb..79ce37930 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorldParticles.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorldParticles.java @@ -61,9 +61,9 @@ public class PonderWorldParticles { public void renderParticles(MatrixStack ms, IRenderTypeBuffer buffer, ActiveRenderInfo renderInfo, float pt) { Minecraft mc = Minecraft.getInstance(); - LightTexture lightTexture = mc.gameRenderer.getLightmapTextureManager(); + LightTexture lightTexture = mc.gameRenderer.lightTexture(); - lightTexture.enableLightmap(); + lightTexture.turnOnLightLayer(); Runnable enable = () -> { RenderSystem.enableAlphaTest(); RenderSystem.defaultAlphaFunc(); @@ -71,34 +71,33 @@ public class PonderWorldParticles { RenderSystem.enableFog(); }; RenderSystem.pushMatrix(); - RenderSystem.multMatrix(ms.peek() - .getModel()); - // check ParticleManager#renderParticles for a replacement if RenderSystem#multMatrix gets removed + RenderSystem.multMatrix(ms.last() + .pose()); - 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); Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferbuilder = tessellator.getBuffer(); - iparticlerendertype.beginRender(bufferbuilder, mc.textureManager); + BufferBuilder bufferbuilder = tessellator.getBuilder(); + iparticlerendertype.begin(bufferbuilder, mc.textureManager); for (Particle particle : iterable) - particle.buildGeometry(bufferbuilder, renderInfo, pt); + particle.render(bufferbuilder, renderInfo, pt); - iparticlerendertype.finishRender(tessellator); + iparticlerendertype.end(tessellator); } } RenderSystem.popMatrix(); RenderSystem.depthMask(true); + RenderSystem.depthFunc(515); RenderSystem.disableBlend(); RenderSystem.defaultAlphaFunc(); - lightTexture.disableLightmap(); + lightTexture.turnOffLightLayer(); RenderSystem.disableFog(); } 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..2415e6fcf 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,7 @@ 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.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; @@ -58,7 +59,7 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -75,6 +76,7 @@ import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; @@ -130,13 +132,13 @@ public class SceneBuilder { * Assign a unique translation key, as well as the standard english translation * for this scene's title using this method, anywhere inside the program * function. - * + * * @param sceneId * @param title */ public void title(String sceneId, String title) { - scene.sceneId = sceneId; - PonderLocalization.registerSpecific(sceneId, PonderScene.TITLE_KEY, title); + scene.sceneId = new ResourceLocation(scene.namespace, sceneId); + PonderLocalization.registerSpecific(scene.sceneId, PonderScene.TITLE_KEY, title); } /** @@ -145,7 +147,7 @@ public class SceneBuilder { * the the base plate.
* As a result, showBasePlate() will only show the configured size, and the * scene's scaling inside the UI will be consistent with its base size. - * + * * @param xOffset Block spaces between the base plate and the schematic * boundary on the Western side. * @param zOffset Block spaces between the base plate and the schematic @@ -162,8 +164,8 @@ public class SceneBuilder { /** * Use this in case you are not happy with the scale of the scene relative to * the overlay - * - * @param factor >1 will make the scene appear larger, smaller otherwise + * + * @param factor {@literal >}1 will make the scene appear larger, smaller otherwise */ public void scaleSceneView(float factor) { scene.scaleFactor = factor; @@ -172,8 +174,8 @@ public class SceneBuilder { /** * Use this in case you are not happy with the vertical alignment of the scene * relative to the overlay - * - * @param yOffset >0 moves the scene up, down otherwise + * + * @param yOffset {@literal >}0 moves the scene up, down otherwise */ public void setSceneOffsetY(float yOffset) { scene.yOffset = yOffset; @@ -190,12 +192,30 @@ public class SceneBuilder { Direction.UP); } + /** + * Adds an instruction to the scene. It is recommended to only use this method + * if another method in this class or its subclasses does not already allow + * adding a certain instruction. + */ + public void addInstruction(PonderInstruction instruction) { + scene.schedule.add(instruction); + } + + /** + * Adds a simple instruction to the scene. It is recommended to only use this + * method if another method in this class or its subclasses does not already + * allow adding a certain instruction. + */ + public void addInstruction(Consumer callback) { + addInstruction(PonderInstruction.simple(callback)); + } + /** * Before running the upcoming instructions, wait for a duration to let previous * actions play out.
* Idle does not stall any animations, only schedules a time gap between * instructions. - * + * * @param ticks Duration to wait for */ public void idle(int ticks) { @@ -207,7 +227,7 @@ public class SceneBuilder { * actions play out.
* Idle does not stall any animations, only schedules a time gap between * instructions. - * + * * @param seconds Duration to wait for */ public void idleSeconds(int seconds) { @@ -227,7 +247,7 @@ public class SceneBuilder { /** * Pans the scene's camera view around the vertical axis by the given amount - * + * * @param degrees */ public void rotateCameraY(float degrees) { @@ -263,7 +283,7 @@ public class SceneBuilder { private void rotationIndicator(BlockPos pos, boolean direction) { addInstruction(scene -> { BlockState blockState = scene.world.getBlockState(pos); - TileEntity tileEntity = scene.world.getTileEntity(pos); + TileEntity tileEntity = scene.world.getBlockEntity(pos); if (!(blockState.getBlock() instanceof KineticBlock)) return; @@ -307,7 +327,7 @@ public class SceneBuilder { } public void createRedstoneParticles(BlockPos pos, int color, int amount) { - Vector3d rgb = ColorHelper.getRGB(color); + Vector3d rgb = Color.vectorFromRGB(color); addInstruction(new EmitParticlesInstruction(VecHelper.getCenterOf(pos), Emitter.withinBlockSpace( new RedstoneParticleData((float) rgb.x, (float) rgb.y, (float) rgb.z, 1), Vector3d.ZERO), amount, 2)); } @@ -563,7 +583,7 @@ public class SceneBuilder { } public void destroyBlock(BlockPos pos) { - setBlock(pos, Blocks.AIR.getDefaultState(), true); + setBlock(pos, Blocks.AIR.defaultBlockState(), true); } public void setBlock(BlockPos pos, BlockState state, boolean spawnParticles) { @@ -580,7 +600,7 @@ public class SceneBuilder { public void cycleBlockProperty(BlockPos pos, Property property) { modifyBlocks(scene.getSceneBuildingUtil().select.position(pos), - s -> s.contains(property) ? s.cycle(property) : s, false); + s -> s.hasProperty(property) ? s.cycle(property) : s, false); } public void modifyBlocks(Selection selection, UnaryOperator stateFunc, boolean spawnParticles) { @@ -589,11 +609,11 @@ public class SceneBuilder { public void toggleRedstonePower(Selection selection) { modifyBlocks(selection, s -> { - if (s.contains(BlockStateProperties.POWER_0_15)) - s = s.with(BlockStateProperties.POWER_0_15, s.get(BlockStateProperties.POWER_0_15) == 0 ? 15 : 0); - if (s.contains(BlockStateProperties.POWERED)) + if (s.hasProperty(BlockStateProperties.POWER)) + s = s.setValue(BlockStateProperties.POWER, s.getValue(BlockStateProperties.POWER) == 0 ? 15 : 0); + if (s.hasProperty(BlockStateProperties.POWERED)) s = s.cycle(BlockStateProperties.POWERED); - if (s.contains(RedstoneTorchBlock.LIT)) + if (s.hasProperty(RedstoneTorchBlock.LIT)) s = s.cycle(RedstoneTorchBlock.LIT); return s; }, false); @@ -606,7 +626,7 @@ public class SceneBuilder { public void modifyEntitiesInside(Class entityClass, Selection area, Consumer entityCallBack) { addInstruction(scene -> scene.forEachWorldEntity(entityClass, e -> { - if (area.test(e.getBlockPos())) + if (area.test(e.blockPosition())) entityCallBack.accept(e); })); } @@ -627,7 +647,7 @@ public class SceneBuilder { EntityElement handle = new EntityElement(entity); scene.addElement(handle); scene.linkElement(handle, link); - world.addEntity(entity); + world.addFreshEntity(entity); }); return link; } @@ -635,7 +655,7 @@ public class SceneBuilder { public ElementLink createItemEntity(Vector3d location, Vector3d motion, ItemStack stack) { return createEntity(world -> { ItemEntity itemEntity = new ItemEntity(world, location.x, location.y, location.z, stack); - itemEntity.setMotion(motion); + itemEntity.setDeltaMovement(motion); return itemEntity; }); } @@ -648,7 +668,7 @@ public class SceneBuilder { public void createItemOnBeltLike(BlockPos location, Direction insertionSide, ItemStack stack) { addInstruction(scene -> { PonderWorld world = scene.getWorld(); - TileEntity tileEntity = world.getTileEntity(location); + TileEntity tileEntity = world.getBlockEntity(location); if (!(tileEntity instanceof SmartTileEntity)) return; SmartTileEntity beltTileEntity = (SmartTileEntity) tileEntity; @@ -657,7 +677,7 @@ public class SceneBuilder { return; behaviour.handleInsertion(stack, insertionSide.getOpposite(), false); }); - flapFunnel(location.up(), true); + flapFunnel(location.above(), true); } public ElementLink createItemOnBelt(BlockPos beltLocation, Direction insertionSide, @@ -665,7 +685,7 @@ public class SceneBuilder { ElementLink link = new ElementLink<>(BeltItemElement.class); addInstruction(scene -> { PonderWorld world = scene.getWorld(); - TileEntity tileEntity = world.getTileEntity(beltLocation); + TileEntity tileEntity = world.getBlockEntity(beltLocation); if (!(tileEntity instanceof BeltTileEntity)) return; @@ -686,14 +706,14 @@ public class SceneBuilder { return TransportedResult.doNothing(); }); }); - flapFunnel(beltLocation.up(), true); + flapFunnel(beltLocation.above(), true); return link; } public void removeItemsFromBelt(BlockPos beltLocation) { addInstruction(scene -> { PonderWorld world = scene.getWorld(); - TileEntity tileEntity = world.getTileEntity(beltLocation); + TileEntity tileEntity = world.getBlockEntity(beltLocation); if (!(tileEntity instanceof SmartTileEntity)) return; SmartTileEntity beltTileEntity = (SmartTileEntity) tileEntity; @@ -739,6 +759,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()); @@ -752,7 +776,7 @@ public class SceneBuilder { public void modifyTileEntity(BlockPos position, Class teType, Consumer consumer) { addInstruction(scene -> { - TileEntity tileEntity = scene.world.getTileEntity(position); + TileEntity tileEntity = scene.world.getBlockEntity(position); if (teType.isInstance(tileEntity)) consumer.accept(teType.cast(tileEntity)); }); @@ -810,12 +834,4 @@ public class SceneBuilder { } - private void addInstruction(PonderInstruction instruction) { - scene.schedule.add(instruction); - } - - private void addInstruction(Consumer callback) { - scene.schedule.add(PonderInstruction.simple(callback)); - } - -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuildingUtil.java b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuildingUtil.java index a7eed2600..3af92af68 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuildingUtil.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuildingUtil.java @@ -61,7 +61,7 @@ public class SceneBuildingUtil { } public Vector3d blockSurface(BlockPos pos, Direction face, float margin) { - return centerOf(pos).add(Vector3d.of(face.getDirectionVec()) + return centerOf(pos).add(Vector3d.atLowerCornerOf(face.getNormal()) .scale(.5f + margin)); } @@ -94,7 +94,7 @@ public class SceneBuildingUtil { } public Selection column(int x, int z) { - return cuboid(new BlockPos(x, 1, z), new Vector3i(0, sceneBounds.getYSize(), 0)); + return cuboid(new BlockPos(x, 1, z), new Vector3i(0, sceneBounds.getYSpan(), 0)); } public Selection layer(int y) { @@ -102,16 +102,16 @@ public class SceneBuildingUtil { } public Selection layersFrom(int y) { - return layers(y, sceneBounds.getYSize() - y); + return layers(y, sceneBounds.getYSpan() - y); } public Selection layers(int y, int height) { - return cuboid(new BlockPos(0, y, 0), new Vector3i(sceneBounds.getXSize() - 1, - Math.min(sceneBounds.getYSize() - y, height) - 1, sceneBounds.getZSize() - 1)); + return cuboid(new BlockPos(0, y, 0), new Vector3i(sceneBounds.getXSpan() - 1, + Math.min(sceneBounds.getYSpan() - y, height) - 1, sceneBounds.getZSpan() - 1)); } public Selection cuboid(BlockPos origin, Vector3i size) { - return Selection.of(new MutableBoundingBox(origin, origin.add(size))); + return Selection.of(new MutableBoundingBox(origin, origin.offset(size))); } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/Selection.java b/src/main/java/com/simibubi/create/foundation/ponder/Selection.java index 4541f1cbe..f0885bce1 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/Selection.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/Selection.java @@ -56,14 +56,14 @@ public abstract class Selection implements Predicate { @Override public Selection add(Selection other) { - other.forEach(p -> posSet.add(p.toImmutable())); + other.forEach(p -> posSet.add(p.immutable())); center = null; return this; } @Override public Selection substract(Selection other) { - other.forEach(p -> posSet.remove(p.toImmutable())); + other.forEach(p -> posSet.remove(p.immutable())); center = null; return this; } @@ -88,7 +88,7 @@ public abstract class Selection implements Predicate { if (posSet.isEmpty()) return center; for (BlockPos blockPos : posSet) - center = center.add(Vector3d.of(blockPos)); + center = center.add(Vector3d.atLowerCornerOf(blockPos)); center = center.scale(1f / posSet.size()); return center.add(new Vector3d(.5, .5, .5)); } @@ -112,7 +112,7 @@ public abstract class Selection implements Predicate { @Override public boolean test(BlockPos t) { - return bb.isVecInside(t); + return bb.isInside(t); } @Override @@ -127,7 +127,7 @@ public abstract class Selection implements Predicate { @Override public void forEach(Consumer callback) { - BlockPos.stream(bb) + BlockPos.betweenClosedStream(bb) .forEach(callback); } @@ -142,7 +142,7 @@ public abstract class Selection implements Predicate { } private AxisAlignedBB getAABB() { - return new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX + 1, bb.maxY + 1, bb.maxZ + 1); + return new AxisAlignedBB(bb.x0, bb.y0, bb.z0, bb.x1 + 1, bb.y1 + 1, bb.z1 + 1); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ArmScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ArmScenes.java index af26370f7..4ba0e1116 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/ArmScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ArmScenes.java @@ -56,8 +56,8 @@ public class ArmScenes { scene.overlay.showControls(new InputWindowElement(depotSurface, Pointing.RIGHT).rightClick() .withItem(armItem), 50); scene.idle(7); - AxisAlignedBB depotBounds = AllShapes.DEPOT.getBoundingBox(); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(4, 2, 1), 400); + AxisAlignedBB depotBounds = AllShapes.DEPOT.bounds(); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.move(4, 2, 1), 400); scene.overlay.showText(70) .attachKeyFrame() @@ -74,11 +74,11 @@ public class ArmScenes { scene.overlay.showControls(input, 20); scene.idle(7); Object second = new Object(); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, second, depotBounds.offset(0, 2, 1), 100); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, second, depotBounds.move(0, 2, 1), 100); scene.idle(25); scene.overlay.showControls(input, 30); scene.idle(7); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, second, depotBounds.offset(0, 2, 1), 280); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, second, depotBounds.move(0, 2, 1), 280); scene.overlay.showText(70) .colored(PonderPalette.OUTPUT) .text("Right-Click again to toggle between Input (Blue) and Output (Orange)") @@ -88,7 +88,7 @@ public class ArmScenes { scene.idle(80); scene.world.showSection(util.select.position(1, 1, 0), Direction.DOWN); scene.idle(15); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(1, 1, 0), 43); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.move(1, 1, 0), 43); scene.overlay.showText(50) .colored(PonderPalette.WHITE) @@ -138,15 +138,15 @@ public class ArmScenes { scene.world.showSection(util.select.position(4, 1, 2), Direction.DOWN); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, new Object(), depotBounds.offset(0, 2, 1), 60); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, new Object(), depotBounds.move(0, 2, 1), 60); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(4, 2, 1), 60); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.move(4, 2, 1), 60); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, new Object(), depotBounds.offset(1, 1, 0), 60); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, new Object(), depotBounds.move(1, 1, 0), 60); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(1, 3, 4), 60); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.move(1, 3, 4), 60); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(4, 1, 2), 60); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.move(4, 1, 2), 60); scene.idle(5); scene.overlay.showText(80) @@ -191,8 +191,8 @@ public class ArmScenes { AxisAlignedBB chestBounds = new AxisAlignedBB(1 / 16f, 0, 1 / 16f, 15 / 16f, 14 / 16f, 15 / 16f); AxisAlignedBB funnelBounds = new AxisAlignedBB(0, 0, 8 / 16f, 16 / 16f, 16 / 16f, 16 / 16f); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, in, chestBounds.offset(4, 2, 3), 120); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, out, chestBounds.offset(0, 2, 3), 120); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, in, chestBounds.move(4, 2, 3), 120); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, out, chestBounds.move(0, 2, 3), 120); scene.overlay.showText(80) .attachKeyFrame() .text("However, not every type of Inventory can be interacted with directly") @@ -206,9 +206,9 @@ public class ArmScenes { scene.world.showSection(util.select.position(0, 2, 2), Direction.SOUTH); scene.idle(10); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, depotBounds.offset(4, 1, 2), 80); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, depotBounds.move(4, 1, 2), 80); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, funnelBounds.offset(0, 2, 2), 80); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, funnelBounds.move(0, 2, 2), 80); scene.idle(5); scene.overlay.showText(60) @@ -381,7 +381,7 @@ public class ArmScenes { public static void modes(SceneBuilder scene, SceneBuildingUtil util) { scene.title("mechanical_arm_modes", "Distribution modes of the Mechanical Arm"); scene.configureBasePlate(0, 1, 5); - scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.BARRIER.getDefaultState(), false); + scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.BARRIER.defaultBlockState(), false); scene.world.showSection(util.select.layer(0), Direction.UP); scene.idle(5); @@ -392,20 +392,20 @@ public class ArmScenes { scene.world.showSection(util.select.fromTo(1, 1, 1, 5, 1, 2), Direction.SOUTH); scene.idle(10); - AxisAlignedBB depotBox = AllShapes.DEPOT.getBoundingBox(); + AxisAlignedBB depotBox = AllShapes.DEPOT.bounds(); AxisAlignedBB beltBox = depotBox.contract(0, -3 / 16f, 0) - .grow(1, 0, 0); + .inflate(1, 0, 0); BlockPos depotPos = util.grid.at(1, 1, 4); BlockPos armPos = util.grid.at(3, 1, 4); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, depotBox, depotBox.offset(1, 1, 4), 60); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, depotBox, depotBox.move(1, 1, 4), 60); scene.overlay.showText(30) .text("Input") .pointAt(util.vector.blockSurface(depotPos, Direction.WEST)) .placeNearTarget() .colored(PonderPalette.INPUT); scene.idle(40); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, depotBox, beltBox.offset(2, 1, 2), 40); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, depotBox, beltBox.move(2, 1, 2), 40); scene.overlay.showText(40) .text("Outputs") .pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.WEST)) @@ -468,13 +468,13 @@ public class ArmScenes { if (i == 12) { scene.world.moveSection(blockage, util.vector.of(-1, 0, 0), 10); - scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.BARRIER.getDefaultState(), false); + scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.BARRIER.defaultBlockState(), false); } int index = i % 3; if (i == 13) { - scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.BARRIER.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.BARRIER.defaultBlockState(), false); ElementLink blockage2 = scene.world.showIndependentSection(util.select.position(4, 1, 0), Direction.UP); scene.world.moveSection(blockage2, util.vector.of(-2, 0, 0), 0); @@ -510,7 +510,7 @@ public class ArmScenes { .colored(PonderPalette.RED); scene.idle(40); scene.world.moveSection(blockage, util.vector.of(1, 0, 0), 10); - scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.AIR.defaultBlockState(), false); scene.idle(50); scene.world.multiplyKineticSpeed(util.select.fromTo(1, 1, 1, 5, 0, 3), 2); } @@ -557,7 +557,7 @@ public class ArmScenes { scene.overlay.showText(60) .colored(PonderPalette.RED) .attachKeyFrame() - .pointAt(util.vector.topOf(armPos.up())) + .pointAt(util.vector.topOf(armPos.above())) .placeNearTarget() .text("When powered by Redstone, Mechanical Arms will not activate"); scene.idle(70); @@ -582,7 +582,7 @@ public class ArmScenes { scene.world.toggleRedstonePower(redstone); scene.effects.indicateRedstone(leverPos); scene.overlay.showText(60) - .pointAt(util.vector.topOf(armPos.up())) + .pointAt(util.vector.topOf(armPos.above())) .placeNearTarget() .text("Before stopping, it will finish any started cycles"); } @@ -593,7 +593,7 @@ public class ArmScenes { scene.overlay.showText(100) .colored(PonderPalette.GREEN) .attachKeyFrame() - .pointAt(util.vector.topOf(armPos.up())) + .pointAt(util.vector.topOf(armPos.above())) .placeNearTarget() .text("Thus, a negative pulse can be used to trigger exactly one activation cycle"); } 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..394241ae8 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 @@ -31,7 +31,7 @@ public class BearingScenes { scene.world.showSection(util.select.fromTo(1, 0, 1, 5, 0, 5), Direction.UP); scene.world.setBlock(util.grid.at(2, -1, 0), AllBlocks.SAIL.getDefaultState() - .with(SailBlock.FACING, Direction.NORTH), false); + .setValue(SailBlock.FACING, Direction.NORTH), false); scene.idle(5); Selection kinetics = util.select.fromTo(3, 1, 1, 4, 1, 4); Selection largeCog = util.select.position(3, 2, 2); @@ -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); @@ -55,39 +56,40 @@ public class BearingScenes { scene.idle(10); for (Direction d : Iterate.directions) if (d.getAxis() != Axis.Z) - scene.world.showSectionAndMerge(util.select.fromTo(anchorPos.offset(d, 1), anchorPos.offset(d, 2)), + scene.world.showSectionAndMerge(util.select.fromTo(anchorPos.relative(d, 1), anchorPos.relative(d, 2)), d.getOpposite(), structure); scene.idle(10); - scene.world.showSectionAndMerge(util.select.fromTo(anchorPos.up() + scene.world.showSectionAndMerge(util.select.fromTo(anchorPos.above() .east(), - anchorPos.up(3) + anchorPos.above(3) .east()), Direction.WEST, structure); - scene.world.showSectionAndMerge(util.select.fromTo(anchorPos.down() + scene.world.showSectionAndMerge(util.select.fromTo(anchorPos.below() .west(), - anchorPos.down(3) + anchorPos.below(3) .west()), Direction.EAST, structure); scene.world.showSectionAndMerge(util.select.fromTo(anchorPos.east() - .down(), + .below(), anchorPos.east(3) - .down()), + .below()), Direction.UP, structure); scene.world.showSectionAndMerge(util.select.fromTo(anchorPos.west() - .up(), + .above(), anchorPos.west(3) - .up()), + .above()), Direction.DOWN, structure); scene.idle(5); for (Direction d : Iterate.directions) if (d.getAxis() != Axis.Z) - scene.effects.superGlue(anchorPos.offset(d, 1), d.getOpposite(), false); + scene.effects.superGlue(anchorPos.relative(d, 1), d.getOpposite(), false); scene.idle(10); 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); @@ -162,7 +166,7 @@ public class BearingScenes { scene.world.showSection(util.select.position(bearingPos), Direction.DOWN); scene.idle(10); ElementLink contraption = - scene.world.showIndependentSection(util.select.position(bearingPos.up()), Direction.DOWN); + scene.world.showIndependentSection(util.select.position(bearingPos.above()), Direction.DOWN); scene.idle(10); scene.world.showSectionAndMerge(util.select.fromTo(3, 2, 2, 3, 3, 1), Direction.SOUTH, contraption); scene.world.showSectionAndMerge(util.select.fromTo(3, 2, 4, 3, 3, 5), Direction.NORTH, contraption); @@ -173,8 +177,8 @@ public class BearingScenes { scene.world.showSectionAndMerge(util.select.position(2, 1, 5), Direction.EAST, contraption); scene.world.showSectionAndMerge(util.select.position(3, 3, 3), Direction.DOWN, contraption); scene.idle(5); - scene.effects.superGlue(bearingPos.up(), Direction.SOUTH, true); - scene.effects.superGlue(bearingPos.up(), Direction.NORTH, true); + scene.effects.superGlue(bearingPos.above(), Direction.SOUTH, true); + scene.effects.superGlue(bearingPos.above(), Direction.NORTH, true); scene.idle(5); scene.effects.superGlue(util.grid.at(3, 1, 5), Direction.UP, true); scene.idle(5); @@ -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); @@ -221,14 +226,15 @@ public class BearingScenes { .add(cog4); BlockPos bearingPos = util.grid.at(3, 2, 3); - scene.overlay.showSelectionWithText(util.select.position(bearingPos.up()), 60) + scene.overlay.showSelectionWithText(util.select.position(bearingPos.above()), 60) .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); - ElementLink plank = scene.world.showIndependentSection(util.select.position(bearingPos.up() + ElementLink plank = scene.world.showIndependentSection(util.select.position(bearingPos.above() .east() .north()), Direction.DOWN); scene.world.moveSection(plank, util.vector.of(-1, 0, 1), 0); @@ -238,13 +244,14 @@ public class BearingScenes { scene.world.setKineticSpeed(cog2, 8); scene.world.setKineticSpeed(cog3, -16); scene.world.setKineticSpeed(cog4, 16); - scene.effects.rotationSpeedIndicator(bearingPos.down()); + scene.effects.rotationSpeedIndicator(bearingPos.below()); scene.world.rotateBearing(bearingPos, 360, 37 * 2); scene.world.rotateSection(plank, 0, 360, 0, 37 * 2); scene.overlay.showText(80) - .pointAt(util.vector.topOf(bearingPos.up())) + .pointAt(util.vector.topOf(bearingPos.above())) .placeNearTarget() + .attachKeyFrame() .text("Upon receiving Rotational Force, it will assemble it into a Rotating Contraption"); scene.idle(37 * 2); scene.world.setKineticSpeed(all, 0); @@ -266,13 +273,14 @@ public class BearingScenes { scene.world.setKineticSpeed(cog2, 8); scene.world.setKineticSpeed(cog3, -16); scene.world.setKineticSpeed(cog4, 16); - scene.effects.rotationSpeedIndicator(bearingPos.down()); + scene.effects.rotationSpeedIndicator(bearingPos.below()); scene.world.rotateBearing(bearingPos, 360 * 2, 37 * 4); scene.world.rotateSection(contraption, 0, 360 * 2, 0, 37 * 4); scene.overlay.showText(120) - .pointAt(util.vector.topOf(bearingPos.up())) + .pointAt(util.vector.topOf(bearingPos.above())) .placeNearTarget() + .attachKeyFrame() .sharedText("movement_anchors"); scene.idle(37 * 4); @@ -321,7 +329,7 @@ public class BearingScenes { scene.world.rotateSection(contraption, 0, 35, 0, 0); scene.world.rotateBearing(bearingPos, 35, 0); - Vector3d target = util.vector.topOf(bearingPos.down()); + Vector3d target = util.vector.topOf(bearingPos.below()); scene.overlay.showLine(PonderPalette.RED, target.add(-2.5, 0, 3.5), target, 50); scene.overlay.showLine(PonderPalette.GREEN, target.add(0, 0, 4.5), target, 50); @@ -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); @@ -589,16 +606,16 @@ public class BearingScenes { scene.world.showSection(util.select.position(bearingPos), Direction.DOWN); scene.idle(5); ElementLink plank = - scene.world.showIndependentSection(util.select.position(bearingPos.up()), Direction.DOWN); + scene.world.showIndependentSection(util.select.position(bearingPos.above()), Direction.DOWN); scene.idle(10); for (int i = 0; i < 3; i++) { for (Direction d : Iterate.horizontalDirections) { - BlockPos location = bearingPos.up(i + 1) - .offset(d); + BlockPos location = bearingPos.above(i + 1) + .relative(d); if (frame) scene.world.modifyBlock(location, s -> AllBlocks.SAIL_FRAME.getDefaultState() - .with(SailBlock.FACING, s.get(SailBlock.FACING)), false); + .setValue(SailBlock.FACING, s.getValue(SailBlock.FACING)), false); scene.world.showSectionAndMerge(util.select.position(location), d.getOpposite(), plank); scene.idle(2); } @@ -611,14 +628,14 @@ public class BearingScenes { .attachKeyFrame(); scene.idle(80); - scene.overlay.showSelectionWithText(util.select.position(bearingPos.up()), 80) + scene.overlay.showSelectionWithText(util.select.position(bearingPos.above()), 80) .colored(PonderPalette.GREEN) .text("They will attach to blocks and each other without the need of Super Glue or Chassis Blocks") .attachKeyFrame() .placeNearTarget(); scene.idle(40); scene.world.configureCenterOfRotation(plank, util.vector.centerOf(bearingPos)); - + if (!frame) { scene.world.rotateBearing(bearingPos, 180, 75); scene.world.rotateSection(plank, 0, 180, 0, 75); @@ -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() + .setValue(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() + .setValue(SailBlock.FACING, Direction.WEST), + false); scene.idle(20); scene.world.rotateBearing(bearingPos, 90, 33); @@ -661,7 +678,7 @@ public class BearingScenes { scene.overlay.showControls(input, 30); scene.idle(7); scene.world.setBlock(util.grid.at(3, 3, 2), AllBlocks.SAIL_FRAME.getDefaultState() - .with(SailBlock.FACING, Direction.NORTH), false); + .setValue(SailBlock.FACING, Direction.NORTH), false); scene.idle(10); scene.overlay.showText(40) .text("Right-Click with Shears to turn them back into frames") @@ -672,7 +689,7 @@ public class BearingScenes { scene.overlay.showControls(input, 30); scene.idle(7); scene.world.replaceBlocks(util.select.fromTo(3, 2, 2, 3, 4, 2), AllBlocks.SAIL_FRAME.getDefaultState() - .with(SailBlock.FACING, Direction.NORTH), false); + .setValue(SailBlock.FACING, Direction.NORTH), false); scene.idle(20); } 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..aabb1480d 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 @@ -61,15 +61,15 @@ public class BeltScenes { Vector3d backEndCenter = util.vector.centerOf(backEnd); AxisAlignedBB connectBB = new AxisAlignedBB(backEndCenter, backEndCenter); AxisAlignedBB shaftBB = AllBlocks.SHAFT.getDefaultState() - .with(ShaftBlock.AXIS, Axis.Z) + .setValue(ShaftBlock.AXIS, Axis.Z) .getShape(null, null) - .getBoundingBox(); + .bounds(); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(backEnd), Pointing.DOWN).rightClick() .withItem(beltItem), 57); scene.idle(7); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, backEnd, shaftBB.offset(backEnd), 42); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, backEnd, shaftBB.move(backEnd), 42); scene.overlay.chaseBoundingBoxOutline(PonderPalette.BLACK, backEndCenter, connectBB, 50); scene.idle(20); @@ -77,8 +77,8 @@ public class BeltScenes { .withItem(beltItem), 37); scene.idle(7); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, frontEnd, shaftBB.offset(frontEnd), 17); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.BLACK, backEndCenter, connectBB.expand(-4, 0, 0), 20); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, frontEnd, shaftBB.move(frontEnd), 17); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.BLACK, backEndCenter, connectBB.expandTowards(-4, 0, 0), 20); scene.idle(20); scene.world.moveSection(shafts, util.vector.of(0, -2, 0), 0); @@ -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); @@ -95,11 +96,12 @@ public class BeltScenes { scene.overlay.showControls(new InputWindowElement(falseSelection, Pointing.DOWN).rightClick() .withItem(beltItem), 37); scene.idle(7); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, backEnd, shaftBB.offset(backEnd.south(1)), 50); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, backEnd, shaftBB.move(backEnd.south(1)), 50); 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); @@ -113,11 +115,12 @@ public class BeltScenes { scene.overlay.showControls(new InputWindowElement(util.vector.topOf(shaftLocation), Pointing.DOWN).rightClick() .withItem(AllBlocks.SHAFT.asStack()), 50); scene.idle(7); - scene.world.modifyBlock(shaftLocation, s -> s.with(BeltBlock.PART, BeltPart.PULLEY), true); + scene.world.modifyBlock(shaftLocation, s -> s.setValue(BeltBlock.PART, BeltPart.PULLEY), true); scene.idle(10); 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); @@ -142,10 +145,11 @@ public class BeltScenes { scene.overlay.showControls(new InputWindowElement(util.vector.topOf(shaftLocation), Pointing.DOWN).rightClick() .withWrench(), 50); scene.idle(7); - scene.world.modifyBlock(shaftLocation, s -> s.with(BeltBlock.PART, BeltPart.MIDDLE), true); + scene.world.modifyBlock(shaftLocation, s -> s.setValue(BeltBlock.PART, BeltPart.MIDDLE), true); 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)); @@ -403,13 +412,13 @@ public class BeltScenes { scene.overlay.showControls(new InputWindowElement(util.vector.topOf(beltPos), Pointing.DOWN).rightClick() .withItem(brassCasingItem), 20); scene.idle(7); - scene.world.modifyBlock(beltPos, s -> s.with(BeltBlock.CASING, true), true); + scene.world.modifyBlock(beltPos, s -> s.setValue(BeltBlock.CASING, true), true); scene.idle(20); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(beltPos2), Pointing.DOWN).rightClick() .withItem(andesiteCasingItem), 20); scene.idle(7); - scene.world.modifyBlock(beltPos2, s -> s.with(BeltBlock.CASING, true), true); + scene.world.modifyBlock(beltPos2, s -> s.setValue(BeltBlock.CASING, true), true); scene.world.modifyTileNBT(util.select.position(beltPos2), BeltTileEntity.class, nbt -> { NBTHelper.writeEnum(nbt, "Casing", BeltTileEntity.CasingType.ANDESITE); }); @@ -420,11 +429,12 @@ public class BeltScenes { .withItem(brassCasingItem), 20); scene.idle(7); - scene.world.modifyBlock(beltPos3, s -> s.with(BeltBlock.CASING, true), true); + scene.world.modifyBlock(beltPos3, s -> s.setValue(BeltBlock.CASING, true), true); scene.idle(20); 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); @@ -436,7 +446,7 @@ public class BeltScenes { brassBelts.add(beltPos.south(z)); for (int x = 1; x <= 3; x++) brassBelts.add(beltPos3.east(x) - .down(x)); + .below(x)); for (int x = 1; x <= 3; x++) andesiteBelts.add(beltPos2.east(x)); @@ -445,22 +455,23 @@ public class BeltScenes { for (BlockPos pos : andesiteBelts) { scene.idle(4); - scene.world.modifyBlock(pos, s -> s.with(BeltBlock.CASING, true), true); + scene.world.modifyBlock(pos, s -> s.setValue(BeltBlock.CASING, true), true); scene.world.modifyTileNBT(util.select.position(pos), BeltTileEntity.class, nbt -> { NBTHelper.writeEnum(nbt, "Casing", BeltTileEntity.CasingType.ANDESITE); }); } for (BlockPos pos : brassBelts) { scene.idle(4); - scene.world.modifyBlock(pos, s -> s.with(BeltBlock.CASING, true), true); + scene.world.modifyBlock(pos, s -> s.setValue(BeltBlock.CASING, true), true); } scene.idle(30); + scene.addKeyframe(); scene.overlay .showControls(new InputWindowElement(util.vector.topOf(beltPos.south()), Pointing.DOWN).rightClick() .withWrench(), 40); scene.idle(7); - scene.world.modifyBlock(beltPos.south(), s -> s.with(BeltBlock.CASING, false), true); + scene.world.modifyBlock(beltPos.south(), s -> s.setValue(BeltBlock.CASING, false), true); scene.overlay.showText(80) .text("A wrench can be used to remove the casing") .placeNearTarget() @@ -472,7 +483,7 @@ public class BeltScenes { scene.configureBasePlate(0, 0, 5); scene.showBasePlate(); scene.idle(5); - scene.world.setBlock(util.grid.at(3, 2, 2), Blocks.WATER.getDefaultState(), false); + scene.world.setBlock(util.grid.at(3, 2, 2), Blocks.WATER.defaultBlockState(), false); BlockPos depotPos = util.grid.at(2, 1, 2); scene.world.showSection(util.select.position(2, 1, 2), Direction.DOWN); @@ -502,31 +513,31 @@ public class BeltScenes { scene.effects.indicateSuccess(depotPos); scene.idle(20); - scene.world.showSection(util.select.position(depotPos.up(2)), Direction.SOUTH); + scene.world.showSection(util.select.position(depotPos.above(2)), Direction.SOUTH); scene.overlay.showText(70) .attachKeyFrame() .text("Just like Mechanical Belts, it can provide items to processing") .placeNearTarget() - .pointAt(util.vector.blockSurface(depotPos.up(2), Direction.WEST)); + .pointAt(util.vector.blockSurface(depotPos.above(2), Direction.WEST)); ItemStack bottle = new ItemStack(Items.BUCKET); scene.world.createItemOnBeltLike(depotPos, Direction.NORTH, bottle); scene.idle(20); - scene.world.modifyTileNBT(util.select.position(depotPos.up(2)), SpoutTileEntity.class, + scene.world.modifyTileNBT(util.select.position(depotPos.above(2)), SpoutTileEntity.class, nbt -> nbt.putInt("ProcessingTicks", 20)); scene.idle(20); scene.world.removeItemsFromBelt(depotPos); scene.world.createItemOnBeltLike(depotPos, Direction.UP, new ItemStack(Items.WATER_BUCKET)); - scene.world.modifyTileNBT(util.select.position(depotPos.up(2)), SpoutTileEntity.class, + scene.world.modifyTileNBT(util.select.position(depotPos.above(2)), SpoutTileEntity.class, nbt -> nbt.putBoolean("Splash", true)); scene.idle(30); scene.world.removeItemsFromBelt(depotPos); - scene.world.hideSection(util.select.position(depotPos.up(2)), Direction.SOUTH); + scene.world.hideSection(util.select.position(depotPos.above(2)), Direction.SOUTH); scene.idle(20); - ElementLink spout = scene.world.showIndependentSection(util.select.position(depotPos.up(2) + ElementLink spout = scene.world.showIndependentSection(util.select.position(depotPos.above(2) .west()), Direction.SOUTH); scene.world.moveSection(spout, util.vector.of(1, 0, 0), 0); - BlockPos pressPos = depotPos.up(2) + BlockPos pressPos = depotPos.above(2) .west(); ItemStack copper = AllItems.COPPER_INGOT.asStack(); scene.world.createItemOnBeltLike(depotPos, Direction.NORTH, copper); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/CartAssemblerScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/CartAssemblerScenes.java index 51616a4bf..046cde559 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/CartAssemblerScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/CartAssemblerScenes.java @@ -38,7 +38,7 @@ public class CartAssemblerScenes { scene.idle(5); BlockPos assemblerPos = util.grid.at(2, 1, 2); - scene.world.setBlock(assemblerPos, Blocks.RAIL.getDefaultState(), false); + scene.world.setBlock(assemblerPos, Blocks.RAIL.defaultBlockState(), false); for (int z = 0; z < 5; z++) { scene.world.showSection(util.select.position(2, 1, z), Direction.DOWN); scene.idle(2); @@ -54,8 +54,8 @@ public class CartAssemblerScenes { .withItem(AllBlocks.CART_ASSEMBLER.asStack()), 30); scene.idle(7); scene.world.setBlock(assemblerPos, AllBlocks.CART_ASSEMBLER.getDefaultState() - .with(CartAssemblerBlock.RAIL_SHAPE, RailShape.NORTH_SOUTH) - .with(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.REGULAR), true); + .setValue(CartAssemblerBlock.RAIL_SHAPE, RailShape.NORTH_SOUTH) + .setValue(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.REGULAR), true); scene.idle(20); scene.world.showSection(util.select.fromTo(0, 1, 2, 1, 1, 2), Direction.EAST); scene.idle(20); @@ -72,12 +72,12 @@ public class CartAssemblerScenes { ElementLink cart = scene.special.createCart(util.vector.topOf(2, 0, 4), 90, MinecartEntity::new); - scene.world.showSection(util.select.position(assemblerPos.up()), Direction.DOWN); + scene.world.showSection(util.select.position(assemblerPos.above()), Direction.DOWN); scene.idle(10); scene.special.moveCart(cart, util.vector.of(0, 0, -2), 20); scene.idle(20); ElementLink plank = - scene.world.makeSectionIndependent(util.select.position(assemblerPos.up())); + scene.world.makeSectionIndependent(util.select.position(assemblerPos.above())); ElementLink anchor = scene.world.showIndependentSectionImmediately(util.select.position(assemblerPos.east())); scene.world.moveSection(anchor, util.vector.of(-1, 0, 0), 0); @@ -111,7 +111,7 @@ public class CartAssemblerScenes { scene.special.moveCart(cart, util.vector.of(0, 0, 2), 20); scene.idle(30); - scene.world.destroyBlock(assemblerPos.up()); + scene.world.destroyBlock(assemblerPos.above()); scene.idle(5); ElementLink contraption = scene.world.showIndependentSection(util.select.fromTo(1, 4, 2, 3, 3, 2), Direction.DOWN); @@ -187,8 +187,8 @@ public class CartAssemblerScenes { BlockPos assemblerPos = util.grid.at(3, 1, 3); scene.idle(5); scene.world.setBlock(assemblerPos, AllBlocks.CART_ASSEMBLER.getDefaultState() - .with(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) - .with(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.REGULAR), true); + .setValue(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) + .setValue(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.REGULAR), true); scene.idle(5); scene.world.showSection(util.select.fromTo(3, 1, 1, 3, 1, 2), Direction.SOUTH); ElementLink contraption = @@ -235,6 +235,13 @@ public class CartAssemblerScenes { .placeNearTarget(); scene.idle(90); + scene.overlay.showText(80) + .attachKeyFrame() + .text("This Arrow indicates which side of the Structure will be considered the front") + .pointAt(util.vector.topOf(assemblerPos)) + .placeNearTarget(); + scene.idle(90); + scene.world.hideIndependentSection(contraption, Direction.UP); scene.world.hideIndependentSection(anchor, Direction.UP); scene.special.hideElement(cart, Direction.UP); @@ -310,17 +317,17 @@ public class CartAssemblerScenes { scene.world.showSection(util.select.fromTo(2, 1, 3, 2, 1, 2), Direction.SOUTH); scene.idle(5); ElementLink cart = - scene.special.createCart(util.vector.topOf(assembler1.down()), 0, MinecartEntity::new); + scene.special.createCart(util.vector.topOf(assembler1.below()), 0, MinecartEntity::new); ElementLink cart2 = - scene.special.createCart(util.vector.topOf(assembler2.down()), 0, ChestMinecartEntity::new); + scene.special.createCart(util.vector.topOf(assembler2.below()), 0, ChestMinecartEntity::new); scene.idle(15); scene.world.setBlock(assembler1, AllBlocks.CART_ASSEMBLER.getDefaultState() - .with(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) - .with(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.CONTROLLER_RAIL), true); + .setValue(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) + .setValue(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.CONTROLLER_RAIL), true); scene.idle(5); scene.world.setBlock(assembler2, AllBlocks.CART_ASSEMBLER.getDefaultState() - .with(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) - .with(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.REGULAR), true); + .setValue(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) + .setValue(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.REGULAR), true); scene.idle(5); ElementLink contraption = scene.world.showIndependentSection(chassis, Direction.DOWN); @@ -422,17 +429,17 @@ public class CartAssemblerScenes { .text("Cart Assemblers on Regular Tracks will not affect the passing carts' motion"); scene.idle(10); scene.world.setBlock(assembler, AllBlocks.CART_ASSEMBLER.getDefaultState() - .with(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) - .with(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.REGULAR), true); + .setValue(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) + .setValue(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.REGULAR), true); scene.idle(70); ElementLink cart = scene.special.createCart(util.vector.topOf(assembler.east(2) - .down()), 0, MinecartEntity::new); + .below()), 0, MinecartEntity::new); ElementLink anchor = scene.world.showIndependentSection(util.select.position(assembler.south()), Direction.DOWN); ElementLink contraption = scene.world.showIndependentSection(util.select.position(assembler.south() - .up()), Direction.DOWN); + .above()), Direction.DOWN); scene.world.moveSection(contraption, util.vector.of(2, 0, -1), 0); scene.world.moveSection(anchor, util.vector.of(2, 0, -1), 0); scene.idle(10); @@ -449,8 +456,8 @@ public class CartAssemblerScenes { .withItem(new ItemStack(Items.POWERED_RAIL)), 50); scene.idle(7); scene.world.setBlock(assembler, AllBlocks.CART_ASSEMBLER.getDefaultState() - .with(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) - .with(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.POWERED_RAIL), true); + .setValue(CartAssemblerBlock.RAIL_SHAPE, RailShape.EAST_WEST) + .setValue(CartAssemblerBlock.RAIL_TYPE, CartAssembleRailType.POWERED_RAIL), true); scene.overlay.showText(100) .attachKeyFrame() .pointAt(util.vector.topOf(assembler)) @@ -460,10 +467,10 @@ public class CartAssemblerScenes { scene.world.hideIndependentSection(anchor, Direction.DOWN); cart = scene.special.createCart(util.vector.topOf(assembler.east(2) - .down()), 0, MinecartEntity::new); + .below()), 0, MinecartEntity::new); anchor = scene.world.showIndependentSection(util.select.position(assembler.south()), Direction.DOWN); contraption = scene.world.showIndependentSection(util.select.position(assembler.south() - .up()), Direction.DOWN); + .above()), Direction.DOWN); scene.world.moveSection(contraption, util.vector.of(2, 0, -1), 0); scene.world.moveSection(anchor, util.vector.of(2, 0, -1), 0); scene.idle(10); @@ -488,7 +495,7 @@ public class CartAssemblerScenes { scene.idle(20); cart = scene.special.createCart(util.vector.topOf(assembler.east(2) - .down()), 0, FurnaceMinecartEntity::new); + .below()), 0, FurnaceMinecartEntity::new); scene.idle(10); scene.overlay.showText(50) .attachKeyFrame() @@ -498,14 +505,14 @@ public class CartAssemblerScenes { scene.idle(50); contraption = scene.world.showIndependentSection(chassis, Direction.DOWN); scene.idle(5); - scene.world.glueBlockOnto(assembler.up(2), Direction.DOWN, contraption); + scene.world.glueBlockOnto(assembler.above(2), Direction.DOWN, contraption); scene.idle(15); - scene.overlay.showControls(new InputWindowElement(util.vector.topOf(assembler.up()), Pointing.UP) + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(assembler.above()), Pointing.UP) .withItem(new ItemStack(Items.CHARCOAL)), 40); scene.idle(7); scene.overlay.showText(80) - .pointAt(util.vector.blockSurface(assembler.up(2), Direction.WEST)) + .pointAt(util.vector.blockSurface(assembler.above(2), Direction.WEST)) .placeNearTarget() .text("Furnace Carts will keep themselves powered, pulling fuel from any attached inventories"); scene.idle(85); 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..8ece78aac 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,13 +50,14 @@ 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); Selection shafts = util.select.fromTo(2, 1, 0, 2, 1, 1); BlockPos rotatedECD = util.grid.at(3, 1, 0); - Selection verticalShaft = util.select.fromTo(rotatedECD.up(), rotatedECD.up(2)); + Selection verticalShaft = util.select.fromTo(rotatedECD.above(), rotatedECD.above(2)); scene.world.showSection(shafts, Direction.EAST); scene.idle(10); @@ -65,16 +66,18 @@ 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); - scene.world.modifyBlock(rotatedECD, s -> s.with(EncasedBeltBlock.AXIS, Axis.Y), true); + scene.world.modifyBlock(rotatedECD, s -> s.setValue(EncasedBeltBlock.AXIS, Axis.Y), true); scene.idle(40); scene.world.showSection(verticalShaft, Direction.DOWN); @@ -99,11 +102,11 @@ public class ChainDriveScenes { BlockPos leverPos = util.grid.at(3, 1, 0); BlockPos eastDrive = util.grid.at(3, 1, 2); - BlockPos eastGauge = eastDrive.up(3); + BlockPos eastGauge = eastDrive.above(3); BlockPos middleGauge = eastGauge.west() - .down(); + .below(); BlockPos westGauge = eastGauge.west(2) - .down(2); + .below(2); ElementLink lever = scene.world.showIndependentSection(util.select.fromTo(leverPos, leverPos.south()), Direction.UP); @@ -112,18 +115,19 @@ public class ChainDriveScenes { scene.world.showSection(util.select.fromTo(4, 1, 3, 4, 2, 3), Direction.DOWN); scene.idle(10); scene.world.showSection(util.select.fromTo(eastDrive, eastDrive.west(2)) - .add(util.select.position(eastDrive.up())), Direction.DOWN); + .add(util.select.position(eastDrive.above())), Direction.DOWN); 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); - scene.world.showSection(util.select.fromTo(eastGauge, eastGauge.down()), Direction.DOWN); + scene.world.showSection(util.select.fromTo(eastGauge, eastGauge.below()), Direction.DOWN); scene.idle(5); - scene.world.showSection(util.select.fromTo(middleGauge, middleGauge.down()), Direction.DOWN); + scene.world.showSection(util.select.fromTo(middleGauge, middleGauge.below()), Direction.DOWN); scene.idle(5); scene.world.showSection(util.select.position(westGauge), Direction.DOWN); scene.idle(5); @@ -141,18 +145,19 @@ public class ChainDriveScenes { scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.south(2))); scene.effects.indicateRedstone(leverPos); - scene.world.modifyKineticSpeed(util.select.fromTo(westGauge.down(), middleGauge), f -> 2 * f); + scene.world.modifyKineticSpeed(util.select.fromTo(westGauge.below(), middleGauge), f -> 2 * f); scene.idle(10); AxisAlignedBB bb = new AxisAlignedBB(eastDrive); scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, eastDrive, bb, 160); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.FAST, eastDrive.west(), bb.offset(-2, 0, 0) - .expand(15 / 16f, 0, 0), 160); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.FAST, eastDrive.west(), bb.move(-2, 0, 0) + .expandTowards(15 / 16f, 0, 0), 160); scene.idle(20); 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)); @@ -175,7 +180,7 @@ public class ChainDriveScenes { Selection newDriveSelect = util.select.fromTo(eastDrive.south(2), eastDrive.south(2) .west(2)); ElementLink drives = scene.world.showIndependentSection(newDriveSelect, Direction.NORTH); - scene.world.modifyKineticSpeed(util.select.fromTo(westGauge.down(), middleGauge), f -> .5f * f); + scene.world.modifyKineticSpeed(util.select.fromTo(westGauge.below(), middleGauge), f -> .5f * f); scene.world.setKineticSpeed(newDriveSelect, -32); scene.world.moveSection(drives, util.vector.of(0, 0, -2), 0); scene.world.moveSection(lever, util.vector.of(-2, 0, 0), 10); @@ -191,12 +196,13 @@ public class ChainDriveScenes { scene.idle(10); bb = new AxisAlignedBB(eastDrive); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, eastDrive, bb.expand(-15 / 16f, 0, 0), 160); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.SLOW, eastDrive.west(), bb.offset(-2, 0, 0), 160); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, eastDrive, bb.expandTowards(-15 / 16f, 0, 0), 160); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.SLOW, eastDrive.west(), bb.move(-2, 0, 0), 160); scene.idle(20); 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); @@ -231,7 +238,7 @@ public class ChainDriveScenes { scene.world.modifyTileNBT(util.select.position(analogPos), AnalogLeverTileEntity.class, nbt -> { nbt.putInt("State", 8); }); - scene.world.modifyBlock(analogPos.south(), s -> s.with(RedstoneWireBlock.POWER, 8), false); + scene.world.modifyBlock(analogPos.south(), s -> s.setValue(RedstoneWireBlock.POWER, 8), false); scene.world.toggleRedstonePower(util.select.position(1, 1, 4)); scene.world.modifyKineticSpeed(util.select.position(westGauge), f -> .75f * f); scene.effects.indicateRedstone(analogPos); @@ -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/ChassisScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ChassisScenes.java index 24c7a768f..831e857a8 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/ChassisScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ChassisScenes.java @@ -43,9 +43,9 @@ public class ChassisScenes { scene.world.showSectionAndMerge(util.select.position(centralChassis.east() .north()), Direction.SOUTH, chassis); scene.idle(3); - scene.world.showSectionAndMerge(util.select.position(centralChassis.up()), Direction.DOWN, chassis); + scene.world.showSectionAndMerge(util.select.position(centralChassis.above()), Direction.DOWN, chassis); scene.idle(2); - scene.world.showSectionAndMerge(util.select.position(centralChassis.up() + scene.world.showSectionAndMerge(util.select.position(centralChassis.above() .east()), Direction.DOWN, chassis); scene.idle(10); @@ -107,7 +107,7 @@ public class ChassisScenes { .withItem(new ItemStack(Items.SLIME_BALL)); scene.overlay.showControls(input, 30); scene.idle(7); - scene.world.modifyBlock(chassisPos, s -> s.with(LinearChassisBlock.STICKY_BOTTOM, true), false); + scene.world.modifyBlock(chassisPos, s -> s.setValue(LinearChassisBlock.STICKY_BOTTOM, true), false); scene.effects.superGlue(chassisPos, Direction.WEST, false); scene.idle(30); @@ -119,7 +119,7 @@ public class ChassisScenes { scene.overlay.showControls(input, 15); scene.idle(7); - scene.world.modifyBlock(chassisPos, s -> s.with(LinearChassisBlock.STICKY_TOP, true), false); + scene.world.modifyBlock(chassisPos, s -> s.setValue(LinearChassisBlock.STICKY_TOP, true), false); scene.effects.superGlue(chassisPos, Direction.EAST, false); scene.idle(15); @@ -138,7 +138,7 @@ public class ChassisScenes { .whileSneaking(), 30); scene.idle(7); - scene.world.modifyBlock(chassisPos, s -> s.with(LinearChassisBlock.STICKY_BOTTOM, false), false); + scene.world.modifyBlock(chassisPos, s -> s.setValue(LinearChassisBlock.STICKY_BOTTOM, false), false); scene.effects.superGlue(chassisPos, Direction.WEST, false); scene.idle(30); @@ -152,7 +152,7 @@ public class ChassisScenes { scene.idle(20); ElementLink glassSection = - scene.world.showIndependentSection(util.select.position(chassisPos.up()), Direction.DOWN); + scene.world.showIndependentSection(util.select.position(chassisPos.above()), Direction.DOWN); scene.world.moveSection(glassSection, util.vector.of(0, -1, 0), 0); scene.idle(25); scene.addKeyframe(); @@ -281,7 +281,7 @@ public class ChassisScenes { scene.idle(20); scene.overlay.showText(80) - .pointAt(util.vector.topOf(chassisPos.up(2))) + .pointAt(util.vector.topOf(chassisPos.above(2))) .text("Using these mechanics, structures of any shape can move as a Contraption") .placeNearTarget(); scene.idle(30); @@ -307,14 +307,14 @@ public class ChassisScenes { ElementLink contraption = scene.world.showIndependentSection(chassis, Direction.DOWN); scene.idle(5); ElementLink top = - scene.world.showIndependentSection(util.select.position(chassisPos.up()), Direction.DOWN); + scene.world.showIndependentSection(util.select.position(chassisPos.above()), Direction.DOWN); scene.idle(10); scene.overlay.showText(50) .attachKeyFrame() .placeNearTarget() .text("Radial Chassis connect to identical Chassis blocks in a row") - .pointAt(util.vector.topOf(chassisPos.up())); + .pointAt(util.vector.topOf(chassisPos.above())); scene.idle(60); BlockPos bearingPos = util.grid.at(2, 1, 2); @@ -340,7 +340,7 @@ public class ChassisScenes { .withItem(new ItemStack(Items.SLIME_BALL)); scene.overlay.showControls(input, 30); scene.idle(7); - scene.world.modifyBlock(chassisPos, s -> s.with(RadialChassisBlock.STICKY_WEST, true), false); + scene.world.modifyBlock(chassisPos, s -> s.setValue(RadialChassisBlock.STICKY_WEST, true), false); scene.effects.superGlue(chassisPos, Direction.WEST, false); scene.idle(30); @@ -352,9 +352,9 @@ public class ChassisScenes { scene.overlay.showControls(input, 15); scene.idle(7); - scene.world.modifyBlock(chassisPos, s -> s.with(RadialChassisBlock.STICKY_EAST, true) - .with(RadialChassisBlock.STICKY_NORTH, true) - .with(RadialChassisBlock.STICKY_SOUTH, true), false); + scene.world.modifyBlock(chassisPos, s -> s.setValue(RadialChassisBlock.STICKY_EAST, true) + .setValue(RadialChassisBlock.STICKY_NORTH, true) + .setValue(RadialChassisBlock.STICKY_SOUTH, true), false); scene.effects.superGlue(chassisPos, Direction.EAST, false); scene.effects.superGlue(chassisPos, Direction.SOUTH, false); scene.effects.superGlue(chassisPos, Direction.NORTH, false); @@ -375,7 +375,7 @@ public class ChassisScenes { .whileSneaking(), 30); scene.idle(7); - scene.world.modifyBlock(chassisPos, s -> s.with(RadialChassisBlock.STICKY_WEST, false), false); + scene.world.modifyBlock(chassisPos, s -> s.setValue(RadialChassisBlock.STICKY_WEST, false), false); scene.effects.superGlue(chassisPos, Direction.WEST, false); scene.idle(30); @@ -407,7 +407,7 @@ public class ChassisScenes { scene.world.showSection(util.select.fromTo(0, 3, 3, 1, 3, 4), Direction.DOWN); scene.idle(10); Vector3d blockSurface = util.vector.blockSurface(chassisPos, Direction.NORTH); - AxisAlignedBB bb = new AxisAlignedBB(blockSurface, blockSurface).grow(.501, .501, 0); + AxisAlignedBB bb = new AxisAlignedBB(blockSurface, blockSurface).inflate(.501, .501, 0); scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, bb, bb, 60); scene.overlay.showOutline(PonderPalette.WHITE, s, s, 80); scene.overlay.showText(40) @@ -535,7 +535,7 @@ public class ChassisScenes { scene.world.glueBlockOnto(central.north() .east(), Direction.WEST, plank); scene.idle(5); - scene.world.glueBlockOnto(central.up(), Direction.DOWN, plank); + scene.world.glueBlockOnto(central.above(), Direction.DOWN, plank); scene.idle(5); scene.world.glueBlockOnto(central.south() .west(), Direction.EAST, plank); @@ -553,7 +553,7 @@ public class ChassisScenes { scene.idle(90); glueEntity = scene.world.createGlueEntity(central, Direction.UP); - scene.world.destroyBlock(central.up()); + scene.world.destroyBlock(central.above()); scene.idle(20); scene.addKeyframe(); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(central), Pointing.DOWN).leftClick(), 40); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ChuteScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ChuteScenes.java index 0c168ee13..766f6beb5 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/ChuteScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ChuteScenes.java @@ -65,7 +65,7 @@ public class ChuteScenes { .withWrench(), 40); scene.idle(7); - scene.world.modifyBlock(util.grid.at(3, 3, 3), s -> s.with(ChuteBlock.SHAPE, ChuteBlock.Shape.WINDOW), false); + scene.world.modifyBlock(util.grid.at(3, 3, 3), s -> s.setValue(ChuteBlock.SHAPE, ChuteBlock.Shape.WINDOW), false); scene.overlay.showText(50) .attachKeyFrame() .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.WEST)) @@ -73,7 +73,7 @@ public class ChuteScenes { .text("Using the Wrench, a window can be created"); scene.idle(10); - scene.world.modifyBlock(util.grid.at(3, 2, 3), s -> s.with(SHAPE, Shape.WINDOW), false); + scene.world.modifyBlock(util.grid.at(3, 2, 3), s -> s.setValue(SHAPE, Shape.WINDOW), false); for (int i = 0; i < 8; i++) { scene.idle(10); @@ -85,7 +85,7 @@ public class ChuteScenes { scene.idle(15); scene.rotateCameraY(-90); - scene.world.modifyBlock(util.grid.at(2, 2, 1), s -> s.with(SHAPE, Shape.NORMAL), false); + scene.world.modifyBlock(util.grid.at(2, 2, 1), s -> s.setValue(SHAPE, Shape.NORMAL), false); scene.world.showSection(util.select.fromTo(2, 1, 1, 2, 2, 1), Direction.DOWN); scene.idle(30); ItemStack chuteItem = AllBlocks.CHUTE.asStack(); @@ -120,14 +120,14 @@ public class ChuteScenes { Direction offset = Direction.NORTH; for (int i = 0; i < 3; i++) { remove = scene.world.createItemEntity(util.vector.centerOf(util.grid.at(2, 6, 3) - .offset(offset)), util.vector.of(0, 0.1, 0) - .add(Vector3d.of(offset.getDirectionVec()).scale(-.1)), + .relative(offset)), util.vector.of(0, 0.1, 0) + .add(Vector3d.atLowerCornerOf(offset.getNormal()).scale(-.1)), stack); scene.idle(12); scene.world.createItemOnBeltLike(util.grid.at(2, 4, 3), Direction.UP, stack); scene.world.modifyEntity(remove, Entity::remove); scene.idle(3); - offset = offset.rotateY(); + offset = offset.getClockWise(); } scene.idle(10); @@ -143,7 +143,7 @@ public class ChuteScenes { scene.scaleSceneView(.9f); scene.showBasePlate(); Selection chute = util.select.fromTo(1, 2, 2, 1, 4, 2); - scene.world.setBlocks(chute, Blocks.AIR.getDefaultState(), false); + scene.world.setBlocks(chute, Blocks.AIR.defaultBlockState(), false); scene.world.showSection(util.select.position(1, 1, 2), Direction.UP); scene.idle(20); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/CrafterScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/CrafterScenes.java index a4da5da9f..14a0e2cf9 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/CrafterScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/CrafterScenes.java @@ -39,7 +39,7 @@ public class CrafterScenes { BlockPos depotPos = util.grid.at(0, 1, 2); Selection crafters = util.select.fromTo(1, 1, 2, 3, 3, 2); - scene.world.modifyBlocks(crafters, s -> s.with(MechanicalCrafterBlock.POINTING, Pointing.DOWN), false); + scene.world.modifyBlocks(crafters, s -> s.setValue(MechanicalCrafterBlock.POINTING, Pointing.DOWN), false); scene.world.setKineticSpeed(crafters, 0); for (int y = 0; y < 3; y++) { @@ -280,7 +280,7 @@ public class CrafterScenes { scene.idle(40); Vector3d v = util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.WEST); - AxisAlignedBB bb = new AxisAlignedBB(v, v).grow(.125f, .5, .5); + AxisAlignedBB bb = new AxisAlignedBB(v, v).inflate(.125f, .5, .5); v = v.add(0, 0, .5); scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, new Object(), bb, 45); @@ -348,7 +348,7 @@ public class CrafterScenes { scene.configureBasePlate(0, 0, 5); scene.world.showSection(util.select.layer(0), Direction.UP); - scene.world.setBlock(util.grid.at(2, 2, 2), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 2, 2), Blocks.AIR.defaultBlockState(), false); Selection kinetics = util.select.fromTo(3, 1, 2, 3, 1, 5); scene.world.setKineticSpeed(util.select.fromTo(1, 2, 2, 3, 1, 2), 0); 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..d682bb774 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 @@ -5,7 +5,6 @@ import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData; import com.simibubi.create.foundation.ponder.ElementLink; -import com.simibubi.create.foundation.ponder.PonderRegistry; import com.simibubi.create.foundation.ponder.PonderStoryBoardEntry.PonderStoryBoard; import com.simibubi.create.foundation.ponder.SceneBuilder; import com.simibubi.create.foundation.ponder.SceneBuildingUtil; @@ -45,14 +44,15 @@ public class DebugScenes { add(DebugScenes::birbScene); add(DebugScenes::sectionsScene); add(DebugScenes::itemScene); + add(DebugScenes::pipeScene); } private static void add(PonderStoryBoard sb) { ItemEntry item = AllItems.BRASS_HAND; String schematicPath = "debug/scene_" + index; - PonderRegistry.addStoryBoard(item, schematicPath, sb) + PonderIndex.HELPER.addStoryBoard(item, schematicPath, sb) .highlightAllTags() - .chapter(PonderChapter.of("debug")); + .chapter(PonderIndex.HELPER.getOrCreateChapter("debug")); index++; } @@ -99,7 +99,7 @@ public class DebugScenes { scene.world.replaceBlocks(util.select.fromTo(1, 1, 3, 2, 2, 4), AllBlocks.REFINED_RADIANCE_CASING.getDefaultState(), true); scene.idle(10); - scene.world.replaceBlocks(util.select.position(3, 1, 1), Blocks.GOLD_BLOCK.getDefaultState(), true); + scene.world.replaceBlocks(util.select.position(3, 1, 1), Blocks.GOLD_BLOCK.defaultBlockState(), true); scene.rotateCameraY(180); scene.markAsFinished(); } @@ -120,10 +120,10 @@ public class DebugScenes { Vector3d vec1 = util.vector.topOf(1, 0, 0); Vector3d vec2 = util.vector.topOf(0, 0, 1); - AxisAlignedBB boundingBox1 = new AxisAlignedBB(vec1, vec1).expand(0, 2.5, 0) - .grow(.15, 0, .15); - AxisAlignedBB boundingBox2 = new AxisAlignedBB(vec2, vec2).expand(0, .125, 0) - .grow(.45, 0, .45); + AxisAlignedBB boundingBox1 = new AxisAlignedBB(vec1, vec1).expandTowards(0, 2.5, 0) + .inflate(.15, 0, .15); + AxisAlignedBB boundingBox2 = new AxisAlignedBB(vec2, vec2).expandTowards(0, .125, 0) + .inflate(.45, 0, .45); Vector3d poi1 = boundingBox1.getCenter(); Vector3d poi2 = boundingBox2.getCenter(); @@ -228,7 +228,7 @@ public class DebugScenes { Object chassisEffectHighlight = new Object(); AxisAlignedBB point = new AxisAlignedBB(chassisSurface, chassisSurface); - AxisAlignedBB expanded = point.grow(1 / 4f, 1 / 4f, 1 / 16f); + AxisAlignedBB expanded = point.inflate(1 / 4f, 1 / 4f, 1 / 16f); Selection singleBlock = util.select.position(1, 2, 3); Selection twoBlocks = util.select.fromTo(1, 2, 3, 1, 3, 3); @@ -301,11 +301,11 @@ public class DebugScenes { BlockPos poi1 = util.grid.at(4, 1, 0); BlockPos poi2 = util.grid.at(0, 1, 4); - scene.world.setBlock(poi1, Blocks.GOLD_BLOCK.getDefaultState(), true); + scene.world.setBlock(poi1, Blocks.GOLD_BLOCK.defaultBlockState(), true); scene.special.movePointOfInterest(poi1); scene.idle(20); - scene.world.setBlock(poi2, Blocks.GOLD_BLOCK.getDefaultState(), true); + scene.world.setBlock(poi2, Blocks.GOLD_BLOCK.defaultBlockState(), true); scene.special.movePointOfInterest(poi2); scene.overlay.showText(20) .text("Point of Interest") @@ -418,20 +418,32 @@ public class DebugScenes { scene.idle(20); scene.world.modifyEntities(ItemEntity.class, entity -> { - if (copperItem.isItemEqual(entity.getItem())) + if (copperItem.sameItem(entity.getItem())) entity.setNoGravity(true); }); scene.idle(20); scene.world.modifyEntities(ItemEntity.class, entity -> { - if (brassItem.isItemEqual(entity.getItem())) - entity.setMotion(util.vector.of(-.15f, .5f, 0)); + if (brassItem.sameItem(entity.getItem())) + entity.setDeltaMovement(util.vector.of(-.15f, .5f, 0)); }); scene.idle(27); 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..543cef424 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; @@ -34,7 +37,7 @@ public class DeployerScenes { BlockPos deployerPos = util.grid.at(3, 1, 2); Selection deployerSelection = util.select.position(deployerPos); - scene.world.setBlock(potPosition, Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(potPosition, Blocks.AIR.defaultBlockState(), false); scene.world.showSection(util.select.layer(0) .add(util.select.position(1, 1, 2)), Direction.UP); scene.idle(5); @@ -123,10 +126,10 @@ public class DeployerScenes { scene.world.moveDeployer(deployerPos, -1, 25); scene.idle(20); - scene.world.showSection(util.select.position(deployerPos.up()), Direction.DOWN); + scene.world.showSection(util.select.position(deployerPos.above()), Direction.DOWN); ItemStack tulip = new ItemStack(Items.RED_TULIP); - Vector3d entitySpawn = util.vector.topOf(deployerPos.up(3)); + Vector3d entitySpawn = util.vector.topOf(deployerPos.above(3)); ElementLink entity1 = scene.world.createItemEntity(entitySpawn, util.vector.of(0, 0.2, 0), tulip); @@ -141,13 +144,13 @@ public class DeployerScenes { scene.idle(30); scene.world.moveDeployer(deployerPos, 1, 25); scene.idle(26); - scene.world.setBlock(potPosition, Blocks.POTTED_RED_TULIP.getDefaultState(), false); + scene.world.setBlock(potPosition, Blocks.POTTED_RED_TULIP.defaultBlockState(), false); scene.world.modifyTileNBT(deployerSelection, teType, nbt -> nbt.put("HeldItem", ItemStack.EMPTY.serializeNBT())); scene.world.moveDeployer(deployerPos, -1, 25); scene.idle(25); scene.world.hideSection(util.select.position(potPosition), Direction.UP); - scene.world.hideSection(util.select.position(deployerPos.up()), Direction.EAST); + scene.world.hideSection(util.select.position(deployerPos.above()), Direction.EAST); scene.idle(20); Vector3d filterSlot = frontVec.add(0.375, 0.25, 0); @@ -173,21 +176,21 @@ public class DeployerScenes { ElementLink sheep = scene.world.createEntity(w -> { SheepEntity entity = EntityType.SHEEP.create(w); - entity.setFleeceColor(DyeColor.PINK); + entity.setColor(DyeColor.PINK); Vector3d p = util.vector.topOf(util.grid.at(1, 0, 2)); - entity.setPosition(p.x, p.y, p.z); - entity.prevPosX = p.x; - entity.prevPosY = p.y; - entity.prevPosZ = p.z; - entity.limbSwing = 0; - entity.prevRotationYaw = 210; - entity.rotationYaw = 210; - entity.prevRotationYawHead = 210; - entity.rotationYawHead = 210; + entity.setPos(p.x, p.y, p.z); + entity.xo = p.x; + entity.yo = p.y; + entity.zo = p.z; + entity.animationPosition = 0; + entity.yRotO = 210; + entity.yRot = 210; + entity.yHeadRotO = 210; + entity.yHeadRot = 210; return entity; }); scene.idle(20); - scene.world.showSection(util.select.position(deployerPos.up()), Direction.WEST); + scene.world.showSection(util.select.position(deployerPos.above()), Direction.WEST); entity1 = scene.world.createItemEntity(entitySpawn, util.vector.of(0, 0.2, 0), shears); scene.idle(17); scene.world.modifyEntity(entity1, Entity::remove); @@ -205,7 +208,7 @@ public class DeployerScenes { scene.world.modifyEntity(sheep, e -> ((SheepEntity) e).setSheared(true)); scene.effects.emitParticles(util.vector.topOf(deployerPos.west(2)) .add(0, -.25, 0), - Emitter.withinBlockSpace(new BlockParticleData(ParticleTypes.BLOCK, Blocks.PINK_WOOL.getDefaultState()), + Emitter.withinBlockSpace(new BlockParticleData(ParticleTypes.BLOCK, Blocks.PINK_WOOL.defaultBlockState()), util.vector.of(0, 0, 0)), 25, 1); scene.world.moveDeployer(deployerPos, -1, 25); @@ -268,7 +271,7 @@ public class DeployerScenes { .text("By default, a Deployer imitates a Right-click interaction"); scene.idle(26); - scene.world.replaceBlocks(grassBlock, Blocks.FARMLAND.getDefaultState(), false); + scene.world.replaceBlocks(grassBlock, Blocks.FARMLAND.defaultBlockState(), false); scene.world.moveDeployer(deployerPos, -1, 25); scene.idle(46); @@ -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.below(), 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.below(2)); + ingot = scene.world.createItemOnBelt(pressPos.below(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.below(2)); + ingot2 = scene.world.createItemOnBelt(pressPos.below(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); @@ -373,7 +492,7 @@ public class DeployerScenes { scene.configureBasePlate(0, 0, 6); scene.scaleSceneView(.9f); Selection flowers = util.select.fromTo(4, 1, 1, 1, 1, 1); - scene.world.replaceBlocks(flowers, Blocks.AIR.getDefaultState(), false); + scene.world.replaceBlocks(flowers, Blocks.AIR.defaultBlockState(), false); Selection kinetics = util.select.fromTo(5, 1, 6, 5, 1, 3); BlockPos deployerPos = util.grid.at(4, 1, 3); @@ -422,7 +541,7 @@ public class DeployerScenes { scene.world.hideSection(flowers, Direction.UP); scene.idle(15); - scene.world.replaceBlocks(flowers, Blocks.AIR.getDefaultState(), false); + scene.world.replaceBlocks(flowers, Blocks.AIR.defaultBlockState(), false); scene.world.showSection(flowers, Direction.UP); Vector3d frontVec = util.vector.blockSurface(deployerPos.west(3), Direction.NORTH) @@ -451,7 +570,7 @@ public class DeployerScenes { scene.world.moveDeployer(deployerPos, 1, 9); scene.idle(10); scene.world.moveDeployer(deployerPos, -1, 9); - scene.world.setBlock(util.grid.at(1 + x, 1, 1), Blocks.POPPY.getDefaultState(), false); + scene.world.setBlock(util.grid.at(1 + x, 1, 1), Blocks.POPPY.defaultBlockState(), false); scene.idle(18); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/EjectorScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/EjectorScenes.java index 4b31f95fb..2ae78d4a9 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/EjectorScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/EjectorScenes.java @@ -77,7 +77,7 @@ public class EjectorScenes { AxisAlignedBB bb = new AxisAlignedBB(ejectorPos.west()); scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, slot, bb, 20); scene.idle(10); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, slot, bb.expand(-15, 15, 0), 100); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, slot, bb.expandTowards(-15, 15, 0), 100); scene.idle(10); scene.overlay.showText(60) @@ -87,7 +87,7 @@ public class EjectorScenes { .pointAt(util.vector.blockSurface(targetPos, Direction.WEST)) .placeNearTarget(); scene.idle(70); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, new Object(), bb.offset(-2, 0, -1), 60); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, new Object(), bb.move(-2, 0, -1), 60); scene.idle(10); scene.overlay.showText(50) .colored(PonderPalette.RED) @@ -303,7 +303,7 @@ public class EjectorScenes { scene.world.showSection(redstone, Direction.EAST); BlockPos ejectorPos = util.grid.at(4, 1, 2); - Vector3d topOf = util.vector.topOf(ejectorPos.up(2)); + Vector3d topOf = util.vector.topOf(ejectorPos.above(2)); ItemStack copper = AllItems.COPPER_INGOT.asStack(); for (int i = 0; i < 3; i++) { 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..cbdf38ea6 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,14 +53,16 @@ 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); BlockPos leverPos = util.grid.at(3, 2, 4); Selection reverse = util.select.fromTo(3, 1, 5, 1, 1, 4); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); 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); @@ -74,7 +76,7 @@ public class FanScenes { scene.markAsFinished(); scene.idle(70); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.effects.indicateRedstone(leverPos); scene.world.modifyKineticSpeed(reverse, f -> -f); scene.world.modifyKineticSpeed(util.select.everywhere(), f -> 4 * f); @@ -101,7 +103,7 @@ public class FanScenes { ElementLink blockInFront = scene.world.showIndependentSection(util.select.position(3, 1, 0), Direction.SOUTH); scene.world.moveSection(blockInFront, util.vector.of(1, 0, 2), 0); - scene.world.setBlock(blockPos, Blocks.LAVA.getDefaultState(), false); + scene.world.setBlock(blockPos, Blocks.LAVA.defaultBlockState(), false); scene.idle(10); scene.overlay.showSelectionWithText(util.select.fromTo(blockPos, blockPos.west(2)), 80) @@ -113,9 +115,9 @@ public class FanScenes { ItemStack smelted = new ItemStack(Items.GOLD_INGOT); ElementLink entityLink = scene.world.createItemEntity(util.vector.centerOf(blockPos.west(2) - .up(2)), util.vector.of(0, 0.1, 0), stack); + .above(2)), util.vector.of(0, 0.1, 0), stack); scene.idle(15); - scene.world.modifyEntity(entityLink, e -> e.setMotion(-0.2f, 0, 0)); + scene.world.modifyEntity(entityLink, e -> e.setDeltaMovement(-0.2f, 0, 0)); Vector3d itemVec = util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.EAST) .add(0.1, 0, 0); scene.overlay.showControls(new InputWindowElement(itemVec, Pointing.DOWN).withItem(stack), 20); @@ -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); @@ -146,7 +149,7 @@ public class FanScenes { // smoking start - BlockState campfire = Blocks.FIRE.getDefaultState(); + BlockState campfire = Blocks.FIRE.defaultBlockState(); scene.world.hideIndependentSection(blockInFront, Direction.NORTH); scene.idle(15); scene.world.setBlock(util.grid.at(3, 1, 0), campfire, false); @@ -157,12 +160,13 @@ 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); // washing start - BlockState water = Blocks.WATER.getDefaultState(); + BlockState water = Blocks.WATER.defaultBlockState(); scene.world.hideIndependentSection(blockInFront, Direction.NORTH); scene.idle(15); scene.world.setBlock(util.grid.at(3, 1, 0), water, false); @@ -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); @@ -180,9 +185,9 @@ public class FanScenes { ItemStack washed = new ItemStack(Items.GOLD_NUGGET, 16); entityLink = scene.world.createItemEntity(util.vector.centerOf(blockPos.west(2) - .up(2)), util.vector.of(0, 0.1, 0), stack); + .above(2)), util.vector.of(0, 0.1, 0), stack); scene.idle(15); - scene.world.modifyEntity(entityLink, e -> e.setMotion(-0.2f, 0, 0)); + scene.world.modifyEntity(entityLink, e -> e.setDeltaMovement(-0.2f, 0, 0)); scene.overlay.showControls(new InputWindowElement(itemVec, Pointing.DOWN).withItem(stack), 20); scene.idle(20); scene.effects.emitParticles(itemVec.add(0, 0.2f, 0), Emitter.simple(ParticleTypes.SPIT, Vector3d.ZERO), 1, 60); @@ -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); @@ -215,8 +221,8 @@ public class FanScenes { scene.world.moveSection(blockInFront, util.vector.of(0, 1, 0), 15); scene.world.destroyBlock(blockPos.east()); scene.world.showSection(util.select.position(blockPos.east() - .up()), Direction.DOWN); - scene.world.setBlock(blockPos.up(), Blocks.WATER.getDefaultState(), false); + .above()), Direction.DOWN); + scene.world.setBlock(blockPos.above(), Blocks.WATER.defaultBlockState(), false); ItemStack sand = new ItemStack(Items.SAND); ItemStack clay = new ItemStack(Items.CLAY_BALL); @@ -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,18 +279,19 @@ 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); scene.world.toggleRedstonePower(util.select.position(pos.north())); scene.effects.indicateRedstone(pos.north()); - scene.world.setKineticSpeed(util.select.fromTo(pos, pos.up()), 4); - scene.effects.rotationSpeedIndicator(pos.up()); + scene.world.setKineticSpeed(util.select.fromTo(pos, pos.above()), 4); + scene.effects.rotationSpeedIndicator(pos.above()); } scene.overlay.showText(90) 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..069484e61 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 @@ -56,7 +56,7 @@ public class FunnelScenes { for (int i = 0; i < 8; i++) { scene.idle(8); scene.world.removeItemsFromBelt(exitBeltPos); - scene.world.flapFunnel(exitBeltPos.up(), false); + scene.world.flapFunnel(exitBeltPos.above(), false); if (i == 2) scene.rotateCameraY(70); if (i < 6) @@ -67,7 +67,7 @@ public class FunnelScenes { scene.idle(10); Selection outputFunnel = util.select.position(1, 2, 4); - scene.world.setBlocks(outputFunnel, Blocks.AIR.getDefaultState(), false); + scene.world.setBlocks(outputFunnel, Blocks.AIR.defaultBlockState(), false); scene.world.setBlocks(util.select.fromTo(2, -1, 4, 2, 0, 4), AllBlocks.ANDESITE_CASING.getDefaultState(), true); ElementLink independentSection = scene.world.showIndependentSection(verticalFunnel, Direction.UP); @@ -88,8 +88,8 @@ public class FunnelScenes { scene.world.moveSection(independentSection, util.vector.of(0, 1, 0), 15); scene.idle(10); scene.world.setBlocks(outputFunnel, AllBlocks.ANDESITE_FUNNEL.getDefaultState() - .with(FunnelBlock.FACING, Direction.WEST) - .with(FunnelBlock.EXTRACTING, true), false); + .setValue(FunnelBlock.FACING, Direction.WEST) + .setValue(FunnelBlock.EXTRACTING, true), false); for (int i = 0; i < 3; i++) { scene.idle(8); @@ -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); @@ -143,13 +144,14 @@ public class FunnelScenes { scene.idle(20); // Placing funnels with sneak - scene.world.modifyBlock(topFunnel, s -> s.with(FunnelBlock.EXTRACTING, false), false); + scene.world.modifyBlock(topFunnel, s -> s.setValue(FunnelBlock.EXTRACTING, false), false); scene.idle(5); scene.world.showSection(topFunnelSelection, Direction.DOWN); 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(); @@ -185,7 +188,7 @@ public class FunnelScenes { // Side funnel BlockPos sideFunnel = util.grid.at(3, 2, 1); - Selection sideFunnelSelection = util.select.fromTo(sideFunnel.down(), sideFunnel); + Selection sideFunnelSelection = util.select.fromTo(sideFunnel.below(), sideFunnel); Vector3d sideCenter = util.vector.centerOf(sideFunnel); scene.world.modifyBlock(sideFunnel, s -> s.cycle(FunnelBlock.EXTRACTING), false); @@ -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); @@ -271,9 +276,9 @@ public class FunnelScenes { .text("Vertical Saws") .colored(PonderPalette.BLUE) .placeNearTarget() - .pointAt(util.vector.centerOf(sawFunnel.down())); + .pointAt(util.vector.centerOf(sawFunnel.below())); scene.idle(8); - scene.world.createItemOnBeltLike(sawFunnel.down(), Direction.SOUTH, new ItemStack(Blocks.OAK_LOG)); + scene.world.createItemOnBeltLike(sawFunnel.below(), Direction.SOUTH, new ItemStack(Blocks.OAK_LOG)); scene.idle(40); scene.world.showSection(util.select.position(depotFunnel), Direction.DOWN); @@ -281,9 +286,9 @@ public class FunnelScenes { .text("Depots") .colored(PonderPalette.BLUE) .placeNearTarget() - .pointAt(util.vector.centerOf(depotFunnel.down())); + .pointAt(util.vector.centerOf(depotFunnel.below())); scene.idle(8); - scene.world.createItemOnBeltLike(depotFunnel.down(), Direction.SOUTH, new ItemStack(Items.GOLDEN_PICKAXE)); + scene.world.createItemOnBeltLike(depotFunnel.below(), Direction.SOUTH, new ItemStack(Items.GOLDEN_PICKAXE)); scene.idle(40); scene.world.showSection(util.select.position(drainFunnel), Direction.DOWN); @@ -291,9 +296,9 @@ public class FunnelScenes { .text("Item Drains") .colored(PonderPalette.BLUE) .placeNearTarget() - .pointAt(util.vector.centerOf(drainFunnel.down())); + .pointAt(util.vector.centerOf(drainFunnel.below())); scene.idle(8); - scene.world.createItemOnBeltLike(drainFunnel.down(), Direction.SOUTH, new ItemStack(Items.WATER_BUCKET)); + scene.world.createItemOnBeltLike(drainFunnel.below(), Direction.SOUTH, new ItemStack(Items.WATER_BUCKET)); scene.idle(40); scene.markAsFinished(); @@ -314,8 +319,8 @@ public class FunnelScenes { BlockPos redstone = util.grid.at(2, 2, 2); BlockPos funnel = util.grid.at(3, 2, 2); - AxisAlignedBB redstoneBB = new AxisAlignedBB(funnel).grow(-1 / 16f, -6 / 16f, -1 / 16f) - .offset(0, -5 / 16f, 0); + AxisAlignedBB redstoneBB = new AxisAlignedBB(funnel).inflate(-1 / 16f, -6 / 16f, -1 / 16f) + .move(0, -5 / 16f, 0); for (int i = 0; i < 4; i++) { if (lastItemEntity != null) @@ -325,7 +330,7 @@ public class FunnelScenes { if (i == 3) { scene.world.modifyBlock(lever, s -> s.cycle(LeverBlock.POWERED), false); - scene.world.modifyBlock(redstone, s -> s.with(RedstoneWireBlock.POWER, 15), false); + scene.world.modifyBlock(redstone, s -> s.setValue(RedstoneWireBlock.POWER, 15), false); scene.world.modifyBlock(funnel, s -> s.cycle(FunnelBlock.POWERED), false); scene.effects.indicateRedstone(lever); scene.idle(4); @@ -368,31 +373,34 @@ 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); - scene.world.createItemOnBeltLike(andesiteFunnel.down() + scene.world.createItemOnBeltLike(andesiteFunnel.below() .north(), Direction.SOUTH, itemStack); scene.world.flapFunnel(andesiteFunnel, true); scene.idle(60); scene.overlay.showText(60) .text("Brass Funnels can extract up to a full stack.") + .attachKeyFrame() .pointAt(util.vector.topOf(brassFunnel)) .placeNearTarget(); scene.idle(10); - scene.world.createItemOnBeltLike(brassFunnel.down() + scene.world.createItemOnBeltLike(brassFunnel.below() .north(), Direction.SOUTH, ItemHandlerHelper.copyStackWithSize(itemStack, 64)); scene.world.flapFunnel(brassFunnel, true); scene.idle(60); - AxisAlignedBB filterSlot = new AxisAlignedBB(brassFunnel).grow(-.35, -.35, -.35) - .offset(0, 0.2, 0); + AxisAlignedBB filterSlot = new AxisAlignedBB(brassFunnel).inflate(-.35, -.35, -.35) + .move(0, 0.2, 0); scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, filterSlot, filterSlot, 80); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(brassFunnel), Pointing.DOWN).scroll(), 60); 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); @@ -414,12 +422,12 @@ public class FunnelScenes { for (int i = 0; i < 14; i++) { if (i < 12) - scene.world.createItemOnBelt(andesiteFunnel.down(), Direction.SOUTH, + scene.world.createItemOnBelt(andesiteFunnel.below(), Direction.SOUTH, i % 3 == 0 ? dirt : i % 3 == 1 ? gravel : emerald); scene.idle(10); if (i > 0 && (i < 3 || i % 3 == 0)) { - scene.world.removeItemsFromBelt(brassFunnel.down()); + scene.world.removeItemsFromBelt(brassFunnel.below()); scene.world.flapFunnel(brassFunnel, false); } @@ -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); @@ -493,7 +504,7 @@ public class FunnelScenes { scene.idle(20); Selection belt = util.select.layer(1); - scene.world.setBlocks(funnelSelect, Blocks.AIR.getDefaultState(), false); + scene.world.setBlocks(funnelSelect, Blocks.AIR.defaultBlockState(), false); scene.world.showSection(belt, Direction.DOWN); scene.world.showSection(util.select.fromTo(0, 2, 2, 4, 2, 2), Direction.DOWN); scene.overlay.showText(120) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java index d1642ccfd..64e0bd06f 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java @@ -122,7 +122,7 @@ public class GantryScenes { scene.overlay.showText(60) .attachKeyFrame() .colored(PonderPalette.RED) - .pointAt(util.vector.centerOf(cogPos.down() + .pointAt(util.vector.centerOf(cogPos.below() .south())) .text("Redstone-powered gantry shafts stop moving their carriages") .placeNearTarget(); @@ -210,7 +210,7 @@ public class GantryScenes { BlockPos leverPos = util.grid.at(4, 1, 0); scene.world.modifyBlocks(util.select.fromTo(1, 1, 0, 3, 1, 1), - s -> s.contains(RedstoneWireBlock.POWER) ? s.with(RedstoneWireBlock.POWER, 15) : s, false); + s -> s.hasProperty(RedstoneWireBlock.POWER) ? s.setValue(RedstoneWireBlock.POWER, 15) : s, false); scene.world.toggleRedstonePower(util.select.position(leverPos)); scene.world.toggleRedstonePower(shafts); scene.effects.indicateRedstone(leverPos); 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..427b31083 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; @@ -89,7 +90,7 @@ public class KineticsScenes { .withItem(andesiteCasingItem), 60); scene.idle(7); scene.world.setBlocks(andesite, andesiteEncased.getDefaultState() - .with(EncasedShaftBlock.AXIS, Axis.X), true); + .setValue(EncasedShaftBlock.AXIS, Axis.X), true); scene.world.setKineticSpeed(shaft, 32); scene.idle(10); @@ -100,7 +101,7 @@ public class KineticsScenes { .withItem(brassCasingItem), 60); scene.idle(7); scene.world.setBlocks(brass, brassEncased.getDefaultState() - .with(EncasedShaftBlock.AXIS, Axis.X), true); + .setValue(EncasedShaftBlock.AXIS, Axis.X), true); scene.world.setKineticSpeed(shaft, 32); scene.idle(10); @@ -153,7 +154,7 @@ public class KineticsScenes { scene.title("large_cogwheel", "Relaying rotational force using Large Cogwheels"); scene.configureBasePlate(1, 1, 5); scene.world.setBlock(util.grid.at(4, 2, 3), AllBlocks.LARGE_COGWHEEL.getDefaultState() - .with(CogWheelBlock.AXIS, Axis.X), false); + .setValue(CogWheelBlock.AXIS, Axis.X), false); scene.showBasePlate(); scene.idle(5); @@ -176,7 +177,7 @@ public class KineticsScenes { scene.world.hideSection(util.select.fromTo(3, 2, 1, 3, 2, 5), Direction.SOUTH); scene.idle(15); - scene.world.modifyBlock(util.grid.at(3, 2, 3), s -> s.with(ShaftBlock.AXIS, Axis.X), false); + scene.world.modifyBlock(util.grid.at(3, 2, 3), s -> s.setValue(ShaftBlock.AXIS, Axis.X), false); scene.world.setKineticSpeed(util.select.fromTo(1, 2, 3, 5, 2, 3), 16); scene.world.showSection(util.select.position(4, 2, 3), Direction.WEST); @@ -208,9 +209,9 @@ public class KineticsScenes { BlockPos lowerCog = util.grid.at(3, 1, 2); BlockPos upperCog = util.grid.at(3, 2, 3); BlockState largeCogState = AllBlocks.LARGE_COGWHEEL.getDefaultState() - .with(CogWheelBlock.AXIS, Axis.X); + .setValue(CogWheelBlock.AXIS, Axis.X); BlockState smallCogState = AllBlocks.COGWHEEL.getDefaultState() - .with(CogWheelBlock.AXIS, Axis.X); + .setValue(CogWheelBlock.AXIS, Axis.X); scene.world.setBlock(lowerCog, largeCogState, false); scene.world.setBlock(upperCog, smallCogState, false); @@ -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); @@ -327,10 +330,10 @@ public class KineticsScenes { BlockState defaultState = AllBlocks.SHAFT.getDefaultState(); BlockState cogState = AllBlocks.COGWHEEL.getDefaultState(); - scene.world.setBlock(largeCogBack, defaultState.with(CogWheelBlock.AXIS, Axis.Z), false); - scene.world.setBlock(largeCogFront, defaultState.with(CogWheelBlock.AXIS, Axis.Z), false); - scene.world.setBlock(largeCogRight, defaultState.with(CogWheelBlock.AXIS, Axis.X), false); - scene.world.setBlock(largeCogLeft, defaultState.with(CogWheelBlock.AXIS, Axis.X), false); + scene.world.setBlock(largeCogBack, defaultState.setValue(CogWheelBlock.AXIS, Axis.Z), false); + scene.world.setBlock(largeCogFront, defaultState.setValue(CogWheelBlock.AXIS, Axis.Z), false); + scene.world.setBlock(largeCogRight, defaultState.setValue(CogWheelBlock.AXIS, Axis.X), false); + scene.world.setBlock(largeCogLeft, defaultState.setValue(CogWheelBlock.AXIS, Axis.X), false); scene.world.showSection(util.select.fromTo(4, 2, 2, 2, 2, 4), Direction.DOWN); scene.idle(20); @@ -338,11 +341,12 @@ 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); - scene.world.setBlock(largeCogFront.north(), cogState.with(CogWheelBlock.AXIS, Axis.Z), true); - scene.world.setBlock(largeCogRight.west(), cogState.with(CogWheelBlock.AXIS, Axis.X), true); + scene.world.setBlock(largeCogFront.north(), cogState.setValue(CogWheelBlock.AXIS, Axis.Z), true); + scene.world.setBlock(largeCogRight.west(), cogState.setValue(CogWheelBlock.AXIS, Axis.X), true); scene.idle(10); scene.effects.rotationDirectionIndicator(largeCogFront.north()); scene.effects.rotationDirectionIndicator(largeCogRight.west()); @@ -356,7 +360,7 @@ public class KineticsScenes { scene.world.hideSection(util.select.fromTo(1, 2, 3, 2, 2, 3), Direction.WEST); scene.world.hideSection(util.select.fromTo(4, 2, 3, 5, 2, 3), Direction.EAST); - scene.world.setBlock(largeCogBack.south(), cogState.with(CogWheelBlock.AXIS, Axis.Z), true); + scene.world.setBlock(largeCogBack.south(), cogState.setValue(CogWheelBlock.AXIS, Axis.Z), true); scene.idle(10); scene.effects.rotationDirectionIndicator(largeCogFront.north()); @@ -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++) { @@ -492,7 +498,7 @@ public class KineticsScenes { Vector3d blockSurface = util.vector.blockSurface(motor, Direction.EAST); AxisAlignedBB point = new AxisAlignedBB(blockSurface, blockSurface); - AxisAlignedBB expanded = point.grow(1 / 16f, 1 / 5f, 1 / 5f); + AxisAlignedBB expanded = point.inflate(1 / 16f, 1 / 5f, 1 / 5f); scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, blockSurface, point, 1); scene.idle(1); @@ -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); @@ -526,7 +533,7 @@ public class KineticsScenes { for (int i = 0; i < 4; i++) { scene.idle(5); scene.world.showSection(util.select.fromTo(gaugePos.east(i) - .down(), gaugePos.east(i)), Direction.DOWN); + .below(), gaugePos.east(i)), Direction.DOWN); } scene.idle(10); @@ -550,17 +557,17 @@ public class KineticsScenes { .pointAt(util.vector.topOf(wheel)); scene.idle(50); - AxisAlignedBB bb = new AxisAlignedBB(wheel).grow(.125f, 0, 0); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, new Object(), bb.offset(0, 1.2, 0) + AxisAlignedBB bb = new AxisAlignedBB(wheel).inflate(.125f, 0, 0); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, new Object(), bb.move(0, 1.2, 0) .contract(0, .75, 0), 80); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, new Object(), bb.offset(0, 0, 1.2) + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, new Object(), bb.move(0, 0, 1.2) .contract(0, 0, .75), 80); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, new Object(), bb.offset(0, -1.2, 0) + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, new Object(), bb.move(0, -1.2, 0) .contract(0, -.75, 0), 80); scene.idle(5); - scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, new Object(), bb.offset(0, 0, -1.2) + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, new Object(), bb.move(0, 0, -1.2) .contract(0, 0, -.75), 80); scene.idle(5); scene.overlay.showText(50) @@ -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); @@ -587,7 +595,7 @@ public class KineticsScenes { scene.idle(10); scene.world.rotateSection(wheelElement, 0, 180, 0, 5); scene.idle(10); - scene.world.modifyBlock(wheel, s -> s.with(WaterWheelBlock.HORIZONTAL_FACING, Direction.WEST), false); + scene.world.modifyBlock(wheel, s -> s.setValue(WaterWheelBlock.FACING, Direction.WEST), false); scene.world.rotateSection(wheelElement, 0, -180, 0, 0); scene.idle(1); scene.world.moveSection(water, util.vector.of(0, -2, 2), 10); @@ -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); @@ -609,7 +618,7 @@ public class KineticsScenes { scene.rotateCameraY(30); scene.world.rotateSection(wheelElement, 0, 180, 0, 5); scene.idle(10); - scene.world.modifyBlock(wheel, s -> s.with(WaterWheelBlock.HORIZONTAL_FACING, Direction.EAST), false); + scene.world.modifyBlock(wheel, s -> s.setValue(WaterWheelBlock.FACING, Direction.EAST), false); scene.world.rotateSection(wheelElement, 0, -180, 0, 0); scene.idle(1); scene.world.moveSection(water, util.vector.of(0, -2, 2), 10); @@ -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() + .setValue(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); @@ -850,7 +861,7 @@ public class KineticsScenes { scene.world.cycleBlockProperty(gearshiftPos, SequencedGearshiftBlock.STATE); scene.world.cycleBlockProperty(gearshiftPos, SequencedGearshiftBlock.STATE); - scene.world.modifyBlock(wire, s -> s.with(RedstoneWireBlock.POWER, 0), false); + scene.world.modifyBlock(wire, s -> s.setValue(RedstoneWireBlock.POWER, 0), false); scene.world.toggleRedstonePower(util.select.position(5, 1, 1)); scene.world.modifyTileNBT(nixie, NixieTubeTileEntity.class, nbt -> nbt.putInt("RedstoneStrength", 0)); scene.world.setKineticSpeed(outputKinetics, 0); @@ -926,9 +937,9 @@ public class KineticsScenes { scene.idle(10); scene.world.hideSection(furnaceSelect, Direction.NORTH); scene.idle(15); - scene.world.setBlock(furnacePos, Blocks.BLAST_FURNACE.getDefaultState() - .with(FurnaceBlock.FACING, Direction.NORTH) - .with(FurnaceBlock.LIT, true), false); + scene.world.setBlock(furnacePos, Blocks.BLAST_FURNACE.defaultBlockState() + .setValue(FurnaceBlock.FACING, Direction.NORTH) + .setValue(FurnaceBlock.LIT, true), false); scene.world.showSection(furnaceSelect, Direction.NORTH); scene.idle(10); scene.world.moveSection(engine, util.vector.of(0, -1, 0), 15); @@ -1041,7 +1052,7 @@ public class KineticsScenes { scene.idle(10); scene.world.setBlock(gaugePos, (speed ? AllBlocks.SPEEDOMETER : AllBlocks.STRESSOMETER).getDefaultState() - .with(GaugeBlock.FACING, Direction.UP), true); + .setValue(GaugeBlock.FACING, Direction.UP), true); scene.world.setKineticSpeed(util.select.position(gaugePos), 32); scene.idle(10); @@ -1061,7 +1072,7 @@ public class KineticsScenes { } else { BlockState state = AllBlocks.CRUSHING_WHEEL.getDefaultState() - .with(CrushingWheelBlock.AXIS, Axis.X); + .setValue(CrushingWheelBlock.AXIS, Axis.X); scene.world.setBlock(util.grid.at(5, 1, 3), state, true); scene.world.setKineticSpeed(util.select.position(5, 1, 3), 32); scene.world.modifyTileNBT(util.select.position(gaugePos), StressGaugeTileEntity.class, diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/MechanicalDrillScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/MechanicalDrillScenes.java index ea3e48654..6d17ab6cb 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/MechanicalDrillScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/MechanicalDrillScenes.java @@ -60,7 +60,7 @@ public class MechanicalDrillScenes { scene.world.modifyKineticSpeed(util.select.everywhere(), f -> 4 * f); scene.effects.rotationSpeedIndicator(breakingPos.east(3)); scene.idle(5); - scene.world.setBlock(breakingPos, Blocks.OAK_PLANKS.getDefaultState(), false); + scene.world.setBlock(breakingPos, Blocks.OAK_PLANKS.defaultBlockState(), false); scene.world.showSection(util.select.position(breakingPos), Direction.DOWN); scene.idle(5); @@ -161,7 +161,7 @@ public class MechanicalDrillScenes { scene.world.hideSection(planks, Direction.UP); scene.idle(40); - scene.world.setBlocks(planks, Blocks.OAK_PLANKS.getDefaultState(), false); + scene.world.setBlocks(planks, Blocks.OAK_PLANKS.defaultBlockState(), false); scene.world.modifyEntities(ItemEntity.class, Entity::remove); scene.world.glueBlockOnto(util.grid.at(4, 3, 2), Direction.DOWN, contraption); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/MechanicalSawScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/MechanicalSawScenes.java index 136722b35..6c254844e 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/MechanicalSawScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/MechanicalSawScenes.java @@ -31,7 +31,7 @@ public class MechanicalSawScenes { BlockPos shaftPos = util.grid.at(2, 1, 3); scene.world.setBlock(shaftPos, AllBlocks.SHAFT.getDefaultState() - .with(ShaftBlock.AXIS, Axis.Z), false); + .setValue(ShaftBlock.AXIS, Axis.Z), false); BlockPos sawPos = util.grid.at(2, 1, 2); Selection sawSelect = util.select.position(sawPos); @@ -54,7 +54,7 @@ public class MechanicalSawScenes { ItemStack strippedLog = new ItemStack(Items.STRIPPED_OAK_LOG); ItemStack planks = new ItemStack(Items.OAK_PLANKS); - Vector3d itemSpawn = util.vector.centerOf(sawPos.up() + Vector3d itemSpawn = util.vector.centerOf(sawPos.above() .west()); ElementLink logItem = scene.world.createItemEntity(itemSpawn, util.vector.of(0, 0, 0), log); scene.idle(12); @@ -62,12 +62,12 @@ public class MechanicalSawScenes { scene.overlay.showControls(new InputWindowElement(itemSpawn, Pointing.DOWN).withItem(log), 20); scene.idle(10); - scene.world.modifyEntity(logItem, e -> e.setMotion(util.vector.of(0.05, 0.2, 0))); + scene.world.modifyEntity(logItem, e -> e.setDeltaMovement(util.vector.of(0.05, 0.2, 0))); scene.idle(12); scene.world.modifyEntity(logItem, Entity::remove); scene.world.createItemOnBeltLike(sawPos, Direction.WEST, log); - scene.idle(30); + scene.idle(50); logItem = scene.world.createItemEntity(util.vector.topOf(sawPos) .add(0.5, -.1, 0), util.vector.of(0.05, 0.18, 0), strippedLog); @@ -85,12 +85,12 @@ public class MechanicalSawScenes { scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -2 * f); scene.effects.rotationDirectionIndicator(shaftPos); - scene.world.modifyEntity(logItem, e -> e.setMotion(util.vector.of(-0.05, 0.2, 0))); + scene.world.modifyEntity(logItem, e -> e.setDeltaMovement(util.vector.of(-0.05, 0.2, 0))); scene.idle(12); scene.world.modifyEntity(logItem, Entity::remove); scene.world.createItemOnBeltLike(sawPos, Direction.EAST, strippedLog); - scene.idle(40); + scene.idle(25); logItem = scene.world.createItemEntity(util.vector.topOf(sawPos) .add(-0.5, -.1, 0), util.vector.of(-0.05, 0.18, 0), planks); @@ -104,7 +104,7 @@ public class MechanicalSawScenes { scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); scene.world.modifyEntity(logItem, Entity::remove); scene.world.setBlock(shaftPos, AllBlocks.COGWHEEL.getDefaultState() - .with(ShaftBlock.AXIS, Axis.Z), true); + .setValue(ShaftBlock.AXIS, Axis.Z), true); scene.idle(3); scene.addKeyframe(); @@ -174,7 +174,7 @@ public class MechanicalSawScenes { scene.title("mechanical_saw_breaker", "Cutting Trees with the Mechanical Saw"); scene.configureBasePlate(0, 0, 5); scene.scaleSceneView(.9f); - scene.world.setBlock(util.grid.at(2, 0, 2), Blocks.GRASS_BLOCK.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 0, 2), Blocks.GRASS_BLOCK.defaultBlockState(), false); scene.world.showSection(util.select.layer(0) .add(util.select.position(3, 1, 1)) .add(util.select.position(1, 1, 2)), Direction.UP); @@ -205,7 +205,7 @@ public class MechanicalSawScenes { } } - scene.world.replaceBlocks(util.select.fromTo(2, 2, 2, 2, 6, 2), Blocks.AIR.getDefaultState(), true); + scene.world.replaceBlocks(util.select.fromTo(2, 2, 2, 2, 6, 2), Blocks.AIR.defaultBlockState(), true); scene.world.destroyBlock(util.grid.at(3, 5, 0)); scene.world.destroyBlock(util.grid.at(0, 4, 1)); @@ -215,10 +215,10 @@ public class MechanicalSawScenes { scene.world.destroyBlock(util.grid.at(1, 5, 3)); scene.world.destroyBlock(util.grid.at(0, 4, 3)); - scene.world.replaceBlocks(util.select.layersFrom(4), Blocks.AIR.getDefaultState(), false); + scene.world.replaceBlocks(util.select.layersFrom(4), Blocks.AIR.defaultBlockState(), false); for (int i = 0; i < 5; i++) { - Vector3d dropPos = util.vector.centerOf(breakingPos.up(i)); + Vector3d dropPos = util.vector.centerOf(breakingPos.above(i)); float distance = (float) dropPos.distanceTo(util.vector.centerOf(breakingPos)); scene.world.createItemEntity(dropPos, util.vector.of(-distance / 20, 0, 0), new ItemStack(Items.OAK_LOG)); } @@ -229,7 +229,7 @@ public class MechanicalSawScenes { .add(util.select.fromTo(2, 1, 2, 1, 1, 3)), Direction.UP); scene.world.modifyEntities(ItemEntity.class, Entity::remove); scene.idle(15); - scene.world.setBlocks(util.select.fromTo(2, 1, 2, 1, 20, 3), Blocks.JUNGLE_LOG.getDefaultState(), false); + scene.world.setBlocks(util.select.fromTo(2, 1, 2, 1, 20, 3), Blocks.JUNGLE_LOG.defaultBlockState(), false); scene.world.showSection(util.select.layersFrom(2) .add(util.select.fromTo(2, 1, 2, 1, 1, 3)), Direction.UP); scene.idle(15); @@ -250,7 +250,7 @@ public class MechanicalSawScenes { } for (int i = 0; i < 30; i++) { - scene.world.replaceBlocks(util.select.fromTo(2, i + 1, 2, 1, i + 1, 3), Blocks.AIR.getDefaultState(), true); + scene.world.replaceBlocks(util.select.fromTo(2, i + 1, 2, 1, i + 1, 3), Blocks.AIR.defaultBlockState(), true); for (int x = 1; x <= 2; x++) { for (int z = 2; z <= 3; z++) { Vector3d dropPos = util.vector.centerOf(x, i + 1, z); @@ -267,7 +267,7 @@ public class MechanicalSawScenes { scene.title("mechanical_saw_contraption", "Using Mechanical Saws on Contraptions"); scene.configureBasePlate(1, 0, 6); scene.scaleSceneView(.9f); - scene.world.setBlock(util.grid.at(2, 0, 3), Blocks.GRASS_BLOCK.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 0, 3), Blocks.GRASS_BLOCK.defaultBlockState(), false); scene.world.showSection(util.select.layer(0) .add(util.select.position(3, 1, 1)) .add(util.select.position(1, 1, 2)) @@ -321,7 +321,7 @@ public class MechanicalSawScenes { } } - scene.world.replaceBlocks(util.select.fromTo(2, 2, 3, 2, 6, 3), Blocks.AIR.getDefaultState(), true); + scene.world.replaceBlocks(util.select.fromTo(2, 2, 3, 2, 6, 3), Blocks.AIR.defaultBlockState(), true); scene.world.destroyBlock(util.grid.at(4, 5, 1)); scene.world.destroyBlock(util.grid.at(1, 4, 2)); scene.world.destroyBlock(util.grid.at(3, 6, 2)); @@ -329,10 +329,10 @@ public class MechanicalSawScenes { scene.world.destroyBlock(util.grid.at(2, 6, 3)); scene.world.destroyBlock(util.grid.at(2, 5, 2)); scene.world.destroyBlock(util.grid.at(1, 4, 2)); - scene.world.replaceBlocks(util.select.layersFrom(4), Blocks.AIR.getDefaultState(), false); + scene.world.replaceBlocks(util.select.layersFrom(4), Blocks.AIR.defaultBlockState(), false); for (int i = 0; i < 5; i++) { - Vector3d dropPos = util.vector.centerOf(breakingPos.up(i)); + Vector3d dropPos = util.vector.centerOf(breakingPos.above(i)); float distance = (float) dropPos.distanceTo(util.vector.centerOf(breakingPos)); scene.world.createItemEntity(dropPos, util.vector.of(-distance / 20, 0, 0), new ItemStack(Items.OAK_LOG)); } @@ -372,7 +372,7 @@ public class MechanicalSawScenes { scene.world.incrementBlockBreakingProgress(breakingPos); } - scene.world.replaceBlocks(util.select.fromTo(2, 2, 3, 2, 6, 3), Blocks.AIR.getDefaultState(), true); + scene.world.replaceBlocks(util.select.fromTo(2, 2, 3, 2, 6, 3), Blocks.AIR.defaultBlockState(), true); scene.world.destroyBlock(util.grid.at(4, 5, 1)); scene.world.destroyBlock(util.grid.at(1, 4, 2)); scene.world.destroyBlock(util.grid.at(3, 6, 2)); @@ -380,7 +380,7 @@ public class MechanicalSawScenes { scene.world.destroyBlock(util.grid.at(2, 6, 3)); scene.world.destroyBlock(util.grid.at(2, 5, 2)); scene.world.destroyBlock(util.grid.at(1, 4, 2)); - scene.world.replaceBlocks(util.select.layersFrom(4), Blocks.AIR.getDefaultState(), false); + scene.world.replaceBlocks(util.select.layersFrom(4), Blocks.AIR.defaultBlockState(), false); scene.world.moveSection(pistonHead, util.vector.of(-1, 0, 0), 20); scene.world.moveSection(contraption, util.vector.of(-1, 0, 0), 20); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java index cecbcfeef..db1125dbe 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 @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.ponder.content; import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.components.actors.HarvesterTileEntity; import com.simibubi.create.content.contraptions.components.actors.PortableItemInterfaceTileEntity; +import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock; import com.simibubi.create.foundation.ponder.ElementLink; import com.simibubi.create.foundation.ponder.SceneBuilder; @@ -46,9 +47,10 @@ public class MovementActorScenes { scene.world.rotateBearing(bearing, 360, 70); scene.world.rotateSection(contraption, 0, 360, 0, 70); scene.overlay.showText(60) - .pointAt(util.vector.topOf(bearing.up(2))) + .pointAt(util.vector.topOf(bearing.above(2))) .colored(PonderPalette.RED) .placeNearTarget() + .attachKeyFrame() .text("Inventories on moving contraptions cannot be accessed by players."); scene.idle(70); @@ -61,6 +63,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 +72,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 +101,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,10 +111,11 @@ 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(); - Vector3d entitySpawn = util.vector.topOf(hopper.up(3)); + Vector3d entitySpawn = util.vector.topOf(hopper.above(3)); ElementLink entity1 = scene.world.createItemEntity(entitySpawn, util.vector.of(0, 0.2, 0), itemStack); @@ -134,7 +140,7 @@ public class MovementActorScenes { scene.world.createItemOnBelt(beltPos, Direction.EAST, itemStack.copy()); scene.overlay.showText(40) .placeNearTarget() - .pointAt(util.vector.topOf(beltPos.up())) + .pointAt(util.vector.topOf(beltPos.above())) .text("...or extracted from the contraption"); scene.idle(15); scene.world.createItemOnBelt(beltPos, Direction.EAST, itemStack); @@ -161,7 +167,7 @@ public class MovementActorScenes { scene.configureBasePlate(0, 0, 5); scene.setSceneOffsetY(-1); - Class psiClass = PortableItemInterfaceTileEntity.class; + Class psiClass = PortableStorageInterfaceTileEntity.class; Selection psis = util.select.fromTo(1, 1, 3, 1, 3, 3); scene.world.modifyTileNBT(psis, psiClass, nbt -> { nbt.putFloat("Distance", 1); @@ -207,8 +213,8 @@ public class MovementActorScenes { .add(util.select.position(2, 1, 3)) .add(util.select.position(1, 1, 2))); - scene.world.setBlocks(crops, Blocks.WHEAT.getDefaultState() - .with(CropsBlock.AGE, 7), false); + scene.world.setBlocks(crops, Blocks.WHEAT.defaultBlockState() + .setValue(CropsBlock.AGE, 7), false); scene.world.showSection(util.select.layer(0), Direction.UP); BlockPos bearingPos = util.grid.at(4, 1, 4); @@ -241,7 +247,7 @@ public class MovementActorScenes { scene.world.rotateBearing(bearingPos, -360, 140); scene.world.rotateSection(contraption, 0, -360, 0, 140); - BlockState harvested = Blocks.WHEAT.getDefaultState(); + BlockState harvested = Blocks.WHEAT.defaultBlockState(); ItemStack wheatItem = new ItemStack(Items.WHEAT); scene.idle(5); @@ -277,8 +283,8 @@ public class MovementActorScenes { scene.world.hideSection(crops, Direction.DOWN); scene.idle(15); scene.world.modifyEntities(ItemEntity.class, Entity::remove); - scene.world.setBlocks(crops, Blocks.WHEAT.getDefaultState() - .with(CropsBlock.AGE, 7), false); + scene.world.setBlocks(crops, Blocks.WHEAT.defaultBlockState() + .setValue(CropsBlock.AGE, 7), false); scene.world.showSection(crops, Direction.UP); for (int i = 0; i < 3; i++) @@ -393,7 +399,7 @@ public class MovementActorScenes { scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); scene.world.hideSection(garbage, Direction.UP); scene.idle(40); - scene.world.setBlocks(garbage, Blocks.SNOW.getDefaultState(), false); + scene.world.setBlocks(garbage, Blocks.SNOW.defaultBlockState(), false); scene.world.modifyEntities(ItemEntity.class, Entity::remove); ElementLink chest = scene.world.showIndependentSection(util.select.position(4, 2, 2), Direction.DOWN); @@ -434,7 +440,7 @@ public class MovementActorScenes { Selection dirt = util.select.fromTo(2, 0, 3, 1, 0, 2); scene.world.hideSection(dirt, Direction.DOWN); scene.idle(15); - scene.world.setBlocks(dirt, Blocks.GRASS_BLOCK.getDefaultState(), false); + scene.world.setBlocks(dirt, Blocks.GRASS_BLOCK.defaultBlockState(), false); scene.world.showSection(dirt, Direction.UP); scene.overlay.showText(60) .placeNearTarget() @@ -448,9 +454,9 @@ public class MovementActorScenes { scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 60); scene.world.moveSection(chest, util.vector.of(-2, 0, 0), 60); scene.idle(15); - scene.world.setBlocks(util.select.fromTo(2, 0, 2, 2, 0, 3), Blocks.FARMLAND.getDefaultState(), true); + scene.world.setBlocks(util.select.fromTo(2, 0, 2, 2, 0, 3), Blocks.FARMLAND.defaultBlockState(), true); scene.idle(30); - scene.world.setBlocks(util.select.fromTo(1, 0, 2, 1, 0, 3), Blocks.FARMLAND.getDefaultState(), true); + scene.world.setBlocks(util.select.fromTo(1, 0, 2, 1, 0, 3), Blocks.FARMLAND.defaultBlockState(), true); scene.idle(20); scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); 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..8994e1667 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 @@ -51,13 +51,14 @@ public class PistonScenes { scene.idle(15); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.modifyKineticSpeed(kinetics, f -> -f); scene.effects.rotationDirectionIndicator(shaft); scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); scene.overlay.showText(55) .pointAt(util.vector.topOf(piston)) .placeNearTarget() + .attachKeyFrame() .text("Mechanical Pistons can move blocks in front of them"); scene.idle(65); @@ -65,10 +66,10 @@ public class PistonScenes { .pointAt(util.vector.blockSurface(shaft, Direction.SOUTH)) .placeNearTarget() .text("Speed and direction of movement depend on the Rotational Input"); - scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.getDefaultState(), false); - scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.OAK_PLANKS.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.defaultBlockState(), false); + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.OAK_PLANKS.defaultBlockState(), false); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.modifyKineticSpeed(kinetics, f -> -f); scene.effects.rotationDirectionIndicator(shaft); scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); @@ -79,12 +80,12 @@ public class PistonScenes { .withItem(new ItemStack(Items.SLIME_BALL)), 30); scene.idle(7); - scene.world.modifyBlock(piston.north(), s -> s.with(MechanicalPistonHeadBlock.TYPE, PistonType.STICKY), false); + scene.world.modifyBlock(piston.north(), s -> s.setValue(MechanicalPistonHeadBlock.TYPE, PistonType.STICKY), false); scene.effects.superGlue(piston, Direction.WEST, true); scene.idle(33); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.modifyKineticSpeed(kinetics, f -> -f); scene.effects.rotationDirectionIndicator(shaft); scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); @@ -93,21 +94,23 @@ 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); - scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.OAK_PLANKS.defaultBlockState(), false); + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.AIR.defaultBlockState(), false); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.modifyKineticSpeed(kinetics, f -> -f); scene.effects.rotationDirectionIndicator(shaft); scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); scene.idle(50); - scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.defaultBlockState(), false); 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); @@ -120,7 +123,7 @@ public class PistonScenes { scene.idle(90); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.modifyKineticSpeed(kinetics, f -> -f); scene.effects.rotationDirectionIndicator(shaft); scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); @@ -147,18 +150,19 @@ public class PistonScenes { BlockPos leverPos = util.grid.at(3, 2, 4); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.setKineticSpeed(kinetics, 16); scene.idle(10); 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); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.setKineticSpeed(kinetics, 0); scene.idle(5); scene.world.showSectionAndMerge(util.select.position(piston.north() @@ -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); @@ -184,7 +189,7 @@ public class PistonScenes { scene.idle(15); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.setKineticSpeed(kinetics, 16); scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); scene.special.moveParrot(birb, util.vector.of(-2, 0, 0), 40); @@ -221,13 +226,13 @@ public class PistonScenes { scene.idle(5); scene.world.showSectionAndMerge(util.select.position(piston.north() .west() - .up()), Direction.DOWN, contraption); + .above()), Direction.DOWN, contraption); scene.idle(15); scene.effects.superGlue(piston.west(), Direction.UP, true); scene.idle(10); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.modifyKineticSpeed(kinetics, f -> -f); scene.effects.rotationDirectionIndicator(shaft); scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); @@ -238,20 +243,21 @@ 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); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.modifyKineticSpeed(kinetics, f -> -f); scene.effects.rotationDirectionIndicator(shaft); scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); scene.world.hideSection(rose, Direction.UP); scene.idle(50); - scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.ROSE_BUSH.getDefaultState(), false); - scene.world.setBlock(util.grid.at(0, 2, 2), Blocks.ROSE_BUSH.getDefaultState() - .with(DoublePlantBlock.HALF, DoubleBlockHalf.UPPER), false); + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.ROSE_BUSH.defaultBlockState(), false); + scene.world.setBlock(util.grid.at(0, 2, 2), Blocks.ROSE_BUSH.defaultBlockState() + .setValue(DoublePlantBlock.HALF, DoubleBlockHalf.UPPER), false); scene.world.showIndependentSection(rose, Direction.DOWN); scene.overlay.showCenteredScrollInput(piston, Direction.UP, 60); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(piston), Pointing.DOWN).scroll() @@ -259,11 +265,12 @@ public class PistonScenes { scene.overlay.showText(70) .pointAt(util.vector.topOf(piston)) .placeNearTarget() + .attachKeyFrame() .sharedText("behaviour_modify_wrench"); scene.idle(80); scene.effects.indicateRedstone(leverPos); - scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.below())); scene.world.modifyKineticSpeed(kinetics, f -> -f); scene.effects.rotationDirectionIndicator(shaft); scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderChapter.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderChapter.java index 616708342..299f81fc5 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderChapter.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderChapter.java @@ -3,8 +3,8 @@ package com.simibubi.create.foundation.ponder.content; import javax.annotation.Nonnull; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.Create; import com.simibubi.create.foundation.gui.IScreenRenderable; +import com.simibubi.create.foundation.ponder.PonderLocalization; import com.simibubi.create.foundation.ponder.PonderRegistry; import net.minecraft.client.Minecraft; @@ -13,41 +13,45 @@ import net.minecraft.util.ResourceLocation; public class PonderChapter implements IScreenRenderable { - private final String id; + private final ResourceLocation id; private final ResourceLocation icon; - private PonderChapter(String id) { + private PonderChapter(ResourceLocation id) { this.id = id; - icon = new ResourceLocation(Create.ID, "textures/ponder/chapter/" + id + ".png"); + icon = new ResourceLocation(id.getNamespace(), "textures/ponder/chapter/" + id.getPath() + ".png"); } - @Override - public void draw(MatrixStack ms, AbstractGui screen, int x, int y) { - ms.push(); - Minecraft.getInstance().getTextureManager().bindTexture(icon); - ms.scale(0.25f, 0.25f, 1); - //x and y offset, blit z offset, tex x and y, tex width and height, entire tex sheet width and height - AbstractGui.drawTexture(ms, x, y, 0, 0, 0, 64, 64, 64, 64); - ms.pop(); + public ResourceLocation getId() { + return id; } - @Nonnull - public static PonderChapter of(String id) { - PonderChapter chapter = PonderRegistry.chapters.getChapter(id); - if (chapter == null) { - chapter = PonderRegistry.chapters.addChapter(new PonderChapter(id)); - } - - return chapter; + public String getTitle() { + return PonderLocalization.getChapter(id); } public PonderChapter addTagsToChapter(PonderTag... tags) { for (PonderTag t : tags) - PonderRegistry.tags.add(t, this); + PonderRegistry.TAGS.add(t, this); return this; } - public String getId() { - return id; + @Override + public void draw(MatrixStack ms, AbstractGui screen, int x, int y) { + ms.pushPose(); + Minecraft.getInstance().getTextureManager().bind(icon); + ms.scale(0.25f, 0.25f, 1); + //x and y offset, blit z offset, tex x and y, tex width and height, entire tex sheet width and height + AbstractGui.blit(ms, x, y, 0, 0, 0, 64, 64, 64, 64); + ms.popPose(); + } + + @Nonnull + public static PonderChapter of(ResourceLocation id) { + PonderChapter chapter = PonderRegistry.CHAPTERS.getChapter(id); + if (chapter == null) { + chapter = PonderRegistry.CHAPTERS.addChapter(new PonderChapter(id)); + } + + return chapter; } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderChapterRegistry.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderChapterRegistry.java index ec861ed1a..f1464ead4 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderChapterRegistry.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderChapterRegistry.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.ponder.content; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -13,25 +13,25 @@ import javax.annotation.Nullable; import com.simibubi.create.foundation.ponder.PonderStoryBoardEntry; import com.simibubi.create.foundation.utility.Pair; +import net.minecraft.util.ResourceLocation; + public class PonderChapterRegistry { - private final Map>> chapters; + private final Map>> chapters; public PonderChapterRegistry() { chapters = new HashMap<>(); } - public void addStoriesToChapter(@Nonnull PonderChapter chapter, PonderStoryBoardEntry... entries) { - chapters.get(chapter.getId()).getSecond().addAll(Arrays.asList(entries)); - } - PonderChapter addChapter(@Nonnull PonderChapter chapter) { - chapters.put(chapter.getId(), Pair.of(chapter, new ArrayList<>())); + synchronized (chapters) { + chapters.put(chapter.getId(), Pair.of(chapter, new ArrayList<>())); + } return chapter; } @Nullable - PonderChapter getChapter(String id) { + PonderChapter getChapter(ResourceLocation id) { Pair> pair = chapters.get(id); if (pair == null) return null; @@ -39,6 +39,13 @@ public class PonderChapterRegistry { return pair.getFirst(); } + public void addStoriesToChapter(@Nonnull PonderChapter chapter, PonderStoryBoardEntry... entries) { + List entryList = chapters.get(chapter.getId()).getSecond(); + synchronized (entryList) { + Collections.addAll(entryList, entries); + } + } + public List getAllChapters() { return chapters .values() 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..be1232eb9 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 @@ -2,12 +2,24 @@ package com.simibubi.create.foundation.ponder.content; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.ponder.PonderRegistrationHelper; 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 { + static final PonderRegistrationHelper HELPER = new PonderRegistrationHelper(Create.ID); + public static final boolean EDITOR_MODE = false; public static void register() { @@ -15,170 +27,170 @@ public class PonderIndex { // (!) Added entries require re-launch // (!) Modifications inside storyboard methods only require re-opening the ui - PonderRegistry.forComponents(AllBlocks.SHAFT) + HELPER.forComponents(AllBlocks.SHAFT) .addStoryBoard("shaft/relay", KineticsScenes::shaftAsRelay, PonderTag.KINETIC_RELAYS); - PonderRegistry.forComponents(AllBlocks.SHAFT, AllBlocks.ANDESITE_ENCASED_SHAFT, AllBlocks.BRASS_ENCASED_SHAFT) + HELPER.forComponents(AllBlocks.SHAFT, AllBlocks.ANDESITE_ENCASED_SHAFT, AllBlocks.BRASS_ENCASED_SHAFT) .addStoryBoard("shaft/encasing", KineticsScenes::shaftsCanBeEncased); - PonderRegistry.forComponents(AllBlocks.COGWHEEL) + HELPER.forComponents(AllBlocks.COGWHEEL) .addStoryBoard("cog/small", KineticsScenes::cogAsRelay, PonderTag.KINETIC_RELAYS) .addStoryBoard("cog/speedup", KineticsScenes::cogsSpeedUp); - PonderRegistry.forComponents(AllBlocks.LARGE_COGWHEEL) + HELPER.forComponents(AllBlocks.LARGE_COGWHEEL) .addStoryBoard("cog/speedup", KineticsScenes::cogsSpeedUp) .addStoryBoard("cog/large", KineticsScenes::largeCogAsRelay, PonderTag.KINETIC_RELAYS); - PonderRegistry.forComponents(AllItems.BELT_CONNECTOR) + HELPER.forComponents(AllItems.BELT_CONNECTOR) .addStoryBoard("belt/connect", BeltScenes::beltConnector, PonderTag.KINETIC_RELAYS) .addStoryBoard("belt/directions", BeltScenes::directions) .addStoryBoard("belt/transport", BeltScenes::transport, PonderTag.LOGISTICS) .addStoryBoard("belt/encasing", BeltScenes::beltsCanBeEncased); - PonderRegistry.forComponents(AllBlocks.ANDESITE_CASING, AllBlocks.BRASS_CASING) + HELPER.forComponents(AllBlocks.ANDESITE_CASING, AllBlocks.BRASS_CASING) .addStoryBoard("shaft/encasing", KineticsScenes::shaftsCanBeEncased) .addStoryBoard("belt/encasing", BeltScenes::beltsCanBeEncased); - PonderRegistry.forComponents(AllBlocks.GEARBOX, AllItems.VERTICAL_GEARBOX) + HELPER.forComponents(AllBlocks.GEARBOX, AllItems.VERTICAL_GEARBOX) .addStoryBoard("gearbox", KineticsScenes::gearbox, PonderTag.KINETIC_RELAYS); - PonderRegistry.addStoryBoard(AllBlocks.CLUTCH, "clutch", KineticsScenes::clutch, PonderTag.KINETIC_RELAYS); - PonderRegistry.addStoryBoard(AllBlocks.GEARSHIFT, "gearshift", KineticsScenes::gearshift, + HELPER.addStoryBoard(AllBlocks.CLUTCH, "clutch", KineticsScenes::clutch, PonderTag.KINETIC_RELAYS); + HELPER.addStoryBoard(AllBlocks.GEARSHIFT, "gearshift", KineticsScenes::gearshift, PonderTag.KINETIC_RELAYS); - PonderRegistry.forComponents(AllBlocks.SEQUENCED_GEARSHIFT) + HELPER.forComponents(AllBlocks.SEQUENCED_GEARSHIFT) .addStoryBoard("sequenced_gearshift", KineticsScenes::sequencedGearshift); - PonderRegistry.forComponents(AllBlocks.ENCASED_FAN) + HELPER.forComponents(AllBlocks.ENCASED_FAN) .addStoryBoard("fan/direction", FanScenes::direction, PonderTag.KINETIC_APPLIANCES) .addStoryBoard("fan/processing", FanScenes::processing) .addStoryBoard("fan/source", FanScenes::source, PonderTag.KINETIC_SOURCES); - PonderRegistry.addStoryBoard(AllBlocks.CREATIVE_MOTOR, "creative_motor", KineticsScenes::creativeMotor, - PonderTag.KINETIC_SOURCES); - PonderRegistry.addStoryBoard(AllBlocks.WATER_WHEEL, "water_wheel", KineticsScenes::waterWheel, - PonderTag.KINETIC_SOURCES); - PonderRegistry.addStoryBoard(AllBlocks.HAND_CRANK, "hand_crank", KineticsScenes::handCrank, - PonderTag.KINETIC_SOURCES); + HELPER.addStoryBoard(AllBlocks.CREATIVE_MOTOR, "creative_motor", KineticsScenes::creativeMotor, + PonderTag.KINETIC_SOURCES); + HELPER.addStoryBoard(AllBlocks.WATER_WHEEL, "water_wheel", KineticsScenes::waterWheel, + PonderTag.KINETIC_SOURCES); + HELPER.addStoryBoard(AllBlocks.HAND_CRANK, "hand_crank", KineticsScenes::handCrank, + 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); + HELPER.addStoryBoard(AllBlocks.COPPER_VALVE_HANDLE, "valve_handle", KineticsScenes::valveHandle, + PonderTag.KINETIC_SOURCES); + HELPER.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); - PonderRegistry.forComponents(AllBlocks.ENCASED_CHAIN_DRIVE, AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT) - .addStoryBoard("chain_drive/gearshift", ChainDriveScenes::adjustableChainGearshift); + HELPER.addStoryBoard(AllBlocks.ENCASED_CHAIN_DRIVE, "chain_drive/relay", + ChainDriveScenes::chainDriveAsRelay, PonderTag.KINETIC_RELAYS); + HELPER.forComponents(AllBlocks.ENCASED_CHAIN_DRIVE, AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT) + .addStoryBoard("chain_drive/gearshift", ChainDriveScenes::adjustableChainGearshift); - PonderRegistry.forComponents(AllBlocks.FURNACE_ENGINE) - .addStoryBoard("furnace_engine", KineticsScenes::furnaceEngine); - PonderRegistry.forComponents(AllBlocks.FLYWHEEL) + HELPER.forComponents(AllBlocks.FURNACE_ENGINE) + .addStoryBoard("furnace_engine", KineticsScenes::furnaceEngine); + HELPER.forComponents(AllBlocks.FLYWHEEL) .addStoryBoard("furnace_engine", KineticsScenes::flywheel); - PonderRegistry.forComponents(AllBlocks.ROTATION_SPEED_CONTROLLER) + HELPER.forComponents(AllBlocks.ROTATION_SPEED_CONTROLLER) .addStoryBoard("speed_controller", KineticsScenes::speedController); // Gauges - PonderRegistry.addStoryBoard(AllBlocks.SPEEDOMETER, "gauges", KineticsScenes::speedometer); - PonderRegistry.addStoryBoard(AllBlocks.STRESSOMETER, "gauges", KineticsScenes::stressometer); + HELPER.addStoryBoard(AllBlocks.SPEEDOMETER, "gauges", KineticsScenes::speedometer); + HELPER.addStoryBoard(AllBlocks.STRESSOMETER, "gauges", KineticsScenes::stressometer); // Item Processing - PonderRegistry.addStoryBoard(AllBlocks.MILLSTONE, "millstone", ProcessingScenes::millstone); - PonderRegistry.addStoryBoard(AllBlocks.CRUSHING_WHEEL, "crushing_wheel", ProcessingScenes::crushingWheels); - PonderRegistry.addStoryBoard(AllBlocks.MECHANICAL_MIXER, "mechanical_mixer/mixing", ProcessingScenes::mixing); - PonderRegistry.forComponents(AllBlocks.MECHANICAL_PRESS) + HELPER.addStoryBoard(AllBlocks.MILLSTONE, "millstone", ProcessingScenes::millstone); + HELPER.addStoryBoard(AllBlocks.CRUSHING_WHEEL, "crushing_wheel", ProcessingScenes::crushingWheels); + HELPER.addStoryBoard(AllBlocks.MECHANICAL_MIXER, "mechanical_mixer/mixing", ProcessingScenes::mixing); + HELPER.forComponents(AllBlocks.MECHANICAL_PRESS) .addStoryBoard("mechanical_press/pressing", ProcessingScenes::pressing) .addStoryBoard("mechanical_press/compacting", ProcessingScenes::compacting); - PonderRegistry.forComponents(AllBlocks.BASIN) + HELPER.forComponents(AllBlocks.BASIN) .addStoryBoard("basin", ProcessingScenes::basin) .addStoryBoard("mechanical_mixer/mixing", ProcessingScenes::mixing) .addStoryBoard("mechanical_press/compacting", ProcessingScenes::compacting); - PonderRegistry.addStoryBoard(AllItems.EMPTY_BLAZE_BURNER, "empty_blaze_burner", + HELPER.addStoryBoard(AllItems.EMPTY_BLAZE_BURNER, "empty_blaze_burner", ProcessingScenes::emptyBlazeBurner); - PonderRegistry.addStoryBoard(AllBlocks.BLAZE_BURNER, "blaze_burner", ProcessingScenes::blazeBurner); - PonderRegistry.addStoryBoard(AllBlocks.DEPOT, "depot", BeltScenes::depot); - PonderRegistry.forComponents(AllBlocks.WEIGHTED_EJECTOR) + HELPER.addStoryBoard(AllBlocks.BLAZE_BURNER, "blaze_burner", ProcessingScenes::blazeBurner); + HELPER.addStoryBoard(AllBlocks.DEPOT, "depot", BeltScenes::depot); + HELPER.forComponents(AllBlocks.WEIGHTED_EJECTOR) .addStoryBoard("weighted_ejector/eject", EjectorScenes::ejector) .addStoryBoard("weighted_ejector/split", EjectorScenes::splitY) .addStoryBoard("weighted_ejector/redstone", EjectorScenes::redstone); // Crafters - PonderRegistry.forComponents(AllBlocks.MECHANICAL_CRAFTER) + HELPER.forComponents(AllBlocks.MECHANICAL_CRAFTER) .addStoryBoard("mechanical_crafter/setup", CrafterScenes::setup) .addStoryBoard("mechanical_crafter/connect", CrafterScenes::connect); - PonderRegistry.forComponents(AllBlocks.MECHANICAL_CRAFTER, AllItems.CRAFTER_SLOT_COVER) + HELPER.forComponents(AllBlocks.MECHANICAL_CRAFTER, AllItems.CRAFTER_SLOT_COVER) .addStoryBoard("mechanical_crafter/covers", CrafterScenes::covers); // Chutes - PonderRegistry.forComponents(AllBlocks.CHUTE) + HELPER.forComponents(AllBlocks.CHUTE) .addStoryBoard("chute/downward", ChuteScenes::downward, PonderTag.LOGISTICS) .addStoryBoard("chute/upward", ChuteScenes::upward); - PonderRegistry.forComponents(AllBlocks.CHUTE, AllBlocks.SMART_CHUTE) + HELPER.forComponents(AllBlocks.CHUTE, AllBlocks.SMART_CHUTE) .addStoryBoard("chute/smart", ChuteScenes::smart); // Funnels - PonderRegistry.addStoryBoard(AllBlocks.BRASS_FUNNEL, "funnels/brass", FunnelScenes::brass); - PonderRegistry.forComponents(AllBlocks.ANDESITE_FUNNEL, AllBlocks.BRASS_FUNNEL) + HELPER.addStoryBoard(AllBlocks.BRASS_FUNNEL, "funnels/brass", FunnelScenes::brass); + HELPER.forComponents(AllBlocks.ANDESITE_FUNNEL, AllBlocks.BRASS_FUNNEL) .addStoryBoard("funnels/intro", FunnelScenes::intro, PonderTag.LOGISTICS) .addStoryBoard("funnels/direction", FunnelScenes::directionality) .addStoryBoard("funnels/compat", FunnelScenes::compat) .addStoryBoard("funnels/redstone", FunnelScenes::redstone) .addStoryBoard("funnels/transposer", FunnelScenes::transposer); - PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_FUNNEL, "funnels/brass", FunnelScenes::brass); + HELPER.addStoryBoard(AllBlocks.ANDESITE_FUNNEL, "funnels/brass", FunnelScenes::brass); // Tunnels - PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_TUNNEL, "tunnels/andesite", TunnelScenes::andesite); - PonderRegistry.forComponents(AllBlocks.BRASS_TUNNEL) + HELPER.addStoryBoard(AllBlocks.ANDESITE_TUNNEL, "tunnels/andesite", TunnelScenes::andesite); + HELPER.forComponents(AllBlocks.BRASS_TUNNEL) .addStoryBoard("tunnels/brass", TunnelScenes::brass) .addStoryBoard("tunnels/brass_modes", TunnelScenes::brassModes); // Chassis & Super Glue - PonderRegistry.forComponents(AllBlocks.LINEAR_CHASSIS, AllBlocks.SECONDARY_LINEAR_CHASSIS) + HELPER.forComponents(AllBlocks.LINEAR_CHASSIS, AllBlocks.SECONDARY_LINEAR_CHASSIS) .addStoryBoard("chassis/linear_group", ChassisScenes::linearGroup, PonderTag.CONTRAPTION_ASSEMBLY) .addStoryBoard("chassis/linear_attachment", ChassisScenes::linearAttachement); - PonderRegistry.forComponents(AllBlocks.RADIAL_CHASSIS) + HELPER.forComponents(AllBlocks.RADIAL_CHASSIS) .addStoryBoard("chassis/radial", ChassisScenes::radial, PonderTag.CONTRAPTION_ASSEMBLY); - PonderRegistry.forComponents(AllItems.SUPER_GLUE) + HELPER.forComponents(AllItems.SUPER_GLUE) .addStoryBoard("super_glue", ChassisScenes::superGlue, PonderTag.CONTRAPTION_ASSEMBLY); - PonderRegistry.forComponents(AllBlocks.STICKER) + HELPER.forComponents(AllBlocks.STICKER) .addStoryBoard("sticker", RedstoneScenes::sticker, PonderTag.CONTRAPTION_ASSEMBLY); // Mechanical Arm - PonderRegistry.forComponents(AllBlocks.MECHANICAL_ARM) + HELPER.forComponents(AllBlocks.MECHANICAL_ARM) .addStoryBoard("mechanical_arm/setup", ArmScenes::setup, PonderTag.ARM_TARGETS) .addStoryBoard("mechanical_arm/filter", ArmScenes::filtering) .addStoryBoard("mechanical_arm/modes", ArmScenes::modes) .addStoryBoard("mechanical_arm/redstone", ArmScenes::redstone); // Mechanical Piston - PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) + HELPER.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) .addStoryBoard("mechanical_piston/anchor", PistonScenes::movement, PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR); - PonderRegistry + HELPER .forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON, AllBlocks.PISTON_EXTENSION_POLE) .addStoryBoard("mechanical_piston/piston_pole", PistonScenes::poles); - PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) + HELPER.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) .addStoryBoard("mechanical_piston/modes", PistonScenes::movementModes); // Windmill Bearing - PonderRegistry.forComponents(AllBlocks.ROPE_PULLEY) + HELPER.forComponents(AllBlocks.ROPE_PULLEY) .addStoryBoard("rope_pulley/anchor", PulleyScenes::movement, PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR) .addStoryBoard("rope_pulley/modes", PulleyScenes::movementModes) .addStoryBoard("rope_pulley/attachment", PulleyScenes::attachment); // Windmill Bearing - PonderRegistry.forComponents(AllBlocks.WINDMILL_BEARING) + HELPER.forComponents(AllBlocks.WINDMILL_BEARING) .addStoryBoard("windmill_bearing/source", BearingScenes::windmillsAsSource, PonderTag.KINETIC_SOURCES) .addStoryBoard("windmill_bearing/structure", BearingScenes::windmillsAnyStructure, PonderTag.MOVEMENT_ANCHOR); - PonderRegistry.forComponents(AllBlocks.SAIL) + HELPER.forComponents(AllBlocks.SAIL) .addStoryBoard("sail", BearingScenes::sail); - PonderRegistry.forComponents(AllBlocks.SAIL_FRAME) + HELPER.forComponents(AllBlocks.SAIL_FRAME) .addStoryBoard("sail", BearingScenes::sailFrame); // Mechanical Bearing - PonderRegistry.forComponents(AllBlocks.MECHANICAL_BEARING) + HELPER.forComponents(AllBlocks.MECHANICAL_BEARING) .addStoryBoard("mechanical_bearing/anchor", BearingScenes::mechanicalBearing, PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR) .addStoryBoard("mechanical_bearing/modes", BearingScenes::bearingModes) @@ -186,66 +198,100 @@ public class PonderIndex { PonderTag.CONTRAPTION_ACTOR); // Clockwork Bearing - PonderRegistry.addStoryBoard(AllBlocks.CLOCKWORK_BEARING, "clockwork_bearing", BearingScenes::clockwork, + HELPER.addStoryBoard(AllBlocks.CLOCKWORK_BEARING, "clockwork_bearing", BearingScenes::clockwork, PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR); // Gantries - PonderRegistry.addStoryBoard(AllBlocks.GANTRY_SHAFT, "gantry/intro", GantryScenes::introForShaft, + HELPER.addStoryBoard(AllBlocks.GANTRY_SHAFT, "gantry/intro", GantryScenes::introForShaft, PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR); - PonderRegistry.addStoryBoard(AllBlocks.GANTRY_CARRIAGE, "gantry/intro", GantryScenes::introForPinion, + HELPER.addStoryBoard(AllBlocks.GANTRY_CARRIAGE, "gantry/intro", GantryScenes::introForPinion, PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR); - PonderRegistry.forComponents(AllBlocks.GANTRY_SHAFT, AllBlocks.GANTRY_CARRIAGE) + HELPER.forComponents(AllBlocks.GANTRY_SHAFT, AllBlocks.GANTRY_CARRIAGE) .addStoryBoard("gantry/redstone", GantryScenes::redstone) .addStoryBoard("gantry/direction", GantryScenes::direction) .addStoryBoard("gantry/subgantry", GantryScenes::subgantry); // Cart Assembler - PonderRegistry.forComponents(AllBlocks.CART_ASSEMBLER) + HELPER.forComponents(AllBlocks.CART_ASSEMBLER) .addStoryBoard("cart_assembler/anchor", CartAssemblerScenes::anchor, PonderTag.MOVEMENT_ANCHOR) .addStoryBoard("cart_assembler/modes", CartAssemblerScenes::modes) .addStoryBoard("cart_assembler/dual", CartAssemblerScenes::dual) .addStoryBoard("cart_assembler/rails", CartAssemblerScenes::rails); // Movement Actors - PonderRegistry.forComponents(AllBlocks.PORTABLE_STORAGE_INTERFACE) + HELPER.forComponents(AllBlocks.PORTABLE_STORAGE_INTERFACE) .addStoryBoard("portable_interface/transfer", MovementActorScenes::psiTransfer, PonderTag.CONTRAPTION_ACTOR) .addStoryBoard("portable_interface/redstone", MovementActorScenes::psiRedstone); - PonderRegistry.forComponents(AllBlocks.REDSTONE_CONTACT) + HELPER.forComponents(AllBlocks.REDSTONE_CONTACT) .addStoryBoard("redstone_contact", RedstoneScenes::contact); - PonderRegistry.forComponents(AllBlocks.MECHANICAL_SAW) + HELPER.forComponents(AllBlocks.MECHANICAL_SAW) .addStoryBoard("mechanical_saw/processing", MechanicalSawScenes::processing, PonderTag.KINETIC_APPLIANCES) .addStoryBoard("mechanical_saw/breaker", MechanicalSawScenes::treeCutting) .addStoryBoard("mechanical_saw/contraption", MechanicalSawScenes::contraption, PonderTag.CONTRAPTION_ACTOR); - PonderRegistry.forComponents(AllBlocks.MECHANICAL_DRILL) + HELPER.forComponents(AllBlocks.MECHANICAL_DRILL) .addStoryBoard("mechanical_drill/breaker", MechanicalDrillScenes::breaker, PonderTag.KINETIC_APPLIANCES) .addStoryBoard("mechanical_drill/contraption", MechanicalDrillScenes::contraption, PonderTag.CONTRAPTION_ACTOR); - PonderRegistry.forComponents(AllBlocks.DEPLOYER) + HELPER.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) + HELPER.forComponents(AllBlocks.MECHANICAL_HARVESTER) .addStoryBoard("harvester", MovementActorScenes::harvester); - PonderRegistry.forComponents(AllBlocks.MECHANICAL_PLOUGH) + HELPER.forComponents(AllBlocks.MECHANICAL_PLOUGH) .addStoryBoard("plough", MovementActorScenes::plough); + // Fluids + HELPER.forComponents(AllBlocks.FLUID_PIPE) + .addStoryBoard("fluid_pipe/flow", PipeScenes::flow, PonderTag.FLUIDS) + .addStoryBoard("fluid_pipe/interaction", PipeScenes::interaction) + .addStoryBoard("fluid_pipe/encasing", PipeScenes::encasing); + HELPER.forComponents(AllBlocks.COPPER_CASING) + .addStoryBoard("fluid_pipe/encasing", PipeScenes::encasing); + HELPER.forComponents(AllBlocks.MECHANICAL_PUMP) + .addStoryBoard("mechanical_pump/flow", PumpScenes::flow, PonderTag.FLUIDS, PonderTag.KINETIC_APPLIANCES) + .addStoryBoard("mechanical_pump/speed", PumpScenes::speed); + HELPER.forComponents(AllBlocks.FLUID_VALVE) + .addStoryBoard("fluid_valve", PipeScenes::valve, PonderTag.FLUIDS, PonderTag.KINETIC_APPLIANCES); + HELPER.forComponents(AllBlocks.SMART_FLUID_PIPE) + .addStoryBoard("smart_pipe", PipeScenes::smart, PonderTag.FLUIDS); + HELPER.forComponents(AllBlocks.FLUID_TANK) + .addStoryBoard("fluid_tank/storage", FluidTankScenes::storage, PonderTag.FLUIDS) + .addStoryBoard("fluid_tank/sizes", FluidTankScenes::sizes); + HELPER.forComponents(AllBlocks.CREATIVE_FLUID_TANK) + .addStoryBoard("fluid_tank/storage_creative", FluidTankScenes::creative, PonderTag.FLUIDS, PonderTag.CREATIVE) + .addStoryBoard("fluid_tank/sizes_creative", FluidTankScenes::sizes); + HELPER.forComponents(AllBlocks.HOSE_PULLEY) + .addStoryBoard("hose_pulley/intro", HosePulleyScenes::intro, PonderTag.FLUIDS, PonderTag.KINETIC_APPLIANCES) + .addStoryBoard("hose_pulley/level", HosePulleyScenes::level) + .addStoryBoard("hose_pulley/infinite", HosePulleyScenes::infinite); + HELPER.forComponents(AllBlocks.SPOUT) + .addStoryBoard("spout", SpoutScenes::filling, PonderTag.FLUIDS); + HELPER.forComponents(AllBlocks.ITEM_DRAIN) + .addStoryBoard("item_drain", DrainScenes::emptying, PonderTag.FLUIDS); + HELPER.forComponents(AllBlocks.PORTABLE_FLUID_INTERFACE) + .addStoryBoard("portable_interface/transfer_fluid", FluidMovementActorScenes::transfer, PonderTag.FLUIDS, + PonderTag.CONTRAPTION_ACTOR) + .addStoryBoard("portable_interface/redstone_fluid", MovementActorScenes::psiRedstone); + // Redstone - PonderRegistry.forComponents(AllBlocks.PULSE_REPEATER) + HELPER.forComponents(AllBlocks.PULSE_REPEATER) .addStoryBoard("pulse_repeater", RedstoneScenes::pulseRepeater); - PonderRegistry.forComponents(AllBlocks.ADJUSTABLE_REPEATER) + HELPER.forComponents(AllBlocks.ADJUSTABLE_REPEATER) .addStoryBoard("adjustable_repeater", RedstoneScenes::adjustableRepeater); - PonderRegistry.forComponents(AllBlocks.ADJUSTABLE_PULSE_REPEATER) + HELPER.forComponents(AllBlocks.ADJUSTABLE_PULSE_REPEATER) .addStoryBoard("adjustable_pulse_repeater", RedstoneScenes::adjustablePulseRepeater); - PonderRegistry.forComponents(AllBlocks.POWERED_LATCH) + HELPER.forComponents(AllBlocks.POWERED_LATCH) .addStoryBoard("powered_latch", RedstoneScenes::poweredLatch); - PonderRegistry.forComponents(AllBlocks.POWERED_TOGGLE_LATCH) + HELPER.forComponents(AllBlocks.POWERED_TOGGLE_LATCH) .addStoryBoard("powered_toggle_latch", RedstoneScenes::poweredToggleLatch); - PonderRegistry.forComponents(AllBlocks.ANALOG_LEVER) + HELPER.forComponents(AllBlocks.ANALOG_LEVER) .addStoryBoard("analog_lever", RedstoneScenes::analogLever); - PonderRegistry.forComponents(AllBlocks.NIXIE_TUBE) + HELPER.forComponents(AllBlocks.ORANGE_NIXIE_TUBE) .addStoryBoard("nixie_tube", RedstoneScenes::nixieTube); - PonderRegistry.forComponents(AllBlocks.REDSTONE_LINK) + HELPER.forComponents(AllBlocks.REDSTONE_LINK) .addStoryBoard("redstone_link", RedstoneScenes::redstoneLink); // Debug scenes, can be found in game via the Brass Hand @@ -256,7 +302,7 @@ public class PonderIndex { public static void registerTags() { // Add items to tags here - PonderRegistry.tags.forTag(PonderTag.KINETIC_RELAYS) + PonderRegistry.TAGS.forTag(PonderTag.KINETIC_RELAYS) .add(AllBlocks.SHAFT) .add(AllBlocks.COGWHEEL) .add(AllBlocks.LARGE_COGWHEEL) @@ -269,7 +315,7 @@ public class PonderIndex { .add(AllBlocks.SEQUENCED_GEARSHIFT) .add(AllBlocks.ROTATION_SPEED_CONTROLLER); - PonderRegistry.tags.forTag(PonderTag.KINETIC_SOURCES) + PonderRegistry.TAGS.forTag(PonderTag.KINETIC_SOURCES) .add(AllBlocks.HAND_CRANK) .add(AllBlocks.COPPER_VALVE_HANDLE) .add(AllBlocks.WATER_WHEEL) @@ -279,7 +325,7 @@ public class PonderIndex { .add(AllBlocks.FLYWHEEL) .add(AllBlocks.CREATIVE_MOTOR); - PonderRegistry.tags.forTag(PonderTag.KINETIC_APPLIANCES) + PonderRegistry.TAGS.forTag(PonderTag.KINETIC_APPLIANCES) .add(AllBlocks.MILLSTONE) .add(AllBlocks.TURNTABLE) .add(AllBlocks.ENCASED_FAN) @@ -300,7 +346,7 @@ public class PonderIndex { .add(AllBlocks.CLOCKWORK_BEARING) .add(AllBlocks.CRUSHING_WHEEL); - PonderRegistry.tags.forTag(PonderTag.FLUIDS) + PonderRegistry.TAGS.forTag(PonderTag.FLUIDS) .add(AllBlocks.FLUID_PIPE) .add(AllBlocks.MECHANICAL_PUMP) .add(AllBlocks.FLUID_VALVE) @@ -312,7 +358,7 @@ public class PonderIndex { .add(AllBlocks.FLUID_TANK) .add(AllBlocks.CREATIVE_FLUID_TANK); - PonderRegistry.tags.forTag(PonderTag.ARM_TARGETS) + PonderRegistry.TAGS.forTag(PonderTag.ARM_TARGETS) .add(AllBlocks.MECHANICAL_ARM) .add(AllItems.BELT_CONNECTOR) .add(AllBlocks.CHUTE) @@ -330,7 +376,7 @@ public class PonderIndex { .add(Blocks.COMPOSTER) .add(Blocks.JUKEBOX); - PonderRegistry.tags.forTag(PonderTag.LOGISTICS) + PonderRegistry.TAGS.forTag(PonderTag.LOGISTICS) .add(AllItems.BELT_CONNECTOR) .add(AllItems.FILTER) .add(AllItems.ATTRIBUTE_FILTER) @@ -349,8 +395,8 @@ public class PonderIndex { .add(AllBlocks.CREATIVE_CRATE) .add(AllBlocks.PORTABLE_STORAGE_INTERFACE); - PonderRegistry.tags.forTag(PonderTag.DECORATION) - .add(AllBlocks.NIXIE_TUBE) + PonderRegistry.TAGS.forTag(PonderTag.DECORATION) + .add(AllBlocks.ORANGE_NIXIE_TUBE) .add(AllBlocks.CUCKOO_CLOCK) .add(AllBlocks.WOODEN_BRACKET) .add(AllBlocks.METAL_BRACKET) @@ -358,18 +404,18 @@ public class PonderIndex { .add(AllBlocks.BRASS_CASING) .add(AllBlocks.COPPER_CASING); - PonderRegistry.tags.forTag(PonderTag.CREATIVE) + PonderRegistry.TAGS.forTag(PonderTag.CREATIVE) .add(AllBlocks.CREATIVE_CRATE) .add(AllBlocks.CREATIVE_FLUID_TANK) .add(AllBlocks.CREATIVE_MOTOR); - PonderRegistry.tags.forTag(PonderTag.SAILS) + PonderRegistry.TAGS.forTag(PonderTag.SAILS) .add(AllBlocks.SAIL) .add(AllBlocks.SAIL_FRAME) .add(Blocks.WHITE_WOOL); - PonderRegistry.tags.forTag(PonderTag.REDSTONE) - .add(AllBlocks.NIXIE_TUBE) + PonderRegistry.TAGS.forTag(PonderTag.REDSTONE) + .add(AllBlocks.ORANGE_NIXIE_TUBE) .add(AllBlocks.REDSTONE_CONTACT) .add(AllBlocks.ANALOG_LEVER) .add(AllBlocks.REDSTONE_LINK) @@ -379,7 +425,7 @@ public class PonderIndex { .add(AllBlocks.POWERED_LATCH) .add(AllBlocks.POWERED_TOGGLE_LATCH); - PonderRegistry.tags.forTag(PonderTag.MOVEMENT_ANCHOR) + PonderRegistry.TAGS.forTag(PonderTag.MOVEMENT_ANCHOR) .add(AllBlocks.MECHANICAL_PISTON) .add(AllBlocks.WINDMILL_BEARING) .add(AllBlocks.MECHANICAL_BEARING) @@ -388,7 +434,7 @@ public class PonderIndex { .add(AllBlocks.GANTRY_CARRIAGE) .add(AllBlocks.CART_ASSEMBLER); - PonderRegistry.tags.forTag(PonderTag.CONTRAPTION_ASSEMBLY) + PonderRegistry.TAGS.forTag(PonderTag.CONTRAPTION_ASSEMBLY) .add(AllBlocks.LINEAR_CHASSIS) .add(AllBlocks.SECONDARY_LINEAR_CHASSIS) .add(AllBlocks.RADIAL_CHASSIS) @@ -397,7 +443,7 @@ public class PonderIndex { .add(Blocks.SLIME_BLOCK) .add(Blocks.HONEY_BLOCK); - PonderRegistry.tags.forTag(PonderTag.CONTRAPTION_ACTOR) + PonderRegistry.TAGS.forTag(PonderTag.CONTRAPTION_ACTOR) .add(AllBlocks.MECHANICAL_HARVESTER) .add(AllBlocks.MECHANICAL_PLOUGH) .add(AllBlocks.MECHANICAL_DRILL) @@ -408,12 +454,11 @@ public class PonderIndex { .add(AllBlocks.MECHANICAL_BEARING) .add(AllBlocks.ANDESITE_FUNNEL) .add(AllBlocks.BRASS_FUNNEL) - .add(AllBlocks.SEATS[0]) + .add(AllBlocks.SEATS.get(DyeColor.WHITE)) .add(AllBlocks.REDSTONE_CONTACT) .add(Blocks.BELL) .add(Blocks.DISPENSER) .add(Blocks.DROPPER); - } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java index e9a0a8097..f86073956 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndexScreen.java @@ -4,8 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import org.apache.commons.lang3.mutable.MutableBoolean; - import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock; @@ -54,10 +52,10 @@ public class PonderIndexScreen extends NavigatableSimiScreen { super.init(); chapters.clear(); - // chapters.addAll(PonderRegistry.chapters.getAllChapters()); + // chapters.addAll(PonderRegistry.CHAPTERS.getAllChapters()); items.clear(); - PonderRegistry.all.keySet() + PonderRegistry.ALL.keySet() .stream() .map(key -> { Item item = ForgeRegistries.ITEMS.getValue(key); @@ -110,7 +108,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen { PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4) .showing(new ItemStack(item)) .withCallback((x, y) -> { - if (!PonderRegistry.all.containsKey(item.getRegistryName())) + if (!PonderRegistry.ALL.containsKey(item.getRegistryName())) return; centerScalingOn(x, y); @@ -139,9 +137,9 @@ public class PonderIndexScreen extends NavigatableSimiScreen { PonderUI.ponderTicks++; hoveredItem = ItemStack.EMPTY; - MainWindow w = client.getWindow(); - double mouseX = client.mouseHelper.getMouseX() * w.getScaledWidth() / w.getWidth(); - double mouseY = client.mouseHelper.getMouseY() * w.getScaledHeight() / w.getHeight(); + MainWindow w = minecraft.getWindow(); + double mouseX = minecraft.mouseHandler.xpos() * w.getGuiScaledWidth() / w.getScreenWidth(); + double mouseY = minecraft.mouseHandler.ypos() * w.getGuiScaledHeight() / w.getScreenHeight(); for (Widget widget : widgets) { if (widget instanceof PonderButton) if (widget.isMouseOver(mouseX, mouseY)) { @@ -156,25 +154,25 @@ public class PonderIndexScreen extends NavigatableSimiScreen { int y = (int) (height * chapterYmult); if (!chapters.isEmpty()) { - ms.push(); + ms.pushPose(); ms.translate(x, y, 0); UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220); - textRenderer.draw(ms, "Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT)); + font.draw(ms, "Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT)); - ms.pop(); + ms.popPose(); } x = (int) (width * itemXmult); y = (int) (height * itemYmult); - ms.push(); + ms.pushPose(); ms.translate(x, y, 0); UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220); - textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, Theme.i(Theme.Key.TEXT)); + font.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, Theme.i(Theme.Key.TEXT)); - ms.pop(); + ms.popPose(); } @Override @@ -182,12 +180,12 @@ public class PonderIndexScreen extends NavigatableSimiScreen { if (hoveredItem.isEmpty()) return; - ms.push(); + ms.pushPose(); ms.translate(0, 0, 200); renderTooltip(ms, hoveredItem, mouseX, mouseY); - ms.pop(); + ms.popPose(); } /*@Override diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderPalette.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderPalette.java index 5e5fbae39..d53685b18 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderPalette.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderPalette.java @@ -1,30 +1,36 @@ package com.simibubi.create.foundation.ponder.content; +import com.simibubi.create.foundation.utility.Color; + public enum PonderPalette { WHITE(0xFF_eeeeee), BLACK(0xFF_221111), - + RED(0xFF_ff5d6c), GREEN(0xFF_8cba51), BLUE(0xFF_5f6caf), - + SLOW(0xFF_22ff22), MEDIUM(0xFF_0084ff), FAST(0xFF_ff55ff), - + INPUT(0xFF_4f8a8b), OUTPUT(0xFF_ffcb74), - + ; - private int color; + private final Color color; - private PonderPalette(int color) { - this.color = color; + PonderPalette(int color) { + this.color = new Color(color); } public int getColor() { + return color.getRGB(); + } + + public Color getColorObject() { return color; } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTag.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTag.java index ab9a6b172..e9f266ec9 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTag.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTag.java @@ -3,9 +3,11 @@ package com.simibubi.create.foundation.ponder.content; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.Create; import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.gui.IScreenRenderable; import com.simibubi.create.foundation.ponder.PonderLocalization; +import com.simibubi.create.foundation.ponder.PonderRegistry; import net.minecraft.block.Blocks; import net.minecraft.client.Minecraft; @@ -19,74 +21,83 @@ import net.minecraftforge.api.distmarker.OnlyIn; public class PonderTag implements IScreenRenderable { - // - public static final PonderTag - KINETIC_RELAYS = new PonderTag("kinetic_relays").item(AllBlocks.COGWHEEL.get(), true, false) - .defaultLang("Kinetic Blocks", "Components which help relaying Rotational Force elsewhere"), + KINETIC_RELAYS = create("kinetic_relays").item(AllBlocks.COGWHEEL.get(), true, false) + .defaultLang("Kinetic Blocks", "Components which help relaying Rotational Force elsewhere") + .addToIndex(), - KINETIC_SOURCES = new PonderTag("kinetic_sources").item(AllBlocks.WATER_WHEEL.get(), true, false) - .defaultLang("Kinetic Sources", "Components which generate Rotational Force"), + KINETIC_SOURCES = create("kinetic_sources").item(AllBlocks.WATER_WHEEL.get(), true, false) + .defaultLang("Kinetic Sources", "Components which generate Rotational Force") + .addToIndex(), - KINETIC_APPLIANCES = new PonderTag("kinetic_appliances").item(AllBlocks.MECHANICAL_PRESS.get(), true, false) - .defaultLang("Kinetic Appliances", "Components which make use of Rotational Force"), + KINETIC_APPLIANCES = create("kinetic_appliances").item(AllBlocks.MECHANICAL_PRESS.get(), true, false) + .defaultLang("Kinetic Appliances", "Components which make use of Rotational Force") + .addToIndex(), - FLUIDS = new PonderTag("fluids").item(AllBlocks.FLUID_PIPE.get(), true, false) - .defaultLang("Fluid Manipulators", "Components which help relaying and making use of Fluids"), + FLUIDS = create("fluids").item(AllBlocks.FLUID_PIPE.get(), true, false) + .defaultLang("Fluid Manipulators", "Components which help relaying and making use of Fluids") + .addToIndex(), - LOGISTICS = new PonderTag("logistics").item(Blocks.CHEST, true, false) - .defaultLang("Item Transportation", "Components which help moving items around"), + LOGISTICS = create("logistics").item(Blocks.CHEST, true, false) + .defaultLang("Item Transportation", "Components which help moving items around") + .addToIndex(), - REDSTONE = new PonderTag("redstone").item(Items.REDSTONE, true, false) - .defaultLang("Logic Components", "Components which help with redstone engineering"), + REDSTONE = create("redstone").item(Items.REDSTONE, true, false) + .defaultLang("Logic Components", "Components which help with redstone engineering") + .addToIndex(), - DECORATION = new PonderTag("decoration").item(Items.ROSE_BUSH, true, false) + DECORATION = create("decoration").item(Items.ROSE_BUSH, true, false) .defaultLang("Aesthetics", "Components used mostly for decorative purposes"), - CREATIVE = new PonderTag("creative").item(AllBlocks.CREATIVE_CRATE.get(), true, false) - .defaultLang("Creative Mode", "Components not usually available for Survival Mode"), + CREATIVE = create("creative").item(AllBlocks.CREATIVE_CRATE.get(), true, false) + .defaultLang("Creative Mode", "Components not usually available for Survival Mode") + .addToIndex(), - MOVEMENT_ANCHOR = new PonderTag("movement_anchor").item(AllBlocks.MECHANICAL_PISTON.get(), true, false) + MOVEMENT_ANCHOR = create("movement_anchor").item(AllBlocks.MECHANICAL_PISTON.get(), true, false) .defaultLang("Movement Anchors", - "Components which allow the creation of moving contraptions, animating an attached structure in a variety of ways"), + "Components which allow the creation of moving contraptions, animating an attached structure in a variety of ways") + .addToIndex(), - CONTRAPTION_ACTOR = new PonderTag("contraption_actor").item(AllBlocks.MECHANICAL_HARVESTER.get(), true, false) + CONTRAPTION_ACTOR = create("contraption_actor").item(AllBlocks.MECHANICAL_HARVESTER.get(), true, false) .defaultLang("Contraption Actors", - "Components which expose special behaviour when attached to a moving contraption"), + "Components which expose special behaviour when attached to a moving contraption") + .addToIndex(), - CONTRAPTION_ASSEMBLY = new PonderTag("contraption_assembly").item(AllItems.SUPER_GLUE.get(), true, false) + CONTRAPTION_ASSEMBLY = create("contraption_assembly").item(AllItems.SUPER_GLUE.get(), true, false) .defaultLang("Block Attachment Utility", - "Tools and Components used to assemble structures moved as an animated Contraption"), + "Tools and Components used to assemble structures moved as an animated Contraption") + .addToIndex(), - SAILS = new PonderTag("windmill_sails").item(AllBlocks.WINDMILL_BEARING.get(), true, true) + SAILS = create("windmill_sails").item(AllBlocks.WINDMILL_BEARING.get(), true, true) .defaultLang("Sails for Windmill Bearings", "Blocks that count towards the strength of a Windmill Contraption when assembled. Each of these have equal efficiency in doing so."), -// FLUID_TRANSFER = new PonderTag("fluid_transfer").idAsIcon(), -// -// OPEN_INVENTORY = new PonderTag("open_inventory").item(AllBlocks.BASIN.get() -// .asItem()), -// -// REDSTONE_CONTROL = new PonderTag("redstone_control").item(Items.REDSTONE, true, false), -// -// ITEM_TRANSFER = new PonderTag("item_transfer").idAsIcon(), - - ARM_TARGETS = new PonderTag("arm_targets").item(AllBlocks.MECHANICAL_ARM.get()) + ARM_TARGETS = create("arm_targets").item(AllBlocks.MECHANICAL_ARM.get()) .defaultLang("Targets for Mechanical Arms", "Components which can be selected as inputs or outputs to the Mechanical Arm"); public static class Highlight { - public static final PonderTag ALL = new PonderTag("_all"); + public static final PonderTag ALL = create("_all"); } - // - - private final String id; + private final ResourceLocation id; private ResourceLocation icon; private ItemStack itemIcon = ItemStack.EMPTY; private ItemStack mainItem = ItemStack.EMPTY; + public PonderTag(ResourceLocation id) { + this.id = id; + } + + public ResourceLocation getId() { + return id; + } + + public ItemStack getMainItem() { + return mainItem; + } + public String getTitle() { return PonderLocalization.getTag(id); } @@ -97,36 +108,30 @@ public class PonderTag implements IScreenRenderable { // Builder - public PonderTag(String id) { - this.id = id; - } - - public String getId() { - return id; - } - public PonderTag defaultLang(String title, String description) { PonderLocalization.registerTag(id, title, description); return this; } - public ItemStack getMainItem() { - return mainItem; + public PonderTag addToIndex() { + PonderRegistry.TAGS.listTag(this); + return this; + } + + public PonderTag icon(ResourceLocation location) { + this.icon = new ResourceLocation(location.getNamespace(), "textures/ponder/tag/" + location.getPath() + ".png"); + return this; + } + + public PonderTag icon(String location) { + this.icon = new ResourceLocation(id.getNamespace(), "textures/ponder/tag/" + location + ".png"); + return this; } public PonderTag idAsIcon() { return icon(id); } - public PonderTag icon(String location) { - this.icon = new ResourceLocation(com.simibubi.create.Create.ID, "textures/ponder/tag/" + location + ".png"); - return this; - } - - public PonderTag item(IItemProvider item) { - return this.item(item, true, true); - } - public PonderTag item(IItemProvider item, boolean useAsIcon, boolean useAsMainItem) { if (useAsIcon) this.itemIcon = new ItemStack(item); @@ -135,25 +140,34 @@ public class PonderTag implements IScreenRenderable { return this; } + public PonderTag item(IItemProvider item) { + return this.item(item, true, true); + } + @Override @OnlyIn(Dist.CLIENT) public void draw(MatrixStack ms, AbstractGui screen, int x, int y) { - ms.push(); + ms.pushPose(); ms.translate(x, y, 0); if (icon != null) { Minecraft.getInstance() .getTextureManager() - .bindTexture(icon); + .bind(icon); ms.scale(0.25f, 0.25f, 1); - // x and y offset, blit z offset, tex x and y, tex width and height, entire tex sheet width and height - AbstractGui.drawTexture(ms, 0, 0, 0, 0, 0, 64, 64, 64, 64); + // x and y offset, blit z offset, tex x and y, tex width and height, entire tex + // sheet width and height + AbstractGui.blit(ms, 0, 0, 0, 0, 0, 64, 64, 64, 64); } else if (!itemIcon.isEmpty()) { ms.translate(-4, -4, 0); ms.scale(1.5f, 1.5f, 1.5f); GuiGameElement.of(itemIcon) .render(ms); } - ms.pop(); + ms.popPose(); + } + + private static PonderTag create(String id) { + return new PonderTag(Create.asResource(id)); } // Load class diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagIndexScreen.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagIndexScreen.java new file mode 100644 index 000000000..1cccb7e4e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagIndexScreen.java @@ -0,0 +1,242 @@ +package com.simibubi.create.foundation.ponder.content; + +import java.util.List; +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.foundation.gui.AllIcons; +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.gui.Theme; +import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.ponder.NavigatableSimiScreen; +import com.simibubi.create.foundation.ponder.PonderLocalization; +import com.simibubi.create.foundation.ponder.PonderRegistry; +import com.simibubi.create.foundation.ponder.PonderUI; +import com.simibubi.create.foundation.ponder.ui.LayoutHelper; +import com.simibubi.create.foundation.ponder.ui.PonderButton; +import com.simibubi.create.foundation.utility.FontHelper; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.MainWindow; +import net.minecraft.client.gui.widget.Widget; +import net.minecraft.client.renderer.Rectangle2d; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; + +public class PonderTagIndexScreen extends NavigatableSimiScreen { + + public static final String EXIT = PonderLocalization.LANG_PREFIX + "exit"; + public static final String TITLE = PonderLocalization.LANG_PREFIX + "index_title"; + public static final String WELCOME = PonderLocalization.LANG_PREFIX + "welcome"; + public static final String CATEGORIES = PonderLocalization.LANG_PREFIX + "categories"; + public static final String DESCRIPTION = PonderLocalization.LANG_PREFIX + "index_description"; + + private final double itemXmult = 0.5; + protected Rectangle2d itemArea; + protected Rectangle2d chapterArea; + private final double mainYmult = 0.15; + + private PonderTag hoveredItem = null; + + // The ponder entry point from the menu. May be changed to include general + // chapters in the future + public PonderTagIndexScreen() {} + + @Override + protected void init() { + widgets.clear(); + super.init(); + + List tags = PonderRegistry.TAGS.getListedTags(); + int rowCount = MathHelper.clamp((int) Math.ceil(tags.size() / 11d), 1, 3); + LayoutHelper layout = LayoutHelper.centeredHorizontal(tags.size(), rowCount, 28, 28, 8); + itemArea = layout.getArea(); + int itemCenterX = (int) (width * itemXmult); + int itemCenterY = getItemsY(); + + for (PonderTag i : tags) { + PonderButton b = + new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4).showingTag(i) + .withCallback((mouseX, mouseY) -> { + centerScalingOn(mouseX, mouseY); + ScreenOpener.transitionTo(new PonderTagScreen(i)); + }); + widgets.add(b); + layout.next(); + } + + widgets.add(backTrack = new PonderButton(31, height - 31 - 20).enableFade(0, 5) + .showing(AllIcons.I_MTD_CLOSE) + .withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty()))); + backTrack.fade(1); + } + + @Override + public void tick() { + super.tick(); + PonderUI.ponderTicks++; + + hoveredItem = null; + MainWindow w = minecraft.getWindow(); + double mouseX = minecraft.mouseHandler.xpos() * w.getGuiScaledWidth() / w.getScreenWidth(); + double mouseY = minecraft.mouseHandler.ypos() * w.getGuiScaledHeight() / w.getScreenHeight(); + for (Widget widget : widgets) { + if (widget == backTrack) + continue; + if (widget instanceof PonderButton) + if (widget.isMouseOver(mouseX, mouseY)) + hoveredItem = ((PonderButton) widget).getTag(); + } + } + + @Override + protected String backTrackingLangKey() { + return EXIT; + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + renderItems(ms, mouseX, mouseY, partialTicks); + + ms.pushPose(); + ms.translate(width / 2 - 120, height * mainYmult - 40, 0); + + ms.pushPose(); + // ms.translate(0, 0, 800); + int x = 31 + 20 + 8; + int y = 31; + + String title = Lang.translate(WELCOME) + .getString(); + + int streakHeight = 35; + UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240); + // PonderUI.renderBox(ms, 21, 21, 30, 30, false); + new BoxElement().withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) + .at(21, 21, 100) + .withBounds(30, 30) + .render(ms); + + font.draw(ms, title, x + 8, y + 1, Theme.i(Theme.Key.TEXT)); +// y += 8; +// x += 0; +// ms.translate(x, y, 0); +// ms.translate(0, 0, 5); +// textRenderer.draw(ms, title, 0, 0, Theme.i(Theme.Key.TEXT)); + ms.popPose(); + + ms.pushPose(); + ms.translate(23, 23, 10); + ms.scale(1.66f, 1.66f, 1.66f); + ms.translate(-4, -4, 0); + ms.scale(1.5f, 1.5f, 1.5f); + GuiGameElement.of(AllItems.WRENCH.asStack()) + .render(ms); + ms.popPose(); + ms.popPose(); + + ms.pushPose(); + int w = (int) (width * .45); + x = (width - w) / 2; + y = getItemsY() - 10 + Math.max(itemArea.getHeight(), 48); + + String desc = Lang.translate(DESCRIPTION) + .getString(); + int h = font.wordWrapHeight(desc, w); + + // PonderUI.renderBox(ms, x - 3, y - 3, w + 6, h + 6, false); + new BoxElement().withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) + .at(x - 3, y - 3, 90) + .withBounds(w + 6, h + 6) + .render(ms); + + ms.translate(0, 0, 100); + FontHelper.drawSplitString(ms, font, desc, x, y, w, Theme.i(Theme.Key.TEXT)); + ms.popPose(); + } + + protected void renderItems(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + List tags = PonderRegistry.TAGS.getListedTags(); + if (tags.isEmpty()) + return; + + int x = (int) (width * itemXmult); + int y = getItemsY(); + + String relatedTitle = Lang.translate(CATEGORIES) + .getString(); + int stringWidth = font.width(relatedTitle); + + ms.pushPose(); + ms.translate(x, y, 0); + // PonderUI.renderBox(ms, (sWidth - stringWidth) / 2 - 5, itemArea.getY() - 21, + // stringWidth + 10, 10, false); + new BoxElement().withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) + .at((windowWidth - stringWidth) / 2f - 5, itemArea.getY() - 21, 100) + .withBounds(stringWidth + 10, 10) + .render(ms); + + ms.translate(0, 0, 200); + +// UIRenderHelper.streak(0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 180, 0x101010); + drawCenteredString(ms, font, relatedTitle, windowWidth / 2, itemArea.getY() - 20, Theme.i(Theme.Key.TEXT)); + + ms.translate(0, 0, -200); + + UIRenderHelper.streak(ms, 0, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75); + UIRenderHelper.streak(ms, 180, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75); + + ms.popPose(); + + } + + public int getItemsY() { + return (int) (mainYmult * height + 85); + } + + @Override + protected void renderWindowForeground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + ms.pushPose(); + RenderSystem.disableRescaleNormal(); + RenderSystem.disableDepthTest(); + + ms.translate(0, 0, 200); + if (hoveredItem != null) { + List list = TooltipHelper.cutStringTextComponent(hoveredItem.getDescription(), + TextFormatting.GRAY, TextFormatting.GRAY); + list.add(0, new StringTextComponent(hoveredItem.getTitle())); + renderComponentTooltip(ms, list, mouseX, mouseY); + } + RenderSystem.enableDepthTest(); + RenderSystem.enableRescaleNormal(); + ms.popPose(); + } + + @Override + protected String getBreadcrumbTitle() { + return Lang.translate(TITLE) + .getString(); + } + + @Override + public boolean isPauseScreen() { + return true; + } + + @Override + public void removed() { + super.removed(); + hoveredItem = null; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagRegistry.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagRegistry.java index 9ff0a6763..8d0da42a2 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagRegistry.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagRegistry.java @@ -1,14 +1,15 @@ package com.simibubi.create.foundation.ponder.content; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.collect.ImmutableSet; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; -import com.simibubi.create.foundation.ponder.PonderRegistry; import com.tterrag.registrate.util.entry.ItemProviderEntry; import net.minecraft.util.IItemProvider; @@ -19,9 +20,12 @@ public class PonderTagRegistry { private final Multimap tags; private final Multimap chapterTags; + private final List listedTags; + public PonderTagRegistry() { tags = LinkedHashMultimap.create(); chapterTags = LinkedHashMultimap.create(); + listedTags = new ArrayList<>(); } public Set getTags(ResourceLocation item) { @@ -48,12 +52,24 @@ public class PonderTagRegistry { .collect(ImmutableSet.toImmutableSet()); } + public List getListedTags() { + return listedTags; + } + + public void listTag(PonderTag tag) { + listedTags.add(tag); + } + public void add(PonderTag tag, ResourceLocation item) { - tags.put(item, tag); + synchronized (tags) { + tags.put(item, tag); + } } public void add(PonderTag tag, PonderChapter chapter) { - chapterTags.put(chapter, tag); + synchronized (chapterTags) { + chapterTags.put(chapter, tag); + } } public ItemBuilder forItems(ResourceLocation... items) { @@ -64,7 +80,7 @@ public class PonderTagRegistry { return new TagBuilder(tag); } - public static class ItemBuilder { + public class ItemBuilder { private final Collection items; @@ -73,13 +89,13 @@ public class PonderTagRegistry { } public ItemBuilder add(PonderTag tag) { - items.forEach(i -> PonderRegistry.tags.add(tag, i)); + items.forEach(i -> PonderTagRegistry.this.add(tag, i)); return this; } } - public static class TagBuilder { + public class TagBuilder { private final PonderTag tag; @@ -88,7 +104,7 @@ public class PonderTagRegistry { } public TagBuilder add(ResourceLocation item) { - PonderRegistry.tags.add(tag, item); + PonderTagRegistry.this.add(tag, item); return this; } @@ -100,5 +116,7 @@ public class PonderTagRegistry { public TagBuilder add(ItemProviderEntry entry) { return add(entry.get()); } + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java index 1e430d63f..203c4890f 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java @@ -4,8 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import org.apache.commons.lang3.mutable.MutableBoolean; - import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.Create; @@ -62,7 +60,7 @@ public class PonderTagScreen extends NavigatableSimiScreen { // items items.clear(); - PonderRegistry.tags.getItems(tag) + PonderRegistry.TAGS.getItems(tag) .stream() .map(key -> { Item item = ForgeRegistries.ITEMS.getValue(key); @@ -89,7 +87,7 @@ public class PonderTagScreen extends NavigatableSimiScreen { PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4) .showing(new ItemStack(i)); - if (PonderRegistry.all.containsKey(i.getRegistryName())) { + if (PonderRegistry.ALL.containsKey(i.getRegistryName())) { b.withCallback((mouseX, mouseY) -> { centerScalingOn(mouseX, mouseY); ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag)); @@ -117,7 +115,7 @@ public class PonderTagScreen extends NavigatableSimiScreen { PonderButton b = new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10) .showing(tag.getMainItem()); - if (PonderRegistry.all.containsKey(registryName)) { + if (PonderRegistry.ALL.containsKey(registryName)) { b.withCallback((mouseX, mouseY) -> { centerScalingOn(mouseX, mouseY); ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag)); @@ -137,7 +135,7 @@ public class PonderTagScreen extends NavigatableSimiScreen { // chapters chapters.clear(); - chapters.addAll(PonderRegistry.tags.getChapters(tag)); + chapters.addAll(PonderRegistry.TAGS.getChapters(tag)); rowCount = MathHelper.clamp((int) Math.ceil(chapters.size() / 3f), 1, 3); layout = LayoutHelper.centeredHorizontal(chapters.size(), rowCount, 200, 38, 16); @@ -164,9 +162,9 @@ public class PonderTagScreen extends NavigatableSimiScreen { PonderUI.ponderTicks++; hoveredItem = ItemStack.EMPTY; - MainWindow w = client.getWindow(); - double mouseX = client.mouseHelper.getMouseX() * w.getScaledWidth() / w.getWidth(); - double mouseY = client.mouseHelper.getMouseY() * w.getScaledHeight() / w.getHeight(); + MainWindow w = minecraft.getWindow(); + double mouseX = minecraft.mouseHandler.xpos() * w.getGuiScaledWidth() / w.getScreenWidth(); + double mouseY = minecraft.mouseHandler.ypos() * w.getGuiScaledHeight() / w.getScreenHeight(); for (Widget widget : widgets) { if (widget == backTrack) continue; @@ -183,10 +181,10 @@ public class PonderTagScreen extends NavigatableSimiScreen { renderChapters(ms, mouseX, mouseY, partialTicks); - ms.push(); + ms.pushPose(); ms.translate(width / 2 - 120, height * mainYmult - 40, 0); - ms.push(); + ms.pushPose(); //ms.translate(0, 0, 800); int x = 31 + 20 + 8; int y = 31; @@ -203,28 +201,28 @@ public class PonderTagScreen extends NavigatableSimiScreen { .withBounds(30, 30) .render(ms); - textRenderer.draw(ms, Lang.translate(PonderUI.PONDERING), x, y - 6, Theme.i(Theme.Key.TEXT_DARKER)); + font.draw(ms, Lang.translate(PonderUI.PONDERING), x, y - 6, Theme.i(Theme.Key.TEXT_DARKER)); y += 8; x += 0; ms.translate(x, y, 0); ms.translate(0, 0, 5); - textRenderer.draw(ms, title, 0, 0, Theme.i(Theme.Key.TEXT)); - ms.pop(); + font.draw(ms, title, 0, 0, Theme.i(Theme.Key.TEXT)); + ms.popPose(); - ms.push(); + ms.pushPose(); ms.translate(23, 23, 10); ms.scale(1.66f, 1.66f, 1.66f); tag.draw(ms, this, 0, 0); - ms.pop(); - ms.pop(); + ms.popPose(); + ms.popPose(); - ms.push(); + ms.pushPose(); int w = (int) (width * .45); x = (width - w) / 2; y = getItemsY() - 10 + Math.max(itemArea.getHeight(), 48); String desc = tag.getDescription(); - int h = textRenderer.getWordWrappedHeight(desc, w); + int h = font.wordWrapHeight(desc, w); //PonderUI.renderBox(ms, x - 3, y - 3, w + 6, h + 6, false); @@ -236,8 +234,8 @@ public class PonderTagScreen extends NavigatableSimiScreen { .render(ms); ms.translate(0, 0, 100); - FontHelper.drawSplitString(ms, textRenderer, desc, x, y, w, Theme.i(Theme.Key.TEXT)); - ms.pop(); + FontHelper.drawSplitString(ms, font, desc, x, y, w, Theme.i(Theme.Key.TEXT)); + ms.popPose(); } protected void renderItems(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { @@ -248,29 +246,29 @@ public class PonderTagScreen extends NavigatableSimiScreen { int y = getItemsY(); String relatedTitle = Lang.translate(ASSOCIATED).getString(); - int stringWidth = textRenderer.getStringWidth(relatedTitle); + int stringWidth = font.width(relatedTitle); - ms.push(); + ms.pushPose(); ms.translate(x, y, 0); //PonderUI.renderBox(ms, (sWidth - stringWidth) / 2 - 5, itemArea.getY() - 21, stringWidth + 10, 10, false); new BoxElement() .withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) - .at((sWidth - stringWidth) / 2f - 5, itemArea.getY() - 21, 100) + .at((windowWidth - stringWidth) / 2f - 5, itemArea.getY() - 21, 100) .withBounds(stringWidth + 10, 10) .render(ms); ms.translate(0, 0, 200); // UIRenderHelper.streak(0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 180, 0x101010); - drawCenteredString(ms, textRenderer, relatedTitle, sWidth / 2, itemArea.getY() - 20, Theme.i(Theme.Key.TEXT)); + drawCenteredString(ms, font, relatedTitle, windowWidth / 2, itemArea.getY() - 20, Theme.i(Theme.Key.TEXT)); ms.translate(0,0, -200); UIRenderHelper.streak(ms, 0, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75); UIRenderHelper.streak(ms, 180, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75); - ms.pop(); + ms.popPose(); } @@ -285,18 +283,18 @@ public class PonderTagScreen extends NavigatableSimiScreen { int chapterX = (int) (width * chapterXmult); int chapterY = (int) (height * chapterYmult); - ms.push(); + ms.pushPose(); ms.translate(chapterX, chapterY, 0); UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220); - textRenderer.draw(ms, "More Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT)); + font.draw(ms, "More Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT)); - ms.pop(); + ms.popPose(); } @Override protected void renderWindowForeground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - ms.push(); + ms.pushPose(); RenderSystem.disableRescaleNormal(); RenderSystem.disableDepthTest(); @@ -306,7 +304,7 @@ public class PonderTagScreen extends NavigatableSimiScreen { } RenderSystem.enableDepthTest(); RenderSystem.enableRescaleNormal(); - ms.pop(); + ms.popPose(); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ProcessingScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ProcessingScenes.java index d852322d9..342b530f8 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/ProcessingScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ProcessingScenes.java @@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.processing.BasinBlock; import com.simibubi.create.content.contraptions.processing.BasinTileEntity; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.contraptions.processing.burner.LitBlazeBurnerBlock; import com.simibubi.create.foundation.ponder.ElementLink; import com.simibubi.create.foundation.ponder.SceneBuilder; import com.simibubi.create.foundation.ponder.SceneBuildingUtil; @@ -86,7 +87,7 @@ public class ProcessingScenes { scene.idle(70); ItemStack itemStack = new ItemStack(Items.WHEAT); - Vector3d entitySpawn = util.vector.topOf(millstone.up(3)); + Vector3d entitySpawn = util.vector.topOf(millstone.above(3)); ElementLink entity1 = scene.world.createItemEntity(entitySpawn, util.vector.of(0, 0.2, 0), itemStack); @@ -150,7 +151,7 @@ public class ProcessingScenes { Selection kinetics2 = util.select.fromTo(0, 2, 5, 4, 2, 3); Selection beltCog = util.select.position(5, 0, 1); scene.world.setKineticSpeed(wheels, 0); - scene.world.setBlock(util.grid.at(2, 3, 2), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 3, 2), Blocks.AIR.defaultBlockState(), false); scene.world.showSection(util.select.layer(0) .substract(beltCog), Direction.UP); @@ -202,7 +203,7 @@ public class ProcessingScenes { ItemStack input = new ItemStack(Items.GOLD_ORE); ItemStack output = AllItems.CRUSHED_GOLD.asStack(); - Vector3d entitySpawn = util.vector.topOf(center.up(2)); + Vector3d entitySpawn = util.vector.topOf(center.above(2)); ElementLink entity1 = scene.world.createItemEntity(entitySpawn, util.vector.of(0, 0.2, 0), input); @@ -253,9 +254,9 @@ public class ProcessingScenes { scene.world.createItemOnBelt(util.grid.at(4, 4, 2), Direction.EAST, input); scene.idle(15); if (i > 0) { - scene.world.createItemOnBelt(center.down(), Direction.UP, output); + scene.world.createItemOnBelt(center.below(), Direction.UP, output); scene.idle(15); - scene.world.createItemOnBelt(center.down(), Direction.UP, output); + scene.world.createItemOnBelt(center.below(), Direction.UP, output); } scene.world.removeItemsFromBelt(util.grid.at(3, 3, 2)); if (i < 4) @@ -353,8 +354,8 @@ public class ProcessingScenes { scene.idle(30); scene.world.modifyTileEntity(pressPos, type, pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper)); - scene.world.removeItemsFromBelt(pressPos.down(2)); - ingot = scene.world.createItemOnBelt(pressPos.down(2), Direction.UP, sheet); + scene.world.removeItemsFromBelt(pressPos.below(2)); + ingot = scene.world.createItemOnBelt(pressPos.below(2), Direction.UP, sheet); scene.world.stallBeltItem(ingot, true); scene.idle(15); scene.world.stallBeltItem(ingot, false); @@ -364,8 +365,8 @@ public class ProcessingScenes { scene.idle(30); scene.world.modifyTileEntity(pressPos, type, pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper)); - scene.world.removeItemsFromBelt(pressPos.down(2)); - ingot2 = scene.world.createItemOnBelt(pressPos.down(2), Direction.UP, sheet); + scene.world.removeItemsFromBelt(pressPos.below(2)); + ingot2 = scene.world.createItemOnBelt(pressPos.below(2), Direction.UP, sheet); scene.world.stallBeltItem(ingot2, true); scene.idle(15); scene.world.stallBeltItem(ingot2, false); @@ -432,7 +433,7 @@ public class ProcessingScenes { scene.rotateCameraY(-30); scene.idle(10); scene.world.setBlock(util.grid.at(1, 1, 2), AllBlocks.BLAZE_BURNER.getDefaultState() - .with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), true); + .setValue(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), true); scene.idle(10); scene.overlay.showText(80) @@ -531,7 +532,7 @@ public class ProcessingScenes { scene.rotateCameraY(-30); scene.idle(10); scene.world.setBlock(util.grid.at(1, 1, 2), AllBlocks.BLAZE_BURNER.getDefaultState() - .with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), true); + .setValue(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), true); scene.idle(10); scene.overlay.showText(80) @@ -563,20 +564,20 @@ public class ProcessingScenes { scene.world.createEntity(w -> { BlazeEntity blazeEntity = EntityType.BLAZE.create(w); Vector3d v = util.vector.topOf(center); - blazeEntity.setPos(v.x, v.y, v.z); - blazeEntity.prevRotationYaw = blazeEntity.rotationYaw = 180; + blazeEntity.setPosRaw(v.x, v.y, v.z); + blazeEntity.yRotO = blazeEntity.yRot = 180; return blazeEntity; }); scene.idle(20); scene.overlay - .showControls(new InputWindowElement(util.vector.centerOf(center.up(2)), Pointing.DOWN).rightClick() + .showControls(new InputWindowElement(util.vector.centerOf(center.above(2)), Pointing.DOWN).rightClick() .withItem(AllItems.EMPTY_BLAZE_BURNER.asStack()), 40); scene.idle(10); scene.overlay.showText(60) .text("Right-click a Blaze with the empty burner to capture it") .attachKeyFrame() - .pointAt(util.vector.blockSurface(center.up(2), Direction.WEST)) + .pointAt(util.vector.blockSurface(center.above(2), Direction.WEST)) .placeNearTarget(); scene.idle(50); @@ -585,13 +586,13 @@ public class ProcessingScenes { scene.world.showSection(util.select.position(2, 1, 2), Direction.DOWN); scene.idle(20); - scene.overlay.showControls(new InputWindowElement(util.vector.topOf(center.up()), Pointing.DOWN).rightClick() + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(center.above()), Pointing.DOWN).rightClick() .withItem(AllItems.EMPTY_BLAZE_BURNER.asStack()), 40); scene.idle(10); scene.overlay.showText(60) .text("Alternatively, Blazes can be collected from their Spawners directly") .attachKeyFrame() - .pointAt(util.vector.blockSurface(center.up(), Direction.WEST)) + .pointAt(util.vector.blockSurface(center.above(), Direction.WEST)) .placeNearTarget(); scene.idle(50); scene.world.hideSection(util.select.position(2, 1, 2), Direction.UP); @@ -599,37 +600,50 @@ public class ProcessingScenes { scene.world.showSection(util.select.position(1, 1, 2), Direction.DOWN); scene.idle(20); - scene.world.modifyBlock(util.grid.at(1, 1, 2), s -> s.with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), + scene.world.modifyBlock(util.grid.at(1, 1, 2), s -> s.setValue(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), false); scene.overlay.showText(70) .text("You now have an ideal heat source for various machines") .attachKeyFrame() .pointAt(util.vector.blockSurface(center.west() - .up(), Direction.WEST)) + .above(), Direction.WEST)) .placeNearTarget(); scene.idle(80); scene.world.showSection(util.select.position(3, 1, 2), Direction.DOWN); scene.idle(20); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(center.east() - .up()), Pointing.DOWN).rightClick() + .above()), Pointing.DOWN).rightClick() .withItem(new ItemStack(Items.FLINT_AND_STEEL)), 40); scene.idle(7); - scene.world.setBlock(util.grid.at(3, 1, 2), AllBlocks.LIT_BLAZE_BURNER.getDefaultState(), true); + scene.world.setBlock(util.grid.at(3, 1, 2), AllBlocks.LIT_BLAZE_BURNER.getDefaultState(), false); scene.idle(10); scene.overlay.showText(70) .text("For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel") .attachKeyFrame() .pointAt(util.vector.blockSurface(center.east() - .up(), Direction.UP)) + .above(), Direction.UP)) .placeNearTarget(); scene.idle(80); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(center.east() + .above()), Pointing.DOWN).rightClick() + .withItem(new ItemStack(Items.SOUL_SAND)), + 40); + scene.idle(7); + scene.world.modifyBlock(util.grid.at(3, 1, 2), s -> s.setValue(LitBlazeBurnerBlock.FLAME_TYPE, LitBlazeBurnerBlock.FlameType.SOUL), + false); scene.overlay.showText(60) - .colored(PonderPalette.RED) - .text("However, these are not suitable for industrial heating") + .text("The flame can be transformed using a soul-infused item") .pointAt(util.vector.blockSurface(center.east() - .up(), Direction.UP)) + .above(), Direction.UP)) + .placeNearTarget(); + scene.idle(80); + scene.overlay.showText(90) + .colored(PonderPalette.RED) + .text("However, without a blaze they are not suitable for industrial heating") + .pointAt(util.vector.blockSurface(center.east() + .above(), Direction.UP)) .placeNearTarget(); scene.idle(70); } @@ -643,7 +657,7 @@ public class ProcessingScenes { BlockPos burner = util.grid.at(2, 1, 2); scene.world.showSection(util.select.position(burner), Direction.DOWN); scene.idle(10); - scene.world.showSection(util.select.position(burner.up()), Direction.DOWN); + scene.world.showSection(util.select.position(burner.above()), Direction.DOWN); scene.idle(10); scene.overlay.showText(70) @@ -653,18 +667,18 @@ public class ProcessingScenes { .placeNearTarget(); scene.idle(80); - scene.world.hideSection(util.select.position(burner.up()), Direction.UP); + scene.world.hideSection(util.select.position(burner.above()), Direction.UP); scene.idle(20); - scene.world.setBlock(burner.up(), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(burner.above(), Blocks.AIR.defaultBlockState(), false); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(burner), Pointing.DOWN).rightClick() .withItem(new ItemStack(Items.OAK_PLANKS)), 15); scene.idle(7); - scene.world.modifyBlock(burner, s -> s.with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.FADING), false); + scene.world.modifyBlock(burner, s -> s.setValue(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.FADING), false); scene.idle(15); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(burner), Pointing.DOWN).rightClick() .withItem(new ItemStack(Items.OAK_PLANKS)), 15); scene.idle(7); - scene.world.modifyBlock(burner, s -> s.with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), false); + scene.world.modifyBlock(burner, s -> s.setValue(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), false); scene.idle(20); scene.overlay.showText(70) @@ -678,7 +692,7 @@ public class ProcessingScenes { scene.overlay.showControls(new InputWindowElement(util.vector.topOf(burner), Pointing.DOWN).rightClick() .withItem(AllItems.BLAZE_CAKE.asStack()), 30); scene.idle(7); - scene.world.modifyBlock(burner, s -> s.with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.SEETHING), false); + scene.world.modifyBlock(burner, s -> s.setValue(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.SEETHING), false); scene.idle(20); scene.overlay.showText(80) @@ -717,7 +731,7 @@ public class ProcessingScenes { scene.world.showSection(util.select.position(1, 1, 2), Direction.DOWN); scene.idle(10); BlockPos basinPos = util.grid.at(1, 2, 2); - scene.world.modifyBlock(basinPos, s -> s.with(BasinBlock.FACING, Direction.DOWN), false); + scene.world.modifyBlock(basinPos, s -> s.setValue(BasinBlock.FACING, Direction.DOWN), false); scene.world.showSection(util.select.position(basinPos), Direction.DOWN); scene.idle(10); Vector3d basinSide = util.vector.blockSurface(basinPos, Direction.WEST); @@ -730,7 +744,7 @@ public class ProcessingScenes { ItemStack stack = new ItemStack(Items.BRICK); for (int i = 0; i < 4; i++) { - scene.world.createItemEntity(util.vector.centerOf(basinPos.up(3)), util.vector.of(0, 0, 0), stack); + scene.world.createItemEntity(util.vector.centerOf(basinPos.above(3)), util.vector.of(0, 0, 0), stack); scene.idle(10); } scene.idle(10); @@ -739,8 +753,8 @@ public class ProcessingScenes { scene.idle(30); for (Direction d : Iterate.horizontalDirections) { - scene.overlay.showOutline(PonderPalette.GREEN, new Object(), util.select.position(basinPos.down() - .offset(d)), 60); + scene.overlay.showOutline(PonderPalette.GREEN, new Object(), util.select.position(basinPos.below() + .relative(d)), 60); scene.idle(4); } @@ -756,7 +770,7 @@ public class ProcessingScenes { scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.EAST); scene.world.moveSection(depot, util.vector.of(-2, 0, 0), 0); scene.idle(10); - scene.world.modifyBlock(basinPos, s -> s.with(BasinBlock.FACING, Direction.NORTH), false); + scene.world.modifyBlock(basinPos, s -> s.setValue(BasinBlock.FACING, Direction.NORTH), false); scene.idle(10); scene.overlay.showText(80) @@ -817,7 +831,7 @@ public class ProcessingScenes { .serializeNBT())); }); scene.idle(4); - scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos.down() + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos.below() .north()), Pointing.RIGHT).withItem(new ItemStack(Items.BRICKS)), 30); scene.overlay.showText(60) @@ -830,7 +844,7 @@ public class ProcessingScenes { scene.world.hideIndependentSection(depot, Direction.NORTH); scene.idle(10); - scene.world.modifyBlock(basinPos, s -> s.with(BasinBlock.FACING, Direction.DOWN), false); + scene.world.modifyBlock(basinPos, s -> s.setValue(BasinBlock.FACING, Direction.DOWN), false); scene.idle(20); scene.overlay.showText(80) 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..8cc9fff31 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); @@ -121,7 +123,7 @@ public class PulleyScenes { scene.world.showSection(util.select.position(pulleyPos), Direction.SOUTH); ElementLink glass = - scene.world.showIndependentSection(util.select.position(pulleyPos.down()), Direction.UP); + scene.world.showIndependentSection(util.select.position(pulleyPos.below()), Direction.UP); scene.idle(20); scene.world.toggleRedstonePower(redstoneStuff); @@ -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); @@ -149,7 +152,7 @@ public class PulleyScenes { scene.world.hideSection(util.select.position(flowerPos), Direction.DOWN); scene.idle(40); - scene.world.setBlock(flowerPos, Blocks.BLUE_ORCHID.getDefaultState(), false); + scene.world.setBlock(flowerPos, Blocks.BLUE_ORCHID.defaultBlockState(), false); scene.world.showSection(util.select.position(flowerPos), Direction.DOWN); scene.overlay.showCenteredScrollInput(pulleyPos, Direction.UP, 60); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(pulleyPos), Pointing.DOWN).scroll() @@ -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/RedstoneScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/RedstoneScenes.java index ef4a004be..b77a3fc5b 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/RedstoneScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/RedstoneScenes.java @@ -1,5 +1,6 @@ package com.simibubi.create.foundation.ponder.content; +import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerTileEntity; import com.simibubi.create.content.logistics.block.diodes.AdjustablePulseRepeaterTileEntity; @@ -9,6 +10,7 @@ import com.simibubi.create.content.logistics.block.diodes.PoweredLatchBlock; import com.simibubi.create.content.logistics.block.diodes.PulseRepeaterBlock; import com.simibubi.create.content.logistics.block.diodes.ToggleLatchBlock; import com.simibubi.create.content.logistics.block.redstone.AnalogLeverTileEntity; +import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlock; import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity; import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock; import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkTileEntity; @@ -22,6 +24,7 @@ import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; import com.simibubi.create.foundation.utility.Pointing; import net.minecraft.block.RedstoneWireBlock; +import net.minecraft.item.DyeColor; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; @@ -64,7 +67,7 @@ public class RedstoneScenes { scene.idle(70); scene.world.toggleRedstonePower(redstone); - scene.world.modifyBlock(stickerPos, s -> s.with(StickerBlock.EXTENDED, true), false); + scene.world.modifyBlock(stickerPos, s -> s.setValue(StickerBlock.EXTENDED, true), false); scene.effects.indicateRedstone(buttonPos); scene.world.modifyTileNBT(stickerSelect, StickerTileEntity.class, nbt -> { }); @@ -90,7 +93,7 @@ public class RedstoneScenes { scene.addKeyframe(); scene.world.toggleRedstonePower(redstone); - scene.world.modifyBlock(stickerPos, s -> s.with(StickerBlock.EXTENDED, false), false); + scene.world.modifyBlock(stickerPos, s -> s.setValue(StickerBlock.EXTENDED, false), false); scene.effects.indicateRedstone(buttonPos); scene.world.modifyTileNBT(stickerSelect, StickerTileEntity.class, nbt -> { }); @@ -399,8 +402,8 @@ public class RedstoneScenes { scene.idle(30); scene.world.toggleRedstonePower(util.select.fromTo(4, 1, 2, 3, 1, 2)); - AxisAlignedBB bb = new AxisAlignedBB(circuitPos).grow(-.48f, -.45f, -.05f) - .offset(.575, -.45, 0); + AxisAlignedBB bb = new AxisAlignedBB(circuitPos).inflate(-.48f, -.45f, -.05f) + .move(.575, -.45, 0); scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, bb, bb, 40); scene.overlay.showText(40) .colored(PonderPalette.GREEN) @@ -416,10 +419,10 @@ public class RedstoneScenes { scene.idle(30); scene.world.toggleRedstonePower(util.select.fromTo(2, 1, 0, 2, 1, 1)); - bb = new AxisAlignedBB(circuitPos).grow(-.05f, -.45f, -.48f) - .offset(0, -.45, .575); - AxisAlignedBB bb2 = new AxisAlignedBB(circuitPos).grow(-.05f, -.45f, -.48f) - .offset(0, -.45, -.575); + bb = new AxisAlignedBB(circuitPos).inflate(-.05f, -.45f, -.48f) + .move(0, -.45, .575); + AxisAlignedBB bb2 = new AxisAlignedBB(circuitPos).inflate(-.05f, -.45f, -.48f) + .move(0, -.45, -.575); scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb, bb, 40); scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb2, bb2, 40); scene.overlay.showText(40) @@ -479,8 +482,8 @@ public class RedstoneScenes { scene.idle(30); scene.world.toggleRedstonePower(util.select.fromTo(4, 1, 2, 3, 1, 2)); - AxisAlignedBB bb = new AxisAlignedBB(circuitPos).grow(-.48f, -.45f, -.05f) - .offset(.575, -.45, 0); + AxisAlignedBB bb = new AxisAlignedBB(circuitPos).inflate(-.48f, -.45f, -.05f) + .move(.575, -.45, 0); scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, bb, bb, 40); scene.overlay.showText(40) .colored(PonderPalette.GREEN) @@ -562,7 +565,7 @@ public class RedstoneScenes { scene.idle(2); final int state = i + 1; scene.world.modifyTileNBT(leverSelection, AnalogLeverTileEntity.class, nbt -> nbt.putInt("State", state)); - scene.world.modifyBlock(wireLocations[i], s -> s.with(power, 7 - state), false); + scene.world.modifyBlock(wireLocations[i], s -> s.setValue(power, 7 - state), false); scene.effects.indicateRedstone(wireLocations[i]); } scene.idle(20); @@ -585,9 +588,9 @@ public class RedstoneScenes { nbt -> nbt.putInt("State", state)); scene.effects.indicateRedstone(wireLocations[i]); } - scene.world.modifyBlock(wireLocations[i], s -> s.with(power, state > 2 ? 0 : 3 - state), false); + scene.world.modifyBlock(wireLocations[i], s -> s.setValue(power, state > 2 ? 0 : 3 - state), false); } - scene.world.modifyBlock(wireLocations[0], s -> s.with(power, 3), false); + scene.world.modifyBlock(wireLocations[0], s -> s.setValue(power, 3), false); scene.idle(20); scene.overlay.showText(60) @@ -607,7 +610,7 @@ public class RedstoneScenes { nbt -> nbt.putInt("State", state)); scene.effects.indicateRedstone(wireLocations[i]); } - scene.world.modifyBlock(wireLocations[i], s -> s.with(power, 15 - state), false); + scene.world.modifyBlock(wireLocations[i], s -> s.setValue(power, 15 - state), false); } scene.world.toggleRedstonePower(lamp); @@ -630,7 +633,7 @@ public class RedstoneScenes { scene.effects.indicateRedstone(util.grid.at(2, 1, 1)); scene.world.modifyTileNBT(util.select.position(2, 1, 1), AnalogLeverTileEntity.class, nbt -> nbt.putInt("State", 11)); - scene.world.modifyBlock(util.grid.at(2, 1, 2), s -> s.with(RedstoneWireBlock.POWER, 11), false); + scene.world.modifyBlock(util.grid.at(2, 1, 2), s -> s.setValue(RedstoneWireBlock.POWER, 11), false); scene.world.modifyTileNBT(tubes, NixieTubeTileEntity.class, nbt -> nbt.putInt("RedstoneStrength", 11)); scene.idle(20); @@ -676,8 +679,26 @@ public class RedstoneScenes { .placeNearTarget() .text("Using name tags edited with an anvil, custom text can be displayed") .pointAt(util.vector.topOf(util.grid.at(3, 1, 3)) - .add(.25, -.05f, 0)); - scene.idle(70); + .add(-.75, -.05f, 0)); + scene.idle(90); + + InputWindowElement input = + new InputWindowElement(util.vector.blockSurface(util.grid.at(3, 1, 3), Direction.UP), Pointing.DOWN) + .withItem(new ItemStack(Items.BLUE_DYE)); + scene.overlay.showControls(input, 30); + scene.idle(7); + scene.world.setBlocks(util.select.fromTo(1, 1, 3, 3, 1, 3), AllBlocks.NIXIE_TUBES.get(DyeColor.BLUE) + .getDefaultState() + .setValue(NixieTubeBlock.FACING, Direction.NORTH), false); + scene.idle(10); + scene.overlay.showText(80) + .colored(PonderPalette.BLUE) + .text("Right-Click with Dye to change their display colour") + .attachKeyFrame() + .pointAt(util.vector.topOf(util.grid.at(3, 1, 3)) + .add(-.75, -.05f, 0)) + .placeNearTarget(); + scene.idle(60); } public static void redstoneLink(SceneBuilder scene, SceneBuildingUtil util) { @@ -788,30 +809,30 @@ public class RedstoneScenes { scene.idle(7); scene.overlay.showControls(new InputWindowElement(frontSlot, Pointing.UP).withItem(sapling), 40); scene.world.modifyTileNBT(link1Select, RedstoneLinkTileEntity.class, - nbt -> nbt.put("FrequencyLast", iron.write(new CompoundNBT()))); + nbt -> nbt.put("FrequencyLast", iron.save(new CompoundNBT()))); scene.idle(7); scene.world.modifyTileNBT(link1Select, RedstoneLinkTileEntity.class, - nbt -> nbt.put("FrequencyFirst", sapling.write(new CompoundNBT()))); + nbt -> nbt.put("FrequencyFirst", sapling.save(new CompoundNBT()))); scene.idle(20); scene.overlay.showControls(new InputWindowElement(top2Slot, Pointing.DOWN).withItem(iron), 40); scene.idle(7); scene.overlay.showControls(new InputWindowElement(bottom2Slot, Pointing.UP).withItem(sapling), 40); scene.world.modifyTileNBT(link2Select, RedstoneLinkTileEntity.class, - nbt -> nbt.put("FrequencyLast", iron.write(new CompoundNBT()))); + nbt -> nbt.put("FrequencyLast", iron.save(new CompoundNBT()))); scene.idle(7); scene.world.modifyTileNBT(link2Select, RedstoneLinkTileEntity.class, - nbt -> nbt.put("FrequencyFirst", sapling.write(new CompoundNBT()))); + nbt -> nbt.put("FrequencyFirst", sapling.save(new CompoundNBT()))); scene.idle(20); scene.overlay.showControls(new InputWindowElement(top3Slot, Pointing.DOWN).withItem(gold), 40); scene.idle(7); scene.overlay.showControls(new InputWindowElement(bottom3Slot, Pointing.UP).withItem(sapling), 40); scene.world.modifyTileNBT(link3Select, RedstoneLinkTileEntity.class, - nbt -> nbt.put("FrequencyLast", gold.write(new CompoundNBT()))); + nbt -> nbt.put("FrequencyLast", gold.save(new CompoundNBT()))); scene.idle(7); scene.world.modifyTileNBT(link3Select, RedstoneLinkTileEntity.class, - nbt -> nbt.put("FrequencyFirst", sapling.write(new CompoundNBT()))); + nbt -> nbt.put("FrequencyFirst", sapling.save(new CompoundNBT()))); scene.idle(20); scene.world.toggleRedstonePower(redstone); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java b/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java index bd83c5bd6..7875705ac 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java @@ -1,7 +1,10 @@ package com.simibubi.create.foundation.ponder.content; +import com.simibubi.create.Create; import com.simibubi.create.foundation.ponder.PonderLocalization; +import net.minecraft.util.ResourceLocation; + public class SharedText { public static void gatherText() { @@ -18,15 +21,18 @@ public class SharedText { add("movement_anchors", "With the help of Chassis or Super Glue, larger structures can be moved."); add("behaviour_modify_wrench", "This behaviour can be modified using a Wrench"); add("storage_on_contraption", "Inventories attached to the Contraption will pick up their drops automatically"); - } - public static String get(String key) { + public static String get(ResourceLocation key) { return PonderLocalization.getShared(key); } - private static void add(String k, String v) { + public static void add(ResourceLocation k, String v) { PonderLocalization.registerShared(k, v); } + private static void add(String k, String v) { + add(Create.asResource(k), v); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/TunnelScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/TunnelScenes.java index 6c80f52b5..28874b1b0 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/TunnelScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/TunnelScenes.java @@ -268,7 +268,7 @@ public class TunnelScenes { ItemStack item3 = new ItemStack(Items.SWEET_BERRIES); tunnelFilterVec = getTunnelFilterVec(tunnelPos, Direction.WEST); - BlockPos newTunnelPos = tunnelPos.up(2) + BlockPos newTunnelPos = tunnelPos.above(2) .south(); scene.overlay .showControls(new InputWindowElement(tunnelFilterVec.add(0, 0, -1), Pointing.RIGHT).withItem(item1), 20); @@ -313,7 +313,7 @@ public class TunnelScenes { scene.world.showSectionAndMerge(util.select.position(3, 5, 2), Direction.DOWN, newBelt); scene.overlay.showText(80) - .pointAt(util.vector.blockSurface(tunnelPos.up() + .pointAt(util.vector.blockSurface(tunnelPos.above() .north(), Direction.WEST)) .placeNearTarget() .text("For this, items can also be inserted into the Tunnel block directly"); @@ -339,14 +339,14 @@ public class TunnelScenes { protected static Vector3d getTunnelFilterVec(BlockPos pos, Direction d) { return VecHelper.getCenterOf(pos) - .add(Vector3d.of(d.getDirectionVec()).scale(.5)) + .add(Vector3d.atLowerCornerOf(d.getNormal()).scale(.5)) .add(0, 0.3, 0); } public static void brassModes(SceneBuilder scene, SceneBuildingUtil util) { scene.title("brass_tunnel_modes", "Distribution Modes of the Brass Tunnel"); scene.configureBasePlate(0, 1, 5); - BlockState barrier = Blocks.BARRIER.getDefaultState(); + BlockState barrier = Blocks.BARRIER.defaultBlockState(); scene.world.setBlock(util.grid.at(1, 1, 0), barrier, false); scene.world.showSection(util.select.layer(0), Direction.UP); scene.idle(5); @@ -419,7 +419,7 @@ public class TunnelScenes { .colored(PonderPalette.RED); scene.idle(60); scene.world.moveSection(blockage, util.vector.of(-1, 0, 0), 10); - scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.defaultBlockState(), false); scene.world.multiplyKineticSpeed(util.select.everywhere(), 1.5f); } @@ -466,7 +466,7 @@ public class TunnelScenes { .colored(PonderPalette.RED); scene.idle(30); scene.world.moveSection(blockage, util.vector.of(-1, 0, 0), 10); - scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.defaultBlockState(), false); } if (i == 19) { @@ -486,16 +486,16 @@ public class TunnelScenes { } if (i == 21) { - scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.BARRIER.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.BARRIER.defaultBlockState(), false); blockage2 = scene.world.showIndependentSection(util.select.position(4, 1, 0), Direction.UP); scene.world.moveSection(blockage2, util.vector.of(-2, 0, 0), 0); } if (i == 25) { scene.world.hideIndependentSection(blockage, Direction.DOWN); - scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.defaultBlockState(), false); scene.world.hideIndependentSection(blockage2, Direction.DOWN); - scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.AIR.defaultBlockState(), false); } if (i == 26) { 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..018d82422 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/DrainScenes.java @@ -0,0 +1,125 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.content.contraptions.fluids.actors.ItemDrainTileEntity; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.fluid.Fluids; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + +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.showBasePlate(); + scene.idle(5); + + Selection drain = util.select.position(3, 1, 2); + BlockPos drainPos = util.grid.at(3, 1, 2); + Selection pipes = util.select.fromTo(3, 1, 3, 3, 1, 4) + .add(util.select.fromTo(3, 2, 4, 2, 2, 4)); + Selection tank = util.select.fromTo(1, 1, 4, 1, 3, 4); + Selection largeCog = util.select.position(1, 0, 5); + Selection kinetics = util.select.fromTo(2, 1, 3, 2, 1, 5); + Selection belt = util.select.fromTo(2, 1, 2, 1, 1, 2); + BlockPos beltPos = util.grid.at(1, 1, 2); + + ElementLink drainLink = scene.world.showIndependentSection(drain, Direction.DOWN); + scene.world.moveSection(drainLink, util.vector.of(-1, 0, 0), 0); + scene.idle(10); + + scene.overlay.showText(40) + .text("Item Drains can extract fluids from items") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(drainPos.west(), Direction.UP)); + scene.idle(50); + + ItemStack lavaBucket = new ItemStack(Items.LAVA_BUCKET); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(drainPos.west(), Direction.UP), Pointing.DOWN).rightClick() + .withItem(lavaBucket), + 40); + scene.idle(7); + scene.world.modifyTileEntity(drainPos, ItemDrainTileEntity.class, te -> { + te.getBehaviour(SmartFluidTankBehaviour.TYPE) + .allowInsertion(); + te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + .ifPresent(ifh -> ifh.fill(new FluidStack(Fluids.LAVA, 1000), FluidAction.EXECUTE)); + }); + scene.idle(10); + + scene.overlay.showText(50) + .text("Right-click it to pour fluids from your held item into it") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(drainPos.west(), Direction.WEST)); + scene.idle(60); + + scene.world.modifyTileEntity(drainPos, ItemDrainTileEntity.class, + te -> te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + .ifPresent(ifh -> ifh.drain(500, FluidAction.EXECUTE))); + + scene.world.moveSection(drainLink, util.vector.of(1, 0, 0), 7); + scene.world.showSection(largeCog, Direction.UP); + scene.idle(3); + scene.world.showSection(kinetics, Direction.NORTH); + scene.idle(4); + scene.world.showSection(belt, Direction.SOUTH); + scene.idle(10); + + scene.overlay.showText(40) + .text("When items are inserted from the side...") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(util.grid.at(2, 1, 2))); + scene.idle(40); + + scene.overlay + .showControls(new InputWindowElement(util.vector.topOf(beltPos), Pointing.DOWN).withItem(lavaBucket), 20); + scene.idle(7); + scene.world.createItemOnBelt(beltPos, Direction.NORTH, lavaBucket); + scene.idle(30); + + scene.overlay.showText(60) + .text("...they roll across, emptying out their contained fluid") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(drainPos)); + scene.idle(40); + + scene.world.showSection(tank, Direction.DOWN); + scene.idle(5); + scene.world.showSection(pipes, Direction.NORTH); + scene.idle(20); + + scene.overlay.showText(90) + .text("Pipe Networks can now pull the fluid from the drains' internal buffer") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(util.grid.at(3, 1, 3))); + scene.idle(50); + scene.markAsFinished(); + scene.idle(50); + + for (int i = 0; i < 5; i++) { + scene.world.createItemOnBelt(beltPos, Direction.NORTH, lavaBucket); + scene.idle(30); + } + + } + +} 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..a98b6e93c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/FluidMovementActorScenes.java @@ -0,0 +1,199 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.AllFluids; +import com.simibubi.create.content.contraptions.components.actors.PortableFluidInterfaceTileEntity; +import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; +import com.simibubi.create.foundation.fluid.FluidHelper; +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.utility.Pointing; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + +public class FluidMovementActorScenes { + + public static void transfer(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("portable_fluid_interface", "Contraption Fluid Exchange"); + scene.configureBasePlate(0, 0, 6); + scene.scaleSceneView(0.95f); + scene.setSceneOffsetY(-1); + scene.showBasePlate(); + scene.idle(5); + + Selection pipes = util.select.fromTo(2, 1, 3, 0, 1, 3) + .add(util.select.position(0, 1, 4)); + BlockPos pumpPos = util.grid.at(0, 1, 4); + Selection kinetics = util.select.fromTo(1, 1, 7, 1, 1, 4); + Selection tank = util.select.fromTo(0, 1, 5, 0, 3, 5); + Selection largeCog = util.select.position(2, 0, 7); + FluidStack chocolate = new FluidStack(FluidHelper.convertToStill(AllFluids.CHOCOLATE.get()), 1000); + BlockPos ct1 = util.grid.at(5, 3, 2); + BlockPos ct2 = util.grid.at(6, 3, 2); + BlockPos st = util.grid.at(0, 1, 5); + Capability fhc = CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + Class type = FluidTankTileEntity.class; + ItemStack bucket = AllFluids.CHOCOLATE.get() + .getAttributes() + .getBucket(chocolate); + + scene.world.modifyTileEntity(st, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.fill(FluidHelper.copyStackWithAmount(chocolate, 10000), FluidAction.EXECUTE))); + + BlockPos bearing = util.grid.at(5, 1, 2); + scene.world.showSection(util.select.position(bearing), Direction.DOWN); + scene.idle(5); + ElementLink contraption = + scene.world.showIndependentSection(util.select.fromTo(5, 2, 2, 6, 4, 2), Direction.DOWN); + scene.world.configureCenterOfRotation(contraption, util.vector.centerOf(bearing)); + scene.idle(10); + scene.world.rotateBearing(bearing, 360, 70); + scene.world.rotateSection(contraption, 0, 360, 0, 70); + scene.overlay.showText(60) + .pointAt(util.vector.topOf(bearing.above(2))) + .colored(PonderPalette.RED) + .placeNearTarget() + .attachKeyFrame() + .text("Fluid Tanks on moving contraptions cannot be accessed by any pipes"); + + scene.idle(70); + BlockPos psi = util.grid.at(4, 2, 2); + scene.world.showSectionAndMerge(util.select.position(psi), Direction.EAST, contraption); + scene.idle(13); + scene.effects.superGlue(psi, Direction.EAST, true); + + scene.overlay.showText(80) + .pointAt(util.vector.topOf(psi)) + .colored(PonderPalette.GREEN) + .placeNearTarget() + .attachKeyFrame() + .text("This component can interact with fluid tanks without the need to stop the contraption"); + scene.idle(90); + + BlockPos psi2 = psi.west(2); + scene.world.showSection(util.select.position(psi2), Direction.DOWN); + 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); + + scene.world.rotateBearing(bearing, 360, 60); + scene.world.rotateSection(contraption, 0, 360, 0, 60); + scene.idle(20); + + scene.overlay.showText(40) + .placeNearTarget() + .pointAt(util.vector.of(3, 3, 2.5)) + .text("Whenever they pass by each other, they will engage in a connection"); + scene.idle(35); + + Selection both = util.select.fromTo(2, 2, 2, 4, 2, 2); + Class psiClass = PortableFluidInterfaceTileEntity.class; + + scene.world.modifyTileNBT(both, psiClass, nbt -> { + nbt.putFloat("Distance", 1); + nbt.putFloat("Timer", 40); + }); + + scene.idle(20); + scene.overlay.showOutline(PonderPalette.GREEN, psi, util.select.fromTo(5, 3, 2, 6, 4, 2), 80); + scene.idle(10); + + scene.overlay.showSelectionWithText(util.select.position(psi2), 70) + .placeNearTarget() + .colored(PonderPalette.GREEN) + .attachKeyFrame() + .text("While engaged, the stationary interface will represent ALL Tanks on the contraption"); + scene.idle(80); + + ElementLink p = scene.world.showIndependentSection(tank, Direction.DOWN); + scene.world.moveSection(p, util.vector.of(0, 0, -1), 0); + scene.idle(5); + scene.world.showSectionAndMerge(pipes, Direction.EAST, p); + scene.idle(5); + scene.world.showSectionAndMerge(largeCog, Direction.UP, p); + scene.world.showSectionAndMerge(kinetics, Direction.NORTH, p); + scene.idle(10); + + scene.overlay.showText(70) + .placeNearTarget() + .pointAt(util.vector.topOf(pumpPos)) + .attachKeyFrame() + .text("Fluid can now be inserted..."); + scene.idle(30); + + for (int i = 0; i < 16; i++) { + if (i == 8) + scene.overlay + .showControls(new InputWindowElement(util.vector.blockSurface(util.grid.at(5, 3, 2), Direction.WEST) + .add(0, 0.5, 0), Pointing.LEFT).withItem(bucket), 30); + scene.world.modifyTileEntity(st, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.drain(1000, FluidAction.EXECUTE))); + scene.world.modifyTileEntity(ct1, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.fill(chocolate, FluidAction.EXECUTE))); + scene.idle(2); + } + for (int i = 0; i < 8; i++) { + scene.world.modifyTileEntity(st, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.drain(1000, FluidAction.EXECUTE))); + scene.world.modifyTileEntity(ct2, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.fill(chocolate, FluidAction.EXECUTE))); + scene.idle(2); + } + + scene.idle(50); + + scene.overlay.showText(40) + .placeNearTarget() + .pointAt(util.vector.topOf(pumpPos)) + .text("...or extracted from the contraption"); + scene.world.multiplyKineticSpeed(util.select.everywhere(), -1); + scene.world.propagatePipeChange(pumpPos); + scene.idle(30); + + for (int i = 0; i < 8; i++) { + scene.world.modifyTileEntity(ct2, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.drain(1000, FluidAction.EXECUTE))); + scene.world.modifyTileEntity(st, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.fill(chocolate, FluidAction.EXECUTE))); + scene.idle(2); + } + for (int i = 0; i < 16; i++) { + scene.world.modifyTileEntity(ct1, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.drain(1000, FluidAction.EXECUTE))); + scene.world.modifyTileEntity(st, type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.fill(chocolate, FluidAction.EXECUTE))); + scene.idle(2); + } + + scene.world.modifyTileEntity(util.grid.at(2, 2, 3), type, te -> te.getCapability(fhc) + .ifPresent(ifh -> ifh.drain(8000, FluidAction.EXECUTE))); + scene.idle(50); + + scene.overlay.showText(120) + .placeNearTarget() + .attachKeyFrame() + .pointAt(util.vector.topOf(psi2)) + .text("After no contents have been exchanged for a while, the contraption will continue on its way"); + scene.world.modifyTileNBT(both, psiClass, nbt -> nbt.putFloat("Timer", 9)); + + scene.idle(15); + scene.markAsFinished(); + scene.world.rotateBearing(bearing, 270, 120); + scene.world.rotateSection(contraption, 0, 270, 0, 120); + } + +} 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..10a6f4b9b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/FluidTankScenes.java @@ -0,0 +1,427 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllFluids; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.fluids.FluidFX; +import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity; +import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity; +import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity.CreativeSmartFluidTank; +import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock; +import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; +import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity; +import com.simibubi.create.foundation.fluid.FluidHelper; +import com.simibubi.create.foundation.gui.AllIcons; +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.ponder.instructions.EmitParticlesInstruction.Emitter; +import com.simibubi.create.foundation.utility.Pointing; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.fluid.Fluids; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + +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.showBasePlate(); + scene.idle(5); + + BlockPos tankPos = util.grid.at(3, 1, 2); + Selection chocolate = util.select.fromTo(1, 5, 0, 0, 8, 1); + Selection tank = util.select.fromTo(3, 1, 2, 3, 2, 2); + Selection largeCog1 = util.select.position(3, 0, 5); + Selection kinetics1 = util.select.fromTo(2, 1, 5, 2, 1, 3) + .add(util.select.position(2, 2, 4)); + Selection largeCog2 = util.select.position(6, 0, 1); + Selection comparatorStuff = util.select.fromTo(2, 1, 1, 2, 1, 0); + Selection pump = util.select.position(1, 1, 3); + BlockPos pumpPos = util.grid.at(1, 1, 3); + Selection spoutstuff = util.select.fromTo(3, 1, 0, 5, 3, 2) + .substract(tank); + Selection pipe = util.select.fromTo(1, 1, 2, 1, 1, 5) + .add(util.select.position(1, 0, 5)) + .add(util.select.position(2, 1, 2)); + + ElementLink tankLink = scene.world.showIndependentSection(tank, Direction.NORTH); + scene.world.moveSection(tankLink, util.vector.of(0, 0, -1), 0); + scene.idle(5); + ElementLink chocLink = scene.world.showIndependentSection(chocolate, Direction.NORTH); + scene.world.moveSection(chocLink, util.vector.of(2, -4, 3), 0); + scene.idle(10); + + scene.overlay.showOutline(PonderPalette.GREEN, chocLink, util.select.fromTo(3, 1, 3, 2, 4, 4), 40); + scene.idle(10); + scene.overlay.showLine(PonderPalette.GREEN, util.vector.of(3, 1, 2), util.vector.of(2, 1, 3), 30); + scene.overlay.showLine(PonderPalette.GREEN, util.vector.of(3, 3, 2), util.vector.of(2, 5, 3), 30); + scene.overlay.showLine(PonderPalette.GREEN, util.vector.of(4, 3, 2), util.vector.of(4, 5, 3), 30); + scene.overlay.showOutline(PonderPalette.GREEN, tankLink, util.select.fromTo(3, 1, 1, 3, 2, 1), 40); + scene.idle(10); + + scene.overlay.showText(40) + .text("Fluid Tanks can be used to store large amounts of fluid") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(3, 2, 1), Direction.WEST)); + scene.idle(50); + + scene.world.hideIndependentSection(chocLink, Direction.DOWN); + scene.idle(5); + FluidStack content = new FluidStack(AllFluids.CHOCOLATE.get() + .getSource(), 16000); + scene.world.modifyTileEntity(tankPos, FluidTankTileEntity.class, te -> te.getTankInventory() + .fill(content, FluidAction.EXECUTE)); + scene.idle(25); + + scene.world.moveSection(tankLink, util.vector.of(0, 0, 1), 10); + scene.idle(5); + scene.world.setKineticSpeed(pump, 0); + scene.world.showSection(pipe, Direction.EAST); + scene.idle(10); + scene.world.showSection(largeCog1, Direction.UP); + scene.world.showSection(kinetics1, Direction.WEST); + scene.idle(10); + scene.world.setBlock(util.grid.at(1, -1, 5), AllBlocks.FLUID_TANK.getDefaultState(), false); + scene.world.setKineticSpeed(pump, 128); + + scene.idle(5); + Selection pumpRedstone = util.select.fromTo(2, 1, 4, 2, 2, 4); + Selection pumpCogs = util.select.fromTo(2, 1, 3, 1, 1, 3); + scene.world.toggleRedstonePower(pumpRedstone); + scene.world.multiplyKineticSpeed(pumpCogs, -1); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationDirectionIndicator(pumpPos); + scene.world.modifyTileEntity(util.grid.at(2, 0, 5), FluidTankTileEntity.class, te -> te.getTankInventory() + .fill(content, FluidAction.EXECUTE)); + scene.idle(20); + + for (int i = 0; i < 4; i++) { + scene.world.modifyTileEntity(tankPos, FluidTankTileEntity.class, te -> te.getTankInventory() + .drain(2000, FluidAction.EXECUTE)); + scene.idle(5); + } + + scene.overlay.showText(60) + .text("Pipe networks can push and pull fluids from any side") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.centerOf(1, 1, 2)); + scene.idle(40); + + scene.world.toggleRedstonePower(pumpRedstone); + scene.world.multiplyKineticSpeed(pumpCogs, -1); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationDirectionIndicator(pumpPos); + for (int i = 0; i < 4; i++) { + scene.world.modifyTileEntity(tankPos, FluidTankTileEntity.class, te -> te.getTankInventory() + .fill(FluidHelper.copyStackWithAmount(content, 2000), FluidAction.EXECUTE)); + scene.idle(5); + } + scene.idle(40); + + scene.world.hideSection(largeCog1, Direction.DOWN); + scene.world.hideSection(kinetics1, Direction.SOUTH); + scene.world.hideSection(pipe, Direction.WEST); + scene.idle(10); + scene.world.showSection(comparatorStuff, Direction.SOUTH); + scene.idle(5); + scene.world.moveSection(tankLink, util.vector.of(-1, 0, 0), 10); + scene.idle(10); + scene.world.toggleRedstonePower(comparatorStuff); + scene.world.modifyTileNBT(util.select.position(2, 1, 0), NixieTubeTileEntity.class, + nbt -> nbt.putInt("RedstoneStrength", 15)); + + scene.overlay.showText(50) + .text("The contained fluid can be measured by a Comparator") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(2, 1, 1), Direction.DOWN) + .add(0, 1 / 8f, 0)); + scene.idle(50); + + scene.world.hideSection(comparatorStuff, Direction.EAST); + scene.idle(20); + + ItemStack bucket = new ItemStack(Items.BUCKET, 1); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.NORTH), Pointing.RIGHT) + .showing(AllIcons.I_MTD_CLOSE) + .withItem(bucket), + 40); + scene.idle(7); + scene.overlay.showSelectionWithText(util.select.fromTo(2, 1, 2, 2, 2, 2), 70) + .text("However, in Survival Mode Fluids cannot be added or taken manually") + .attachKeyFrame() + .colored(PonderPalette.RED) + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.WEST)); + scene.idle(80); + scene.world.modifyTileEntity(util.grid.at(4, 3, 0), SpoutTileEntity.class, + te -> te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + .ifPresent(ifh -> ifh.fill(content, FluidAction.EXECUTE))); + + scene.world.moveSection(tankLink, util.vector.of(0, 0, 1), 7); + scene.world.multiplyKineticSpeed(spoutstuff, -1); + scene.world.multiplyKineticSpeed(largeCog2, -1); + scene.idle(7); + ElementLink spoutLink = scene.world.showIndependentSection(spoutstuff, Direction.SOUTH); + ElementLink largeCogLink = scene.world.showIndependentSection(largeCog2, Direction.UP); + scene.world.moveSection(spoutLink, util.vector.of(-1, 0, 1), 0); + scene.world.moveSection(largeCogLink, util.vector.of(-1, 0, 1), 0); + scene.idle(20); + scene.overlay.showOutline(PonderPalette.GREEN, new Object(), util.select.position(2, 1, 1), 50); + scene.idle(5); + scene.overlay.showOutline(PonderPalette.GREEN, new Object(), util.select.position(3, 3, 1), 50); + scene.idle(5); + + scene.overlay.showText(80) + .text("You can use Basins, Item Drains and Spouts to drain or fill fluid containing items") + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .placeNearTarget() + .pointAt(util.vector.topOf(2, 1, 1)); + scene.idle(90); + + ItemStack chocBucket = AllFluids.CHOCOLATE.get() + .getAttributes() + .getBucket(new FluidStack(FluidHelper.convertToStill(AllFluids.CHOCOLATE.get()), 1000)); + scene.world.createItemOnBeltLike(util.grid.at(3, 1, 0), Direction.WEST, chocBucket); + scene.idle(40); + scene.world.modifyTileNBT(util.select.position(util.grid.at(4, 3, 0)), SpoutTileEntity.class, + nbt -> nbt.putInt("ProcessingTicks", 20)); + scene.idle(20); + scene.world.removeItemsFromBelt(util.grid.at(4, 1, 0)); + scene.world.createItemOnBeltLike(util.grid.at(4, 1, 0), Direction.UP, chocBucket); + for (int i = 0; i < 10; i++) { + scene.effects.emitParticles(util.vector.topOf(3, 1, 1) + .add(0, 1 / 16f, 0), + Emitter.simple(FluidFX.getFluidParticle(content), + VecHelper.offsetRandomly(Vector3d.ZERO, Create.RANDOM, .1f)), + 1, 1); + } + + } + + public static void sizes(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("fluid_tank_sizes", "Dimensions of a Fluid tank"); + scene.configureBasePlate(0, 0, 6); + scene.showBasePlate(); + scene.idle(5); + + Selection single = util.select.position(0, 3, 0); + Selection single2 = util.select.fromTo(1, 2, 1, 0, 2, 0); + Selection single3 = util.select.fromTo(2, 1, 0, 0, 1, 2); + + ElementLink s1 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s1, util.vector.of(2, -2, 2), 0); + scene.idle(10); + + scene.overlay.showText(60) + .text("Fluid Tanks can be combined to increase the total capacity") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(2, 1, 2)); + scene.idle(40); + + ElementLink s2 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s2, util.vector.of(2, -2, 3), 0); + scene.idle(5); + ElementLink s3 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s3, util.vector.of(3, -2, 3), 0); + scene.idle(5); + ElementLink s4 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s4, util.vector.of(3, -2, 2), 0); + scene.idle(10); + + scene.world.moveSection(s1, util.vector.of(0, -100, 0), 0); + scene.world.moveSection(s2, util.vector.of(0, -100, 0), 0); + scene.world.moveSection(s3, util.vector.of(0, -100, 0), 0); + scene.world.moveSection(s4, util.vector.of(0, -100, 0), 0); + + ElementLink d = scene.world.showIndependentSectionImmediately(single2); + scene.world.moveSection(d, util.vector.of(2, -1, 2), 0); + scene.effects.indicateSuccess(util.grid.at(2, 1, 2)); + scene.effects.indicateSuccess(util.grid.at(3, 1, 2)); + scene.effects.indicateSuccess(util.grid.at(2, 1, 3)); + scene.effects.indicateSuccess(util.grid.at(3, 1, 3)); + scene.world.hideIndependentSection(s1, Direction.DOWN); + scene.world.hideIndependentSection(s2, Direction.DOWN); + scene.world.hideIndependentSection(s3, Direction.DOWN); + scene.world.hideIndependentSection(s4, Direction.DOWN); + scene.idle(25); + + scene.overlay.showText(60) + .text("Their base square can be up to 3 blocks wide...") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(2, 1, 2)); + scene.idle(40); + + s1 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s1, util.vector.of(2, -2, 4), 0); + scene.idle(3); + s2 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s2, util.vector.of(3, -2, 4), 0); + scene.idle(3); + s3 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s3, util.vector.of(4, -2, 4), 0); + scene.idle(3); + s4 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s4, util.vector.of(4, -2, 3), 0); + scene.idle(3); + ElementLink s5 = scene.world.showIndependentSection(single, Direction.DOWN); + scene.world.moveSection(s5, util.vector.of(4, -2, 2), 0); + scene.idle(10); + + scene.world.moveSection(d, util.vector.of(0, -100, 0), 0); + scene.world.moveSection(s1, util.vector.of(0, -100, 0), 0); + scene.world.moveSection(s2, util.vector.of(0, -100, 0), 0); + scene.world.moveSection(s3, util.vector.of(0, -100, 0), 0); + scene.world.moveSection(s4, util.vector.of(0, -100, 0), 0); + scene.world.moveSection(s5, util.vector.of(0, -100, 0), 0); + + ElementLink t = scene.world.showIndependentSectionImmediately(single3); + scene.world.moveSection(t, util.vector.of(2, 0, 2), 0); + + for (int i = 2; i < 5; i++) + for (int j = 2; j < 5; j++) + scene.effects.indicateSuccess(util.grid.at(i, 1, j)); + + scene.world.hideIndependentSection(d, Direction.DOWN); + scene.world.hideIndependentSection(s1, Direction.DOWN); + scene.world.hideIndependentSection(s2, Direction.DOWN); + scene.world.hideIndependentSection(s3, Direction.DOWN); + scene.world.hideIndependentSection(s4, Direction.DOWN); + scene.world.hideIndependentSection(s5, Direction.DOWN); + scene.idle(25); + + scene.world.hideIndependentSection(t, Direction.DOWN); + scene.idle(10); + + Selection full1 = util.select.fromTo(5, 1, 0, 5, 6, 0); + Selection full2 = util.select.fromTo(4, 1, 1, 3, 6, 2); + Selection full3 = util.select.fromTo(0, 6, 5, 2, 1, 3); + + scene.world.showSection(full1, Direction.DOWN); + scene.idle(5); + scene.world.showSection(full2, Direction.DOWN); + scene.idle(5); + scene.world.showSection(full3, Direction.DOWN); + scene.idle(10); + + Vector3d blockSurface = util.vector.blockSurface(util.grid.at(3, 3, 1), Direction.WEST); + scene.overlay.showText(60) + .text("...and grow in height by more than 30 additional layers") + .attachKeyFrame() + .placeNearTarget() + .pointAt(blockSurface); + scene.idle(70); + + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(3, 3, 1), Direction.NORTH), Pointing.RIGHT) + .rightClick() + .withWrench(), + 60); + scene.idle(7); + scene.world.modifyBlocks(full2, s -> s.setValue(FluidTankBlock.SHAPE, FluidTankBlock.Shape.PLAIN), false); + scene.idle(30); + + scene.overlay.showText(60) + .text("Using a Wrench, a tanks' window can be toggled") + .attachKeyFrame() + .placeNearTarget() + .pointAt(blockSurface); + scene.idle(50); + } + + public static void creative(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("creative_fluid_tank", "Creative Fluid Tanks"); + scene.configureBasePlate(0, 0, 5); + scene.showBasePlate(); + scene.idle(5); + + Selection largeCog = util.select.position(5, 0, 2); + Selection cTank = util.select.fromTo(3, 1, 1, 3, 2, 1); + Selection tank = util.select.fromTo(1, 1, 3, 1, 3, 3); + Selection pipes = util.select.fromTo(3, 1, 2, 2, 1, 3); + Selection cog = util.select.position(4, 1, 2); + BlockPos cTankPos = util.grid.at(3, 1, 1); + BlockPos pumpPos = util.grid.at(3, 1, 2); + + ElementLink cTankLink = scene.world.showIndependentSection(cTank, Direction.DOWN); + scene.world.moveSection(cTankLink, util.vector.of(-1, 0, 1), 0); + + scene.overlay.showText(70) + .text("Creative Fluid Tanks can be used to provide a bottomless supply of fluid") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.WEST)); + scene.idle(80); + + ItemStack bucket = new ItemStack(Items.LAVA_BUCKET); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.NORTH), Pointing.RIGHT) + .rightClick() + .withItem(bucket), + 40); + scene.idle(7); + scene.world.modifyTileEntity(cTankPos, CreativeFluidTankTileEntity.class, + te -> ((CreativeSmartFluidTank) te.getTankInventory()) + .setContainedFluid(new FluidStack(Fluids.FLOWING_LAVA, 1000))); + scene.idle(5); + + scene.overlay.showText(50) + .text("Right-Click with a fluid containing item to configure it") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.WEST)); + scene.idle(60); + scene.world.moveSection(cTankLink, util.vector.of(1, 0, -1), 6); + scene.idle(7); + scene.world.showSection(tank, Direction.DOWN); + scene.idle(5); + + scene.world.showSection(largeCog, Direction.UP); + scene.world.showSection(cog, Direction.NORTH); + scene.world.showSection(pipes, Direction.NORTH); + scene.world.multiplyKineticSpeed(util.select.everywhere(), -1); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationDirectionIndicator(pumpPos); + scene.idle(40); + + scene.overlay.showText(70) + .text("Pipe Networks can now endlessly draw the assigned fluid from the tank") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 2), Direction.WEST)); + scene.idle(120); + + scene.world.multiplyKineticSpeed(util.select.everywhere(), -1); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationDirectionIndicator(pumpPos); + scene.idle(40); + + scene.overlay.showText(70) + .text("Any Fluids pushed back into a Creative Fluid Tank will be voided") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 2), Direction.WEST)); + scene.idle(40); + + } + +} 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..a8cacb2f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/HosePulleyScenes.java @@ -0,0 +1,358 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyFluidHandler; +import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyTileEntity; +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.WorldSectionElement; + +import net.minecraft.block.Blocks; +import net.minecraft.fluid.Fluids; +import net.minecraft.util.Direction; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + +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, 3); + scene.setSceneOffsetY(-1); + scene.scaleSceneView(.9f); + scene.showBasePlate(); + scene.idle(5); + + Selection cogs = util.select.fromTo(3, 1, 2, 3, 2, 2); + Selection pipes = util.select.fromTo(3, 1, 1, 3, 5, 1) + .add(util.select.position(2, 5, 1)); + BlockPos hosePos = util.grid.at(1, 5, 1); + Selection hose = util.select.position(1, 5, 1); + Selection crank = util.select.position(0, 5, 1); + + ElementLink hoselink = scene.world.showIndependentSection(hose, Direction.UP); + scene.world.moveSection(hoselink, util.vector.of(0, -1, 0), 0); + scene.idle(10); + + Vector3d shaftInput = util.vector.blockSurface(hosePos.below(), Direction.WEST); + scene.overlay.showText(70) + .text("Hose Pulleys can be used to fill or drain large bodies of Fluid") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(hosePos.below())); + scene.idle(80); + + scene.overlay.showText(80) + .text("With the Kinetic Input, the height of the pulleys' hose can be controlled") + .attachKeyFrame() + .placeNearTarget() + .pointAt(shaftInput); + scene.idle(40); + + scene.world.showSectionAndMerge(crank, Direction.EAST, hoselink); + scene.idle(20); + + Selection kinetics = util.select.fromTo(1, 5, 1, 0, 5, 1); + scene.world.setKineticSpeed(kinetics, 32); + scene.idle(50); + + scene.world.setKineticSpeed(kinetics, 0); + scene.overlay.showText(80) + .text("The Pulley retracts while the input rotation is inverted") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.centerOf(hosePos.below(3))); + scene.idle(30); + + scene.world.setKineticSpeed(kinetics, -32); + scene.idle(16); + scene.world.setKineticSpeed(kinetics, 0); + scene.idle(10); + scene.rotateCameraY(70); + scene.idle(40); + + scene.overlay.showText(60) + .text("On the opposite side, pipes can be connected") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(hosePos.below(), Direction.EAST)); + scene.idle(70); + + scene.rotateCameraY(-70); + scene.idle(10); + + scene.world.showSectionAndMerge(cogs, Direction.NORTH, hoselink); + scene.world.showSectionAndMerge(pipes, Direction.WEST, hoselink); + scene.world.showSection(util.select.fromTo(0, 1, 0, 2, 2, 2), Direction.UP); + scene.idle(10); + + scene.overlay.showText(70) + .text("Attached pipe networks can either provide fluid to the hose...") + .attachKeyFrame() + .pointAt(util.vector.centerOf(util.grid.at(3, 1, 1))); + scene.idle(40); + + List blocks = new LinkedList<>(); + for (int y = 1; y < 3; y++) { + blocks.add(util.grid.at(1, y, 1)); + blocks.add(util.grid.at(0, y, 1)); + blocks.add(util.grid.at(1, y, 0)); + blocks.add(util.grid.at(2, y, 1)); + blocks.add(util.grid.at(1, y, 2)); + blocks.add(util.grid.at(0, y, 0)); + blocks.add(util.grid.at(2, y, 0)); + blocks.add(util.grid.at(2, y, 2)); + blocks.add(util.grid.at(0, y, 2)); + } + + for (BlockPos blockPos : blocks) { + scene.world.setBlock(blockPos, Blocks.WATER.defaultBlockState(), false); + scene.idle(3); + } + + scene.world.multiplyKineticSpeed(util.select.fromTo(3, 1, 2, 3, 2, 1), -1); + scene.world.modifyTileEntity(util.grid.at(1, 5, 1), HosePulleyTileEntity.class, te -> te + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + .ifPresent( + ifh -> ((HosePulleyFluidHandler) ifh).fill(new FluidStack(Fluids.WATER, 100), FluidAction.EXECUTE))); + scene.world.propagatePipeChange(util.grid.at(3, 2, 1)); + + scene.idle(40); + scene.world.setKineticSpeed(kinetics, 32); + scene.idle(16); + scene.world.setKineticSpeed(kinetics, 0); + scene.idle(5); + scene.overlay.showText(70) + .text("...or pull from it, draining the pool instead") + .attachKeyFrame() + .pointAt(util.vector.centerOf(util.grid.at(3, 1, 1))); + scene.idle(40); + + Collections.reverse(blocks); + for (BlockPos blockPos : blocks) { + scene.world.destroyBlock(blockPos); + scene.idle(3); + } + + scene.idle(20); + scene.overlay.showText(120) + .text("Fill and Drain speed of the pulley depends entirely on the fluid networks' throughput") + .placeNearTarget() + .colored(PonderPalette.MEDIUM) + .attachKeyFrame() + .pointAt(util.vector.centerOf(util.grid.at(3, 1, 1))); + scene.idle(40); + + } + + public static void level(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("hose_pulley_level", "Fill and Drain level of Hose Pulleys"); + scene.configureBasePlate(0, 0, 3); + scene.setSceneOffsetY(-1.5f); + scene.scaleSceneView(.9f); + scene.showBasePlate(); + + List blocks = new LinkedList<>(); + for (int y = 1; y < 4; y++) { + blocks.add(util.grid.at(1, y, 1)); + blocks.add(util.grid.at(0, y, 1)); + blocks.add(util.grid.at(1, y, 0)); + blocks.add(util.grid.at(2, y, 1)); + blocks.add(util.grid.at(1, y, 2)); + blocks.add(util.grid.at(0, y, 0)); + blocks.add(util.grid.at(2, y, 0)); + blocks.add(util.grid.at(2, y, 2)); + blocks.add(util.grid.at(0, y, 2)); + } + + for (BlockPos blockPos : blocks) + scene.world.setBlock(blockPos, Blocks.WATER.defaultBlockState(), false); + scene.idle(5); + + Selection water = util.select.fromTo(2, 1, 0, 0, 4, 2); + scene.world.showSection(water, Direction.UP); + scene.idle(10); + + Selection cogs = util.select.fromTo(3, 1, 2, 3, 2, 2); + Selection pipes = util.select.fromTo(3, 1, 1, 3, 6, 1) + .add(util.select.position(2, 6, 1)); + BlockPos hosePos = util.grid.at(1, 6, 1); + Selection hose = util.select.position(1, 6, 1); + Selection crank = util.select.position(0, 6, 1); + + ElementLink hoselink = scene.world.showIndependentSection(hose, Direction.DOWN); + scene.world.moveSection(hoselink, util.vector.of(0, -1, 0), 0); + scene.idle(10); + + scene.world.showSectionAndMerge(crank, Direction.EAST, hoselink); + scene.idle(20); + + scene.overlay.showSelectionWithText(util.select.position(hosePos.below()), 50) + .text("While fully retracted, the Hose Pulley cannot operate") + .placeNearTarget() + .colored(PonderPalette.RED) + .attachKeyFrame() + .pointAt(util.vector.blockSurface(hosePos.below(), Direction.UP)); + scene.idle(55); + + Selection kinetics = util.select.fromTo(1, 6, 1, 0, 6, 1); + scene.world.setKineticSpeed(kinetics, 32); + scene.idle(50); + + scene.world.setKineticSpeed(kinetics, 0); + scene.overlay.showText(40) + .text("Draining runs from top to bottom") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.centerOf(hosePos.below(3))); + scene.idle(10); + + scene.world.showSectionAndMerge(cogs, Direction.NORTH, hoselink); + scene.world.showSectionAndMerge(pipes, Direction.WEST, hoselink); + scene.world.multiplyKineticSpeed(util.select.fromTo(3, 1, 2, 3, 2, 1), -1); + scene.world.modifyTileEntity(util.grid.at(1, 6, 1), HosePulleyTileEntity.class, te -> te + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + .ifPresent( + ifh -> ((HosePulleyFluidHandler) ifh).fill(new FluidStack(Fluids.WATER, 100), FluidAction.EXECUTE))); + scene.world.propagatePipeChange(util.grid.at(3, 2, 1)); + + Vector3d surface = util.vector.topOf(1, 3, 1) + .subtract(0, 2 / 8f, 0); + AxisAlignedBB bb = new AxisAlignedBB(surface, surface).inflate(1.5, 0, 1.5); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, bb, bb, 3); + scene.idle(3); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, bb, bb.expandTowards(0, -2, 0), 70); + scene.idle(20); + + Collections.reverse(blocks); + int i = 0; + for (BlockPos blockPos : blocks) { + if (i++ == 18) + break; + scene.world.destroyBlock(blockPos); + scene.idle(3); + } + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, bb, bb.move(0, -2, 0), 60); + scene.overlay.showText(60) + .text("The surface level will end up just below where the hose ends") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.of(0, 2 - 1 / 8f, 1.5f)); + scene.idle(30); + + scene.idle(10); + scene.world.multiplyKineticSpeed(util.select.fromTo(3, 1, 2, 3, 2, 1), -1); + scene.world.propagatePipeChange(util.grid.at(3, 2, 1)); + scene.idle(30); + scene.world.hideSection(water, Direction.SOUTH); + scene.idle(15); + for (BlockPos blockPos : blocks) + scene.world.destroyBlock(blockPos); + scene.world.showSection(water, Direction.UP); + scene.idle(15); + scene.world.setKineticSpeed(kinetics, -32); + scene.idle(16); + scene.world.setKineticSpeed(kinetics, 0); + + scene.overlay.showText(40) + .text("Filling runs from bottom to top") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.centerOf(hosePos.below(3))); + scene.idle(10); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, bb, bb.move(0, -3 + 2 / 8f, 0), 3); + scene.idle(3); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.MEDIUM, bb, bb.expandTowards(0, -3 + 2 / 8f, 0), 120); + scene.idle(20); + + scene.world.setBlock(util.grid.at(1, 3, 1), Blocks.WATER.defaultBlockState(), false); + scene.idle(3); + scene.world.setBlock(util.grid.at(1, 2, 1), Blocks.WATER.defaultBlockState(), false); + scene.idle(3); + + Collections.reverse(blocks); + for (BlockPos blockPos : blocks) { + scene.world.setBlock(blockPos, Blocks.WATER.defaultBlockState(), false); + scene.idle(3); + } + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, bb, bb, 100); + scene.overlay.showText(100) + .text("The filled pool will not grow beyond the layer above the hose end") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.of(0, 4 - 1 / 8f, 1.5f)); + scene.idle(80); + } + + 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.setSceneOffsetY(-.5f); + scene.scaleSceneView(.9f); + scene.showBasePlate(); + scene.idle(5); + + Selection tank = util.select.fromTo(4, 1, 1, 4, 3, 1); + Selection pipes = util.select.fromTo(3, 1, 1, 2, 3, 2); + Selection kinetics = util.select.fromTo(5, 1, 2, 4, 2, 2) + .add(util.select.position(5, 0, 2)); + Selection hose = util.select.fromTo(1, 3, 2, 0, 3, 2); + BlockPos pumpPos = util.grid.at(3, 2, 2); + + scene.world.showSection(hose, Direction.UP); + scene.idle(5); + scene.world.showSection(tank, Direction.DOWN); + scene.idle(10); + scene.world.showSection(pipes, Direction.NORTH); + scene.idle(5); + scene.world.showSection(kinetics, Direction.DOWN); + scene.idle(10); + + scene.world.setKineticSpeed(hose, 32); + scene.idle(10); + + Vector3d entryPoint = util.vector.topOf(1, 0, 2); + scene.overlay.showText(60) + .text("When deploying the Hose Pulley into a large enough ocean...") + .attachKeyFrame() + .placeNearTarget() + .pointAt(entryPoint); + + scene.idle(40); + scene.world.setKineticSpeed(hose, 0); + scene.world.multiplyKineticSpeed(util.select.everywhere(), -1); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationDirectionIndicator(pumpPos); + scene.idle(30); + + Selection pulleyPos = util.select.position(1, 3, 2); + scene.overlay.showSelectionWithText(pulleyPos, 60) + .text("It will provide/dispose fluids without affecting the source") + .attachKeyFrame() + .colored(PonderPalette.BLUE) + .placeNearTarget() + .pointAt(util.vector.topOf(util.grid.at(1, 3, 2))); + + scene.idle(80); + scene.overlay.showText(60) + .text("Pipe networks can limitlessly take fluids from/to such pulleys") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(3, 2, 2), Direction.WEST)); + scene.idle(40); + } + +} 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..8f84ac781 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/PipeScenes.java @@ -0,0 +1,603 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllFluids; +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.pipes.FluidValveBlock; +import com.simibubi.create.content.contraptions.fluids.pipes.FluidValveTileEntity; +import com.simibubi.create.content.contraptions.fluids.pipes.GlassFluidPipeBlock; +import com.simibubi.create.content.contraptions.fluids.pipes.SmartFluidPipeTileEntity; +import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; +import com.simibubi.create.content.contraptions.processing.BasinTileEntity; +import com.simibubi.create.foundation.fluid.FluidHelper; +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.item.Items; +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.common.ForgeMod; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +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() + .setValue(FluidPipeBlock.UP, false) + .setValue(FluidPipeBlock.DOWN, false); + + scene.world.setBlock(util.grid.at(2, 1, 1), pipeState.setValue(FluidPipeBlock.NORTH, false) + .setValue(FluidPipeBlock.SOUTH, false), false); + scene.world.setBlock(util.grid.at(1, 1, 2), pipeState.setValue(FluidPipeBlock.WEST, false) + .setValue(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).inflate(1 / 6f); + AxisAlignedBB bb1 = bb.move(-0.5, 0, 0); + AxisAlignedBB bb2 = bb.move(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() + .setValue(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.defaultBlockState(), 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.defaultBlockState(), false); + scene.idle(5); + scene.world.setBlock(util.grid.at(3, 1, 3), AllBlocks.GLASS_FLUID_PIPE.getDefaultState() + .setValue(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.defaultBlockState(), 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.defaultBlockState(), 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.defaultBlockState() + .setValue(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.defaultBlockState() + .setValue(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() + .setValue(FluidPipeBlock.SOUTH, true) + .setValue(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.setValue(FluidPipeBlock.EAST, false) + .setValue(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.PROPERTY_BY_DIRECTION.values()) + defaultState = defaultState.setValue(booleanProperty, false); + + scene.world.setBlock(util.grid.at(3, 2, 1), defaultState.setValue(FluidPipeBlock.EAST, true) + .setValue(FluidPipeBlock.WEST, true), false); + scene.world.setBlock(util.grid.at(1, 2, 1), defaultState.setValue(FluidPipeBlock.UP, true) + .setValue(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.setValue(FluidPipeBlock.UP, true) + .setValue(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.showBasePlate(); + + Selection cogs = util.select.fromTo(5, 0, 2, 5, 1, 2); + Selection tank1 = util.select.fromTo(3, 1, 3, 3, 2, 3); + Selection tank2 = util.select.fromTo(1, 1, 3, 1, 2, 3); + BlockPos valvePos = util.grid.at(2, 1, 1); + BlockPos handlePos = util.grid.at(2, 2, 1); + BlockPos pumpPos = util.grid.at(4, 1, 2); + Selection pipes1 = util.select.fromTo(4, 1, 3, 4, 1, 1); + Selection pipes2 = util.select.fromTo(3, 1, 1, 1, 1, 1); + Selection pipes3 = util.select.fromTo(0, 1, 1, 0, 1, 3); + + scene.world.setKineticSpeed(pipes1, 0); + scene.world.propagatePipeChange(pumpPos); + scene.world.setBlock(valvePos, AllBlocks.FLUID_PIPE.get() + .getAxisState(Axis.X), false); + scene.world.setBlock(util.grid.at(3, 1, 1), Blocks.AIR.defaultBlockState(), false); + scene.world.setBlock(util.grid.at(3, 1, 1), AllBlocks.GLASS_FLUID_PIPE.getDefaultState() + .setValue(GlassFluidPipeBlock.AXIS, Axis.X), false); + + scene.idle(5); + scene.world.showSection(tank1, Direction.NORTH); + scene.idle(5); + scene.world.showSection(tank2, Direction.NORTH); + scene.idle(10); + scene.world.showSection(pipes1, Direction.WEST); + scene.idle(5); + scene.world.showSection(pipes2, Direction.SOUTH); + scene.idle(5); + scene.world.showSection(pipes3, Direction.EAST); + scene.idle(15); + + scene.world.destroyBlock(valvePos); + scene.world.restoreBlocks(util.select.position(valvePos)); + + scene.overlay.showText(60) + .placeNearTarget() + .text("Valve pipes help control fluids propagating through pipe networks") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(valvePos, Direction.WEST)); + scene.idle(75); + + scene.world.showSection(cogs, Direction.WEST); + scene.idle(10); + scene.world.setKineticSpeed(util.select.position(pumpPos), 64); + scene.world.propagatePipeChange(pumpPos); + + scene.overlay.showText(60) + .placeNearTarget() + .text("Their shaft input controls whether fluid is currently allowed through") + .attachKeyFrame() + .pointAt(util.vector.topOf(valvePos)); + scene.idle(60); + scene.world.showSection(util.select.position(handlePos), Direction.DOWN); + scene.idle(15); + + Selection valveKinetics = util.select.fromTo(2, 1, 1, 2, 2, 1); + scene.world.setKineticSpeed(valveKinetics, 16); + scene.effects.rotationSpeedIndicator(handlePos); + scene.world.modifyTileEntity(valvePos, FluidValveTileEntity.class, te -> te.onSpeedChanged(0)); + scene.idle(22); + scene.world.modifyBlock(valvePos, s -> s.setValue(FluidValveBlock.ENABLED, true), false); + scene.effects.indicateSuccess(valvePos); + scene.idle(5); + scene.world.setKineticSpeed(valveKinetics, 0); + + scene.overlay.showText(60) + .placeNearTarget() + .text("Given Rotational Force in the opening direction, the valve will open up") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(valvePos, Direction.NORTH)); + scene.idle(90); + + scene.overlay.showText(50) + .placeNearTarget() + .text("It can be closed again by reversing the input rotation") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(valvePos, Direction.NORTH)); + scene.idle(40); + + scene.world.setKineticSpeed(valveKinetics, -16); + scene.effects.rotationSpeedIndicator(handlePos); + scene.world.modifyTileEntity(valvePos, FluidValveTileEntity.class, te -> te.onSpeedChanged(0)); + scene.idle(22); + scene.world.modifyBlock(valvePos, s -> s.setValue(FluidValveBlock.ENABLED, false), false); + scene.effects.indicateRedstone(valvePos); + scene.world.propagatePipeChange(pumpPos); + scene.idle(5); + scene.world.setKineticSpeed(valveKinetics, 0); + } + + public static void smart(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("smart_pipe", "Controlling Fluid flow using Smart Pipes"); + scene.configureBasePlate(1, 0, 5); + scene.showBasePlate(); + scene.idle(5); + + Selection tank1 = util.select.fromTo(4, 1, 3, 4, 2, 3); + Selection tank2 = util.select.fromTo(4, 1, 4, 4, 2, 4); + Selection additionalPipes = util.select.fromTo(3, 1, 4, 1, 1, 4); + Selection mainPipes = util.select.fromTo(3, 1, 3, 1, 1, 1); + Selection kinetics1 = util.select.fromTo(0, 0, 2, 0, 0, 5); + Selection kinetics2 = util.select.position(1, 0, 5); + BlockPos basinPos = util.grid.at(4, 1, 1); + BlockPos pumpPos = util.grid.at(1, 1, 2); + Selection pump = util.select.position(1, 1, 2); + Selection basin = util.select.position(basinPos); + BlockPos smartPos = util.grid.at(3, 1, 1); + + scene.world.modifyTileEntity(basinPos, BasinTileEntity.class, + te -> te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + .ifPresent(ifh -> ifh.fill(new FluidStack(ForgeMod.MILK.get(), 1000), FluidAction.EXECUTE))); + + scene.world.setBlock(util.grid.at(3, 1, 3), AllBlocks.FLUID_PIPE.get() + .getAxisState(Axis.X), false); + scene.world.setBlock(smartPos, AllBlocks.FLUID_PIPE.get() + .getAxisState(Axis.X), false); + scene.world.setBlock(util.grid.at(2, 1, 3), AllBlocks.GLASS_FLUID_PIPE.getDefaultState() + .setValue(GlassFluidPipeBlock.AXIS, Axis.X), false); + scene.world.setBlock(util.grid.at(1, 1, 3), AllBlocks.FLUID_PIPE.get() + .getAxisState(Axis.X) + .setValue(FluidPipeBlock.NORTH, true) + .setValue(FluidPipeBlock.WEST, false), false); + + scene.world.showSection(basin, Direction.DOWN); + scene.idle(5); + scene.world.showSection(tank1, Direction.DOWN); + scene.idle(5); + scene.world.showSection(mainPipes, Direction.EAST); + scene.idle(15); + + scene.world.destroyBlock(smartPos); + scene.world.restoreBlocks(util.select.position(smartPos)); + + Vector3d filterVec = util.vector.topOf(smartPos) + .subtract(0.25, 0, 0); + scene.overlay.showText(50) + .placeNearTarget() + .text("Smart pipes can help control flows by fluid type") + .attachKeyFrame() + .pointAt(filterVec); + scene.idle(60); + + scene.overlay.showSelectionWithText(util.select.position(basinPos), 80) + .placeNearTarget() + .colored(PonderPalette.GREEN) + .text("When placed directly at the source, they can specify the type of fluid to extract") + .attachKeyFrame() + .pointAt(filterVec); + scene.idle(90); + + FluidStack chocolate = new FluidStack(FluidHelper.convertToStill(AllFluids.CHOCOLATE.get()), 1000); + ItemStack bucket = AllFluids.CHOCOLATE.get() + .getAttributes() + .getBucket(chocolate); + ItemStack milkBucket = new ItemStack(Items.MILK_BUCKET); + scene.overlay.showControls(new InputWindowElement(filterVec, Pointing.DOWN).rightClick() + .withItem(bucket), 80); + scene.idle(7); + scene.world.setFilterData(util.select.position(3, 1, 1), SmartFluidPipeTileEntity.class, bucket); + scene.idle(10); + scene.overlay.showText(60) + .placeNearTarget() + .attachKeyFrame() + .text("Simply Right-Click their filter slot with any item containing the desired fluid") + .pointAt(filterVec); + scene.idle(50); + + scene.world.showSection(kinetics2, Direction.WEST); + scene.world.setKineticSpeed(kinetics2, 64); + scene.idle(5); + scene.world.showSection(kinetics1, Direction.EAST); + scene.world.setKineticSpeed(kinetics1, -64); + scene.idle(10); + scene.world.setKineticSpeed(pump, 128); + scene.world.propagatePipeChange(pumpPos); + scene.idle(120); + scene.world.setKineticSpeed(util.select.everywhere(), 0); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationSpeedIndicator(pumpPos); + scene.idle(15); + scene.world.showSection(tank2, Direction.DOWN); + scene.world.showSection(additionalPipes, Direction.NORTH); + scene.world.setBlock(util.grid.at(3, 1, 1), AllBlocks.FLUID_PIPE.get() + .getAxisState(Axis.X), true); + scene.idle(10); + for (int i = 0; i < 3; i++) { + BlockPos pos = util.grid.at(1 + i, 1, 3); + scene.world.destroyBlock(pos); + scene.world.restoreBlocks(util.select.position(pos)); + scene.idle(2); + } + scene.idle(15); + scene.world.modifyTileEntity(basinPos, BasinTileEntity.class, + te -> te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + .ifPresent(ifh -> ifh.fill(chocolate, FluidAction.EXECUTE))); + scene.idle(10); + + scene.overlay.showText(80) + .placeNearTarget() + .colored(PonderPalette.GREEN) + .text("When placed further down a pipe network, smart pipes will only let matching fluids continue") + .attachKeyFrame() + .pointAt(filterVec.add(-1, 0, 2)); + scene.idle(90); + + scene.overlay.showControls(new InputWindowElement(filterVec.add(-1, 0, 3), Pointing.DOWN).rightClick() + .withItem(milkBucket), 30); + scene.idle(7); + scene.world.setFilterData(util.select.position(2, 1, 4), SmartFluidPipeTileEntity.class, milkBucket); + scene.idle(30); + + scene.overlay.showControls(new InputWindowElement(filterVec.add(-1, 0, 2), Pointing.DOWN).rightClick() + .withItem(bucket), 30); + scene.idle(7); + scene.world.setFilterData(util.select.position(2, 1, 3), SmartFluidPipeTileEntity.class, bucket); + scene.idle(30); + + scene.world.setKineticSpeed(kinetics2, 64); + scene.world.setKineticSpeed(kinetics1, -64); + scene.world.setKineticSpeed(pump, 128); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationSpeedIndicator(pumpPos); + scene.idle(40); + } + +} 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..6c1a89f4f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/PumpScenes.java @@ -0,0 +1,341 @@ +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.pipes.FluidPipeBlock; +import com.simibubi.create.content.contraptions.fluids.pipes.GlassFluidPipeBlock; +import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; +import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; +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.utility.Pointing; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +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.capability.IFluidHandler.FluidAction; + +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.showBasePlate(); + scene.world.multiplyKineticSpeed(util.select.everywhere(), -1); + scene.idle(5); + + BlockPos pumpPos = util.grid.at(2, 1, 1); + Selection tank1 = util.select.fromTo(0, 2, 3, 0, 1, 3); + Selection tank2 = util.select.fromTo(4, 2, 3, 4, 1, 3); + Selection pipes = util.select.fromTo(3, 1, 3, 1, 1, 1); + Selection largeCog = util.select.position(5, 0, 1); + Selection kinetics = util.select.fromTo(5, 1, 0, 2, 1, 0); + BlockPos leverPos = util.grid.at(4, 2, 0); + Selection pump = util.select.position(pumpPos); + + scene.world.setBlock(pumpPos, AllBlocks.FLUID_PIPE.get() + .getAxisState(Axis.X), false); + + scene.world.showSection(tank1, Direction.DOWN); + scene.idle(5); + scene.world.showSection(tank2, Direction.DOWN); + scene.idle(5); + scene.world.showSection(pipes, Direction.NORTH); + scene.idle(15); + + scene.world.destroyBlock(pumpPos); + scene.world.restoreBlocks(pump); + scene.world.setKineticSpeed(pump, 0); + + scene.idle(15); + + scene.overlay.showText(60) + .text("Mechanical Pumps govern the flow of their attached pipe networks") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(pumpPos)); + + scene.idle(70); + scene.world.showSection(largeCog, Direction.UP); + scene.idle(5); + scene.world.showSection(kinetics, Direction.SOUTH); + scene.world.showSection(util.select.position(leverPos), Direction.SOUTH); + scene.idle(10); + scene.world.setKineticSpeed(pump, 64); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationDirectionIndicator(pumpPos.north()); + scene.idle(15); + + scene.overlay.showText(60) + .text("When powered, their arrow indicates the direction of flow") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(pumpPos) + .subtract(0.5f, 0.125f, 0)); + + AxisAlignedBB bb1 = new AxisAlignedBB(Vector3d.ZERO, Vector3d.ZERO).inflate(.25, .25, 0) + .move(0, 0, .25); + AxisAlignedBB bb2 = new AxisAlignedBB(Vector3d.ZERO, Vector3d.ZERO).inflate(.25, .25, 1.25); + scene.idle(65); + + Object in = new Object(); + Object out = new Object(); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, bb1.move(util.vector.centerOf(3, 1, 3)), 3); + scene.idle(2); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, bb2.move(util.vector.centerOf(3, 1, 2)), 50); + scene.idle(10); + + scene.overlay.showText(50) + .text("The network behind is now pulling fluids...") + .attachKeyFrame() + .placeNearTarget() + .colored(PonderPalette.INPUT) + .pointAt(util.vector.centerOf(3, 1, 2)); + + scene.idle(60); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, bb1.move(util.vector.centerOf(1, 1, 1) + .add(0, 0, -.5)), 3); + scene.idle(2); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, bb2.move(util.vector.centerOf(1, 1, 2)), 50); + scene.idle(10); + + scene.overlay.showText(50) + .text("...while the network in front is transferring it outward") + .placeNearTarget() + .colored(PonderPalette.OUTPUT) + .pointAt(util.vector.centerOf(1, 1, 2)); + + scene.idle(70); + scene.world.toggleRedstonePower(util.select.fromTo(4, 2, 0, 4, 1, 0)); + scene.effects.indicateRedstone(leverPos); + scene.world.multiplyKineticSpeed(util.select.fromTo(3, 1, 0, 2, 1, 1), -1); + scene.effects.rotationDirectionIndicator(pumpPos.north()); + scene.world.propagatePipeChange(pumpPos); + scene.idle(15); + + scene.overlay.showText(70) + .text("Reversing the input rotation reverses the direction of flow") + .placeNearTarget() + .attachKeyFrame() + .pointAt(util.vector.topOf(pumpPos) + .subtract(0.5f, 0.125f, 0)); + + scene.idle(25); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, bb1.move(util.vector.centerOf(1, 1, 3)), 3); + scene.idle(2); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, bb2.move(util.vector.centerOf(1, 1, 2)), 30); + scene.idle(15); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, bb1.move(util.vector.centerOf(3, 1, 1) + .add(0, 0, -.5)), 3); + scene.idle(2); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, bb2.move(util.vector.centerOf(3, 1, 2)), 30); + scene.idle(55); + + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(pumpPos), Pointing.DOWN).rightClick() + .withWrench(), 40); + scene.idle(7); + scene.world.modifyBlock(pumpPos, s -> s.setValue(PumpBlock.FACING, Direction.EAST), true); + scene.overlay.showText(70) + .attachKeyFrame() + .pointAt(util.vector.centerOf(2, 1, 1)) + .placeNearTarget() + .text("Use a Wrench to reverse the orientation of pumps manually"); + scene.world.propagatePipeChange(pumpPos); + scene.idle(40); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, bb1.move(util.vector.centerOf(3, 1, 3)), 3); + scene.idle(2); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, bb2.move(util.vector.centerOf(3, 1, 2)), 30); + scene.idle(15); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, bb1.move(util.vector.centerOf(1, 1, 1) + .add(0, 0, -.5)), 3); + scene.idle(2); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, bb2.move(util.vector.centerOf(1, 1, 2)), 30); + scene.idle(25); + + } + + public static void speed(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_pump_speed", "Throughput of Mechanical Pumps"); + scene.configureBasePlate(0, 0, 5); + scene.showBasePlate(); + scene.idle(5); +// scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + Selection largeCog = util.select.position(5, 0, 3); + Selection cogs = util.select.fromTo(5, 1, 4, 2, 1, 4) + .add(util.select.position(2, 1, 3)); + BlockPos pumpPos = util.grid.at(2, 1, 2); + Selection pump = util.select.position(pumpPos); + Selection tank1 = util.select.fromTo(4, 1, 2, 4, 2, 2); + Selection tank2 = util.select.fromTo(0, 1, 2, 0, 2, 2); + Selection megapipe1 = util.select.fromTo(0, 3, 5, 1, 4, 2); + Selection megapipe2 = util.select.fromTo(3, 3, 1, 5, 6, 2); + + scene.world.modifyTileEntity(util.grid.at(0, 1, 2), FluidTankTileEntity.class, te -> te.getTankInventory() + .drain(3000, FluidAction.EXECUTE)); + + BlockPos east = pumpPos.east(); + scene.world.setBlock(east, Blocks.AIR.defaultBlockState(), false); + scene.world.setBlock(east, AllBlocks.GLASS_FLUID_PIPE.getDefaultState() + .setValue(GlassFluidPipeBlock.AXIS, Axis.X), false); + + scene.world.setBlock(pumpPos.south(), AllBlocks.COGWHEEL.getDefaultState() + .setValue(CogWheelBlock.AXIS, Axis.X), false); + Selection southPump = util.select.position(pumpPos.south()); + scene.world.setKineticSpeed(southPump, 32); + + scene.world.setKineticSpeed(pump, 0); + scene.world.showSection(pump, Direction.DOWN); + scene.idle(10); + ElementLink mp1 = scene.world.showIndependentSection(megapipe1, Direction.EAST); + scene.world.moveSection(mp1, util.vector.of(0, -3, 0), 0); + scene.idle(5); + ElementLink mp2 = scene.world.showIndependentSection(megapipe2, Direction.WEST); + scene.world.moveSection(mp2, util.vector.of(0, -3, 0), 0); + scene.idle(15); + + scene.overlay.showText(70) + .attachKeyFrame() + .pointAt(util.vector.topOf(pumpPos)) + .placeNearTarget() + .text("Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away"); + scene.idle(75); + + scene.world.hideIndependentSection(mp1, Direction.WEST); + scene.idle(5); + scene.world.hideIndependentSection(mp2, Direction.EAST); + scene.idle(15); + + scene.world.showSection(tank1, Direction.DOWN); + scene.idle(2); + scene.world.showSection(util.select.position(east), Direction.DOWN); + scene.idle(5); + BlockPos west = pumpPos.west(); + scene.world.showSection(util.select.position(west), Direction.DOWN); + scene.idle(2); + scene.world.showSection(tank2, Direction.DOWN); + scene.idle(5); + + scene.world.showSection(largeCog, Direction.UP); + scene.world.showSection(cogs, Direction.SOUTH); + scene.idle(10); + scene.world.setKineticSpeed(util.select.position(pumpPos), -32); + scene.effects.rotationSpeedIndicator(pumpPos); + scene.world.propagatePipeChange(pumpPos); + scene.idle(40); + + scene.world.multiplyKineticSpeed(util.select.everywhere(), 4); + scene.effects.rotationSpeedIndicator(pumpPos); + scene.world.propagatePipeChange(pumpPos); + scene.idle(20); + + scene.overlay.showText(60) + .attachKeyFrame() + .pointAt(util.vector.topOf(pumpPos)) + .placeNearTarget() + .text("Speeding up the input rotation changes the speed of flow propagation..."); + scene.idle(70); + + scene.overlay.showText(50) + .pointAt(util.vector.blockSurface(util.grid.at(0, 1, 2), Direction.WEST)) + .placeNearTarget() + .text("...aswell as how quickly fluids are transferred"); + scene.idle(60); + + BlockState pipeState = AllBlocks.FLUID_PIPE.getDefaultState() + .setValue(FluidPipeBlock.DOWN, false) + .setValue(FluidPipeBlock.UP, false); + scene.world.setKineticSpeed(util.select.everywhere(), 0); + scene.idle(10); + + scene.world.setBlock(east, pipeState, true); + scene.world.setBlock(west, pipeState, true); + + scene.world.setBlock(east.north(), pipeState.setValue(FluidPipeBlock.NORTH, false) + .setValue(FluidPipeBlock.EAST, false), false); + scene.world.setBlock(east.south(), pipeState.setValue(FluidPipeBlock.SOUTH, false) + .setValue(FluidPipeBlock.EAST, false), false); + scene.world.showSection(util.select.position(east.north()), Direction.DOWN); + scene.world.showSection(util.select.position(east.south()), Direction.DOWN); + Selection northPump = util.select.position(pumpPos.north()); + + scene.world.setBlock(west.north(), pipeState.setValue(FluidPipeBlock.NORTH, false) + .setValue(FluidPipeBlock.WEST, false), false); + scene.world.setBlock(west.south(), pipeState.setValue(FluidPipeBlock.SOUTH, false) + .setValue(FluidPipeBlock.WEST, false), false); + scene.world.showSection(util.select.position(west.north()), Direction.DOWN); + scene.world.showSection(util.select.position(west.south()), Direction.DOWN); + + scene.world.restoreBlocks(southPump); + scene.world.modifyBlock(pumpPos.south(), s -> s.setValue(PumpBlock.FACING, Direction.EAST), false); + scene.world.setKineticSpeed(util.select.everywhere(), 0); + scene.world.showSection(northPump, Direction.DOWN); + scene.world.modifyBlock(pumpPos.north(), s -> s.setValue(PumpBlock.FACING, Direction.EAST), false); + scene.idle(4); + + scene.world.setKineticSpeed(util.select.everywhere(), -16); + scene.world.setKineticSpeed(northPump, 16); + scene.world.setKineticSpeed(southPump, 16); + scene.world.setKineticSpeed(largeCog, 8); + scene.idle(20); + + scene.overlay.showSelectionWithText(util.select.fromTo(2, 1, 1, 2, 1, 3), 60) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .pointAt(util.vector.topOf(pumpPos)) + .placeNearTarget() + .text("Pumps can combine their throughputs within shared pipe networks"); + scene.idle(70); + + scene.overlay + .showControls(new InputWindowElement(util.vector.topOf(pumpPos.south()), Pointing.DOWN).rightClick() + .withWrench(), 30); + scene.idle(7); + scene.world.modifyBlock(pumpPos.south(), s -> s.setValue(PumpBlock.FACING, Direction.WEST), true); + scene.idle(30); + scene.overlay + .showControls(new InputWindowElement(util.vector.topOf(pumpPos.north()), Pointing.DOWN).rightClick() + .withWrench(), 30); + scene.idle(7); + scene.world.modifyBlock(pumpPos.north(), s -> s.setValue(PumpBlock.FACING, Direction.WEST), true); + scene.idle(30); + + scene.overlay.showText(70) + .attachKeyFrame() + .pointAt(util.vector.topOf(pumpPos.north()) + .subtract(0.5f, 0.125f, 0)) + .placeNearTarget() + .text("Alternating their orientation can help align their flow directions"); + scene.idle(40); + + scene.world.multiplyKineticSpeed(util.select.everywhere(), 8); + scene.effects.rotationSpeedIndicator(pumpPos); + scene.effects.rotationSpeedIndicator(pumpPos.north()); + scene.effects.rotationSpeedIndicator(pumpPos.south()); + scene.world.propagatePipeChange(pumpPos); + scene.world.propagatePipeChange(pumpPos.north()); + scene.world.propagatePipeChange(pumpPos.south()); + scene.idle(100); + + scene.world.multiplyKineticSpeed(util.select.everywhere(), -1); + scene.effects.rotationSpeedIndicator(pumpPos); + scene.effects.rotationSpeedIndicator(pumpPos.north()); + scene.effects.rotationSpeedIndicator(pumpPos.south()); + scene.world.propagatePipeChange(pumpPos); + scene.world.propagatePipeChange(pumpPos.north()); + scene.world.propagatePipeChange(pumpPos.south()); + } + +} 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..e28dbe06d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/SpoutScenes.java @@ -0,0 +1,176 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.AllFluids; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.fluids.FluidFX; +import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity; +import com.simibubi.create.foundation.fluid.FluidHelper; +import com.simibubi.create.foundation.gui.AllIcons; +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.BeltItemElement; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction.Emitter; +import com.simibubi.create.foundation.utility.Pointing; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.particles.IParticleData; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.fluids.FluidStack; + +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.showBasePlate(); + 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 largeCog = util.select.position(3, 0, 5); + Selection kinetics = util.select.fromTo(2, 1, 5, 2, 2, 3); + Selection tank = util.select.fromTo(1, 1, 4, 1, 2, 4); + Selection pipes = util.select.fromTo(1, 3, 4, 2, 3, 3); + + Selection spoutS = util.select.position(2, 3, 2); + BlockPos spoutPos = util.grid.at(2, 3, 2); + BlockPos depotPos = util.grid.at(2, 1, 1); + scene.world.showSection(spoutS, Direction.DOWN); + scene.idle(10); + + Vector3d spoutSide = util.vector.blockSurface(spoutPos, Direction.WEST); + scene.overlay.showText(60) + .pointAt(spoutSide) + .placeNearTarget() + .attachKeyFrame() + .text("The Spout can fill fluid holding items provided beneath it"); + + scene.idle(50); + + scene.world.showSection(tank, Direction.DOWN); + scene.idle(5); + scene.world.showSection(largeCog, Direction.UP); + scene.world.showSection(kinetics, Direction.NORTH); + scene.world.showSection(pipes, Direction.NORTH); + + scene.idle(20); + FluidStack honey = new FluidStack(FluidHelper.convertToStill(AllFluids.HONEY.get()), 1000); + ItemStack bucket = AllFluids.HONEY.get() + .getAttributes() + .getBucket(honey); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.NORTH), Pointing.RIGHT) + .showing(AllIcons.I_MTD_CLOSE) + .withItem(bucket), + 40); + scene.idle(7); + scene.overlay.showSelectionWithText(util.select.position(2, 3, 2), 50) + .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.WEST)) + .attachKeyFrame() + .colored(PonderPalette.RED) + .placeNearTarget() + .text("The content of a Spout cannot be accessed manually"); + scene.idle(60); + scene.overlay.showText(70) + .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 3), Direction.WEST)) + .colored(PonderPalette.GREEN) + .placeNearTarget() + .text("Instead, Pipes can be used to supply it with fluids"); + + scene.idle(90); + scene.overlay.showText(60) + .pointAt(spoutSide.subtract(0, 2, 0)) + .attachKeyFrame() + .placeNearTarget() + .text("The Input items can be placed on a Depot under the Spout"); + scene.idle(50); + ItemStack bottle = new ItemStack(Items.GLASS_BOTTLE); + scene.world.createItemOnBeltLike(depotPos, Direction.NORTH, bottle); + Vector3d depotCenter = util.vector.centerOf(depotPos.south()); + scene.overlay.showControls(new InputWindowElement(depotCenter, Pointing.UP).withItem(bottle), 30); + scene.idle(10); + + scene.idle(20); + scene.world.modifyTileNBT(spoutS, SpoutTileEntity.class, nbt -> nbt.putInt("ProcessingTicks", 20)); + scene.idle(20); + scene.world.removeItemsFromBelt(depotPos); + ItemStack potion = new ItemStack(Items.HONEY_BOTTLE); + scene.world.createItemOnBeltLike(depotPos, Direction.UP, potion); + IParticleData fluidParticle = FluidFX.getFluidParticle(new FluidStack(AllFluids.HONEY.get(), 1000)); + for (int i = 0; i < 10; i++) { + scene.effects.emitParticles(util.vector.topOf(depotPos.south()) + .add(0, 1 / 16f, 0), + Emitter.simple(fluidParticle, VecHelper.offsetRandomly(Vector3d.ZERO, Create.RANDOM, .1f)), 1, 1); + } + scene.idle(10); + scene.overlay.showControls(new InputWindowElement(depotCenter, Pointing.UP).withItem(potion), 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, bottle); + scene.idle(15); + ElementLink ingot2 = scene.world.createItemOnBelt(beltPos, Direction.SOUTH, bottle); + scene.idle(15); + scene.world.stallBeltItem(ingot, true); + scene.world.modifyTileNBT(spoutS, SpoutTileEntity.class, nbt -> nbt.putInt("ProcessingTicks", 20)); + + scene.overlay.showText(50) + .pointAt(spoutSide) + .placeNearTarget() + .attachKeyFrame() + .text("The Spout will hold and process them automatically"); + + scene.idle(20); + for (int i = 0; i < 10; i++) { + scene.effects.emitParticles(util.vector.topOf(depotPos.south()) + .add(0, 1 / 16f, 0), + Emitter.simple(fluidParticle, VecHelper.offsetRandomly(Vector3d.ZERO, Create.RANDOM, .1f)), 1, 1); + } + scene.world.removeItemsFromBelt(spoutPos.below(2)); + ingot = scene.world.createItemOnBelt(spoutPos.below(2), Direction.UP, potion); + scene.world.stallBeltItem(ingot, true); + scene.idle(5); + scene.world.stallBeltItem(ingot, false); + scene.idle(15); + scene.world.stallBeltItem(ingot2, true); + scene.world.modifyTileNBT(spoutS, SpoutTileEntity.class, nbt -> nbt.putInt("ProcessingTicks", 20)); + scene.idle(20); + for (int i = 0; i < 10; i++) { + scene.effects.emitParticles(util.vector.topOf(depotPos.south()) + .add(0, 1 / 16f, 0), + Emitter.simple(fluidParticle, VecHelper.offsetRandomly(Vector3d.ZERO, Create.RANDOM, .1f)), 1, 1); + } + scene.world.removeItemsFromBelt(spoutPos.below(2)); + ingot2 = scene.world.createItemOnBelt(spoutPos.below(2), Direction.UP, potion); + scene.world.stallBeltItem(ingot2, true); + scene.idle(5); + scene.world.stallBeltItem(ingot2, false); + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/AnimatedSceneElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/AnimatedSceneElement.java index d4c619e61..3adc64113 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/AnimatedSceneElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/AnimatedSceneElement.java @@ -1,8 +1,8 @@ package com.simibubi.create.foundation.ponder.elements; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.ponder.PonderWorld; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -34,33 +34,33 @@ public abstract class AnimatedSceneElement extends PonderSceneElement { @Override public final void renderFirst(PonderWorld world, IRenderTypeBuffer buffer, MatrixStack ms, float pt) { - ms.push(); + ms.pushPose(); float currentFade = applyFade(ms, pt); renderFirst(world, buffer, ms, currentFade, pt); - ms.pop(); + ms.popPose(); } @Override public final void renderLayer(PonderWorld world, IRenderTypeBuffer buffer, RenderType type, MatrixStack ms, float pt) { - ms.push(); + ms.pushPose(); float currentFade = applyFade(ms, pt); renderLayer(world, buffer, type, ms, currentFade, pt); - ms.pop(); + ms.popPose(); } @Override public final void renderLast(PonderWorld world, IRenderTypeBuffer buffer, MatrixStack ms, float pt) { - ms.push(); + ms.pushPose(); float currentFade = applyFade(ms, pt); renderLast(world, buffer, ms, currentFade, pt); - ms.pop(); + ms.popPose(); } protected float applyFade(MatrixStack ms, float pt) { float currentFade = fade.getValue(pt); if (fadeVec != null) - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .translate(fadeVec.scale(-1 + currentFade)); return currentFade; } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/InputWindowElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/InputWindowElement.java index f87c70c28..efcfbeaab 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/InputWindowElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/InputWindowElement.java @@ -3,24 +3,25 @@ package com.simibubi.create.foundation.ponder.elements; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllItems; +import com.simibubi.create.Create; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.ponder.PonderLocalization; import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.content.PonderPalette; -import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Pointing; import net.minecraft.client.gui.FontRenderer; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.vector.Vector2f; import net.minecraft.util.math.vector.Vector3d; public class InputWindowElement extends AnimatedOverlayElement { private Pointing direction; - String key; + ResourceLocation key; AllIcons icon; ItemStack item = ItemStack.EMPTY; private Vector3d sceneSpace; @@ -57,7 +58,7 @@ public class InputWindowElement extends AnimatedOverlayElement { icon = AllIcons.I_RMB; return this; } - + public InputWindowElement showing(AllIcons icon) { this.icon = icon; return this; @@ -69,12 +70,12 @@ public class InputWindowElement extends AnimatedOverlayElement { } public InputWindowElement whileSneaking() { - key = "sneak_and"; + key = Create.asResource("sneak_and"); return this; } public InputWindowElement whileCTRL() { - key = "ctrl_and"; + key = Create.asResource("ctrl_and"); return this; } @@ -106,7 +107,7 @@ public class InputWindowElement extends AnimatedOverlayElement { } if (hasText) { - keyWidth = font.getStringWidth(text); + keyWidth = font.width(text); width += keyWidth; } @@ -115,7 +116,7 @@ public class InputWindowElement extends AnimatedOverlayElement { height = 24; } - ms.push(); + ms.pushPose(); ms.translate(sceneToScreen.x + xFade, sceneToScreen.y + yFade, 400); PonderUI.renderSpeechBox(ms, 0, 0, width, height, false, direction, true); @@ -123,15 +124,15 @@ public class InputWindowElement extends AnimatedOverlayElement { ms.translate(0, 0, 100); if (hasText) - font.draw(ms, text, 2, (height - font.FONT_HEIGHT) / 2f + 2, - ColorHelper.applyAlpha(PonderPalette.WHITE.getColor(), fade)); + font.draw(ms, text, 2, (height - font.lineHeight) / 2f + 2, + PonderPalette.WHITE.getColorObject().scaleAlpha(fade).getRGB()); if (hasIcon) { - ms.push(); + ms.pushPose(); ms.translate(keyWidth, 0, 0); ms.scale(1.5f, 1.5f, 1.5f); icon.draw(ms, screen, 0, 0); - ms.pop(); + ms.popPose(); } if (hasItem) { @@ -142,7 +143,7 @@ public class InputWindowElement extends AnimatedOverlayElement { RenderSystem.disableDepthTest(); } - ms.pop(); + ms.popPose(); } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/MinecartElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/MinecartElement.java index 93c0be467..d088ba165 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/MinecartElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/MinecartElement.java @@ -1,9 +1,9 @@ package com.simibubi.create.foundation.ponder.elements; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderWorld; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.client.Minecraft; @@ -37,13 +37,13 @@ public class MinecartElement extends AnimatedSceneElement { @Override public void reset(PonderScene scene) { super.reset(scene); - entity.setPos(0, 0, 0); - entity.prevPosX = 0; - entity.prevPosY = 0; - entity.prevPosZ = 0; - entity.lastTickPosX = 0; - entity.lastTickPosY = 0; - entity.lastTickPosZ = 0; + entity.setPosRaw(0, 0, 0); + entity.xo = 0; + entity.yo = 0; + entity.zo = 0; + entity.xOld = 0; + entity.yOld = 0; + entity.zOld = 0; rotation.startWithValue(initialRotation); } @@ -53,25 +53,25 @@ public class MinecartElement extends AnimatedSceneElement { if (entity == null) entity = constructor.create(scene.getWorld(), 0, 0, 0); - entity.ticksExisted++; + entity.tickCount++; entity.onGround = true; - entity.prevPosX = entity.getX(); - entity.prevPosY = entity.getY(); - entity.prevPosZ = entity.getZ(); - entity.lastTickPosX = entity.getX(); - entity.lastTickPosY = entity.getY(); - entity.lastTickPosZ = entity.getZ(); + entity.xo = entity.getX(); + entity.yo = entity.getY(); + entity.zo = entity.getZ(); + entity.xOld = entity.getX(); + entity.yOld = entity.getY(); + entity.zOld = entity.getZ(); } public void setPositionOffset(Vector3d position, boolean immediate) { if (entity == null) return; - entity.setPosition(position.x, position.y, position.z); + entity.setPos(position.x, position.y, position.z); if (!immediate) return; - entity.prevPosX = position.x; - entity.prevPosY = position.y; - entity.prevPosZ = position.z; + entity.xo = position.x; + entity.yo = position.y; + entity.zo = position.z; } public void setRotation(float angle, boolean immediate) { @@ -84,7 +84,7 @@ public class MinecartElement extends AnimatedSceneElement { } public Vector3d getPositionOffset() { - return entity != null ? entity.getPositionVec() : Vector3d.ZERO; + return entity != null ? entity.position() : Vector3d.ZERO; } public Vector3d getRotation() { @@ -94,20 +94,20 @@ public class MinecartElement extends AnimatedSceneElement { @Override protected void renderLast(PonderWorld world, IRenderTypeBuffer buffer, MatrixStack ms, float fade, float pt) { EntityRendererManager entityrenderermanager = Minecraft.getInstance() - .getRenderManager(); + .getEntityRenderDispatcher(); if (entity == null) entity = constructor.create(world, 0, 0, 0); - ms.push(); + ms.pushPose(); ms.translate(location.x, location.y, location.z); - ms.translate(MathHelper.lerp(pt, entity.prevPosX, entity.getX()), - MathHelper.lerp(pt, entity.prevPosY, entity.getY()), MathHelper.lerp(pt, entity.prevPosZ, entity.getZ())); + ms.translate(MathHelper.lerp(pt, entity.xo, entity.getX()), + MathHelper.lerp(pt, entity.yo, entity.getY()), MathHelper.lerp(pt, entity.zo, entity.getZ())); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .rotateY(rotation.getValue(pt)); entityrenderermanager.render(entity, 0, 0, 0, 0, pt, ms, buffer, lightCoordsFromFade(fade)); - ms.pop(); + ms.popPose(); } } 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..9b07cc2ec 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 @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.ponder.elements; import java.util.function.Supplier; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.base.KineticTileEntity; @@ -9,7 +10,6 @@ import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.PonderWorld; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.client.MainWindow; import net.minecraft.client.Minecraft; @@ -43,15 +43,15 @@ public class ParrotElement extends AnimatedSceneElement { public void reset(PonderScene scene) { super.reset(scene); setPose(initialPose.get()); - entity.setPos(0, 0, 0); - entity.prevPosX = 0; - entity.prevPosY = 0; - entity.prevPosZ = 0; - entity.lastTickPosX = 0; - entity.lastTickPosY = 0; - entity.lastTickPosZ = 0; - entity.prevRotationPitch = entity.rotationPitch = 0; - entity.prevRotationYaw = entity.rotationYaw = 180; + entity.setPosRaw(0, 0, 0); + entity.xo = 0; + entity.yo = 0; + entity.zo = 0; + entity.xOld = 0; + entity.yOld = 0; + entity.zOld = 0; + entity.xRotO = entity.xRot = 0; + entity.yRotO = entity.yRot = 180; } @Override @@ -59,78 +59,78 @@ public class ParrotElement extends AnimatedSceneElement { super.tick(scene); if (entity == null) { entity = pose.create(scene.getWorld()); - entity.prevRotationYaw = entity.rotationYaw = 180; + entity.yRotO = entity.yRot = 180; } - entity.ticksExisted++; - entity.prevRotationYawHead = entity.rotationYawHead; + entity.tickCount++; + entity.yHeadRotO = entity.yHeadRot; entity.oFlapSpeed = entity.flapSpeed; entity.oFlap = entity.flap; entity.onGround = true; - entity.prevPosX = entity.getX(); - entity.prevPosY = entity.getY(); - entity.prevPosZ = entity.getZ(); - entity.prevRotationYaw = entity.rotationYaw; - entity.prevRotationPitch = entity.rotationPitch; + entity.xo = entity.getX(); + entity.yo = entity.getY(); + entity.zo = entity.getZ(); + entity.yRotO = entity.yRot; + entity.xRotO = entity.xRot; pose.tick(scene, entity, location); - entity.lastTickPosX = entity.getX(); - entity.lastTickPosY = entity.getY(); - entity.lastTickPosZ = entity.getZ(); + entity.xOld = entity.getX(); + entity.yOld = entity.getY(); + entity.zOld = entity.getZ(); } public void setPositionOffset(Vector3d position, boolean immediate) { if (entity == null) return; - entity.setPosition(position.x, position.y, position.z); + entity.setPos(position.x, position.y, position.z); if (!immediate) return; - entity.prevPosX = position.x; - entity.prevPosY = position.y; - entity.prevPosZ = position.z; + entity.xo = position.x; + entity.yo = position.y; + entity.zo = position.z; } public void setRotation(Vector3d eulers, boolean immediate) { if (entity == null) return; - entity.rotationPitch = (float) eulers.x; - entity.rotationYaw = (float) eulers.y; + entity.xRot = (float) eulers.x; + entity.yRot = (float) eulers.y; if (!immediate) return; - entity.prevRotationPitch = entity.rotationPitch; - entity.prevRotationYaw = entity.rotationYaw; + entity.xRotO = entity.xRot; + entity.yRotO = entity.yRot; } public Vector3d getPositionOffset() { - return entity != null ? entity.getPositionVec() : Vector3d.ZERO; + return entity != null ? entity.position() : Vector3d.ZERO; } public Vector3d getRotation() { - return entity != null ? new Vector3d(entity.rotationPitch, entity.rotationYaw, 0) : Vector3d.ZERO; + return entity != null ? new Vector3d(entity.xRot, entity.yRot, 0) : Vector3d.ZERO; } @Override protected void renderLast(PonderWorld world, IRenderTypeBuffer buffer, MatrixStack ms, float fade, float pt) { EntityRendererManager entityrenderermanager = Minecraft.getInstance() - .getRenderManager(); + .getEntityRenderDispatcher(); if (entity == null) { entity = pose.create(world); - entity.prevRotationYaw = entity.rotationYaw = 180; + entity.yRotO = entity.yRot = 180; } - ms.push(); + ms.pushPose(); ms.translate(location.x, location.y, location.z); - ms.translate(MathHelper.lerp(pt, entity.prevPosX, entity.getX()), - MathHelper.lerp(pt, entity.prevPosY, entity.getY()), MathHelper.lerp(pt, entity.prevPosZ, entity.getZ())); + ms.translate(MathHelper.lerp(pt, entity.xo, entity.getX()), + MathHelper.lerp(pt, entity.yo, entity.getY()), MathHelper.lerp(pt, entity.zo, entity.getZ())); - MatrixStacker.of(ms) - .rotateY(AngleHelper.angleLerp(pt, entity.prevRotationYaw, entity.rotationYaw)); + MatrixTransformStack.of(ms) + .rotateY(AngleHelper.angleLerp(pt, entity.yRotO, entity.yRot)); entityrenderermanager.render(entity, 0, 0, 0, 0, pt, ms, buffer, lightCoordsFromFade(fade)); - ms.pop(); + ms.popPose(); } public void setPose(ParrotPose pose) { @@ -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; } @@ -155,14 +155,14 @@ public class ParrotElement extends AnimatedSceneElement { @Override ParrotEntity create(PonderWorld world) { ParrotEntity entity = super.create(world); - entity.setPartying(BlockPos.ZERO, true); + entity.setRecordPlayingNearby(BlockPos.ZERO, true); return entity; } @Override void tick(PonderScene scene, ParrotEntity entity, Vector3d location) { - entity.prevRotationYaw = entity.rotationYaw; - entity.rotationYaw -= 2; + entity.yRotO = entity.yRot; + entity.yRot -= 2; } } @@ -171,8 +171,8 @@ public class ParrotElement extends AnimatedSceneElement { @Override void tick(PonderScene scene, ParrotEntity entity, Vector3d location) { - double length = entity.getPositionVec() - .subtract(entity.lastTickPosX, entity.lastTickPosY, entity.lastTickPosZ) + double length = entity.position() + .subtract(entity.xOld, entity.yOld, entity.zOld) .length(); entity.onGround = false; double phase = Math.min(length * 15, 8); @@ -195,12 +195,12 @@ public class ParrotElement extends AnimatedSceneElement { @Override void tick(PonderScene scene, ParrotEntity entity, Vector3d location) { TileEntity tileEntity = scene.getWorld() - .getTileEntity(componentPos); + .getBlockEntity(componentPos); if (!(tileEntity instanceof KineticTileEntity)) return; float rpm = ((KineticTileEntity) tileEntity).getSpeed(); - entity.prevRotationYaw = entity.rotationYaw; - entity.rotationYaw += (rpm * .3f); + entity.yRotO = entity.yRot; + entity.yRot += (rpm * .3f); } } @@ -220,8 +220,8 @@ public class ParrotElement extends AnimatedSceneElement { float targetYaw = MathHelper.wrapDegrees((float) -(MathHelper.atan2(d2, d0) * (double) (180F / (float) Math.PI)) + 90); - entity.rotationPitch = AngleHelper.angleLerp(.4f, entity.rotationPitch, targetPitch); - entity.rotationYaw = AngleHelper.angleLerp(.4f, entity.rotationYaw, targetYaw); + entity.xRot = AngleHelper.angleLerp(.4f, entity.xRot, targetPitch); + entity.yRot = AngleHelper.angleLerp(.4f, entity.yRot, targetYaw); } protected abstract Vector3d getFacedVec(PonderScene scene); @@ -243,8 +243,8 @@ public class ParrotElement extends AnimatedSceneElement { protected Vector3d getFacedVec(PonderScene scene) { Minecraft minecraft = Minecraft.getInstance(); MainWindow w = minecraft.getWindow(); - double mouseX = minecraft.mouseHelper.getMouseX() * w.getScaledWidth() / w.getWidth(); - double mouseY = minecraft.mouseHelper.getMouseY() * w.getScaledHeight() / w.getHeight(); + double mouseX = minecraft.mouseHandler.xpos() * w.getGuiScaledWidth() / w.getScreenWidth(); + double mouseY = minecraft.mouseHandler.ypos() * w.getGuiScaledHeight() / w.getScreenHeight(); return scene.getTransform() .screenToScene(mouseX, mouseY, 300, 0); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java index 31da2fb41..cbfb14e7a 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java @@ -10,8 +10,9 @@ import com.simibubi.create.foundation.ponder.PonderLocalization; import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.content.PonderPalette; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector2f; @@ -65,11 +66,15 @@ public class TextWindowElement extends AnimatedOverlayElement { return this; } - public Builder sharedText(String key) { + public Builder sharedText(ResourceLocation key) { textGetter = () -> PonderLocalization.getShared(key); return this; } + public Builder sharedText(String key) { + return sharedText(new ResourceLocation(scene.getNamespace(), key)); + } + public Builder placeNearTarget() { TextWindowElement.this.nearScene = true; return this; @@ -100,16 +105,16 @@ public class TextWindowElement extends AnimatedOverlayElement { int textWidth = Math.min(screen.width - targetX, 180); - List lines = screen.getFontRenderer().getTextHandler().wrapLines(bakedText, textWidth, Style.EMPTY); + List lines = screen.getFontRenderer().getSplitter().splitLines(bakedText, textWidth, Style.EMPTY); int boxWidth = 0; for (ITextProperties line : lines) - boxWidth = Math.max(boxWidth, screen.getFontRenderer().getWidth(line)); + boxWidth = Math.max(boxWidth, screen.getFontRenderer().width(line)); int boxHeight = screen.getFontRenderer() - .getWordWrappedHeight(bakedText, boxWidth); + .wordWrapHeight(bakedText, boxWidth); - ms.push(); + ms.pushPose(); ms.translate(0, sceneToScreen.y, 400); new BoxElement() @@ -121,25 +126,25 @@ public class TextWindowElement extends AnimatedOverlayElement { //PonderUI.renderBox(ms, targetX - 10, 3, boxWidth, boxHeight - 1, 0xaa000000, 0x30eebb00, 0x10eebb00); - int brighterColor = ColorHelper.mixAlphaColors(color, 0xFFffffdd, 1 / 2f); + int brighterColor = Color.mixColors(color, 0xFFffffdd, 1 / 2f); if (vec != null) { - ms.push(); + ms.pushPose(); ms.translate(sceneToScreen.x, 0, 0); double lineTarget = (targetX - sceneToScreen.x) * fade; ms.scale((float) lineTarget, 1, 1); - Matrix4f model = ms.peek().getModel(); + Matrix4f model = ms.last().pose(); GuiUtils.drawGradientRect(model, -100, 0, 0, 1, 1, brighterColor, brighterColor); GuiUtils.drawGradientRect(model, -100, 0, 1, 1, 2, 0xFF494949, 0xFF393939); - ms.pop(); + ms.popPose(); } ms.translate(0, 0, 400); for (int i = 0; i < lines.size(); i++) { screen.getFontRenderer() .draw(ms, lines.get(i) - .getString(), targetX - 10, 3 + 9 * i, ColorHelper.applyAlpha(brighterColor, fade)); + .getString(), targetX - 10, 3 + 9 * i, new Color(brighterColor).scaleAlpha(fade).getRGB()); } - ms.pop(); + ms.popPose(); } public int getColor() { 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..d8c05fbdf 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 @@ -8,6 +8,7 @@ import java.util.Random; import org.lwjgl.opengl.GL11; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.IVertexBuilder; @@ -21,7 +22,6 @@ 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.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; @@ -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; @@ -179,22 +180,22 @@ public class WorldSectionElement extends AnimatedSceneElement { public Pair rayTrace(PonderWorld world, Vector3d source, Vector3d target) { world.setMask(this.section); Vector3d transformedTarget = reverseTransformVec(target); - BlockRayTraceResult rayTraceBlocks = world.rayTraceBlocks(new RayTraceContext(reverseTransformVec(source), + BlockRayTraceResult rayTraceBlocks = world.clip(new RayTraceContext(reverseTransformVec(source), transformedTarget, BlockMode.OUTLINE, FluidMode.NONE, null)); world.clearMask(); if (rayTraceBlocks == null) return null; - if (rayTraceBlocks.getHitVec() == null) + if (rayTraceBlocks.getLocation() == null) return null; - double t = rayTraceBlocks.getHitVec() + double t = rayTraceBlocks.getLocation() .subtract(transformedTarget) - .lengthSquared() + .lengthSqr() / source.subtract(target) - .lengthSquared(); + .lengthSqr(); Vector3d actualHit = VecHelper.lerp((float) t, target, source); - return Pair.of(actualHit, rayTraceBlocks.getPos()); + return Pair.of(actualHit, rayTraceBlocks.getBlockPos()); } private Vector3d reverseTransformVec(Vector3d in) { @@ -223,7 +224,7 @@ public class WorldSectionElement extends AnimatedSceneElement { } public void transformMS(MatrixStack ms, float pt) { - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .translate(VecHelper.lerp(pt, prevAnimatedOffset, animatedOffset)); if (!animatedRotation.equals(Vector3d.ZERO) || !prevAnimatedRotation.equals(Vector3d.ZERO)) { if (centerOfRotation == null) @@ -231,14 +232,14 @@ public class WorldSectionElement extends AnimatedSceneElement { double rotX = MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x); double rotZ = MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z); double rotY = MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y); - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .translate(centerOfRotation) .rotateX(rotX) .rotateZ(rotZ) .rotateY(rotY) .translateBack(centerOfRotation); if (stabilizationAnchor != null) { - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .translate(stabilizationAnchor) .rotateX(-rotX) .rotateZ(-rotZ) @@ -255,30 +256,36 @@ public class WorldSectionElement extends AnimatedSceneElement { return; loadTEsIfMissing(scene.getWorld()); renderedTileEntities.removeIf(te -> scene.getWorld() - .getTileEntity(te.getPos()) != te); - renderedTileEntities.forEach(te -> { + .getBlockEntity(te.getBlockPos()) != te); + tickableTileEntities.removeIf(te -> scene.getWorld() + .getBlockEntity(te.getBlockPos()) != 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); + TileEntity tileEntity = world.getBlockEntity(pos); if (tileEntity == null) return; + tickableTileEntities.add(tileEntity); renderedTileEntities.add(tileEntity); - tileEntity.updateContainingBlockInfo(); + tileEntity.clearCache(); }); } @@ -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); @@ -314,30 +323,30 @@ public class WorldSectionElement extends AnimatedSceneElement { .apply(overlayMS, pt, true); transformMS(overlayMS, pt); } - ms.push(); + ms.pushPose(); ms.translate(pos.getX(), pos.getY(), pos.getZ()); IVertexBuilder builder = new MatrixApplyingVertexBuilder( - buffer.getBuffer(ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(entry.getValue())), - overlayMS.peek().getModel(), - overlayMS.peek().getNormal()); + buffer.getBuffer(ModelBakery.DESTROY_TYPES.get(entry.getValue())), + overlayMS.last().pose(), + overlayMS.last().normal()); Minecraft.getInstance() - .getBlockRendererDispatcher() - .renderModel(world.getBlockState(pos), pos, world, ms, builder, true, world.rand, EmptyModelData.INSTANCE); - ms.pop(); + .getBlockRenderer() + .renderModel(world.getBlockState(pos), pos, world, ms, builder, true, world.random, EmptyModelData.INSTANCE); + ms.popPose(); } } 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)); + Pair key = Pair.of(code, RenderType.chunkBufferLayers() + .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,32 +361,32 @@ 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)); + blockState.getShape(world, selectedBlock, ISelectionContext.of(Minecraft.getInstance().player)); if (shape.isEmpty()) return; - ms.push(); + ms.pushPose(); transformMS(ms, pt); RenderSystem.disableTexture(); - WorldRenderer.drawBox(ms, buffer.getBuffer(RenderType.getLines()), shape.getBoundingBox() - .offset(selectedBlock), 1, 1, 1, 0.6f); - ms.pop(); + WorldRenderer.renderLineBox(ms, buffer.getBuffer(RenderType.lines()), shape.bounds() + .move(selectedBlock), 1, 1, 1, 0.6f); + ms.popPose(); } 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) { ForgeHooksClient.setRenderLayer(layer); MatrixStack ms = new MatrixStack(); BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRendererDispatcher(); - BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); + .getBlockRenderer(); + BlockModelRenderer blockRenderer = dispatcher.getModelRenderer(); Random random = new Random(); BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); @@ -387,25 +396,25 @@ public class WorldSectionElement extends AnimatedSceneElement { BlockState state = world.getBlockState(pos); FluidState ifluidstate = world.getFluidState(pos); - ms.push(); + ms.pushPose(); ms.translate(pos.getX(), pos.getY(), pos.getZ()); - if (state.getRenderType() != BlockRenderType.ENTITYBLOCK_ANIMATED && state.getBlock() != Blocks.AIR + if (state.getRenderShape() != BlockRenderType.ENTITYBLOCK_ANIMATED && state.getBlock() != Blocks.AIR && RenderTypeLookup.canRenderInLayer(state, layer)) { - TileEntity tileEntity = world.getTileEntity(pos); - blockRenderer.renderModel(world, dispatcher.getModelForState(state), state, pos, ms, builder, true, - random, 42, OverlayTexture.DEFAULT_UV, + TileEntity tileEntity = world.getBlockEntity(pos); + blockRenderer.renderModel(world, dispatcher.getBlockModel(state), state, pos, ms, builder, true, + random, 42, OverlayTexture.NO_OVERLAY, tileEntity != null ? tileEntity.getModelData() : EmptyModelData.INSTANCE); } if (!ifluidstate.isEmpty() && RenderTypeLookup.canRenderInLayer(ifluidstate, layer)) - dispatcher.renderFluid(pos, world, builder, ifluidstate); + dispatcher.renderLiquid(pos, world, builder, ifluidstate); - ms.pop(); + ms.popPose(); }); world.clearMask(); - builder.finishDrawing(); + builder.end(); return new SuperByteBuffer(builder); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java index 273d520b2..74d943fd0 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java @@ -74,7 +74,7 @@ public class AnimateTileEntityInstruction extends TickingInstruction { } private static Optional castIfPresent(PonderWorld world, BlockPos pos, Class teType) { - TileEntity tileEntity = world.getTileEntity(pos); + TileEntity tileEntity = world.getBlockEntity(pos); if (teType.isInstance(tileEntity)) return Optional.of(teType.cast(tileEntity)); return Optional.empty(); 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..d66a4c2a9 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,13 +23,13 @@ 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() { - return Minecraft.getInstance().particles; + return Minecraft.getInstance().particleEngine; } public void create(PonderWorld world, double x, double y, double z); @@ -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/instructions/FadeIntoSceneInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeIntoSceneInstruction.java index 10a1bbaa9..be5faf3e2 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeIntoSceneInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeIntoSceneInstruction.java @@ -25,7 +25,7 @@ public abstract class FadeIntoSceneInstruction e scene.addElement(element); element.setVisible(true); element.setFade(0); - element.setFadeVec(Vector3d.of(fadeInFrom.getDirectionVec()).scale(.5f)); + element.setFadeVec(Vector3d.atLowerCornerOf(fadeInFrom.getNormal()).scale(.5f)); if (elementLink != null) scene.linkElement(element, elementLink); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeOutOfSceneInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeOutOfSceneInstruction.java index 269ca682a..83680d1a2 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeOutOfSceneInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/FadeOutOfSceneInstruction.java @@ -27,7 +27,7 @@ public class FadeOutOfSceneInstruction extends T return; element.setVisible(true); element.setFade(1); - element.setFadeVec(Vector3d.of(fadeOutTo.getDirectionVec()).scale(.5f)); + element.setFadeVec(Vector3d.atLowerCornerOf(fadeOutTo.getNormal()).scale(.5f)); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/HideAllInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/HideAllInstruction.java index 227893e68..63e0f91ef 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/HideAllInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/HideAllInstruction.java @@ -25,7 +25,7 @@ public class HideAllInstruction extends TickingInstruction { AnimatedSceneElement animatedSceneElement = (AnimatedSceneElement) element; animatedSceneElement.setFade(1); animatedSceneElement - .setFadeVec(fadeOutTo == null ? null : Vector3d.of(fadeOutTo.getDirectionVec()).scale(.5f)); + .setFadeVec(fadeOutTo == null ? null : Vector3d.atLowerCornerOf(fadeOutTo.getNormal()).scale(.5f)); } else if (element instanceof AnimatedOverlayElement) { AnimatedOverlayElement animatedSceneElement = (AnimatedOverlayElement) element; animatedSceneElement.setFade(1); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/HighlightValueBoxInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/HighlightValueBoxInstruction.java index b00f89dd2..95207ad96 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/HighlightValueBoxInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/HighlightValueBoxInstruction.java @@ -21,7 +21,7 @@ public class HighlightValueBoxInstruction extends TickingInstruction { public void tick(PonderScene scene) { super.tick(scene); AxisAlignedBB point = new AxisAlignedBB(vec, vec); - AxisAlignedBB expanded = point.grow(expands.x, expands.y, expands.z); + AxisAlignedBB expanded = point.inflate(expands.x, expands.y, expands.z); scene.getOutliner() .chaseAABB(vec, remainingTicks == totalTicks ? point : expanded) .lineWidth(1 / 32f) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/ReplaceBlocksInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/ReplaceBlocksInstruction.java index d71ad0919..e2e9d016b 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/ReplaceBlocksInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/ReplaceBlocksInstruction.java @@ -28,14 +28,14 @@ public class ReplaceBlocksInstruction extends WorldModifyInstruction { PonderWorld world = scene.getWorld(); selection.forEach(pos -> { if (!world.getBounds() - .isVecInside(pos)) + .isInside(pos)) return; BlockState prevState = world.getBlockState(pos); - if (!replaceAir && prevState == Blocks.AIR.getDefaultState()) + if (!replaceAir && prevState == Blocks.AIR.defaultBlockState()) return; if (spawnParticles) world.addBlockDestroyEffects(pos, prevState); - world.setBlockState(pos, stateToUse.apply(prevState)); + world.setBlockAndUpdate(pos, stateToUse.apply(prevState)); }); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/TileEntityDataInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/TileEntityDataInstruction.java index 391b73063..2a8a46b3d 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/TileEntityDataInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/TileEntityDataInstruction.java @@ -30,16 +30,16 @@ public class TileEntityDataInstruction extends WorldModifyInstruction { PonderWorld world = scene.getWorld(); selection.forEach(pos -> { if (!world.getBounds() - .isVecInside(pos)) + .isInside(pos)) return; - TileEntity tileEntity = world.getTileEntity(pos); + TileEntity tileEntity = world.getBlockEntity(pos); if (!type.isInstance(tileEntity)) return; - CompoundNBT apply = data.apply(tileEntity.write(new CompoundNBT())); + CompoundNBT apply = data.apply(tileEntity.save(new CompoundNBT())); BlockState state = world.getBlockState(pos); if (tileEntity instanceof SyncedTileEntity) ((SyncedTileEntity) tileEntity).readClientUpdate(state, apply); - tileEntity.fromTag(state, apply); + tileEntity.load(state, apply); }); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/ui/ChapterLabel.java b/src/main/java/com/simibubi/create/foundation/ponder/ui/ChapterLabel.java index c77273bab..59abb1d59 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/ui/ChapterLabel.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/ui/ChapterLabel.java @@ -9,7 +9,6 @@ import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.ponder.content.PonderChapter; -import com.simibubi.create.foundation.utility.Lang; import net.minecraft.client.Minecraft; @@ -31,7 +30,7 @@ public class ChapterLabel extends AbstractSimiWidget { @Override public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { UIRenderHelper.streak(ms, 0, x, y + height / 2, height - 2, width); - Minecraft.getInstance().fontRenderer.draw(ms, Lang.translate("ponder.chapter." + chapter.getId()), x + 50, + Minecraft.getInstance().font.draw(ms, chapter.getTitle(), x + 50, y + 20, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT)); button.renderButton(ms, mouseX, mouseY, partialTicks); 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..bce4be1b4 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,17 +1,17 @@ package com.simibubi.create.foundation.ponder.ui; -import java.awt.Color; - import javax.annotation.Nonnull; 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.ponder.content.PonderTag; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.client.Minecraft; @@ -22,6 +22,7 @@ import net.minecraft.util.math.MathHelper; public class PonderButton extends BoxWidget { protected ItemStack item; + protected PonderTag tag; protected KeyBinding shortcut; protected LerpedFloat flash = LerpedFloat.linear().startWithValue(0).chase(0, 0.1f, LerpedFloat.Chaser.EXP); @@ -42,6 +43,10 @@ public class PonderButton extends BoxWidget { return (T) this; } + public T showingTag(PonderTag tag) { + return showing(this.tag = tag); + } + public T showing(ItemStack item) { this.item = item; return super.showingElement(GuiGameElement.of(item) @@ -74,14 +79,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)); - gradientColor1 = ColorHelper.mixColors(c1, nc1, sin); - gradientColor2 = ColorHelper.mixColors(c2, nc2, sin); + Color nc1 = new Color(255, 255, 255, MathHelper.clamp(gradientColor1.getAlpha() + 150, 0, 255)); + Color nc2 = new Color(155, 155, 155, MathHelper.clamp(gradientColor2.getAlpha() + 150, 0, 255)); + gradientColor1 = gradientColor1.mixWith(nc1, sin); + gradientColor2 = gradientColor2.mixWith(nc2, sin); } } @@ -94,12 +97,37 @@ public class PonderButton extends BoxWidget { return; if (shortcut != null) { - 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)); + ms.translate(0, 0, z + 50); + drawCenteredString(ms, Minecraft.getInstance().font, shortcut.getTranslatedKeyMessage(), x + width / 2 + 8, y + height - 6, Theme.c(Theme.Key.TEXT_DARKER).scaleAlpha(fadeValue).getRGB()); } } public ItemStack getItem() { return item; } + + public PonderTag getTag() { + return tag; + } + + @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..4017777fc --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java @@ -0,0 +1,40 @@ +package com.simibubi.create.foundation.render; + +import com.jozufozu.flywheel.backend.material.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.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +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 void flwInit(GatherContextEvent event) { + event.getBackend().register(ROTATING); + event.getBackend().register(BELTS); + event.getBackend().register(ACTORS); + event.getBackend().register(FLAPS); + } + + public static class Locations { + public static final ResourceLocation ROTATING = Create.asResource("rotating"); + public static final ResourceLocation BELTS = Create.asResource("belts"); + public static final ResourceLocation ACTORS = Create.asResource("actors"); + public static final ResourceLocation FLAPS = Create.asResource("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..5dd47e831 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,16 @@ 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 static com.simibubi.create.Create.asResource; 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 = asResource("rotating"); + public static final ResourceLocation CHROMATIC = asResource("chromatic"); + public static final ResourceLocation BELT = asResource("belt"); + public static final ResourceLocation FLAPS = asResource("flap"); + public static final ResourceLocation STRUCTURE = asResource("contraption_structure"); + public static final ResourceLocation ACTOR = asResource("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); - } - } } 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..60ab31a97 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/CreateContexts.java @@ -0,0 +1,41 @@ +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 net.minecraft.util.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public class CreateContexts { + private static final ResourceLocation CONTRAPTION = new ResourceLocation("create", "context/contraption"); + + public static WorldContext CWORLD; + public static WorldContext STRUCTURE; + + public static void flwInit(GatherContextEvent event) { + Backend backend = event.getBackend(); + + SpecMetaRegistry.register(RainbowDebugStateProvider.INSTANCE); + + 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..9c5c4d59d 100644 --- a/src/main/java/com/simibubi/create/foundation/render/PartialBufferer.java +++ b/src/main/java/com/simibubi/create/foundation/render/PartialBufferer.java @@ -4,11 +4,11 @@ import static net.minecraft.state.properties.BlockStateProperties.FACING; import java.util.function.Supplier; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; @@ -16,22 +16,22 @@ 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) { - Direction facing = referenceState.get(FACING); + Direction facing = referenceState.getValue(FACING); return getFacing(partial, referenceState, facing); } 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) { return () -> { MatrixStack stack = new MatrixStack(); - MatrixStacker.of(stack) + MatrixTransformStack.of(stack) .centre() .rotateY(AngleHelper.horizontalAngle(facing)) .rotateX(AngleHelper.verticalAngle(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..9c925cd74 --- /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 = Create.asResource("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/RenderTypes.java b/src/main/java/com/simibubi/create/foundation/render/RenderTypes.java new file mode 100644 index 000000000..21bf27add --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/RenderTypes.java @@ -0,0 +1,128 @@ +package com.simibubi.create.foundation.render; + +import org.lwjgl.opengl.GL11; + +import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.Create; + +import net.minecraft.client.renderer.RenderState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.inventory.container.PlayerContainer; +import net.minecraft.util.ResourceLocation; + +public class RenderTypes extends RenderState { + + public static RenderType getOutlineTranslucent(ResourceLocation texture, boolean cull) { + RenderType.State rendertype$state = RenderType.State.builder() + .setTextureState(new RenderState.TextureState(texture, false, false)) + .setTransparencyState(TRANSLUCENT_TRANSPARENCY) + .setDiffuseLightingState(DIFFUSE_LIGHTING) + .setAlphaState(DEFAULT_ALPHA) + .setCullState(cull ? CULL : NO_CULL) + .setLightmapState(LIGHTMAP) + .setOverlayState(OVERLAY) + .createCompositeState(true); + return RenderType.create(createLayerName("outline_translucent" + (cull ? "_cull" : "")), + DefaultVertexFormats.NEW_ENTITY, GL11.GL_QUADS, 256, true, true, rendertype$state); + } + + private static final RenderType OUTLINE_SOLID = + RenderType.create(createLayerName("outline_solid"), DefaultVertexFormats.NEW_ENTITY, GL11.GL_QUADS, 256, true, + false, RenderType.State.builder() + .setTextureState(new RenderState.TextureState(AllSpecialTextures.BLANK.getLocation(), false, false)) + .setDiffuseLightingState(DIFFUSE_LIGHTING) + .setLightmapState(LIGHTMAP) + .setOverlayState(OVERLAY) + .createCompositeState(true)); + + public static RenderType getGlowingSolid(ResourceLocation texture) { + RenderType.State rendertype$state = RenderType.State.builder() + .setTextureState(new RenderState.TextureState(texture, false, false)) + .setLightmapState(LIGHTMAP) + .setOverlayState(OVERLAY) + .createCompositeState(true); + return RenderType.create(createLayerName("glowing_solid"), DefaultVertexFormats.NEW_ENTITY, GL11.GL_QUADS, 256, + true, false, rendertype$state); + } + + public static RenderType getGlowingTranslucent(ResourceLocation texture) { + RenderType.State rendertype$state = RenderType.State.builder() + .setTextureState(new RenderState.TextureState(texture, false, false)) + .setTransparencyState(TRANSLUCENT_TRANSPARENCY) + .setAlphaState(DEFAULT_ALPHA) + .setCullState(NO_CULL) + .setLightmapState(LIGHTMAP) + .setOverlayState(OVERLAY) + .createCompositeState(true); + return RenderType.create(createLayerName("glowing_translucent"), DefaultVertexFormats.NEW_ENTITY, GL11.GL_QUADS, + 256, true, true, rendertype$state); + } + + private static final RenderType GLOWING_SOLID = getGlowingSolid(PlayerContainer.BLOCK_ATLAS); + private static final RenderType GLOWING_TRANSLUCENT = getGlowingTranslucent(PlayerContainer.BLOCK_ATLAS); + + private static final RenderType ITEM_PARTIAL_SOLID = + RenderType.create(createLayerName("item_solid"), DefaultVertexFormats.NEW_ENTITY, GL11.GL_QUADS, 256, true, + false, RenderType.State.builder() + .setTextureState(BLOCK_SHEET) + .setTransparencyState(NO_TRANSPARENCY) + .setDiffuseLightingState(DIFFUSE_LIGHTING) + .setLightmapState(LIGHTMAP) + .setOverlayState(OVERLAY) + .createCompositeState(true)); + + private static final RenderType ITEM_PARTIAL_TRANSLUCENT = RenderType.create(createLayerName("item_translucent"), + DefaultVertexFormats.NEW_ENTITY, GL11.GL_QUADS, 256, true, true, RenderType.State.builder() + .setTextureState(BLOCK_SHEET) + .setTransparencyState(TRANSLUCENT_TRANSPARENCY) + .setDiffuseLightingState(DIFFUSE_LIGHTING) + .setAlphaState(DEFAULT_ALPHA) + .setLightmapState(LIGHTMAP) + .setOverlayState(OVERLAY) + .createCompositeState(true)); + + private static final RenderType FLUID = RenderType.create(createLayerName("fluid"), + DefaultVertexFormats.NEW_ENTITY, GL11.GL_QUADS, 256, true, true, RenderType.State.builder() + .setTextureState(BLOCK_SHEET_MIPPED) + .setTransparencyState(TRANSLUCENT_TRANSPARENCY) + .setShadeModelState(SMOOTH_SHADE) + .setAlphaState(DEFAULT_ALPHA) + .setLightmapState(LIGHTMAP) + .setOverlayState(OVERLAY) + .createCompositeState(true)); + + private static String createLayerName(String name) { + return Create.ID + ":" + name; + } + + public static RenderType getItemPartialSolid() { + return ITEM_PARTIAL_SOLID; + } + + public static RenderType getItemPartialTranslucent() { + return ITEM_PARTIAL_TRANSLUCENT; + } + + public static RenderType getOutlineSolid() { + return OUTLINE_SOLID; + } + + public static RenderType getGlowingSolid() { + return GLOWING_SOLID; + } + + public static RenderType getGlowingTranslucent() { + return GLOWING_TRANSLUCENT; + } + + public static RenderType getFluid() { + return FLUID; + } + + // Mmm gimme those protected fields + public RenderTypes() { + super(null, null, null); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/render/ShadowRenderHelper.java b/src/main/java/com/simibubi/create/foundation/render/ShadowRenderHelper.java index e5d31c07f..57296b74b 100644 --- a/src/main/java/com/simibubi/create/foundation/render/ShadowRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/render/ShadowRenderHelper.java @@ -23,26 +23,26 @@ import net.minecraft.world.IWorldReader; public class ShadowRenderHelper { private static final RenderType SHADOW_LAYER = - RenderType.getEntityNoOutline(new ResourceLocation("textures/misc/shadow.png")); + RenderType.entityNoOutline(new ResourceLocation("textures/misc/shadow.png")); public static void renderShadow(MatrixStack p_229096_0_, IRenderTypeBuffer p_229096_1_, Vector3d pos, float p_229096_3_, float p_229096_6_) { float f = p_229096_6_; - double d2 = pos.getX(); - double d0 = pos.getY(); - double d1 = pos.getZ(); + double d2 = pos.x(); + double d0 = pos.y(); + double d1 = pos.z(); int i = MathHelper.floor(d2 - (double) f); int j = MathHelper.floor(d2 + (double) f); int k = MathHelper.floor(d0 - (double) f); int l = MathHelper.floor(d0); int i1 = MathHelper.floor(d1 - (double) f); int j1 = MathHelper.floor(d1 + (double) f); - MatrixStack.Entry matrixstack$entry = p_229096_0_.peek(); + MatrixStack.Entry matrixstack$entry = p_229096_0_.last(); IVertexBuilder ivertexbuilder = p_229096_1_.getBuffer(SHADOW_LAYER); - for (BlockPos blockpos : BlockPos.getAllInBoxMutable(new BlockPos(i, k, i1), new BlockPos(j, l, j1))) { - renderShadowPart(matrixstack$entry, ivertexbuilder, Minecraft.getInstance().world, blockpos, d2, d0, d1, f, + for (BlockPos blockpos : BlockPos.betweenClosed(new BlockPos(i, k, i1), new BlockPos(j, l, j1))) { + renderShadowPart(matrixstack$entry, ivertexbuilder, Minecraft.getInstance().level, blockpos, d2, d0, d1, f, p_229096_3_); } @@ -51,11 +51,11 @@ public class ShadowRenderHelper { private static void renderShadowPart(MatrixStack.Entry p_229092_0_, IVertexBuilder p_229092_1_, IWorldReader p_229092_2_, BlockPos p_229092_3_, double p_229092_4_, double p_229092_6_, double p_229092_8_, float p_229092_10_, float p_229092_11_) { - BlockPos blockpos = p_229092_3_.down(); + BlockPos blockpos = p_229092_3_.below(); BlockState blockstate = p_229092_2_.getBlockState(blockpos); - if (blockstate.getRenderType() != BlockRenderType.INVISIBLE && p_229092_2_.getLight(p_229092_3_) > 3) { - if (blockstate.isFullCube(p_229092_2_, blockpos)) { - VoxelShape voxelshape = blockstate.getShape(p_229092_2_, p_229092_3_.down()); + if (blockstate.getRenderShape() != BlockRenderType.INVISIBLE && p_229092_2_.getMaxLocalRawBrightness(p_229092_3_) > 3) { + if (blockstate.isCollisionShapeFullBlock(p_229092_2_, blockpos)) { + VoxelShape voxelshape = blockstate.getShape(p_229092_2_, p_229092_3_.below()); if (!voxelshape.isEmpty()) { @SuppressWarnings("deprecation") float f = (float) (((double) p_229092_11_ - (p_229092_6_ - (double) p_229092_3_.getY()) / 2.0D) @@ -65,7 +65,7 @@ public class ShadowRenderHelper { f = 1.0F; } - AxisAlignedBB axisalignedbb = voxelshape.getBoundingBox(); + AxisAlignedBB axisalignedbb = voxelshape.bounds(); double d0 = (double) p_229092_3_.getX() + axisalignedbb.minX; double d1 = (double) p_229092_3_.getX() + axisalignedbb.maxX; double d2 = (double) p_229092_3_.getY() + axisalignedbb.minY; @@ -93,12 +93,12 @@ public class ShadowRenderHelper { private static void shadowVertex(MatrixStack.Entry p_229091_0_, IVertexBuilder p_229091_1_, float p_229091_2_, float p_229091_3_, float p_229091_4_, float p_229091_5_, float p_229091_6_, float p_229091_7_) { - p_229091_1_.vertex(p_229091_0_.getModel(), p_229091_3_, p_229091_4_, p_229091_5_) + p_229091_1_.vertex(p_229091_0_.pose(), p_229091_3_, p_229091_4_, p_229091_5_) .color(1.0F, 1.0F, 1.0F, p_229091_2_) - .texture(p_229091_6_, p_229091_7_) - .overlay(OverlayTexture.DEFAULT_UV) - .light(15728880) - .normal(p_229091_0_.getNormal(), 0.0F, 1.0F, 0.0F) + .uv(p_229091_6_, p_229091_7_) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(15728880) + .normal(p_229091_0_.normal(), 0.0F, 1.0F, 0.0F) .endVertex(); } } 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..98273c1d2 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -1,177 +1,235 @@ package com.simibubi.create.foundation.render; -import java.nio.Buffer; -import java.nio.ByteBuffer; - +import com.jozufozu.flywheel.util.BufferBuilderReader; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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 com.simibubi.create.foundation.utility.Color; -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; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Matrix3f; import net.minecraft.util.math.vector.Matrix4f; 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; - // Vertex Coloring private boolean shouldColor; private int r, g, b, a; + private boolean disableDiffuseDiv; + private boolean disableDiffuseMult; + + // Vertex Texture Coords + private SpriteShiftFunc spriteShiftFunc; + + // Vertex Overlay Color + private boolean hasOverlay; + private int overlay = OverlayTexture.NO_OVERLAY;; + + // Vertex Lighting + private boolean useWorldLight; + private Matrix4f lightTransform; + private boolean hasCustomLight; + private int packedLightCoords; + private boolean hybridLight; + + // Vertex Normals + private boolean fullNormalTransform; + + // Temporary + private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap(); + private final Vector4f pos = new Vector4f(); + private final Vector3f normal = new Vector3f(); + private final Vector4f lightPos = new Vector4f(); + private final MatrixTransformStack stacker; public SuperByteBuffer(BufferBuilder buf) { - super(buf); + template = new BufferBuilderReader(buf); transforms = new MatrixStack(); + transforms.pushPose(); + stacker = MatrixTransformStack.of(transforms); } public static float getUnInterpolatedU(TextureAtlasSprite sprite, float u) { - float f = sprite.getMaxU() - sprite.getMinU(); - return (u - sprite.getMinU()) / f * 16.0F; + float f = sprite.getU1() - sprite.getU0(); + return (u - sprite.getU0()) / f * 16.0F; } public static float getUnInterpolatedV(TextureAtlasSprite sprite, float v) { - float f = sprite.getMaxV() - sprite.getMinV(); - return (v - sprite.getMinV()) / f * 16.0F; + float f = sprite.getV1() - sprite.getV0(); + return (v - sprite.getV0()) / f * 16.0F; } - private static final Long2DoubleMap skyLightCache = new Long2DoubleOpenHashMap(); - private static final Long2DoubleMap blockLightCache = new Long2DoubleOpenHashMap(); - Vector4f pos = new Vector4f(); - Vector3f normal = new Vector3f(); - Vector4f lightPos = new Vector4f(); - public void renderInto(MatrixStack input, IVertexBuilder builder) { - 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(); - - Matrix4f localTransforms = transforms.peek() - .getModel(); + Matrix4f modelMat = input.last() + .pose() + .copy(); + Matrix4f localTransforms = transforms.last() + .pose(); modelMat.multiply(localTransforms); - if (shouldLight && lightTransform != null) { - skyLightCache.clear(); - blockLightCache.clear(); + Matrix3f normalMat; + if (fullNormalTransform) { + normalMat = input.last().normal().copy(); + Matrix3f localNormalTransforms = transforms.last().normal(); + normalMat.mul(localNormalTransforms); + } else { + normalMat = transforms.last().normal().copy(); + } + + if (useWorldLight) { + WORLD_LIGHT_CACHE.clear(); } 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); normal.transform(normalMat); - float nx = normal.getX(); - float ny = normal.getY(); - float nz = normal.getZ(); + float nx = normal.x(); + float ny = normal.y(); + float nz = normal.z(); + + float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ); float instanceDiffuse = LightUtil.diffuseLight(nx, ny, nz); pos.set(x, y, z, 1F); pos.transform(modelMat); - builder.vertex(pos.getX(), pos.getY(), pos.getZ()); + builder.vertex(pos.x(), pos.y(), pos.z()); - // 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; - int colorR = Math.min(255, (int) (((float) this.r) * instanceDiffuse)); - int colorG = Math.min(255, (int) (((float) this.g) * instanceDiffuse)); - int colorB = Math.min(255, (int) (((float) this.b) * instanceDiffuse)); - builder.color(colorR, colorG, colorB, this.a); + if (disableDiffuseMult) { + builder.color(this.r, this.g, this.b, this.a); + } else { + int colorR = transformColor(this.r, instanceDiffuse); + int colorG = transformColor(this.g, instanceDiffuse); + int colorB = transformColor(this.b, instanceDiffuse); + builder.color(colorR, colorG, colorB, this.a); + } } else { - float diffuseMult = instanceDiffuse / staticDiffuse; - int colorR = Math.min(255, (int) (((float) Byte.toUnsignedInt(r)) * diffuseMult)); - int colorG = Math.min(255, (int) (((float) Byte.toUnsignedInt(g)) * diffuseMult)); - int colorB = Math.min(255, (int) (((float) Byte.toUnsignedInt(b)) * diffuseMult)); - builder.color(colorR, colorG, colorB, a); + if (disableDiffuseDiv && disableDiffuseMult) { + builder.color(r, g, b, a); + } else { + float diffuseMult; + if (disableDiffuseDiv) { + diffuseMult = instanceDiffuse; + } else if (disableDiffuseMult) { + diffuseMult = 1 / staticDiffuse; + } else { + diffuseMult = instanceDiffuse / staticDiffuse; + } + int colorR = transformColor(r, diffuseMult); + int colorG = transformColor(g, diffuseMult); + int colorB = transformColor(b, diffuseMult); + 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); + } else { + builder.uv(u, v); + } - if (shouldLight) { - int light = packedLightCoords; + if (hasOverlay) { + builder.overlayCoords(overlay); + } + + 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().level, lightPos); + if (hasCustomLight) { + light = maxLight(light, packedLightCoords); + } + } else if (hasCustomLight) { + light = packedLightCoords; + } else { + light = template.getLight(i); + } + + if (hybridLight) { + builder.uv2(maxLight(light, template.getLight(i))); + } else { + builder.uv2(light); + } + + builder.normal(nx, ny, nz); + + builder.endVertex(); } - transforms = new MatrixStack(); - - spriteShiftFunc = null; - shouldColor = false; - shouldLight = false; - otherBlockLight = -1; + reset(); } - public MatrixStacker matrixStacker() { - return MatrixStacker.of(transforms); + public SuperByteBuffer reset() { + while (!transforms.clear()) + transforms.popPose(); + transforms.pushPose(); + + shouldColor = false; + r = 0; + g = 0; + b = 0; + a = 0; + disableDiffuseDiv = false; + disableDiffuseMult = false; + spriteShiftFunc = null; + hasOverlay = false; + overlay = OverlayTexture.NO_OVERLAY; + useWorldLight = false; + lightTransform = null; + hasCustomLight = false; + packedLightCoords = 0; + hybridLight = false; + fullNormalTransform = false; + return this; + } + + public MatrixTransformStack matrixStacker() { + return stacker; } public SuperByteBuffer translate(Vector3d vec) { @@ -188,27 +246,27 @@ public class SuperByteBuffer extends TemplateBuffer { } public SuperByteBuffer transform(MatrixStack stack) { - transforms.peek() - .getModel() - .multiply(stack.peek() - .getModel()); - transforms.peek() - .getNormal() - .multiply(stack.peek() - .getNormal()); + transforms.last() + .pose() + .multiply(stack.last() + .pose()); + transforms.last() + .normal() + .mul(stack.last() + .normal()); return this; } public SuperByteBuffer rotate(Direction axis, float radians) { if (radians == 0) return this; - transforms.multiply(axis.getUnitVector() - .getRadialQuaternion(radians)); + transforms.mulPose(axis.step() + .rotation(radians)); return this; } public SuperByteBuffer rotate(Quaternion q) { - transforms.multiply(q); + transforms.mulPose(q); return this; } @@ -222,59 +280,12 @@ public class SuperByteBuffer extends TemplateBuffer { .translate(-.5f, -.5f, -.5f); } - public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { - this.spriteShiftFunc = (builder, u, v) -> { - float targetU = entry.getTarget() - .getInterpolatedU((getUnInterpolatedU(entry.getOriginal(), u))); - float targetV = entry.getTarget() - .getInterpolatedV((getUnInterpolatedV(entry.getOriginal(), v))); - builder.texture(targetU, targetV); - }; - return this; - } - - public SuperByteBuffer shiftUVScrolling(SpriteShiftEntry entry, float scrollV) { - this.spriteShiftFunc = (builder, u, v) -> { - float targetU = u - entry.getOriginal() - .getMinU() + entry.getTarget() - .getMinU(); - float targetV = v - entry.getOriginal() - .getMinV() + entry.getTarget() - .getMinV() - + scrollV; - builder.texture(targetU, targetV); - }; - return this; - } - - public SuperByteBuffer shiftUVtoSheet(SpriteShiftEntry entry, float uTarget, float vTarget, int sheetSize) { - this.spriteShiftFunc = (builder, u, v) -> { - float targetU = entry.getTarget() - .getInterpolatedU((getUnInterpolatedU(entry.getOriginal(), u) / sheetSize) + uTarget * 16); - float targetV = entry.getTarget() - .getInterpolatedV((getUnInterpolatedV(entry.getOriginal(), v) / sheetSize) + vTarget * 16); - builder.texture(targetU, targetV); - }; - return this; - } - - public SuperByteBuffer light(int packedLightCoords) { - shouldLight = true; - lightTransform = null; - this.packedLightCoords = packedLightCoords; - return this; - } - - public SuperByteBuffer light(Matrix4f lightTransform) { - shouldLight = true; - this.lightTransform = lightTransform; - return this; - } - - public SuperByteBuffer light(Matrix4f lightTransform, int otherBlockLight) { - shouldLight = true; - this.lightTransform = lightTransform; - this.otherBlockLight = otherBlockLight; + public SuperByteBuffer color(int r, int g, int b, int a) { + shouldColor = true; + this.r = r; + this.g = g; + this.b = b; + this.a = a; return this; } @@ -287,17 +298,146 @@ public class SuperByteBuffer extends TemplateBuffer { return this; } - 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; + public SuperByteBuffer color(Color c) { + return color(c.getRGB()); + } + + /** + * Prevents vertex colors from being divided by the diffuse value calculated from the raw untransformed normal vector. + * Useful when passed vertex colors do not have diffuse baked in. + * Disabled when custom color is used. + */ + public SuperByteBuffer disableDiffuseDiv() { + disableDiffuseDiv = true; + return this; + } + + /** + * Prevents vertex colors from being multiplied by the diffuse value calculated from the final transformed normal vector. + * Useful for entity rendering, when diffuse is applied automatically later. + */ + public SuperByteBuffer disableDiffuseMult() { + disableDiffuseMult = true; + return this; + } + + public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { + this.spriteShiftFunc = (builder, u, v) -> { + float targetU = entry.getTarget() + .getU((getUnInterpolatedU(entry.getOriginal(), u))); + float targetV = entry.getTarget() + .getV((getUnInterpolatedV(entry.getOriginal(), v))); + builder.uv(targetU, targetV); + }; + return this; + } + + public SuperByteBuffer shiftUVScrolling(SpriteShiftEntry entry, float scrollV) { + this.spriteShiftFunc = (builder, u, v) -> { + float targetU = u - entry.getOriginal() + .getU0() + entry.getTarget() + .getU0(); + float targetV = v - entry.getOriginal() + .getV0() + entry.getTarget() + .getV0() + + scrollV; + builder.uv(targetU, targetV); + }; + return this; + } + + public SuperByteBuffer shiftUVtoSheet(SpriteShiftEntry entry, float uTarget, float vTarget, int sheetSize) { + this.spriteShiftFunc = (builder, u, v) -> { + float targetU = entry.getTarget() + .getU((getUnInterpolatedU(entry.getOriginal(), u) / sheetSize) + uTarget * 16); + float targetV = entry.getTarget() + .getV((getUnInterpolatedV(entry.getOriginal(), v) / sheetSize) + vTarget * 16); + builder.uv(targetU, targetV); + }; + return this; + } + + public SuperByteBuffer overlay() { + hasOverlay = true; + return this; + } + + public SuperByteBuffer overlay(int overlay) { + hasOverlay = true; + this.overlay = overlay; + return this; + } + + public SuperByteBuffer light() { + useWorldLight = true; + return this; + } + + public SuperByteBuffer light(Matrix4f lightTransform) { + useWorldLight = true; + this.lightTransform = lightTransform; + return this; + } + + public SuperByteBuffer light(int packedLightCoords) { + hasCustomLight = true; + this.packedLightCoords = packedLightCoords; + return this; + } + + public SuperByteBuffer light(Matrix4f lightTransform, int packedLightCoords) { + light(lightTransform); + light(packedLightCoords); + return this; + } + + /** + * Uses max light from calculated light (world light or custom light) and vertex light for the final light value. + * Ineffective if any other light method was not called. + */ + public SuperByteBuffer hybridLight() { + hybridLight = true; + return this; + } + + /** + * Transforms normals not only by the local matrix stack, but also by the passed matrix stack. + */ + public SuperByteBuffer fullNormalTransform() { + fullNormalTransform = true; + return this; + } + + public SuperByteBuffer forEntityRender() { + disableDiffuseMult(); + overlay(); + fullNormalTransform(); + return this; } public boolean isEmpty() { - return ((Buffer) template).limit() == 0; + return template.isEmpty(); + } + + public static int transformColor(byte component, float scale) { + return MathHelper.clamp((int) (Byte.toUnsignedInt(component) * scale), 0, 255); + } + + public static int transformColor(int component, float scale) { + return MathHelper.clamp((int) (component * scale), 0, 255); + } + + public static int maxLight(int packedLight1, int packedLight2) { + int blockLight1 = LightTexture.block(packedLight1); + int skyLight1 = LightTexture.sky(packedLight1); + int blockLight2 = LightTexture.block(packedLight2); + int skyLight2 = LightTexture.sky(packedLight2); + return LightTexture.pack(Math.max(blockLight1, blockLight2), Math.max(skyLight1, skyLight2)); + } + + private static int getLight(World world, Vector4f lightPos) { + BlockPos pos = new BlockPos(lightPos.x(), lightPos.y(), lightPos.z()); + return WORLD_LIGHT_CACHE.computeIfAbsent(pos.asLong(), $ -> WorldRenderer.getLightColor(world, pos)); } @FunctionalInterface @@ -305,4 +445,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..5027a0313 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; @@ -28,7 +28,7 @@ import net.minecraft.util.math.BlockPos; public class SuperByteBufferCache { - Map, Cache> cache; + private Map, Cache> cache; public SuperByteBufferCache() { cache = new HashMap<>(); @@ -87,20 +87,24 @@ public class SuperByteBufferCache { } public void registerCompartment(Compartment instance) { - cache.put(instance, CacheBuilder.newBuilder() - .build()); + synchronized (cache) { + cache.put(instance, CacheBuilder.newBuilder() + .build()); + } } public void registerCompartment(Compartment instance, long ticksUntilExpired) { - cache.put(instance, CacheBuilder.newBuilder() - .expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS) - .build()); + synchronized (cache) { + cache.put(instance, CacheBuilder.newBuilder() + .expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS) + .build()); + } } private SuperByteBuffer standardBlockRender(BlockState renderedState) { BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRendererDispatcher(); - return standardModelRender(dispatcher.getModelForState(renderedState), renderedState); + .getBlockRenderer(); + return standardModelRender(dispatcher.getBlockModel(renderedState), renderedState); } private SuperByteBuffer standardModelRender(IBakedModel model, BlockState referenceState) { @@ -115,14 +119,14 @@ public class SuperByteBufferCache { public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) { Minecraft mc = Minecraft.getInstance(); - BlockRendererDispatcher dispatcher = mc.getBlockRendererDispatcher(); - BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); + BlockRendererDispatcher dispatcher = mc.getBlockRenderer(); + BlockModelRenderer blockRenderer = dispatcher.getModelRenderer(); BufferBuilder builder = new BufferBuilder(512); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true, - mc.world.rand, 42, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); - builder.finishDrawing(); + blockRenderer.renderModel(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, + mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); + builder.end(); return builder; } diff --git a/src/main/java/com/simibubi/create/foundation/renderState/SuperRenderTypeBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperRenderTypeBuffer.java similarity index 63% rename from src/main/java/com/simibubi/create/foundation/renderState/SuperRenderTypeBuffer.java rename to src/main/java/com/simibubi/create/foundation/render/SuperRenderTypeBuffer.java index 8cc83176a..f55ad3870 100644 --- a/src/main/java/com/simibubi/create/foundation/renderState/SuperRenderTypeBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperRenderTypeBuffer.java @@ -1,8 +1,7 @@ -package com.simibubi.create.foundation.renderState; +package com.simibubi.create.foundation.render; import java.util.SortedMap; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.IVertexBuilder; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; @@ -48,17 +47,15 @@ public class SuperRenderTypeBuffer implements IRenderTypeBuffer { } public void draw() { - RenderSystem.disableCull(); - earlyBuffer.draw(); - defaultBuffer.draw(); - lateBuffer.draw(); + earlyBuffer.endBatch(); + defaultBuffer.endBatch(); + lateBuffer.endBatch(); } public void draw(RenderType type) { - RenderSystem.disableCull(); - earlyBuffer.draw(type); - defaultBuffer.draw(type); - lateBuffer.draw(type); + earlyBuffer.endBatch(type); + defaultBuffer.endBatch(type); + lateBuffer.endBatch(type); } private static class SuperRenderTypeBufferPhase extends IRenderTypeBuffer.Impl { @@ -68,28 +65,28 @@ public class SuperRenderTypeBuffer implements IRenderTypeBuffer { static final SortedMap createEntityBuilders() { return Util.make(new Object2ObjectLinkedOpenHashMap<>(), (map) -> { - map.put(Atlases.getEntitySolid(), blockBuilders.get(RenderType.getSolid())); + map.put(Atlases.solidBlockSheet(), blockBuilders.builder(RenderType.solid())); assign(map, RenderTypes.getOutlineSolid()); - map.put(Atlases.getEntityCutout(), blockBuilders.get(RenderType.getCutout())); - map.put(Atlases.getBannerPatterns(), blockBuilders.get(RenderType.getCutoutMipped())); - map.put(Atlases.getEntityTranslucentCull(), blockBuilders.get(RenderType.getTranslucent())); // FIXME new equivalent of getEntityTranslucent() ? - assign(map, Atlases.getShieldPatterns()); - assign(map, Atlases.getBeds()); - assign(map, Atlases.getShulkerBoxes()); - assign(map, Atlases.getSign()); - assign(map, Atlases.getChest()); - assign(map, RenderType.getTranslucentNoCrumbling()); - assign(map, RenderType.getGlint()); - assign(map, RenderType.getEntityGlint()); - assign(map, RenderType.getWaterMask()); - ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.forEach((p_228488_1_) -> { + map.put(Atlases.cutoutBlockSheet(), blockBuilders.builder(RenderType.cutout())); + map.put(Atlases.bannerSheet(), blockBuilders.builder(RenderType.cutoutMipped())); + map.put(Atlases.translucentCullBlockSheet(), blockBuilders.builder(RenderType.translucent())); // FIXME new equivalent of getEntityTranslucent() ? + assign(map, Atlases.shieldSheet()); + assign(map, Atlases.bedSheet()); + assign(map, Atlases.shulkerBoxSheet()); + assign(map, Atlases.signSheet()); + assign(map, Atlases.chestSheet()); + assign(map, RenderType.translucentNoCrumbling()); + assign(map, RenderType.glint()); + assign(map, RenderType.entityGlint()); + assign(map, RenderType.waterMask()); + ModelBakery.DESTROY_TYPES.forEach((p_228488_1_) -> { assign(map, p_228488_1_); }); }); } private static void assign(Object2ObjectLinkedOpenHashMap map, RenderType type) { - map.put(type, new BufferBuilder(type.getExpectedBufferSize())); + map.put(type, new BufferBuilder(type.bufferSize())); } protected SuperRenderTypeBufferPhase() { 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..78462e4ba 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,19 @@ package com.simibubi.create.foundation.render; import java.util.Iterator; +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; 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,30 +27,29 @@ 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 + if (Backend.getInstance().canUseInstancing(renderWorld) && InstancedRenderRegistry.getInstance() + .shouldSkipRender(tileEntity)) continue; TileEntityRenderer renderer = TileEntityRendererDispatcher.instance.getRenderer(tileEntity); if (renderer == null) { @@ -54,17 +57,22 @@ public class TileEntityRenderHelper { continue; } - BlockPos pos = tileEntity.getPos(); - ms.push(); - MatrixStacker.of(ms) + BlockPos pos = tileEntity.getBlockPos(); + ms.pushPose(); + MatrixTransformStack.of(ms) .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); - renderer.render(tileEntity, pt, ms, buffer, worldLight, OverlayTexture.DEFAULT_UV); + 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.x(), lightVec.y(), lightVec.z()); + } else { + lightPos = pos; + } + int worldLight = getCombinedLight(world, lightPos, renderWorld, pos); + renderer.render(tileEntity, pt, ms, buffer, worldLight, OverlayTexture.NO_OVERLAY); } catch (Exception e) { iterator.remove(); @@ -73,13 +81,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(); + ms.popPose(); } } + public static int getCombinedLight(World world, BlockPos worldPos, @Nullable PlacementSimulationWorld renderWorld, + BlockPos renderWorldPos) { + int worldLight = WorldRenderer.getLightColor(world, worldPos); + + if (renderWorld != null) { + int renderWorldLight = WorldRenderer.getLightColor(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/backend/light/LightVolumeDebugger.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolumeDebugger.java deleted file mode 100644 index e63257d04..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolumeDebugger.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.simibubi.create.foundation.render.backend.light; - -import java.util.ArrayList; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.outliner.AABBOutline; - -public class LightVolumeDebugger { - public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { - ContraptionRenderDispatcher.renderers.values() - .stream() - .flatMap(r -> { - GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume(); - GridAlignedBB sample = r.getLighter().lightVolume.getSampleVolume(); - - ArrayList> pairs = new ArrayList<>(2); - - pairs.add(Pair.of(texture, 0xFFFFFF)); - pairs.add(Pair.of(sample, 0xFFFF00)); - - return pairs.stream(); - }) - .map(pair -> { - AABBOutline outline = new AABBOutline(GridAlignedBB.toAABB(pair.getFirst())); - - outline.getParams().colored(pair.getSecond()); - return outline; - }) - .forEach(outline -> outline.render(ms, buffer, AnimationTickHolder.getPartialTicks())); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java b/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java deleted file mode 100644 index 31c129642..000000000 --- a/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.simibubi.create.foundation.renderState; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.simibubi.create.AllSpecialTextures; - -import net.minecraft.client.renderer.RenderState; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.inventory.container.PlayerContainer; -import net.minecraft.util.ResourceLocation; - -public class RenderTypes extends RenderState { - - protected static final RenderState.CullState DISABLE_CULLING = new NoCullState(); - - public static RenderType getOutlineTranslucent(ResourceLocation texture, boolean cull) { - RenderType.State rendertype$state = RenderType.State.builder() - .texture(new RenderState.TextureState(texture, false, false)) - .transparency(TRANSLUCENT_TRANSPARENCY) - .diffuseLighting(ENABLE_DIFFUSE_LIGHTING) - .alpha(ONE_TENTH_ALPHA) - .cull(cull ? ENABLE_CULLING : DISABLE_CULLING) - .lightmap(ENABLE_LIGHTMAP) - .overlay(ENABLE_OVERLAY_COLOR) - .build(true); - return RenderType.of("outline_translucent" + (cull ? "_cull" : ""), - DefaultVertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, 7, 256, true, true, rendertype$state); - } - - private static final RenderType OUTLINE_SOLID = - RenderType.of("outline_solid", DefaultVertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, 7, 256, true, - false, RenderType.State.builder() - .texture(new RenderState.TextureState(AllSpecialTextures.BLANK.getLocation(), false, false)) - .transparency(NO_TRANSPARENCY) - .diffuseLighting(ENABLE_DIFFUSE_LIGHTING) - .lightmap(ENABLE_LIGHTMAP) - .overlay(ENABLE_OVERLAY_COLOR) - .build(true)); - - public static RenderType getGlowingSolid(ResourceLocation texture) { - RenderType.State rendertype$state = RenderType.State.builder() - .texture(new RenderState.TextureState(texture, false, false)) - .transparency(NO_TRANSPARENCY) - .diffuseLighting(DISABLE_DIFFUSE_LIGHTING) - .lightmap(ENABLE_LIGHTMAP) - .overlay(ENABLE_OVERLAY_COLOR) - .build(true); - return RenderType.of("glowing_solid", DefaultVertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, 7, 256, - true, false, rendertype$state); - } - - public static RenderType getGlowingTranslucent(ResourceLocation texture) { - RenderType.State rendertype$state = RenderType.State.builder() - .texture(new RenderState.TextureState(texture, false, false)) - .transparency(TRANSLUCENT_TRANSPARENCY) - .diffuseLighting(DISABLE_DIFFUSE_LIGHTING) - .alpha(ONE_TENTH_ALPHA) - .cull(DISABLE_CULLING) - .lightmap(ENABLE_LIGHTMAP) - .overlay(ENABLE_OVERLAY_COLOR) - .build(true); - return RenderType.of("glowing_translucent", DefaultVertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, 7, - 256, true, true, rendertype$state); - } - - private static final RenderType GLOWING_SOLID = RenderTypes.getGlowingSolid(PlayerContainer.BLOCK_ATLAS_TEXTURE); - private static final RenderType GLOWING_TRANSLUCENT = - RenderTypes.getGlowingTranslucent(PlayerContainer.BLOCK_ATLAS_TEXTURE); - - private static final RenderType ITEM_PARTIAL_SOLID = - RenderType.of("item_solid", DefaultVertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, 7, 256, true, - false, RenderType.State.builder() - .texture(new RenderState.TextureState(PlayerContainer.BLOCK_ATLAS_TEXTURE, false, false)) - .transparency(NO_TRANSPARENCY) - .diffuseLighting(ENABLE_DIFFUSE_LIGHTING) - .lightmap(ENABLE_LIGHTMAP) - .overlay(ENABLE_OVERLAY_COLOR) - .build(true)); - - private static final RenderType ITEM_PARTIAL_TRANSLUCENT = RenderType.of("entity_translucent", - DefaultVertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL, 7, 256, true, true, RenderType.State.builder() - .texture(new RenderState.TextureState(PlayerContainer.BLOCK_ATLAS_TEXTURE, false, false)) - .transparency(TRANSLUCENT_TRANSPARENCY) - .diffuseLighting(ENABLE_DIFFUSE_LIGHTING) - .alpha(ONE_TENTH_ALPHA) - .cull(DISABLE_CULLING) - .lightmap(ENABLE_LIGHTMAP) - .overlay(ENABLE_OVERLAY_COLOR) - .build(true)); - - public static RenderType getItemPartialSolid() { - return ITEM_PARTIAL_SOLID; - } - - public static RenderType getItemPartialTranslucent() { - return ITEM_PARTIAL_TRANSLUCENT; - } - - public static RenderType getOutlineSolid() { - return OUTLINE_SOLID; - } - - public static RenderType getGlowingSolid() { - return GLOWING_SOLID; - } - - public static RenderType getGlowingTranslucent() { - return GLOWING_TRANSLUCENT; - } - - protected static class NoCullState extends RenderState.CullState { - public NoCullState() { - super(false); - } - - @Override - public void startDrawing() { - RenderSystem.disableCull(); - } - } - - // Mmm gimme those protected fields - public RenderTypes() { - super(null, null, null); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/sound/ContinuousSound.java b/src/main/java/com/simibubi/create/foundation/sound/ContinuousSound.java index 6055b26db..9f2dceeb1 100644 --- a/src/main/java/com/simibubi/create/foundation/sound/ContinuousSound.java +++ b/src/main/java/com/simibubi/create/foundation/sound/ContinuousSound.java @@ -15,13 +15,13 @@ public class ContinuousSound extends TickableSound { this.scape = scape; this.sharedPitch = sharedPitch; this.relativeVolume = relativeVolume; - this.repeat = true; - this.repeatDelay = 0; - this.global = false; + this.looping = true; + this.delay = 0; + this.relative = false; } public void remove() { - setDone(); + stop(); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/sound/RepeatingSound.java b/src/main/java/com/simibubi/create/foundation/sound/RepeatingSound.java index 0c8d4c97e..61d460214 100644 --- a/src/main/java/com/simibubi/create/foundation/sound/RepeatingSound.java +++ b/src/main/java/com/simibubi/create/foundation/sound/RepeatingSound.java @@ -29,10 +29,10 @@ public class RepeatingSound { if (AnimationTickHolder.getTicks() % repeatDelay != 0) return; - ClientWorld world = Minecraft.getInstance().world; + ClientWorld world = Minecraft.getInstance().level; Vector3d meanPos = scape.getMeanPos(); - world.playSound(meanPos.x, meanPos.y, meanPos.z, event, SoundCategory.AMBIENT, + world.playLocalSound(meanPos.x, meanPos.y, meanPos.z, event, SoundCategory.AMBIENT, scape.getVolume() * relativeVolume, sharedPitch, true); } 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..ab95e1a48 100644 --- a/src/main/java/com/simibubi/create/foundation/sound/SoundScape.java +++ b/src/main/java/com/simibubi/create/foundation/sound/SoundScape.java @@ -3,12 +3,14 @@ package com.simibubi.create.foundation.sound; import java.util.ArrayList; import java.util.List; +import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; import com.simibubi.create.foundation.sound.SoundScapes.PitchGroup; 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; @@ -50,7 +52,7 @@ class SoundScape { public void play() { continuous.forEach(Minecraft.getInstance() - .getSoundHandler()::play); + .getSoundManager()::play); } public void tick() { @@ -80,9 +82,17 @@ class SoundScape { } public float getVolume() { + Entity renderViewEntity = Minecraft.getInstance().cameraEntity; + float distanceMultiplier = 0; + if (renderViewEntity != null) { + double distanceTo = renderViewEntity.position() + .distanceTo(getMeanPos()); + distanceMultiplier = (float) MathHelper.lerp(distanceTo / SoundScapes.MAX_AMBIENT_SOURCE_DISTANCE, 2, 0); + } int soundCount = SoundScapes.getSoundCount(group, pitchGroup); + float max = AllConfigs.CLIENT.ambientVolumeCap.getF(); 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, max) * 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..d62449315 100644 --- a/src/main/java/com/simibubi/create/foundation/sound/SoundScapes.java +++ b/src/main/java/com/simibubi/create/foundation/sound/SoundScapes.java @@ -11,6 +11,7 @@ import java.util.Set; import java.util.function.BiFunction; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Pair; @@ -25,9 +26,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), + CRUSHING(SoundScapes::crushing), + MILLING(SoundScapes::milling), ; @@ -44,11 +48,22 @@ public class SoundScapes { } private static SoundScape kinetic(float pitch, AmbienceGroup group) { - return new SoundScape(pitch, group).continuous(SoundEvents.ENTITY_MINECART_INSIDE, .25f, 1); + return new SoundScape(pitch, group).continuous(SoundEvents.MINECART_INSIDE, .25f, 1); } 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); + } + + private static SoundScape crushing(float pitch, AmbienceGroup group) { + return new SoundScape(pitch, group).repeating(AllSoundEvents.CRUSHING_1.getMainEvent(), 1.545f, .75f, 1) + .repeating(AllSoundEvents.CRUSHING_2.getMainEvent(), 0.425f, .75f, 2) + .repeating(AllSoundEvents.CRUSHING_3.getMainEvent(), 2f, 1.75f, 2); + } + + private static SoundScape milling(float pitch, AmbienceGroup group) { + return new SoundScape(pitch, group).repeating(AllSoundEvents.CRUSHING_1.getMainEvent(), 1.545f, .75f, 1) + .repeating(AllSoundEvents.CRUSHING_2.getMainEvent(), 0.425f, .75f, 2); } enum PitchGroup { @@ -58,14 +73,11 @@ 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 (!AllConfigs.CLIENT.enableAmbientSounds.get()) + return; 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() { @@ -75,6 +87,7 @@ public class SoundScapes { if (AnimationTickHolder.getTicks() % UPDATE_INTERVAL != 0) return; + boolean disable = !AllConfigs.CLIENT.enableAmbientSounds.get(); for (Iterator, SoundScape>> iterator = activeSounds.entrySet() .iterator(); iterator.hasNext();) { @@ -82,7 +95,7 @@ public class SoundScapes { Pair key = entry.getKey(); SoundScape value = entry.getValue(); - if (getSoundCount(key.getFirst(), key.getSecond()) == 0) { + if (disable || getSoundCount(key.getFirst(), key.getSecond()) == 0) { value.remove(); iterator.remove(); } @@ -93,7 +106,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,22 +120,21 @@ 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) { - return !getCameraPos().withinDistance(pos, MAX_AMBIENT_SOURCE_DISTANCE); + return !getCameraPos().closerThan(pos, MAX_AMBIENT_SOURCE_DISTANCE); } protected static BlockPos getCameraPos() { - Entity renderViewEntity = Minecraft.getInstance().renderViewEntity; + Entity renderViewEntity = Minecraft.getInstance().cameraEntity; if (renderViewEntity == null) return BlockPos.ZERO; - BlockPos playerLocation = renderViewEntity.getBlockPos(); + BlockPos playerLocation = renderViewEntity.blockPosition(); return playerLocation; } 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..7d88ca00f 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java @@ -6,17 +6,25 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; +import com.simibubi.create.api.event.TileEntityBehaviourEvent; +import com.simibubi.create.content.schematics.ItemRequirement; +import com.simibubi.create.foundation.gui.IInteractionChecker; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.utility.IPartialSafeNBT; import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntityType; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; 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, IInteractionChecker { private final Map, TileEntityBehaviour> behaviours; // Internally maintained to be identical to behaviorMap.values() in order to improve iteration performance. @@ -54,7 +62,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka @Override public void tick() { - if (!initialized && hasWorld()) { + if (!initialized && hasLevel()) { initialize(); initialized = true; } @@ -68,12 +76,18 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka } public void initialize() { + if (firstNbtRead) { + firstNbtRead = false; + MinecraftForge.EVENT_BUS.post(new TileEntityBehaviourEvent<>(getBlockState(), this, behaviours)); + updateBehaviorList(); + } + behaviourList.forEach(TileEntityBehaviour::initialize); lazyTick(); } @Override - public final CompoundNBT write(CompoundNBT compound) { + public final CompoundNBT save(CompoundNBT compound) { write(compound, false); return compound; } @@ -90,7 +104,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka } @Override - public final void fromTag(BlockState state, CompoundNBT tag) { + public final void load(BlockState state, CompoundNBT tag) { fromTag(state, tag, false); } @@ -103,10 +117,10 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka ArrayList list = new ArrayList<>(); addBehavioursDeferred(list); list.forEach(b -> behaviours.put(b.getType(), b)); - + MinecraftForge.EVENT_BUS.post(new TileEntityBehaviourEvent<>(state, this, behaviours)); updateBehaviorList(); } - super.fromTag(state, compound); + super.load(state, compound); behaviourList.forEach(tb -> tb.read(compound, clientPacket)); } @@ -114,14 +128,31 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka * Hook only these in future subclasses of STE */ protected void write(CompoundNBT compound, boolean clientPacket) { - super.write(compound); + super.save(compound); behaviourList.forEach(tb -> tb.write(compound, clientPacket)); } @Override - public void remove() { + public void writeSafe(CompoundNBT compound, boolean clientPacket) { + super.save(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 setRemoved() { forEachBehaviour(TileEntityBehaviour::remove); - super.remove(); + super.setRemoved(); } public void setLazyTickRate(int slowTickRate) { @@ -182,4 +213,20 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka return virtualMode; } + @Override + public boolean canPlayerUse(PlayerEntity player) { + if (level == null || level.getBlockEntity(worldPosition) != this) + return false; + return player.distanceToSqr(worldPosition.getX() + 0.5D, worldPosition.getY() + 0.5D, + worldPosition.getZ() + 0.5D) <= 64.0D; + } + + public void sendToContainer(PacketBuffer buffer) { + buffer.writeBlockPos(getBlockPos()); + buffer.writeNbt(getUpdateTag()); + } + + public World getWorld() { + return getLevel(); + } } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/SyncedTileEntity.java b/src/main/java/com/simibubi/create/foundation/tileEntity/SyncedTileEntity.java index 2c8929358..dcc242b5a 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/SyncedTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/SyncedTileEntity.java @@ -28,46 +28,46 @@ public abstract class SyncedTileEntity extends TileEntity { @Override public CompoundNBT getUpdateTag() { - return write(new CompoundNBT()); + return save(new CompoundNBT()); } @Override public void handleUpdateTag(BlockState state, CompoundNBT tag) { - fromTag(state, tag); + load(state, tag); } public void sendData() { - if (world != null) - world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 4 | 16); + if (level != null && !level.isClientSide) + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 2 | 4 | 16); } public void causeBlockUpdate() { - if (world != null) - world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 1); + if (level != null) + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 1); } @Override public SUpdateTileEntityPacket getUpdatePacket() { - return new SUpdateTileEntityPacket(getPos(), 1, writeToClient(new CompoundNBT())); + return new SUpdateTileEntityPacket(getBlockPos(), 1, writeToClient(new CompoundNBT())); } @Override public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) { - readClientUpdate(getBlockState(), pkt.getNbtCompound()); + readClientUpdate(getBlockState(), pkt.getTag()); } // Special handling for client update packets public void readClientUpdate(BlockState state, CompoundNBT tag) { - fromTag(state, tag); + load(state, tag); } // Special handling for client update packets public CompoundNBT writeToClient(CompoundNBT tag) { - return write(tag); + return save(tag); } public void notifyUpdate() { - markDirty(); + setChanged(); sendData(); } @@ -76,7 +76,7 @@ public abstract class SyncedTileEntity extends TileEntity { } public Chunk containedChunk() { - SectionPos sectionPos = SectionPos.from(pos); - return world.getChunk(sectionPos.getSectionX(), sectionPos.getSectionZ()); + SectionPos sectionPos = SectionPos.of(worldPosition); + return level.getChunk(sectionPos.x(), sectionPos.z()); } } 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..7eb8241ac 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,8 @@ package com.simibubi.create.foundation.tileEntity; +import java.util.ConcurrentModificationException; + +import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import net.minecraft.block.BlockState; @@ -42,6 +45,14 @@ public abstract class TileEntityBehaviour { } + public boolean isSafeNBT() { + return false; + } + + public ItemRequirement getRequiredItems() { + return ItemRequirement.NONE; + } + public void onBlockChanged(BlockState oldState) { } @@ -68,20 +79,26 @@ public abstract class TileEntityBehaviour { } public BlockPos getPos() { - return tileEntity.getPos(); + return tileEntity.getBlockPos(); } public World getWorld() { - return tileEntity.getWorld(); + return tileEntity.getLevel(); } public static T get(IBlockReader reader, BlockPos pos, BehaviourType type) { - return get(reader.getTileEntity(pos), type); + TileEntity te; + try { + te = reader.getBlockEntity(pos); + } catch (ConcurrentModificationException e) { + te = null; + } + return get(te, type); } public static void destroy(IBlockReader reader, BlockPos pos, BehaviourType type) { - T behaviour = get(reader.getTileEntity(pos), type); + T behaviour = get(reader.getBlockEntity(pos), type); if (behaviour != null) behaviour.destroy(); } @@ -94,5 +111,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/ValueBox.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java index a81df38bb..0fd48ee01 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java @@ -3,10 +3,10 @@ package com.simibubi.create.foundation.tileEntity.behaviour; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform.Sided; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; -import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.outliner.ChasingAABBOutline; @@ -40,7 +40,7 @@ public class ValueBox extends ChasingAABBOutline { super(bb); this.label = label; this.pos = pos; - this.blockState = Minecraft.getInstance().world.getBlockState(pos); + this.blockState = Minecraft.getInstance().level.getBlockState(pos); } public ValueBox transform(ValueBoxTransform transform) { @@ -82,12 +82,12 @@ public class ValueBox extends ChasingAABBOutline { if (hasTransform && !transform.shouldRender(blockState)) return; - ms.push(); + ms.pushPose(); ms.translate(pos.getX(), pos.getY(), pos.getZ()); if (hasTransform) transform.transform(blockState, ms); - transformNormals = ms.peek() - .getNormal() + transformNormals = ms.last() + .normal() .copy(); params.colored(isPassive ? passiveColor : highlightColor); super.render(ms, buffer, pt); @@ -95,12 +95,12 @@ public class ValueBox extends ChasingAABBOutline { float fontScale = hasTransform ? -transform.getFontScale() : -1 / 64f; ms.scale(fontScale, fontScale, fontScale); - ms.push(); + ms.pushPose(); renderContents(ms, buffer); - ms.pop(); + ms.popPose(); if (!isPassive) { - ms.push(); + ms.pushPose(); ms.translate(17.5, -.5, 7); ms.translate(labelOffset.x, labelOffset.y, labelOffset.z); @@ -109,15 +109,15 @@ public class ValueBox extends ChasingAABBOutline { ms.translate(0, 10, 0); renderHoveringText(ms, buffer, sublabel); } - if (!scrollTooltip.getUnformattedComponentText().isEmpty()) { + if (!scrollTooltip.getContents().isEmpty()) { ms.translate(0, 10, 0); renderHoveringText(ms, buffer, scrollTooltip, 0x998899, 0x111111); } - ms.pop(); + ms.popPose(); } - ms.pop(); + ms.popPose(); } public void renderContents(MatrixStack ms, IRenderTypeBuffer buffer) {} @@ -135,15 +135,15 @@ public class ValueBox extends ChasingAABBOutline { @Override public void renderContents(MatrixStack ms, IRenderTypeBuffer buffer) { super.renderContents(ms, buffer); - FontRenderer font = Minecraft.getInstance().fontRenderer; + FontRenderer font = Minecraft.getInstance().font; ITextComponent countString = new StringTextComponent(count == 0 ? "*" : count + ""); ms.translate(17.5f, -5f, 7f); boolean isFilter = stack.getItem() instanceof FilterItem; boolean isEmpty = stack.isEmpty(); float scale = 1.5f; - ms.translate(-font.getWidth(countString), 0, 0); - + ms.translate(-font.width(countString), 0, 0); + if (isFilter) ms.translate(3, 8, 7.25f); else if (isEmpty) { @@ -172,17 +172,17 @@ public class ValueBox extends ChasingAABBOutline { @Override public void renderContents(MatrixStack ms, IRenderTypeBuffer buffer) { super.renderContents(ms, buffer); - FontRenderer font = Minecraft.getInstance().fontRenderer; + FontRenderer font = Minecraft.getInstance().font; float scale = 4; ms.scale(scale, scale, 1); ms.translate(-4, -4, 5); - int stringWidth = font.getWidth(text); - float numberScale = (float) font.FONT_HEIGHT / stringWidth; + int stringWidth = font.width(text); + float numberScale = (float) font.lineHeight / stringWidth; boolean singleDigit = stringWidth < 10; if (singleDigit) numberScale = numberScale / 2; - float verticalMargin = (stringWidth - font.FONT_HEIGHT) / 2f; + float verticalMargin = (stringWidth - font.lineHeight) / 2f; ms.scale(numberScale, numberScale, numberScale); ms.translate(singleDigit ? stringWidth / 2 : 0, singleDigit ? -verticalMargin : verticalMargin, 0); @@ -215,21 +215,21 @@ public class ValueBox extends ChasingAABBOutline { // util protected void renderHoveringText(MatrixStack ms, IRenderTypeBuffer buffer, ITextComponent text) { - renderHoveringText(ms, buffer, text, highlightColor, ColorHelper.mixColors(passiveColor, 0, 0.75f)); + renderHoveringText(ms, buffer, text, highlightColor, Color.mixColors(passiveColor, 0, 0.75f)); } protected void renderHoveringText(MatrixStack ms, IRenderTypeBuffer buffer, ITextComponent text, int color, int shadowColor) { - ms.push(); + ms.pushPose(); drawString(ms, buffer, text, 0, 0, color); ms.translate(0, 0, -.25); drawString(ms, buffer, text, 1, 1, shadowColor); - ms.pop(); + ms.popPose(); } private static void drawString(MatrixStack ms, IRenderTypeBuffer buffer, ITextComponent text, float x, float y, int color) { - Minecraft.getInstance().fontRenderer.draw(text, x, y, color, false, ms.peek() - .getModel(), buffer, false, 0, 15728880); + Minecraft.getInstance().font.drawInBatch(text, x, y, color, false, ms.last() + .pose(), buffer, false, 0, 15728880); } } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxRenderer.java index fd37abb2a..083fca71a 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxRenderer.java @@ -16,18 +16,19 @@ import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tags.BlockTags; +import net.minecraftforge.client.model.ItemMultiLayerBakedModel; public class ValueBoxRenderer { public static void renderItemIntoValueBox(ItemStack filter, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer(); - IBakedModel modelWithOverrides = itemRenderer.getItemModelWithOverrides(filter, Minecraft.getInstance().world, null); - boolean blockItem = modelWithOverrides.isGui3d(); + IBakedModel modelWithOverrides = itemRenderer.getModel(filter, Minecraft.getInstance().level, null); + boolean blockItem = modelWithOverrides.isGui3d() && !(modelWithOverrides instanceof ItemMultiLayerBakedModel); float scale = (!blockItem ? .5f : 1f) - 1 / 64f; float zOffset = (!blockItem ? -.225f : 0) + customZOffset(filter.getItem()); ms.scale(scale, scale, scale); ms.translate(0, 0, zOffset); - itemRenderer.renderItem(filter, TransformType.FIXED, light, overlay, ms, buffer); + itemRenderer.renderStatic(filter, TransformType.FIXED, light, overlay, ms, buffer); } private static float customZOffset(Item item) { @@ -40,7 +41,7 @@ public class ValueBoxRenderer { return NUDGE; if (block instanceof FenceBlock) return NUDGE; - if (block.isIn(BlockTags.BUTTONS)) + if (block.is(BlockTags.BUTTONS)) return NUDGE; if (block == Blocks.END_ROD) return NUDGE; diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java index 0d74f4e52..d701a8ae7 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java @@ -4,9 +4,9 @@ import java.util.function.Function; import org.apache.commons.lang3.tuple.Pair; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -46,10 +46,10 @@ public abstract class ValueBoxTransform { protected Vector3d rotateHorizontally(BlockState state, Vector3d vec) { float yRot = 0; - if (state.contains(BlockStateProperties.FACING)) - yRot = AngleHelper.horizontalAngle(state.get(BlockStateProperties.FACING)); - if (state.contains(BlockStateProperties.HORIZONTAL_FACING)) - yRot = AngleHelper.horizontalAngle(state.get(BlockStateProperties.HORIZONTAL_FACING)); + if (state.hasProperty(BlockStateProperties.FACING)) + yRot = AngleHelper.horizontalAngle(state.getValue(BlockStateProperties.FACING)); + if (state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) + yRot = AngleHelper.horizontalAngle(state.getValue(BlockStateProperties.HORIZONTAL_FACING)); return VecHelper.rotateCentered(vec, yRot, Axis.Y); } @@ -109,7 +109,7 @@ public abstract class ValueBoxTransform { protected void rotate(BlockState state, MatrixStack ms) { float yRot = AngleHelper.horizontalAngle(getSide()) + 180; float xRot = getSide() == Direction.UP ? 90 : getSide() == Direction.DOWN ? 270 : 0; - MatrixStacker.of(ms) + MatrixTransformStack.of(ms) .rotateY(yRot) .rotateX(xRot); } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/BeltProcessingBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/BeltProcessingBehaviour.java index 8725bce5d..3d9af3d78 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/BeltProcessingBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/BeltProcessingBehaviour.java @@ -43,10 +43,10 @@ public class BeltProcessingBehaviour extends TileEntityBehaviour { } public static boolean isBlocked(IBlockReader world, BlockPos processingSpace) { - BlockState blockState = world.getBlockState(processingSpace.up()); + BlockState blockState = world.getBlockState(processingSpace.above()); if (AbstractFunnelBlock.isFunnel(blockState)) return false; - return !blockState.getCollisionShape(world, processingSpace.up()) + return !blockState.getCollisionShape(world, processingSpace.above()) .isEmpty(); } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/DirectBeltInputBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/DirectBeltInputBehaviour.java index 823568969..a11f4f4a0 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/DirectBeltInputBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/DirectBeltInputBehaviour.java @@ -99,20 +99,20 @@ public class DirectBeltInputBehaviour extends TileEntityBehaviour { @Nullable public ItemStack tryExportingToBeltFunnel(ItemStack stack, @Nullable Direction side, boolean simulate) { - BlockPos funnelPos = tileEntity.getPos() - .up(); + BlockPos funnelPos = tileEntity.getBlockPos() + .above(); World world = getWorld(); BlockState funnelState = world.getBlockState(funnelPos); if (!(funnelState.getBlock() instanceof BeltFunnelBlock)) return null; - if (funnelState.get(BeltFunnelBlock.SHAPE) != Shape.PULLING) + if (funnelState.getValue(BeltFunnelBlock.SHAPE) != Shape.PULLING) return null; if (side != null && FunnelBlock.getFunnelFacing(funnelState) != side) return null; - TileEntity te = world.getTileEntity(funnelPos); + TileEntity te = world.getBlockEntity(funnelPos); if (!(te instanceof FunnelTileEntity)) return null; - if (funnelState.get(BeltFunnelBlock.POWERED)) + if (funnelState.getValue(BeltFunnelBlock.POWERED)) return stack; ItemStack insert = FunnelBlock.tryInsert(world, funnelPos, stack, simulate); if (insert.getCount() != stack.getCount() && !simulate) diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java index 56fcc5c91..9e43eca67 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java @@ -86,7 +86,7 @@ public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour { public TransportedItemStackHandlerBehaviour(SmartTileEntity te, ProcessingCallback processingCallback) { super(te); this.processingCallback = processingCallback; - positionGetter = t -> VecHelper.getCenterOf(te.getPos()); + positionGetter = t -> VecHelper.getCenterOf(te.getBlockPos()); } public TransportedItemStackHandlerBehaviour withStackPlacement(PositionGetter function) { diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java index 82ca086b9..47bb85727 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java @@ -35,9 +35,9 @@ public class EdgeInteractionHandler { BlockPos pos = event.getPos(); PlayerEntity player = event.getPlayer(); Hand hand = event.getHand(); - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getItemInHand(hand); - if (player.isSneaking() || player.isSpectator()) + if (player.isShiftKeyDown() || player.isSpectator()) return; EdgeInteractionBehaviour behaviour = TileEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE); if (behaviour == null) @@ -48,28 +48,28 @@ public class EdgeInteractionHandler { if (behaviour.requiredItem.orElse(heldItem.getItem()) != heldItem.getItem()) return; - Direction activatedDirection = getActivatedDirection(world, pos, ray.getFace(), ray.getHitVec(), behaviour); + Direction activatedDirection = getActivatedDirection(world, pos, ray.getDirection(), ray.getLocation(), behaviour); if (activatedDirection == null) return; if (event.getSide() != LogicalSide.CLIENT) - behaviour.connectionCallback.apply(world, pos, pos.offset(activatedDirection)); + behaviour.connectionCallback.apply(world, pos, pos.relative(activatedDirection)); event.setCanceled(true); event.setCancellationResult(ActionResultType.SUCCESS); - world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f); + world.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f); } public static List getConnectiveSides(World world, BlockPos pos, Direction face, EdgeInteractionBehaviour behaviour) { List sides = new ArrayList<>(6); - if (BlockHelper.hasBlockSolidSide(world.getBlockState(pos.offset(face)), world, pos.offset(face), face.getOpposite())) + if (BlockHelper.hasBlockSolidSide(world.getBlockState(pos.relative(face)), world, pos.relative(face), face.getOpposite())) return sides; for (Direction direction : Iterate.directions) { if (direction.getAxis() == face.getAxis()) continue; - BlockPos neighbourPos = pos.offset(direction); - if (BlockHelper.hasBlockSolidSide(world.getBlockState(neighbourPos.offset(face)), world, neighbourPos.offset(face), + BlockPos neighbourPos = pos.relative(direction); + if (BlockHelper.hasBlockSolidSide(world.getBlockState(neighbourPos.relative(face)), world, neighbourPos.relative(face), face.getOpposite())) continue; if (!behaviour.connectivityPredicate.test(world, pos, face, direction)) @@ -92,7 +92,7 @@ public class EdgeInteractionHandler { static AxisAlignedBB getBB(BlockPos pos, Direction direction) { AxisAlignedBB bb = new AxisAlignedBB(pos); - Vector3i vec = direction.getDirectionVec(); + Vector3i vec = direction.getNormal(); int x = vec.getX(); int y = vec.getY(); int z = vec.getZ(); @@ -102,9 +102,9 @@ public class EdgeInteractionHandler { double absZ = Math.abs(z) * margin; bb = bb.contract(absX, absY, absZ); - bb = bb.offset(absX / 2d, absY / 2d, absZ / 2d); - bb = bb.offset(x / 2d, y / 2d, z / 2d); - bb = bb.grow(1 / 256f); + bb = bb.move(absX / 2d, absY / 2d, absZ / 2d); + bb = bb.move(x / 2d, y / 2d, z / 2d); + bb = bb.inflate(1 / 256f); return bb; } 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..1c6d512ad 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 @@ -25,17 +25,17 @@ public class EdgeInteractionRenderer { public static void tick() { Minecraft mc = Minecraft.getInstance(); - RayTraceResult target = mc.objectMouseOver; + RayTraceResult target = mc.hitResult; if (target == null || !(target instanceof BlockRayTraceResult)) return; BlockRayTraceResult result = (BlockRayTraceResult) target; - ClientWorld world = mc.world; - BlockPos pos = result.getPos(); + ClientWorld world = mc.level; + BlockPos pos = result.getBlockPos(); PlayerEntity player = mc.player; - ItemStack heldItem = player.getHeldItemMainhand(); + ItemStack heldItem = player.getMainHandItem(); - if (player.isSneaking()) + if (player.isShiftKeyDown()) return; EdgeInteractionBehaviour behaviour = TileEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE); if (behaviour == null) @@ -43,7 +43,7 @@ public class EdgeInteractionRenderer { if (behaviour.requiredItem.orElse(heldItem.getItem()) != heldItem.getItem()) return; - Direction face = result.getFace(); + Direction face = result.getDirection(); List connectiveSides = EdgeInteractionHandler.getConnectiveSides(world, pos, face, behaviour); if (connectiveSides.isEmpty()) return; @@ -52,7 +52,7 @@ public class EdgeInteractionRenderer { double bestDistance = Double.MAX_VALUE; Vector3d center = VecHelper.getCenterOf(pos); for (Direction direction : connectiveSides) { - double distance = Vector3d.of(direction.getDirectionVec()).subtract(target.getHitVec() + double distance = Vector3d.atLowerCornerOf(direction.getNormal()).subtract(target.getLocation() .subtract(center)) .length(); if (distance > bestDistance) @@ -62,9 +62,9 @@ public class EdgeInteractionRenderer { } AxisAlignedBB bb = EdgeInteractionHandler.getBB(pos, closestEdge); - boolean hit = bb.contains(target.getHitVec()); + boolean hit = bb.contains(target.getLocation()); - ValueBox box = new ValueBox(StringTextComponent.EMPTY, bb.offset(-pos.getX(), -pos.getY(), -pos.getZ()), pos); + ValueBox box = new ValueBox(StringTextComponent.EMPTY, bb.move(-pos.getX(), -pos.getY(), -pos.getZ()), pos); Vector3d textOffset = Vector3d.ZERO; boolean positive = closestEdge.getAxisDirection() == AxisDirection.POSITIVE; @@ -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..b7098e455 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()); @@ -71,7 +76,7 @@ public class FilteringBehaviour extends TileEntityBehaviour { @Override public void read(CompoundNBT nbt, boolean clientPacket) { - filter = ItemStack.read(nbt.getCompound("Filter")); + filter = ItemStack.of(nbt.getCompound("Filter")); count = nbt.getInt("FilterAmount"); if (nbt.contains("ForceScrollable")) { scrollableValue = count; @@ -84,7 +89,7 @@ public class FilteringBehaviour extends TileEntityBehaviour { public void tick() { super.tick(); - if (!getWorld().isRemote) + if (!getWorld().isClientSide) return; if (ticksUntilScrollPacket == -1) return; @@ -150,7 +155,7 @@ public class FilteringBehaviour extends TileEntityBehaviour { : (filter.getItem() instanceof FilterItem) ? 0 : Math.min(stack.getCount(), stack.getMaxStackSize()); forceClientState = true; - tileEntity.markDirty(); + tileEntity.setChanged(); tileEntity.sendData(); } @@ -159,12 +164,21 @@ public class FilteringBehaviour extends TileEntityBehaviour { if (filter.getItem() instanceof FilterItem) { Vector3d pos = VecHelper.getCenterOf(getPos()); World world = getWorld(); - world.addEntity(new ItemEntity(world, pos.x, pos.y, pos.z, filter.copy())); + world.addFreshEntity(new ItemEntity(world, pos.x, pos.y, pos.z, filter.copy())); } 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(); } @@ -178,11 +192,11 @@ public class FilteringBehaviour extends TileEntityBehaviour { } public boolean test(ItemStack stack) { - return !isActive() || filter.isEmpty() || FilterItem.test(tileEntity.getWorld(), stack, filter); + return !isActive() || filter.isEmpty() || FilterItem.test(tileEntity.getLevel(), stack, filter); } public boolean test(FluidStack stack) { - return !isActive() || filter.isEmpty() || FilterItem.test(tileEntity.getWorld(), stack, filter); + return !isActive() || filter.isEmpty() || FilterItem.test(tileEntity.getLevel(), stack, filter); } @Override @@ -192,7 +206,7 @@ public class FilteringBehaviour extends TileEntityBehaviour { public boolean testHit(Vector3d hit) { BlockState state = tileEntity.getBlockState(); - Vector3d localHit = hit.subtract(Vector3d.of(tileEntity.getPos())); + Vector3d localHit = hit.subtract(Vector3d.atLowerCornerOf(tileEntity.getBlockPos())); return slotPositioning.testHit(state, localHit); } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringCountUpdatePacket.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringCountUpdatePacket.java index d6548d1e8..562ba13ab 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringCountUpdatePacket.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringCountUpdatePacket.java @@ -36,7 +36,7 @@ public class FilteringCountUpdatePacket extends TileEntityConfigurationPacket (max * max)) + return; + + FilteringBehaviour behaviour = te.getBehaviour(FilteringBehaviour.TYPE); if (behaviour == null) return; if (!behaviour.isActive()) @@ -101,7 +111,7 @@ public class FilteringRenderer { return; ValueBoxTransform slotPositioning = behaviour.slotPositioning; - BlockState blockState = tileEntityIn.getBlockState(); + BlockState blockState = te.getBlockState(); if (slotPositioning instanceof ValueBoxTransform.Sided) { ValueBoxTransform.Sided sided = (ValueBoxTransform.Sided) slotPositioning; @@ -115,18 +125,18 @@ public class FilteringRenderer { if (!slotPositioning.shouldRender(blockState)) continue; - ms.push(); + ms.pushPose(); slotPositioning.transform(blockState, ms); ValueBoxRenderer.renderItemIntoValueBox(filter, ms, buffer, light, overlay); - ms.pop(); + ms.popPose(); } sided.fromSide(side); return; } else if (slotPositioning.shouldRender(blockState)) { - ms.push(); + ms.pushPose(); slotPositioning.transform(blockState, ms); ValueBoxRenderer.renderItemIntoValueBox(behaviour.getFilter(), ms, buffer, light, overlay); - ms.pop(); + ms.popPose(); } } 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..bf32c08e6 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; @@ -63,7 +64,7 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { nbt.put("Filters", NBTHelper.writeCompoundList(sidedFilters.entrySet(), entry -> { CompoundNBT compound = new CompoundNBT(); compound.putInt("Side", entry.getKey() - .getIndex()); + .get3DDataValue()); entry.getValue() .write(compound, clientPacket); return compound; @@ -74,7 +75,7 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { @Override public void read(CompoundNBT nbt, boolean clientPacket) { NBTHelper.iterateCompoundList(nbt.getList("Filters", NBT.TAG_COMPOUND), compound -> { - Direction face = Direction.byIndex(compound.getInt("Side")); + Direction face = Direction.from3DDataValue(compound.getInt("Side")); if (sidedFilters.containsKey(face)) sidedFilters.get(face) .read(compound, clientPacket); @@ -109,27 +110,36 @@ 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) { ValueBoxTransform.Sided sidedPositioning = (Sided) slotPositioning; BlockState state = tileEntity.getBlockState(); - Vector3d localHit = hit.subtract(Vector3d.of(tileEntity.getPos())); + Vector3d localHit = hit.subtract(Vector3d.atLowerCornerOf(tileEntity.getBlockPos())); return sidedPositioning.fromSide(direction) .testHit(state, localHit); } 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..f004b8529 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 @@ -88,9 +88,9 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { @Override public void initialize() { super.initialize(); - if (getWorld().isRemote) + if (getWorld().isClientSide) return; - foreach(ts -> { + forEach(ts -> { ts.fluidLevel.forceNextSync(); ts.onFluidStackChanged(); }); @@ -102,11 +102,11 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { if (syncCooldown > 0) { syncCooldown--; - if (syncCooldown == 0 && queuedSync) + if (syncCooldown == 0 && queuedSync) updateFluids(); } - foreach(te -> { + forEach(te -> { LerpedFloat fluidLevel = te.getFluidLevel(); if (fluidLevel != null) fluidLevel.tickChaser(); @@ -132,7 +132,7 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { protected void updateFluids() { fluidUpdateCallback.run(); tileEntity.sendData(); - tileEntity.markDirty(); + tileEntity.setChanged(); } @Override @@ -160,7 +160,7 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { return true; } - public void foreach(Consumer action) { + public void forEach(Consumer action) { for (TankSegment tankSegment : tanks) action.accept(tankSegment); } @@ -173,7 +173,7 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { public void write(CompoundNBT nbt, boolean clientPacket) { super.write(nbt, clientPacket); ListNBT tanksNBT = new ListNBT(); - foreach(ts -> tanksNBT.add(ts.writeNBT())); + forEach(ts -> tanksNBT.add(ts.writeNBT())); nbt.put(getType().getName() + "Tanks", tanksNBT); } @@ -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); } @@ -239,11 +239,14 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { } public void onFluidStackChanged() { - if (!tileEntity.hasWorld()) + if (!tileEntity.hasLevel()) return; fluidLevel.chase(tank.getFluidAmount() / (float) tank.getCapacity(), .25, Chaser.EXP); - if (!getWorld().isRemote) + if (!getWorld().isClientSide) 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/CapManipulationBehaviourBase.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/CapManipulationBehaviourBase.java new file mode 100644 index 000000000..3375b59e7 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/CapManipulationBehaviourBase.java @@ -0,0 +1,143 @@ +package com.simibubi.create.foundation.tileEntity.behaviour.inventory; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.BlockFace; + +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public abstract class CapManipulationBehaviourBase> + extends TileEntityBehaviour { + + protected InterfaceProvider target; + protected LazyOptional targetCapability; + protected boolean simulateNext; + protected boolean bypassSided; + private boolean findNewNextTick; + + public CapManipulationBehaviourBase(SmartTileEntity te, InterfaceProvider target) { + super(te); + setLazyTickRate(5); + this.target = target; + targetCapability = LazyOptional.empty(); + simulateNext = false; + bypassSided = false; + } + + protected abstract Capability capability(); + + @Override + public void initialize() { + super.initialize(); + findNewNextTick = true; + } + + @Override + public void onNeighborChanged(BlockPos neighborPos) { + BlockFace targetBlockFace = target.getTarget(getWorld(), tileEntity.getBlockPos(), tileEntity.getBlockState()); + if (targetBlockFace.getConnectedPos() + .equals(neighborPos)) + onHandlerInvalidated(targetCapability); + } + + @SuppressWarnings("unchecked") + public S bypassSidedness() { + bypassSided = true; + return (S) this; + } + + /** + * Only simulate the upcoming operation + */ + @SuppressWarnings("unchecked") + public S simulate() { + simulateNext = true; + return (S) this; + } + + public boolean hasInventory() { + return targetCapability.isPresent(); + } + + @Nullable + public T getInventory() { + return targetCapability.orElse(null); + } + + protected void onHandlerInvalidated(LazyOptional handler) { + findNewNextTick = true; + targetCapability = LazyOptional.empty(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (!targetCapability.isPresent()) + findNewCapability(); + } + + @Override + public void tick() { + super.tick(); + if (findNewNextTick || getWorld().getGameTime() % 64 == 0) { + findNewNextTick = false; + findNewCapability(); + } + } + + public int getAmountFromFilter() { + int amount = -1; + FilteringBehaviour filter = tileEntity.getBehaviour(FilteringBehaviour.TYPE); + if (filter != null && !filter.anyAmount()) + amount = filter.getAmount(); + return amount; + } + + public void findNewCapability() { + World world = getWorld(); + BlockFace targetBlockFace = target.getTarget(world, tileEntity.getBlockPos(), tileEntity.getBlockState()) + .getOpposite(); + BlockPos pos = targetBlockFace.getPos(); + + targetCapability = LazyOptional.empty(); + + if (!world.isLoaded(pos)) + return; + TileEntity invTE = world.getBlockEntity(pos); + if (invTE == null) + return; + Capability capability = capability(); + targetCapability = + bypassSided ? invTE.getCapability(capability) : invTE.getCapability(capability, targetBlockFace.getFace()); + if (targetCapability.isPresent()) + targetCapability.addListener(this::onHandlerInvalidated); + } + + @FunctionalInterface + public interface InterfaceProvider { + + public static InterfaceProvider towardBlockFacing() { + return (w, p, s) -> new BlockFace(p, + s.hasProperty(BlockStateProperties.FACING) ? s.getValue(BlockStateProperties.FACING) + : s.getValue(BlockStateProperties.HORIZONTAL_FACING)); + } + + public static InterfaceProvider oppositeOfBlockFacing() { + return (w, p, s) -> new BlockFace(p, + (s.hasProperty(BlockStateProperties.FACING) ? s.getValue(BlockStateProperties.FACING) + : s.getValue(BlockStateProperties.HORIZONTAL_FACING)).getOpposite()); + } + + public BlockFace getTarget(World world, BlockPos pos, BlockState blockState); + } + +} 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..8bcee8739 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 @@ -3,40 +3,25 @@ package com.simibubi.create.foundation.tileEntity.behaviour.inventory; import java.util.function.Function; import java.util.function.Predicate; -import javax.annotation.Nullable; - import com.google.common.base.Predicates; 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; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.BlockFace; -import net.minecraft.block.BlockState; import net.minecraft.item.ItemStack; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; -public class InvManipulationBehaviour extends TileEntityBehaviour { +public class InvManipulationBehaviour extends CapManipulationBehaviourBase { // Extra types available for multibehaviour public static BehaviourType TYPE = new BehaviourType<>(), EXTRACT = new BehaviourType<>(), INSERT = new BehaviourType<>(); - protected InterfaceProvider target; - protected LazyOptional targetCapability; - protected boolean simulateNext; - protected boolean bypassSided; - private boolean findNewNextTick; - private BehaviourType behaviourType; public static InvManipulationBehaviour forExtraction(SmartTileEntity te, InterfaceProvider target) { @@ -53,35 +38,13 @@ public class InvManipulationBehaviour extends TileEntityBehaviour { private InvManipulationBehaviour(BehaviourType type, SmartTileEntity te, InterfaceProvider target) { - super(te); + super(te, target); behaviourType = type; - setLazyTickRate(5); - this.target = target; - this.targetCapability = LazyOptional.empty(); - simulateNext = false; - bypassSided = false; } - - public InvManipulationBehaviour bypassSidedness() { - bypassSided = true; - return this; - } - - /** - * Only simulate the upcoming operation - */ - public InvManipulationBehaviour simulate() { - simulateNext = true; - return this; - } - - public boolean hasInventory() { - return targetCapability.isPresent(); - } - - @Nullable - public IItemHandler getInventory() { - return targetCapability.orElse(null); + + @Override + protected Capability capability() { + return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; } public ItemStack extract() { @@ -100,19 +63,26 @@ public class InvManipulationBehaviour extends TileEntityBehaviour { boolean shouldSimulate = simulateNext; simulateNext = false; - if (getWorld().isRemote) + if (getWorld().isClientSide) return ItemStack.EMPTY; IItemHandler inventory = targetCapability.orElse(null); if (inventory == null) 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) { @@ -132,87 +102,9 @@ public class InvManipulationBehaviour extends TileEntityBehaviour { return test; } - @Override - public void initialize() { - super.initialize(); - findNewNextTick = true; - } - - @Override - public void onNeighborChanged(BlockPos neighborPos) { - BlockFace targetBlockFace = target.getTarget(getWorld(), tileEntity.getPos(), tileEntity.getBlockState()); - if (targetBlockFace.getConnectedPos().equals(neighborPos)) - onHandlerInvalidated(targetCapability); - } - - protected void onHandlerInvalidated(LazyOptional handler) { - findNewNextTick = true; - targetCapability = LazyOptional.empty(); - } - - @Override - public void lazyTick() { - super.lazyTick(); - if (!targetCapability.isPresent()) - findNewCapability(); - } - - @Override - public void tick() { - super.tick(); - if (findNewNextTick || getWorld().getGameTime() % 64 == 0) { - findNewNextTick = false; - findNewCapability(); - } - } - - public int getAmountFromFilter() { - int amount = -1; - FilteringBehaviour filter = tileEntity.getBehaviour(FilteringBehaviour.TYPE); - if (filter != null && !filter.anyAmount()) - amount = filter.getAmount(); - return amount; - } - - public void findNewCapability() { - BlockFace targetBlockFace = target.getTarget(getWorld(), tileEntity.getPos(), tileEntity.getBlockState()) - .getOpposite(); - BlockPos pos = targetBlockFace.getPos(); - World world = getWorld(); - - targetCapability = LazyOptional.empty(); - - if (!world.isBlockPresent(pos)) - return; - TileEntity invTE = world.getTileEntity(pos); - if (invTE == null) - return; - targetCapability = bypassSided ? invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - : invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetBlockFace.getFace()); - if (targetCapability.isPresent()) - targetCapability.addListener(this::onHandlerInvalidated); - } - @Override public BehaviourType getType() { return behaviourType; } - @FunctionalInterface - public interface InterfaceProvider { - - public static InterfaceProvider towardBlockFacing() { - return (w, p, s) -> new BlockFace(p, s.contains(BlockStateProperties.FACING) ? s.get(BlockStateProperties.FACING) - : s.get(BlockStateProperties.HORIZONTAL_FACING)); - } - - public static InterfaceProvider oppositeOfBlockFacing() { - return (w, p, s) -> new BlockFace(p, - (s.contains(BlockStateProperties.FACING) ? s.get(BlockStateProperties.FACING) - : s.get(BlockStateProperties.HORIZONTAL_FACING)).getOpposite()); - } - - public BlockFace getTarget(World world, BlockPos pos, BlockState blockState); - } - } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/TankManipulationBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/TankManipulationBehaviour.java new file mode 100644 index 000000000..786d43e1c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/TankManipulationBehaviour.java @@ -0,0 +1,69 @@ +package com.simibubi.create.foundation.tileEntity.behaviour.inventory; + +import java.util.function.Predicate; + +import com.google.common.base.Predicates; +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; + +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + +public class TankManipulationBehaviour extends CapManipulationBehaviourBase { + + public static BehaviourType OBSERVE = new BehaviourType<>(); + private BehaviourType behaviourType; + + public TankManipulationBehaviour(SmartTileEntity te, InterfaceProvider target) { + this(OBSERVE, te, target); + } + + private TankManipulationBehaviour(BehaviourType type, SmartTileEntity te, + InterfaceProvider target) { + super(te, target); + behaviourType = type; + } + + public FluidStack extractAny() { + if (!hasInventory()) + return FluidStack.EMPTY; + IFluidHandler inventory = getInventory(); + Predicate filterTest = getFilterTest(Predicates.alwaysTrue()); + for (int i = 0; i < inventory.getTanks(); i++) { + FluidStack fluidInTank = inventory.getFluidInTank(i); + if (fluidInTank.isEmpty()) + continue; + if (!filterTest.test(fluidInTank)) + continue; + FluidStack drained = + inventory.drain(fluidInTank, simulateNext ? FluidAction.SIMULATE : FluidAction.EXECUTE); + if (!drained.isEmpty()) + return drained; + } + + return FluidStack.EMPTY; + } + + protected Predicate getFilterTest(Predicate customFilter) { + Predicate test = customFilter; + FilteringBehaviour filter = tileEntity.getBehaviour(FilteringBehaviour.TYPE); + if (filter != null) + test = customFilter.and(filter::test); + return test; + } + + @Override + protected Capability capability() { + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + } + + @Override + public BehaviourType getType() { + return behaviourType; + } + +} 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..e10bc096e 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().isClientSide) return; - getHandler().addToNetwork(this); + getHandler().addToNetwork(getWorld(), this); newPosition = true; } + @Override public Pair getNetworkKey() { return Pair.of(frequencyFirst, frequencyLast); } @@ -110,32 +116,37 @@ public class LinkBehaviour extends TileEntityBehaviour { @Override public void remove() { super.remove(); - if (tileEntity.getWorld().isRemote) + if (getWorld().isClientSide) return; - getHandler().removeFromNetwork(this); + getHandler().removeFromNetwork(getWorld(), this); + } + + @Override + public boolean isSafeNBT() { + return true; } @Override public void write(CompoundNBT nbt, boolean clientPacket) { super.write(nbt, clientPacket); nbt.put("FrequencyFirst", frequencyFirst.getStack() - .write(new CompoundNBT())); + .save(new CompoundNBT())); nbt.put("FrequencyLast", frequencyLast.getStack() - .write(new CompoundNBT())); - nbt.putLong("LastKnownPosition", tileEntity.getPos() - .toLong()); + .save(new CompoundNBT())); + nbt.putLong("LastKnownPosition", tileEntity.getBlockPos() + .asLong()); } @Override public void read(CompoundNBT nbt, boolean clientPacket) { - long positionInTag = tileEntity.getPos() - .toLong(); + long positionInTag = tileEntity.getBlockPos() + .asLong(); long positionKey = nbt.getLong("LastKnownPosition"); newPosition = positionInTag != positionKey; super.read(nbt, clientPacket); - frequencyFirst = Frequency.of(ItemStack.read(nbt.getCompound("FrequencyFirst"))); - frequencyLast = Frequency.of(ItemStack.read(nbt.getCompound("FrequencyLast"))); + frequencyFirst = Frequency.of(ItemStack.of(nbt.getCompound("FrequencyFirst"))); + frequencyLast = Frequency.of(ItemStack.of(nbt.getCompound("FrequencyLast"))); } public void setFrequency(boolean first, ItemStack stack) { @@ -143,10 +154,10 @@ public class LinkBehaviour extends TileEntityBehaviour { stack.setCount(1); ItemStack toCompare = first ? frequencyFirst.getStack() : frequencyLast.getStack(); boolean changed = - !ItemStack.areItemsEqual(stack, toCompare) || !ItemStack.areItemStackTagsEqual(stack, toCompare); + !ItemStack.isSame(stack, toCompare) || !ItemStack.tagMatches(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 { @@ -190,8 +201,18 @@ public class LinkBehaviour extends TileEntityBehaviour { public boolean testHit(Boolean first, Vector3d hit) { BlockState state = tileEntity.getBlockState(); - Vector3d localHit = hit.subtract(Vector3d.of(tileEntity.getPos())); + Vector3d localHit = hit.subtract(Vector3d.atLowerCornerOf(tileEntity.getBlockPos())); return (first ? firstSlot : secondSlot).testHit(state, localHit); } + @Override + public boolean isAlive() { + return !tileEntity.isRemoved() && getWorld().getBlockEntity(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..1c428e62d 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; @@ -28,24 +30,29 @@ public class LinkHandler { PlayerEntity player = event.getPlayer(); Hand hand = event.getHand(); - if (player.isSneaking() || player.isSpectator()) + if (player.isShiftKeyDown() || player.isSpectator()) return; LinkBehaviour behaviour = TileEntityBehaviour.get(world, pos, LinkBehaviour.TYPE); if (behaviour == null) return; + ItemStack heldItem = player.getItemInHand(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 (behaviour.testHit(first, ray.getLocation())) { + 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); + world.playSound(null, pos, SoundEvents.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..23962d3c4 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 @@ -4,6 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.datafixers.util.Pair; import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; @@ -11,10 +12,12 @@ import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -27,13 +30,13 @@ public class LinkRenderer { public static void tick() { Minecraft mc = Minecraft.getInstance(); - RayTraceResult target = mc.objectMouseOver; + RayTraceResult target = mc.hitResult; if (target == null || !(target instanceof BlockRayTraceResult)) return; BlockRayTraceResult result = (BlockRayTraceResult) target; - ClientWorld world = mc.world; - BlockPos pos = result.getPos(); + ClientWorld world = mc.level; + BlockPos pos = result.getBlockPos(); LinkBehaviour behaviour = TileEntityBehaviour.get(world, pos, LinkBehaviour.TYPE); if (behaviour == null) @@ -43,18 +46,18 @@ public class LinkRenderer { ITextComponent freq2 = Lang.translate("logistics.secondFrequency"); for (boolean first : Iterate.trueAndFalse) { - AxisAlignedBB bb = new AxisAlignedBB(Vector3d.ZERO, Vector3d.ZERO).grow(.25f); - ITextComponent label = first ? freq2 : freq1; - boolean hit = behaviour.testHit(first, target.getHitVec()); + AxisAlignedBB bb = new AxisAlignedBB(Vector3d.ZERO, Vector3d.ZERO).inflate(.25f); + ITextComponent label = first ? freq1 : freq2; + boolean hit = behaviour.testHit(first, target.getLocation()); 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.getDirection()); } } @@ -63,6 +66,13 @@ public class LinkRenderer { if (te == null || te.isRemoved()) return; + + Entity cameraEntity = Minecraft.getInstance().cameraEntity; + float max = AllConfigs.CLIENT.filterItemRenderDistance.getF(); + if (!te.isVirtual() && cameraEntity != null && cameraEntity.position() + .distanceToSqr(VecHelper.getCenterOf(te.getBlockPos())) > (max * max)) + return; + LinkBehaviour behaviour = te.getBehaviour(LinkBehaviour.TYPE); if (behaviour == null) return; @@ -71,10 +81,10 @@ public class LinkRenderer { ValueBoxTransform transform = first ? behaviour.firstSlot : behaviour.secondSlot; ItemStack stack = first ? behaviour.frequencyFirst.getStack() : behaviour.frequencyLast.getStack(); - ms.push(); + ms.pushPose(); transform.transform(te.getBlockState(), ms); ValueBoxRenderer.renderItemIntoValueBox(stack, ms, buffer, light, overlay); - ms.pop(); + ms.popPose(); } } 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..090c32a21 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); @@ -78,7 +81,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { public void tick() { super.tick(); - if (!getWorld().isRemote) + if (!getWorld().isClientSide) return; if (ticksUntilScrollPacket == -1) return; @@ -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; @@ -151,7 +154,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { this.value = value; forceClientState = true; callback.accept(value); - tileEntity.markDirty(); + tileEntity.setChanged(); tileEntity.sendData(); scrollableValue = value; } @@ -168,21 +171,21 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { public BehaviourType getType() { return TYPE; } - + public boolean isActive() { return isActive.get(); } public boolean testHit(Vector3d hit) { BlockState state = tileEntity.getBlockState(); - Vector3d localHit = hit.subtract(Vector3d.of(tileEntity.getPos())); + Vector3d localHit = hit.subtract(Vector3d.atLowerCornerOf(tileEntity.getBlockPos())); return slotPositioning.testHit(state, localHit); } 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/ScrollValueHandler.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueHandler.java index 1ae96c132..0f7f15667 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueHandler.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueHandler.java @@ -30,32 +30,32 @@ public class ScrollValueHandler { @OnlyIn(Dist.CLIENT) public static boolean onScroll(double delta) { - RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver; + RayTraceResult objectMouseOver = Minecraft.getInstance().hitResult; if (!(objectMouseOver instanceof BlockRayTraceResult)) return false; BlockRayTraceResult result = (BlockRayTraceResult) objectMouseOver; Minecraft mc = Minecraft.getInstance(); - ClientWorld world = mc.world; - BlockPos blockPos = result.getPos(); + ClientWorld world = mc.level; + BlockPos blockPos = result.getBlockPos(); ScrollValueBehaviour scrolling = TileEntityBehaviour.get(world, blockPos, ScrollValueBehaviour.TYPE); if (scrolling == null) return false; if (!scrolling.isActive()) return false; - if (!mc.player.isAllowEdit()) + if (!mc.player.mayBuild()) return false; passiveScrollDirection = (float) -delta; wrenchCog.bump(3, -delta * 10); int prev = scrolling.scrollableValue; - if (scrolling.needsWrench && !AllItems.WRENCH.isIn(mc.player.getHeldItemMainhand())) + if (scrolling.needsWrench && !AllItems.WRENCH.isIn(mc.player.getMainHandItem())) return false; if (scrolling.slotPositioning instanceof Sided) - ((Sided) scrolling.slotPositioning).fromSide(result.getFace()); - if (!scrolling.testHit(objectMouseOver.getHitVec())) + ((Sided) scrolling.slotPositioning).fromSide(result.getDirection()); + if (!scrolling.testHit(objectMouseOver.getLocation())) return false; if (scrolling instanceof BulkScrollValueBehaviour && AllKeys.ctrlDown()) { @@ -83,9 +83,12 @@ public class ScrollValueHandler { @OnlyIn(Dist.CLIENT) public static void tick() { - lastPassiveScroll = passiveScroll; - wrenchCog.tick(); - passiveScroll += passiveScrollDirection * 0.5; + if (!Minecraft.getInstance() + .isPaused()) { + lastPassiveScroll = passiveScroll; + wrenchCog.tick(); + passiveScroll += passiveScrollDirection * 0.5; + } } protected static void applyTo(double delta, ScrollValueBehaviour scrolling) { 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..f157c98fc 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 @@ -25,30 +25,30 @@ public class ScrollValueRenderer { public static void tick() { Minecraft mc = Minecraft.getInstance(); - RayTraceResult target = mc.objectMouseOver; + RayTraceResult target = mc.hitResult; if (target == null || !(target instanceof BlockRayTraceResult)) return; BlockRayTraceResult result = (BlockRayTraceResult) target; - ClientWorld world = mc.world; - BlockPos pos = result.getPos(); - Direction face = result.getFace(); + ClientWorld world = mc.level; + BlockPos pos = result.getBlockPos(); + Direction face = result.getDirection(); ScrollValueBehaviour behaviour = TileEntityBehaviour.get(world, pos, ScrollValueBehaviour.TYPE); if (behaviour == null) return; if (!behaviour.isActive()) return; - if (behaviour.needsWrench && !AllItems.WRENCH.isIn(mc.player.getHeldItemMainhand())) + if (behaviour.needsWrench && !AllItems.WRENCH.isIn(mc.player.getMainHandItem())) return; - boolean highlight = behaviour.testHit(target.getHitVec()); + boolean highlight = behaviour.testHit(target.getLocation()); if (behaviour instanceof BulkScrollValueBehaviour && AllKeys.ctrlDown()) { BulkScrollValueBehaviour bulkScrolling = (BulkScrollValueBehaviour) behaviour; for (SmartTileEntity smartTileEntity : bulkScrolling.getBulk()) { ScrollValueBehaviour other = smartTileEntity.getBehaviour(ScrollValueBehaviour.TYPE); if (other != null) - addBox(world, smartTileEntity.getPos(), face, other, highlight); + addBox(world, smartTileEntity.getBlockPos(), face, other, highlight); } } else addBox(world, pos, face, behaviour, highlight); @@ -56,9 +56,9 @@ public class ScrollValueRenderer { protected static void addBox(ClientWorld world, BlockPos pos, Direction face, ScrollValueBehaviour behaviour, boolean highlight) { - AxisAlignedBB bb = new AxisAlignedBB(Vector3d.ZERO, Vector3d.ZERO).grow(.5f) + AxisAlignedBB bb = new AxisAlignedBB(Vector3d.ZERO, Vector3d.ZERO).inflate(.5f) .contract(0, 0, -.5f) - .offset(0, 0, -.125f); + .move(0, 0, -.125f); ITextComponent label = behaviour.label; ValueBox box; @@ -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..c6366b8da 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,10 +19,10 @@ 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.getLevel())) return; SuperByteBuffer render = render(getOverlayBuffer(te), getColor(te, partialTicks), light); - render.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + render.renderInto(ms, buffer.getBuffer(RenderType.solid())); } protected abstract int getColor(T te, float partialTicks); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/SafeTileEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/SafeTileEntityRenderer.java index 6c02f67f9..d69e54731 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/SafeTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/SafeTileEntityRenderer.java @@ -26,7 +26,7 @@ public abstract class SafeTileEntityRenderer extends TileE int overlay); public boolean isInvalid(T te) { - return !te.hasWorld() || te.getBlockState() + return !te.hasLevel() || te.getBlockState() .getBlock() == Blocks.AIR; } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/AbstractBlockBreakQueue.java b/src/main/java/com/simibubi/create/foundation/utility/AbstractBlockBreakQueue.java index cc4989e8d..4bef24374 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/AbstractBlockBreakQueue.java +++ b/src/main/java/com/simibubi/create/foundation/utility/AbstractBlockBreakQueue.java @@ -28,7 +28,7 @@ public abstract class AbstractBlockBreakQueue { public void destroyBlocks(World world, @Nullable LivingEntity entity, BiConsumer drop) { PlayerEntity playerEntity = entity instanceof PlayerEntity ? ((PlayerEntity) entity) : null; ItemStack toDamage = - playerEntity != null && !playerEntity.isCreative() ? playerEntity.getHeldItemMainhand() : ItemStack.EMPTY; + playerEntity != null && !playerEntity.isCreative() ? playerEntity.getMainHandItem() : ItemStack.EMPTY; destroyBlocks(world, toDamage, playerEntity, drop); } 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..4ed984af0 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/AngleHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/AngleHelper.java @@ -5,8 +5,24 @@ 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(); + float angle = facing.toYRot(); + if (facing.getAxis() == Axis.X) + angle = -angle; + 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.toYRot(); if (facing.getAxis() == Axis.X) angle = -angle; return angle; diff --git a/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java b/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java index efc5f90f8..2564c2cc6 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java +++ b/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java @@ -19,7 +19,7 @@ public class AnimationTickHolder { public static void tick() { if (!Minecraft.getInstance() - .isGamePaused()) { + .isPaused()) { ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision } else { paused_ticks = (paused_ticks + 1) % 1_728_000; @@ -40,7 +40,7 @@ public class AnimationTickHolder { public static float getPartialTicks() { Minecraft mc = Minecraft.getInstance(); - return (mc.isGamePaused() ? mc.renderPartialTicksPaused : mc.getRenderPartialTicks()); + return (mc.isPaused() ? mc.pausePartialTick : mc.getFrameTime()); } public static int getTicks(IWorld world) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/BlockFace.java b/src/main/java/com/simibubi/create/foundation/utility/BlockFace.java index b26edb76c..a995e5fae 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BlockFace.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BlockFace.java @@ -34,7 +34,7 @@ public class BlockFace extends Pair { } public BlockPos getConnectedPos() { - return getPos().offset(getFace()); + return getPos().relative(getFace()); } public CompoundNBT serializeNBT() { 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..b8f0102dc 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java @@ -10,6 +10,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.actors.SeatBlock; +import net.minecraft.block.AbstractRailBlock; import net.minecraft.block.BedBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -40,6 +41,8 @@ import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.GameRules; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -57,10 +60,10 @@ public class BlockHelper { ClientWorld world = (ClientWorld) worldIn; VoxelShape voxelshape = state.getShape(world, pos); MutableInt amtBoxes = new MutableInt(0); - voxelshape.forEachBox((x1, y1, z1, x2, y2, z2) -> amtBoxes.increment()); + voxelshape.forAllBoxes((x1, y1, z1, x2, y2, z2) -> amtBoxes.increment()); double chance = 1d / amtBoxes.getValue(); - voxelshape.forEachBox((x1, y1, z1, x2, y2, z2) -> { + voxelshape.forAllBoxes((x1, y1, z1, x2, y2, z2) -> { double d1 = Math.min(1.0D, x2 - x1); double d2 = Math.min(1.0D, y2 - y1); double d3 = Math.min(1.0D, z2 - z1); @@ -71,7 +74,7 @@ public class BlockHelper { for (int l = 0; l < i; ++l) { for (int i1 = 0; i1 < j; ++i1) { for (int j1 = 0; j1 < k; ++j1) { - if (world.rand.nextDouble() > chance) + if (world.random.nextDouble() > chance) continue; double d4 = ((double) l + 0.5D) / (double) i; @@ -81,8 +84,8 @@ public class BlockHelper { double d8 = d5 * d2 + y1; double d9 = d6 * d3 + z1; manager - .addEffect((new DiggingParticle(world, (double) pos.getX() + d7, (double) pos.getY() + d8, - (double) pos.getZ() + d9, d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state)).setBlockPos(pos)); + .add((new DiggingParticle(world, (double) pos.getX() + d7, (double) pos.getY() + d8, + (double) pos.getZ() + d9, d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state)).init(pos)); } } } @@ -91,32 +94,32 @@ public class BlockHelper { } public static BlockState setZeroAge(BlockState blockState) { - if (blockState.contains(BlockStateProperties.AGE_0_1)) - return blockState.with(BlockStateProperties.AGE_0_1, 0); - if (blockState.contains(BlockStateProperties.AGE_0_2)) - return blockState.with(BlockStateProperties.AGE_0_2, 0); - if (blockState.contains(BlockStateProperties.AGE_0_3)) - return blockState.with(BlockStateProperties.AGE_0_3, 0); - if (blockState.contains(BlockStateProperties.AGE_0_5)) - return blockState.with(BlockStateProperties.AGE_0_5, 0); - if (blockState.contains(BlockStateProperties.AGE_0_7)) - return blockState.with(BlockStateProperties.AGE_0_7, 0); - if (blockState.contains(BlockStateProperties.AGE_0_15)) - return blockState.with(BlockStateProperties.AGE_0_15, 0); - if (blockState.contains(BlockStateProperties.AGE_0_25)) - return blockState.with(BlockStateProperties.AGE_0_25, 0); - if (blockState.contains(BlockStateProperties.HONEY_LEVEL)) - return blockState.with(BlockStateProperties.HONEY_LEVEL, 0); - if (blockState.contains(BlockStateProperties.HATCH_0_2)) - return blockState.with(BlockStateProperties.HATCH_0_2, 0); - if (blockState.contains(BlockStateProperties.STAGE_0_1)) - return blockState.with(BlockStateProperties.STAGE_0_1, 0); - if (blockState.contains(BlockStateProperties.LEVEL_0_3)) - return blockState.with(BlockStateProperties.LEVEL_0_3, 0); - if (blockState.contains(BlockStateProperties.LEVEL_0_8)) - return blockState.with(BlockStateProperties.LEVEL_0_8, 0); - if (blockState.contains(BlockStateProperties.EXTENDED)) - return blockState.with(BlockStateProperties.EXTENDED, false); + if (blockState.hasProperty(BlockStateProperties.AGE_1)) + return blockState.setValue(BlockStateProperties.AGE_1, 0); + if (blockState.hasProperty(BlockStateProperties.AGE_2)) + return blockState.setValue(BlockStateProperties.AGE_2, 0); + if (blockState.hasProperty(BlockStateProperties.AGE_3)) + return blockState.setValue(BlockStateProperties.AGE_3, 0); + if (blockState.hasProperty(BlockStateProperties.AGE_5)) + return blockState.setValue(BlockStateProperties.AGE_5, 0); + if (blockState.hasProperty(BlockStateProperties.AGE_7)) + return blockState.setValue(BlockStateProperties.AGE_7, 0); + if (blockState.hasProperty(BlockStateProperties.AGE_15)) + return blockState.setValue(BlockStateProperties.AGE_15, 0); + if (blockState.hasProperty(BlockStateProperties.AGE_25)) + return blockState.setValue(BlockStateProperties.AGE_25, 0); + if (blockState.hasProperty(BlockStateProperties.LEVEL_HONEY)) + return blockState.setValue(BlockStateProperties.LEVEL_HONEY, 0); + if (blockState.hasProperty(BlockStateProperties.HATCH)) + return blockState.setValue(BlockStateProperties.HATCH, 0); + if (blockState.hasProperty(BlockStateProperties.STAGE)) + return blockState.setValue(BlockStateProperties.STAGE, 0); + if (blockState.hasProperty(BlockStateProperties.LEVEL_CAULDRON)) + return blockState.setValue(BlockStateProperties.LEVEL_CAULDRON, 0); + if (blockState.hasProperty(BlockStateProperties.LEVEL_COMPOSTER)) + return blockState.setValue(BlockStateProperties.LEVEL_COMPOSTER, 0); + if (blockState.hasProperty(BlockStateProperties.EXTENDED)) + return blockState.setValue(BlockStateProperties.EXTENDED, false); return blockState; } @@ -124,41 +127,41 @@ public class BlockHelper { int amountFound = 0; Item required = getRequiredItem(block).getItem(); - boolean needsTwo = block.contains(BlockStateProperties.SLAB_TYPE) - && block.get(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE; + boolean needsTwo = block.hasProperty(BlockStateProperties.SLAB_TYPE) + && block.getValue(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE; if (needsTwo) amount *= 2; - if (block.contains(BlockStateProperties.EGGS_1_4)) - amount *= block.get(BlockStateProperties.EGGS_1_4); + if (block.hasProperty(BlockStateProperties.EGGS)) + amount *= block.getValue(BlockStateProperties.EGGS); - if (block.contains(BlockStateProperties.PICKLES_1_4)) - amount *= block.get(BlockStateProperties.PICKLES_1_4); + if (block.hasProperty(BlockStateProperties.PICKLES)) + amount *= block.getValue(BlockStateProperties.PICKLES); { // Try held Item first - int preferredSlot = player.inventory.currentItem; - ItemStack itemstack = player.inventory.getStackInSlot(preferredSlot); + int preferredSlot = player.inventory.selected; + ItemStack itemstack = player.inventory.getItem(preferredSlot); int count = itemstack.getCount(); if (itemstack.getItem() == required && count > 0) { int taken = Math.min(count, amount - amountFound); - player.inventory.setInventorySlotContents(preferredSlot, + player.inventory.setItem(preferredSlot, new ItemStack(itemstack.getItem(), count - taken)); amountFound += taken; } } // Search inventory - for (int i = 0; i < player.inventory.getSizeInventory(); ++i) { + for (int i = 0; i < player.inventory.getContainerSize(); ++i) { if (amountFound == amount) break; - ItemStack itemstack = player.inventory.getStackInSlot(i); + ItemStack itemstack = player.inventory.getItem(i); int count = itemstack.getCount(); if (itemstack.getItem() == required && count > 0) { int taken = Math.min(count, amount - amountFound); - player.inventory.setInventorySlotContents(i, new ItemStack(itemstack.getItem(), count - taken)); + player.inventory.setItem(i, new ItemStack(itemstack.getItem(), count - taken)); amountFound += taken; } } @@ -166,7 +169,7 @@ public class BlockHelper { if (needsTwo) { // Give back 1 if uneven amount was removed if (amountFound % 2 != 0) - player.inventory.addItemStackToInventory(new ItemStack(required)); + player.inventory.add(new ItemStack(required)); amountFound /= 2; } @@ -183,7 +186,7 @@ public class BlockHelper { } public static void destroyBlock(World world, BlockPos pos, float effectChance) { - destroyBlock(world, pos, effectChance, stack -> Block.spawnAsEntity(world, pos, stack)); + destroyBlock(world, pos, effectChance, stack -> Block.popResource(world, pos, stack)); } public static void destroyBlock(World world, BlockPos pos, float effectChance, @@ -195,9 +198,9 @@ public class BlockHelper { float effectChance, Consumer droppedItemCallback) { FluidState fluidState = world.getFluidState(pos); BlockState state = world.getBlockState(pos); - if (world.rand.nextFloat() < effectChance) - world.playEvent(2001, pos, Block.getStateId(state)); - TileEntity tileentity = state.hasTileEntity() ? world.getTileEntity(pos) : null; + if (world.random.nextFloat() < effectChance) + world.levelEvent(2001, pos, Block.getId(state)); + TileEntity tileentity = state.hasTileEntity() ? world.getBlockEntity(pos) : null; if (player != null) { BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, player); MinecraftForge.EVENT_BUS.post(event); @@ -206,25 +209,25 @@ public class BlockHelper { if (event.getExpToDrop() > 0 && world instanceof ServerWorld) state.getBlock() - .dropXpOnBlockBreak((ServerWorld) world, pos, event.getExpToDrop()); + .popExperience((ServerWorld) world, pos, event.getExpToDrop()); - usedTool.onBlockDestroyed(world, state, pos, player); - player.addStat(Stats.BLOCK_MINED.get(state.getBlock())); + usedTool.mineBlock(world, state, pos, player); + player.awardStat(Stats.BLOCK_MINED.get(state.getBlock())); } if (world instanceof ServerWorld && world.getGameRules() - .getBoolean(GameRules.DO_TILE_DROPS) && !world.restoringBlockSnapshots + .getBoolean(GameRules.RULE_DOBLOCKDROPS) && !world.restoringBlockSnapshots && (player == null || !player.isCreative())) { for (ItemStack itemStack : Block.getDrops(state, (ServerWorld) world, pos, tileentity, player, usedTool)) droppedItemCallback.accept(itemStack); - state.spawnAdditionalDrops((ServerWorld) world, pos, ItemStack.EMPTY); + state.spawnAfterBreak((ServerWorld) world, pos, ItemStack.EMPTY); } - world.setBlockState(pos, fluidState.getBlockState()); + world.setBlockAndUpdate(pos, fluidState.createLegacyBlock()); } public static boolean isSolidWall(IBlockReader reader, BlockPos fromPos, Direction toDirection) { - return hasBlockSolidSide(reader.getBlockState(fromPos.offset(toDirection)), reader, fromPos.offset(toDirection), + return hasBlockSolidSide(reader.getBlockState(fromPos.relative(toDirection)), reader, fromPos.relative(toDirection), toDirection.getOpposite()); } @@ -234,56 +237,80 @@ 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.markUnsaved(); + world.markAndNotifyBlock(target, chunk, old, state, 82, 512); + + world.setBlock(target, state, 82); + world.neighborChanged(target, world.getBlockState(target.below()).getBlock(), target.below()); + } + public static void placeSchematicBlock(World world, BlockState state, BlockPos target, ItemStack stack, @Nullable CompoundNBT data) { // Piston - if (state.contains(BlockStateProperties.EXTENDED)) - state = state.with(BlockStateProperties.EXTENDED, Boolean.FALSE); - if (state.contains(BlockStateProperties.WATERLOGGED)) - state = state.with(BlockStateProperties.WATERLOGGED, Boolean.FALSE); + if (state.hasProperty(BlockStateProperties.EXTENDED)) + state = state.setValue(BlockStateProperties.EXTENDED, Boolean.FALSE); + if (state.hasProperty(BlockStateProperties.WATERLOGGED)) + state = state.setValue(BlockStateProperties.WATERLOGGED, Boolean.FALSE); if (AllBlocks.BELT.has(state)) { - world.setBlockState(target, state, 2); + world.setBlock(target, state, 2); return; } else if (state.getBlock() == Blocks.COMPOSTER) - state = Blocks.COMPOSTER.getDefaultState(); + state = Blocks.COMPOSTER.defaultBlockState(); else if (state.getBlock() != Blocks.SEA_PICKLE && state.getBlock() instanceof IPlantable) state = ((IPlantable) state.getBlock()).getPlant(world, target); - if (world.getDimension() - .isUltrawarm() + if (world.dimensionType() + .ultraWarm() && state.getFluidState() - .getFluid() - .isIn(FluidTags.WATER)) { + .getType() + .is(FluidTags.WATER)) { int i = target.getX(); int j = target.getY(); int k = target.getZ(); - world.playSound(null, target, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, - 2.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.8F); + world.playSound(null, target, SoundEvents.FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, + 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F); for (int l = 0; l < 8; ++l) { world.addParticle(ParticleTypes.LARGE_SMOKE, i + Math.random(), j + Math.random(), k + Math.random(), 0.0D, 0.0D, 0.0D); } - Block.spawnDrops(state, world, target); + Block.dropResources(state, world, target); return; } - world.setBlockState(target, state, 18); + + if (state.getBlock() instanceof AbstractRailBlock) { + placeRailWithoutUpdate(world, state, target); + } else { + world.setBlock(target, state, 18); + } + if (data != null) { - TileEntity tile = world.getTileEntity(target); + TileEntity tile = world.getBlockEntity(target); if (tile != null) { data.putInt("x", target.getX()); data.putInt("y", target.getY()); data.putInt("z", target.getZ()); if (tile instanceof KineticTileEntity) ((KineticTileEntity) tile).warnOfMovement(); - tile.fromTag(tile.getBlockState(), data); + tile.load(tile.getBlockState(), data); } } try { state.getBlock() - .onBlockPlacedBy(world, target, state, null, stack); + .setPlacedBy(world, target, state, null, stack); } catch (Exception e) { } } @@ -298,16 +325,16 @@ public class BlockHelper { public static boolean hasBlockSolidSide(BlockState p_220056_0_, IBlockReader p_220056_1_, BlockPos p_220056_2_, Direction p_220056_3_) { - return !p_220056_0_.isIn(BlockTags.LEAVES) - && Block.doesSideFillSquare(p_220056_0_.getCollisionShape(p_220056_1_, p_220056_2_), p_220056_3_); + return !p_220056_0_.is(BlockTags.LEAVES) + && Block.isFaceFull(p_220056_0_.getCollisionShape(p_220056_1_, p_220056_2_), p_220056_3_); } public static boolean extinguishFire(World world, @Nullable PlayerEntity p_175719_1_, BlockPos p_175719_2_, Direction p_175719_3_) { - p_175719_2_ = p_175719_2_.offset(p_175719_3_); + p_175719_2_ = p_175719_2_.relative(p_175719_3_); if (world.getBlockState(p_175719_2_) .getBlock() == Blocks.FIRE) { - world.playEvent(p_175719_1_, 1009, p_175719_2_, 0); + world.levelEvent(p_175719_1_, 1009, p_175719_2_, 0); world.removeBlock(p_175719_2_, false); return true; } else { diff --git a/src/main/java/com/simibubi/create/foundation/utility/Color.java b/src/main/java/com/simibubi/create/foundation/utility/Color.java new file mode 100644 index 000000000..1872f3be0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/Color.java @@ -0,0 +1,327 @@ +package com.simibubi.create.foundation.utility; + +import java.util.function.UnaryOperator; + +import javax.annotation.Nonnull; + +import com.google.common.hash.Hashing; + +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Vector3d; + +@SuppressWarnings("PointlessBitwiseExpression") +public class Color { + public final static Color TRANSPARENT_BLACK = new Color(0, 0, 0, 0).setImmutable(); + public final static Color BLACK = new Color(0, 0, 0).setImmutable(); + public final static Color WHITE = new Color(255, 255, 255).setImmutable(); + public final static Color RED = new Color(255, 0, 0).setImmutable(); + public final static Color GREEN = new Color(0, 255, 0).setImmutable(); + public final static Color SPRING_GREEN = new Color(0, 255, 187).setImmutable(); + + protected boolean mutable = true; + protected int value; + + public Color(int r, int g, int b) { + this(r, g, b, 0xff); + } + + public Color(int r, int g, int b, int a) { + value = ((a & 0xff) << 24) | + ((r & 0xff) << 16) | + ((g & 0xff) << 8) | + ((b & 0xff) << 0); + } + + public Color(float r, float g, float b, float a) { + this( + (int) (0.5 + 0xff * MathHelper.clamp(r, 0, 1)), + (int) (0.5 + 0xff * MathHelper.clamp(g, 0, 1)), + (int) (0.5 + 0xff * MathHelper.clamp(b, 0, 1)), + (int) (0.5 + 0xff * MathHelper.clamp(a, 0, 1)) + ); + } + + public Color(int rgba) { + value = rgba; + } + + public Color(int rgb, boolean hasAlpha) { + if (hasAlpha) { + value = rgb; + } else { + value = rgb | 0xff_000000; + } + } + + public Color copy() { + return copy(true); + } + + public Color copy(boolean mutable) { + if (mutable) + return new Color(value); + else + return new Color(value).setImmutable(); + } + + /** + * Mark this color as immutable. Attempting to mutate this color in the future + * will instead cause a copy to be created that can me modified. + */ + public Color setImmutable() { + this.mutable = false; + return this; + } + + /** + * @return the red component in the range 0-255. + * @see #getRGB + */ + public int getRed() { + return (getRGB() >> 16) & 0xff; + } + + /** + * @return the green component in the range 0-255. + * @see #getRGB + */ + public int getGreen() { + return (getRGB() >> 8) & 0xff; + } + + /** + * @return the blue component in the range 0-255. + * @see #getRGB + */ + public int getBlue() { + return (getRGB() >> 0) & 0xff; + } + + /** + * @return the alpha component in the range 0-255. + * @see #getRGB + */ + public int getAlpha() { + return (getRGB() >> 24) & 0xff; + } + + /** + * @return the red component in the range 0-1f. + */ + public float getRedAsFloat() { + return getRed() / 255f; + } + + /** + * @return the green component in the range 0-1f. + */ + public float getGreenAsFloat() { + return getGreen() / 255f; + } + + /** + * @return the blue component in the range 0-1f. + */ + public float getBlueAsFloat() { + return getBlue() / 255f; + } + + /** + * @return the alpha component in the range 0-1f. + */ + public float getAlphaAsFloat() { + return getAlpha() / 255f; + } + + /** + * Returns the RGB value representing this color + * (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue). + * @return the RGB value of the color + */ + public int getRGB() { + return value; + } + + public Vector3d asVector() { + return new Vector3d(getRedAsFloat(), getGreenAsFloat(), getBlueAsFloat()); + } + + public Color setRed(int r) { + return ensureMutable().setRedUnchecked(r); + } + + public Color setGreen(int g) { + return ensureMutable().setGreenUnchecked(g); + } + + public Color setBlue(int b) { + return ensureMutable().setBlueUnchecked(b); + } + + public Color setAlpha(int a) { + return ensureMutable().setAlphaUnchecked(a); + } + + public Color setRed(float r) { + return ensureMutable().setRedUnchecked((int) (0xff * MathHelper.clamp(r, 0, 1))); + } + + public Color setGreen(float g) { + return ensureMutable().setGreenUnchecked((int) (0xff * MathHelper.clamp(g, 0, 1))); + } + + public Color setBlue(float b) { + return ensureMutable().setBlueUnchecked((int) (0xff * MathHelper.clamp(b, 0, 1))); + } + + public Color setAlpha(float a) { + return ensureMutable().setAlphaUnchecked((int) (0xff * MathHelper.clamp(a, 0, 1))); + } + + public Color scaleAlpha(float factor) { + return ensureMutable().setAlphaUnchecked((int) (getAlpha() * MathHelper.clamp(factor, 0, 1))); + } + + @Deprecated + public Color applyAlpha(float alpha) { + if (getAlpha() == 0) + return setAlpha(alpha); + else + return scaleAlpha(alpha); + } + + public Color mixWith(Color other, float weight) { + return ensureMutable() + .setRedUnchecked((int) (getRed() + (other.getRed() - getRed()) * weight)) + .setGreenUnchecked((int) (getGreen() + (other.getGreen() - getGreen()) * weight)) + .setBlueUnchecked((int) (getBlue() + (other.getBlue() - getBlue()) * weight)) + .setAlphaUnchecked((int) (getAlpha() + (other.getAlpha() - getAlpha()) * weight)); + } + + public Color darker() { + int a = getAlpha(); + return ensureMutable().mixWith(BLACK, .25f).setAlphaUnchecked(a); + } + + public Color brighter() { + int a = getAlpha(); + return ensureMutable().mixWith(WHITE, .25f).setAlphaUnchecked(a); + } + + public Color setValue(int value) { + return ensureMutable().setValueUnchecked(value); + } + + public Color modifyValue(UnaryOperator function) { + int newValue = function.apply(value); + if (newValue == value) + return this; + + return ensureMutable().setValueUnchecked(newValue); + } + + // ********* // + + protected Color ensureMutable() { + if (this.mutable) + return this; + + return new Color(this.value); + } + + protected Color setRedUnchecked(int r) { + this.value = (this.value & 0xff_00ffff) | ((r & 0xff) << 16); + return this; + } + + protected Color setGreenUnchecked(int g) { + this.value = (this.value & 0xff_ff00ff) | ((g & 0xff) << 8); + return this; + } + + protected Color setBlueUnchecked(int b) { + this.value = (this.value & 0xff_ffff00) | ((b & 0xff) << 0); + return this; + } + + protected Color setAlphaUnchecked(int a) { + this.value = (this.value & 0x00_ffffff) | ((a & 0xff) << 24); + return this; + } + + protected Color setValueUnchecked(int value) { + this.value = value; + return this; + } + + // ********* // + + public static Color mixColors(@Nonnull Color c1, @Nonnull Color c2, float w) { + return new Color( + (int) (c1.getRed() + (c2.getRed() - c1.getRed()) * w), + (int) (c1.getGreen() + (c2.getGreen() - c1.getGreen()) * w), + (int) (c1.getBlue() + (c2.getBlue() - c1.getBlue()) * w), + (int) (c1.getAlpha() + (c2.getAlpha() - c1.getAlpha()) * w) + ); + } + + public static Color mixColors(@Nonnull Couple colors, float w) { + return mixColors(colors.getFirst(), colors.getSecond(), w); + } + + public static int mixColors(int color1, int color2, float w) { + int a1 = (color1 >> 24); + int r1 = (color1 >> 16) & 0xFF; + int g1 = (color1 >> 8) & 0xFF; + int b1 = color1 & 0xFF; + int a2 = (color2 >> 24); + int r2 = (color2 >> 16) & 0xFF; + int g2 = (color2 >> 8) & 0xFF; + int b2 = color2 & 0xFF; + + return + ((int) (a1 + (a2 - a1) * w) << 24) + + ((int) (r1 + (r2 - r1) * w) << 16) + + ((int) (g1 + (g2 - g1) * w) << 8) + + ((int) (b1 + (b2 - b1) * w) << 0); + } + + public static Color rainbowColor(int timeStep) { + int localTimeStep = Math.abs(timeStep) % 1536; + int timeStepInPhase = localTimeStep % 256; + int phaseBlue = localTimeStep / 256; + int red = colorInPhase(phaseBlue + 4, timeStepInPhase); + int green = colorInPhase(phaseBlue + 2, timeStepInPhase); + int blue = colorInPhase(phaseBlue, timeStepInPhase); + return new Color(red, green, blue); + } + + private static int colorInPhase(int phase, int progress) { + phase = phase % 6; + if (phase <= 1) + return 0; + if (phase == 2) + return progress; + if (phase <= 4) + return 255; + else + return 255 - progress; + } + + public static Color generateFromLong(long l) { + return rainbowColor(Hashing.crc32().hashLong(l).asInt()) + .mixWith(WHITE, 0.5f); + } + + /** + * Try not to introduce new usages of this method and instead use Color instances directly + */ + @Deprecated + public static Vector3d vectorFromRGB(int color) { + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + return new Vector3d(r, g, b).scale(1 / 255d); + } + +} 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..4022dba98 --- /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.getAverageGrassColor(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 + .getColorForPower(pos != null && world != null ? state.getValue(BlockStateProperties.POWER) : 0); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java b/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java deleted file mode 100644 index d02fb3156..000000000 --- a/src/main/java/com/simibubi/create/foundation/utility/ColorHelper.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.simibubi.create.foundation.utility; - -import java.awt.Color; -import java.util.UUID; - -import javax.annotation.Nonnull; - -import com.mojang.blaze3d.systems.RenderSystem; - -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Vector3d; - -public class ColorHelper { - - public static int rainbowColor(int timeStep) { - int localTimeStep = timeStep % 1536; - int timeStepInPhase = localTimeStep % 256; - int phaseBlue = localTimeStep / 256; - int red = colorInPhase(phaseBlue + 4, timeStepInPhase); - int green = colorInPhase(phaseBlue + 2, timeStepInPhase); - int blue = colorInPhase(phaseBlue, timeStepInPhase); - return (red << 16) + (green << 8) + (blue); - } - - private static int colorInPhase(int phase, int progress) { - phase = phase % 6; - if (phase <= 1) - return 0; - if (phase == 2) - return progress; - if (phase <= 4) - return 255; - else - return 255 - progress; - } - - public static int applyAlpha(int color, float alpha) { - int prevAlphaChannel = (color >> 24) & 0xFF; - if (prevAlphaChannel > 0) - alpha *= prevAlphaChannel / 256f; - int alphaChannel = (int) (0xFF * MathHelper.clamp(alpha, 0, 1)); - return (color & 0xFFFFFF) | alphaChannel << 24; - } - - public static Color applyAlpha(Color c, float alpha) { - return new Color(applyAlpha(c.getRGB(), alpha), true); - } - - public static int mixColors(int color1, int color2, float w) { - int r1 = (color1 >> 16); - int g1 = (color1 >> 8) & 0xFF; - int b1 = color1 & 0xFF; - int r2 = (color2 >> 16); - int g2 = (color2 >> 8) & 0xFF; - int b2 = color2 & 0xFF; - - int color = ((int) (r1 + (r2 - r1) * w) << 16) + ((int) (g1 + (g2 - g1) * w) << 8) + (int) (b1 + (b2 - b1) * w); - - return color; - } - - @Nonnull - public static Color mixColors(@Nonnull Color c1, @Nonnull Color c2, float w) { - float[] cmp1 = c1.getRGBComponents(null); - float[] cmp2 = c2.getRGBComponents(null); - return new Color( - cmp1[0] + (cmp2[0] - cmp1[0]) * w, - cmp1[1] + (cmp2[1] - cmp1[1]) * w, - cmp1[2] + (cmp2[2] - cmp1[2]) * w, - cmp1[3] + (cmp2[3] - cmp1[3]) * w - ); - } - - @Nonnull - public static Color mixColors(@Nonnull Couple colors, float w) { - return mixColors(colors.getFirst(), colors.getSecond(), w); - } - - public static int mixAlphaColors(int color1, int color2, float w) { - int a1 = (color1 >> 24); - int r1 = (color1 >> 16) & 0xFF; - int g1 = (color1 >> 8) & 0xFF; - int b1 = color1 & 0xFF; - int a2 = (color2 >> 24); - int r2 = (color2 >> 16) & 0xFF; - int g2 = (color2 >> 8) & 0xFF; - int b2 = color2 & 0xFF; - - int color = ((int) (a1 + (a2 - a1) * w) << 24) + ((int) (r1 + (r2 - r1) * w) << 16) - + ((int) (g1 + (g2 - g1) * w) << 8) + (int) (b1 + (b2 - b1) * w); - - return color; - } - - public static void glColor(int color) { - color = mixColors(color, 0xFFFFFF, .5f); - int r = (color >> 16) & 0xFF; - int g = (color >> 8) & 0xFF; - int b = color & 0xFF; - - RenderSystem.color4f(r / 256f, g / 256f, b / 256f, 1); - } - - public static void glResetColor() { - RenderSystem.color4f(1, 1, 1, 1); - } - - public static Vector3d getRGB(int color) { - int r = (color >> 16) & 0xFF; - int g = (color >> 8) & 0xFF; - int b = color & 0xFF; - return new Vector3d(r, g, b).scale(1 / 256d); - } - - public static int colorFromUUID(UUID uuid) { - if (uuid == null) - return 0x333333; - return colorFromLong(uuid.getLeastSignificantBits()); - } - - public static int colorFromLong(long l) { - int rainbowColor = ColorHelper.rainbowColor(String.valueOf(l) - .hashCode()); - return ColorHelper.mixColors(rainbowColor, 0xFFFFFF, .5f); - } - -} 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..f59840d5b 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.displayClientMessage(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.displayClientMessage(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.displayClientMessage(new StringTextComponent(message), true); + } + + @Deprecated + public static void log(String message) { + Create.LOGGER.info(message); } @Deprecated @@ -44,17 +50,17 @@ public class Debug { StackTraceElement[] stackTraceElements = Thread.currentThread() .getStackTrace(); IFormattableTextComponent text = new StringTextComponent("[") - .append(new StringTextComponent(getLogicalSide()).formatted(TextFormatting.GOLD)) + .append(new StringTextComponent(getLogicalSide()).withStyle(TextFormatting.GOLD)) .append("] "); for (int i = 1; i < depth + 2 && i < stackTraceElements.length; i++) { StackTraceElement e = stackTraceElements[i]; if (e.getClassName() .equals(Debug.class.getName())) continue; - text.append(new StringTextComponent(e.getMethodName()).formatted(TextFormatting.YELLOW)) + text.append(new StringTextComponent(e.getMethodName()).withStyle(TextFormatting.YELLOW)) .append(", "); } - return text.append(new StringTextComponent(" ...").formatted(TextFormatting.GRAY)); + return text.append(new StringTextComponent(" ...").withStyle(TextFormatting.GRAY)); } @Deprecated diff --git a/src/main/java/com/simibubi/create/foundation/utility/DirectionHelper.java b/src/main/java/com/simibubi/create/foundation/utility/DirectionHelper.java index 88ce27061..14996e0ea 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/DirectionHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/DirectionHelper.java @@ -27,7 +27,7 @@ public class DirectionHelper { return dir; case Y: if (dir != UP && dir != DOWN) { - return dir.rotateY(); + return dir.getClockWise(); } return dir; diff --git a/src/main/java/com/simibubi/create/foundation/utility/EmptyNamedTag.java b/src/main/java/com/simibubi/create/foundation/utility/EmptyNamedTag.java deleted file mode 100644 index 6e33ff6d1..000000000 --- a/src/main/java/com/simibubi/create/foundation/utility/EmptyNamedTag.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.simibubi.create.foundation.utility; - -import java.util.Collections; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - -import mcp.MethodsReturnNonnullByDefault; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.common.Tags; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class EmptyNamedTag implements Tags.IOptionalNamedTag { - private final ResourceLocation id; - - public EmptyNamedTag(ResourceLocation id) { - this.id = id; - } - - @Override - public boolean isDefaulted() { - return false; - } - - @Override - public ResourceLocation getId() { - return id; - } - - @Override - public boolean contains(Object p_230235_1_) { - return false; - } - - @Override - public List values() { - return Collections.emptyList(); - } -} 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/FontHelper.java b/src/main/java/com/simibubi/create/foundation/utility/FontHelper.java index c81ffef70..ce5f20f32 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/FontHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/FontHelper.java @@ -31,7 +31,7 @@ public final class FontHelper { StringBuilder currentLine = new StringBuilder(); int width = 0; for (String word : words) { - int newWidth = font.getStringWidth(word); + int newWidth = font.width(word); if (width + newWidth > maxWidthPerLine) { if (width > 0) { String line = currentLine.toString(); @@ -55,13 +55,13 @@ public final class FontHelper { public static void drawSplitString(MatrixStack ms, FontRenderer font, String text, int x, int y, int width, int color) { List list = cutString(font, text, width); - Matrix4f matrix4f = ms.peek() - .getModel(); + Matrix4f matrix4f = ms.last() + .pose(); for (String s : list) { float f = (float) x; - if (font.getBidiFlag()) { - int i = font.getStringWidth(font.bidiReorder(s)); + if (font.isBidirectional()) { + int i = font.width(font.bidirectionalShaping(s)); f += (float) (width - i); } @@ -76,10 +76,10 @@ public final class FontHelper { return 0; } else { IRenderTypeBuffer.Impl irendertypebuffer$impl = IRenderTypeBuffer.immediate(Tessellator.getInstance() - .getBuffer()); - int i = font.draw(p_228078_1_, p_228078_2_, p_228078_3_, p_228078_4_, p_228078_6_, p_228078_5_, + .getBuilder()); + int i = font.drawInBatch(p_228078_1_, p_228078_2_, p_228078_3_, p_228078_4_, p_228078_6_, p_228078_5_, irendertypebuffer$impl, false, 0, 15728880); - irendertypebuffer$impl.draw(); + irendertypebuffer$impl.endBatch(); return i; } } 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/ISimpleReloadListener.java b/src/main/java/com/simibubi/create/foundation/utility/ISimpleReloadListener.java index 1b361b789..fb923c13a 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ISimpleReloadListener.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ISimpleReloadListener.java @@ -13,7 +13,7 @@ public interface ISimpleReloadListener extends IFutureReloadListener { @Override default CompletableFuture reload(IFutureReloadListener.IStage stage, IResourceManager resourceManager, IProfiler prepareProfiler, IProfiler applyProfiler, Executor prepareExecutor, Executor applyExecutor) { - return stage.markCompleteAwaitingOthers(Unit.INSTANCE).thenRunAsync(() -> { + return stage.wait(Unit.INSTANCE).thenRunAsync(() -> { onReload(resourceManager, applyProfiler); }, applyExecutor); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/Iterate.java b/src/main/java/com/simibubi/create/foundation/utility/Iterate.java index 71b621cd2..138d2642c 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Iterate.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Iterate.java @@ -21,7 +21,7 @@ public class Iterate { private static Direction[] getHorizontals() { Direction[] directions = new Direction[4]; for (int i = 0; i < 4; i++) - directions[i] = Direction.byHorizontalIndex(i); + directions[i] = Direction.from2DDataValue(i); return directions; } @@ -38,10 +38,10 @@ public class Iterate { } public static List hereAndBelow(BlockPos pos) { - return Arrays.asList(pos, pos.down()); + return Arrays.asList(pos, pos.below()); } public static List hereBelowAndAbove(BlockPos pos) { - return Arrays.asList(pos, pos.down(), pos.up()); + return Arrays.asList(pos, pos.below(), pos.above()); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/Lang.java b/src/main/java/com/simibubi/create/foundation/utility/Lang.java index 62384d800..4572424b2 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Lang.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Lang.java @@ -21,7 +21,7 @@ public class Lang { } public static void sendStatus(PlayerEntity player, String key, Object... args) { - player.sendStatusMessage(createTranslationTextComponent(key, args), true); + player.displayClientMessage(createTranslationTextComponent(key, args), true); } public static List translatedOptions(String prefix, String... keys) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java b/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java deleted file mode 100644 index 11ff390c7..000000000 --- a/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.simibubi.create.foundation.utility; - -import com.mojang.blaze3d.matrix.MatrixStack; - -import net.minecraft.util.Direction; -import net.minecraft.util.Direction.Axis; -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; -import net.minecraft.util.math.vector.Vector3i; - -public class MatrixStacker { - - public static final Vector3d center = VecHelper.getCenterOf(BlockPos.ZERO); - static MatrixStacker instance; - - MatrixStack ms; - - public static MatrixStacker of(MatrixStack ms) { - if (instance == null) - instance = new MatrixStacker(); - instance.ms = ms; - return instance; - } - - public MatrixStacker restoreIdentity() { - MatrixStack.Entry entry = ms.peek(); - - entry.getModel() - .loadIdentity(); - entry.getNormal() - .loadIdentity(); - - return this; - } - - public MatrixStacker rotate(Direction axis, float radians) { - if (radians == 0) - return this; - ms.multiply(axis.getUnitVector() - .getRadialQuaternion(radians)); - return this; - } - - public MatrixStacker rotate(double angle, Axis axis) { - Vector3f vec = - axis == Axis.X ? Vector3f.POSITIVE_X : axis == Axis.Y ? Vector3f.POSITIVE_Y : Vector3f.POSITIVE_Z; - return multiply(vec, angle); - } - - public MatrixStacker rotateX(double angle) { - return multiply(Vector3f.POSITIVE_X, angle); - } - - public MatrixStacker rotateY(double angle) { - return multiply(Vector3f.POSITIVE_Y, angle); - } - - public MatrixStacker rotateZ(double angle) { - return multiply(Vector3f.POSITIVE_Z, angle); - } - - public MatrixStacker centre() { - return translate(center); - } - - public MatrixStacker unCentre() { - return translateBack(center); - } - - public MatrixStacker translate(Vector3i vec) { - ms.translate(vec.getX(), vec.getY(), vec.getZ()); - return this; - } - - public MatrixStacker translate(Vector3d vec) { - ms.translate(vec.x, vec.y, vec.z); - return this; - } - - public MatrixStacker translateBack(Vector3d vec) { - ms.translate(-vec.x, -vec.y, -vec.z); - return this; - } - - public MatrixStacker translate(double x, double y, double z) { - ms.translate(x, y, z); - return this; - } - - public MatrixStacker multiply(Quaternion quaternion) { - ms.multiply(quaternion); - return this; - } - - public MatrixStacker nudge(int id) { - long randomBits = (long) id * 31L * 493286711L; - randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L; - float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - ms.translate(xNudge, yNudge, zNudge); - return this; - } - - public MatrixStacker multiply(Vector3f axis, double angle) { - if (angle == 0) - return this; - ms.multiply(axis.getDegreesQuaternion((float) angle)); - return this; - } - - public MatrixStacker push() { - ms.push(); - return this; - } - - public MatrixStacker pop() { - ms.pop(); - return this; - } - - public MatrixStack unwrap() { - return ms; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/utility/ModelSwapper.java b/src/main/java/com/simibubi/create/foundation/utility/ModelSwapper.java new file mode 100644 index 000000000..df5244978 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/ModelSwapper.java @@ -0,0 +1,94 @@ +package com.simibubi.create.foundation.utility; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import com.simibubi.create.foundation.block.render.CustomBlockModels; +import com.simibubi.create.foundation.item.render.CustomItemModels; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItems; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.BlockModelShapes; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.model.ModelResourceLocation; +import net.minecraft.item.Item; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.ModelBakeEvent; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.eventbus.api.IEventBus; + +public class ModelSwapper { + + protected CustomBlockModels customBlockModels = new CustomBlockModels(); + protected CustomItemModels customItemModels = new CustomItemModels(); + protected CustomRenderedItems customRenderedItems = new CustomRenderedItems(); + + public CustomBlockModels getCustomBlockModels() { + return customBlockModels; + } + + public CustomItemModels getCustomItemModels() { + return customItemModels; + } + + public CustomRenderedItems getCustomRenderedItems() { + return customRenderedItems; + } + + public void onModelRegistry(ModelRegistryEvent event) { + customRenderedItems.forEach((item, modelFunc) -> modelFunc.apply(null) + .getModelLocations() + .forEach(ModelLoader::addSpecialModel)); + } + + public void onModelBake(ModelBakeEvent event) { + Map modelRegistry = event.getModelRegistry(); + + customBlockModels.forEach((block, modelFunc) -> swapModels(modelRegistry, getAllBlockStateModelLocations(block), modelFunc)); + customItemModels.forEach((item, modelFunc) -> swapModels(modelRegistry, getItemModelLocation(item), modelFunc)); + customRenderedItems.forEach((item, modelFunc) -> { + swapModels(modelRegistry, getItemModelLocation(item), m -> { + CustomRenderedItemModel swapped = modelFunc.apply(m); + swapped.loadPartials(event); + return swapped; + }); + }); + } + + public void registerListeners(IEventBus modEventBus) { + modEventBus.addListener(this::onModelRegistry); + modEventBus.addListener(this::onModelBake); + } + + public static void swapModels(Map modelRegistry, + List locations, Function factory) { + locations.forEach(location -> { + swapModels(modelRegistry, location, factory); + }); + } + + public static void swapModels(Map modelRegistry, + ModelResourceLocation location, Function factory) { + modelRegistry.put(location, factory.apply(modelRegistry.get(location))); + } + + public static List getAllBlockStateModelLocations(Block block) { + List models = new ArrayList<>(); + ResourceLocation blockRl = block.getRegistryName(); + block.getStateDefinition() + .getPossibleStates() + .forEach(state -> { + models.add(BlockModelShapes.stateToModelLocation(blockRl, state)); + }); + return models; + } + + public static ModelResourceLocation getItemModelLocation(Item item) { + return new ModelResourceLocation(item.getRegistryName(), "inventory"); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/NBTHelper.java b/src/main/java/com/simibubi/create/foundation/utility/NBTHelper.java index abb7f39c5..1c877414e 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/NBTHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/NBTHelper.java @@ -13,6 +13,7 @@ import net.minecraft.nbt.FloatNBT; import net.minecraft.nbt.INBT; import net.minecraft.nbt.ListNBT; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraftforge.common.util.Constants.NBT; public class NBTHelper { @@ -22,13 +23,15 @@ public class NBTHelper { public static > T readEnum(CompoundNBT nbt, String key, Class enumClass) { T[] enumConstants = enumClass.getEnumConstants(); - String name = nbt.getString(key); if (enumConstants == null) - throw new IllegalArgumentException("Non-Enum class passed to readEnum(): " + enumClass.getName()); - for (T t : enumConstants) { - if (t.name() - .equals(name)) - return t; + throw new IllegalArgumentException("Non-Enum class passed to readEnum: " + enumClass.getName()); + if (nbt.contains(key, NBT.TAG_STRING)) { + String name = nbt.getString(key); + for (T t : enumConstants) { + if (t.name() + .equals(name)) + return t; + } } return enumConstants[0]; } @@ -53,22 +56,22 @@ public class NBTHelper { listNBT.forEach(inbt -> consumer.accept((CompoundNBT) inbt)); } - public static ListNBT writeItemList(List stacks) { + public static ListNBT writeItemList(Iterable stacks) { return writeCompoundList(stacks, ItemStack::serializeNBT); } public static List readItemList(ListNBT stacks) { - return readCompoundList(stacks, ItemStack::read); + return readCompoundList(stacks, ItemStack::of); } public static ListNBT writeAABB(AxisAlignedBB bb) { ListNBT bbtag = new ListNBT(); - bbtag.add(FloatNBT.of((float) bb.minX)); - bbtag.add(FloatNBT.of((float) bb.minY)); - bbtag.add(FloatNBT.of((float) bb.minZ)); - bbtag.add(FloatNBT.of((float) bb.maxX)); - bbtag.add(FloatNBT.of((float) bb.maxY)); - bbtag.add(FloatNBT.of((float) bb.maxZ)); + bbtag.add(FloatNBT.valueOf((float) bb.minX)); + bbtag.add(FloatNBT.valueOf((float) bb.minY)); + bbtag.add(FloatNBT.valueOf((float) bb.minZ)); + bbtag.add(FloatNBT.valueOf((float) bb.maxX)); + bbtag.add(FloatNBT.valueOf((float) bb.maxY)); + bbtag.add(FloatNBT.valueOf((float) bb.maxZ)); return bbtag; } 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..8c1cc871a 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,17 +35,33 @@ 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.getAsString())) return null; } return data; }); addSurvivalProcessor(AllTileEntities.FUNNEL.get(), data -> { if (data.contains("Filter")) { - ItemStack filter = ItemStack.read(data.getCompound("Filter")); + ItemStack filter = ItemStack.of(data.getCompound("Filter")); if (filter.getItem() instanceof FilterItem) data.remove("Filter"); } @@ -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) { @@ -65,7 +90,7 @@ public final class NBTProcessors { .apply(compound); if (tileEntity instanceof MobSpawnerTileEntity) return compound; - if (tileEntity.onlyOpsCanSetNbt()) + if (tileEntity.onlyOpCanSetNbt()) return null; return compound; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/Pointing.java b/src/main/java/com/simibubi/create/foundation/utility/Pointing.java index c9eac4486..c734ab4e5 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Pointing.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Pointing.java @@ -15,7 +15,7 @@ public enum Pointing implements IStringSerializable { } @Override - public String getString() { + public String getSerializedName() { return Lang.asId(name()); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/RaycastHelper.java b/src/main/java/com/simibubi/create/foundation/utility/RaycastHelper.java index 057c2b378..2b8b6af84 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/RaycastHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/RaycastHelper.java @@ -19,7 +19,7 @@ public class RaycastHelper { Vector3d origin = getTraceOrigin(playerIn); Vector3d target = getTraceTarget(playerIn, range, origin); RayTraceContext context = new RayTraceContext(origin, target, BlockMode.COLLIDER, FluidMode.NONE, playerIn); - return worldIn.rayTraceBlocks(context); + return worldIn.clip(context); } public static PredicateTraceResult rayTraceUntil(PlayerEntity playerIn, double range, @@ -30,8 +30,8 @@ public class RaycastHelper { } public static Vector3d getTraceTarget(PlayerEntity playerIn, double range, Vector3d origin) { - float f = playerIn.rotationPitch; - float f1 = playerIn.rotationYaw; + float f = playerIn.xRot; + float f1 = playerIn.yRot; float f2 = MathHelper.cos(-f1 * 0.017453292F - (float) Math.PI); float f3 = MathHelper.sin(-f1 * 0.017453292F - (float) Math.PI); float f4 = -MathHelper.cos(-f * 0.017453292F); @@ -67,7 +67,7 @@ public class RaycastHelper { BlockPos currentPos = new BlockPos(x, y, z); if (predicate.test(currentPos)) - return new PredicateTraceResult(currentPos, Direction.getFacingFromVector(dx - x, dy - y, dz - z)); + return new PredicateTraceResult(currentPos, Direction.getNearest(dx - x, dy - y, dz - z)); int remainingDistance = 200; 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..5b471e63b 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/RemapHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/RemapHelper.java @@ -29,7 +29,6 @@ import static com.simibubi.create.AllItems.CRUSHED_GOLD; import static com.simibubi.create.AllItems.CRUSHED_IRON; import static com.simibubi.create.AllItems.CRUSHED_ZINC; import static com.simibubi.create.AllItems.GOLDEN_SHEET; -import static com.simibubi.create.AllItems.LAPIS_SHEET; import static com.simibubi.create.AllItems.POWDERED_OBSIDIAN; import static com.simibubi.create.AllItems.SCHEMATIC; import static com.simibubi.create.AllItems.SCHEMATIC_AND_QUILL; @@ -54,17 +53,17 @@ import static com.simibubi.create.content.palettes.AllPaletteBlocks.SPRUCE_WINDO import java.util.HashMap; import java.util.Map; -import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; import net.minecraft.block.Block; +import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.ForgeMod; import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.event.RegistryEvent.MissingMappings.Mapping; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.registries.ForgeRegistries; @@ -77,17 +76,12 @@ public class RemapHelper { reMap.put("encased_shaft", ANDESITE_ENCASED_SHAFT.getId()); reMap.put("encased_belt", AllBlocks.ENCASED_CHAIN_DRIVE.getId()); reMap.put("adjustable_pulley", AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT.getId()); -// reMap.put("linked_extractor", ); reMap.put("limestone_stairs", Create.asResource("polished_limestone_stairs")); -// reMap.put("window_in_a_block", ); reMap.put("weathered_limestone_layers", Create.asResource("layered_weathered_limestone")); reMap.put("stockswitch", STOCKPILE_SWITCH.getId()); reMap.put("indented_gabbro_slab", Create.asResource("polished_gabbro_slab")); -// reMap.put("vertical_extractor", ); reMap.put("andesite_layers", Create.asResource("layered_andesite")); reMap.put("scoria_layers", Create.asResource("layered_scoria")); -// reMap.put("extractor", ); -// reMap.put("linked_transposer", ); reMap.put("dark_scoria_tiles_stairs", Create.asResource("dark_scoria_bricks_stairs")); reMap.put("redstone_latch", POWERED_LATCH.getId()); reMap.put("oak_glass", OAK_WINDOW.getId()); @@ -99,9 +93,6 @@ public class RemapHelper { reMap.put("limestone_wall", Create.asResource("polished_limestone_wall")); reMap.put("acacia_glass_pane", ACACIA_WINDOW_PANE.getId()); reMap.put("dark_oak_glass", DARK_OAK_WINDOW.getId()); -// reMap.put("vertical_linked_extractor", ); -// reMap.put("vertical_funnel", ); -// reMap.put("vertical_linked_transposer", ); reMap.put("dark_oak_glass_pane", DARK_OAK_WINDOW_PANE.getId()); reMap.put("belt_funnel", BRASS_BELT_FUNNEL.getId()); reMap.put("dark_scoria_tiles", Create.asResource("dark_scoria_bricks")); @@ -110,7 +101,6 @@ public class RemapHelper { reMap.put("weathered_limestone_stairs", Create.asResource("polished_weathered_limestone_stairs")); reMap.put("dolomite_layers", Create.asResource("layered_dolomite")); reMap.put("jungle_glass", JUNGLE_WINDOW.getId()); -// reMap.put("transposer", ); reMap.put("iron_glass", ORNATE_IRON_WINDOW.getId()); reMap.put("limestone_slab", Create.asResource("polished_limestone_slab")); reMap.put("entity_detector", CONTENT_OBSERVER.getId()); @@ -118,7 +108,6 @@ public class RemapHelper { reMap.put("scoria_slab", Create.asResource("polished_scoria_slab")); reMap.put("birch_glass", BIRCH_WINDOW.getId()); reMap.put("saw", MECHANICAL_SAW.getId()); -// reMap.put("vertical_transposer", ); reMap.put("flexpulsepeater", ADJUSTABLE_PULSE_REPEATER.getId()); reMap.put("dolomite_wall", Create.asResource("polished_dolomite_wall")); reMap.put("gabbro_layers", Create.asResource("layered_gabbro")); @@ -126,7 +115,6 @@ public class RemapHelper { reMap.put("stress_gauge", STRESSOMETER.getId()); reMap.put("gabbro_slab", Create.asResource("polished_gabbro_slab")); reMap.put("spruce_glass", SPRUCE_WINDOW.getId()); -// reMap.put("cocoa_log", ); reMap.put("iron_glass_pane", ORNATE_IRON_WINDOW_PANE.getId()); reMap.put("birch_glass_pane", BIRCH_WINDOW_PANE.getId()); reMap.put("harvester", MECHANICAL_HARVESTER.getId()); @@ -148,63 +136,39 @@ public class RemapHelper { reMap.put("diorite_layers", Create.asResource("layered_diorite")); reMap.put("oak_glass_pane", OAK_WINDOW_PANE.getId()); reMap.put("translation_chassis", LINEAR_CHASSIS.getId()); -// reMap.put("symmetry_tripleplane", Create.asResource("")); reMap.put("weathered_limestone_slab", Create.asResource("polished_weathered_limestone_slab")); reMap.put("gabbro_stairs", Create.asResource("polished_gabbro_stairs")); reMap.put("limestone_layers", Create.asResource("layered_limestone")); -// reMap.put("symmetry_plane", Create.asResource("")); reMap.put("translation_chassis_secondary", SECONDARY_LINEAR_CHASSIS.getId()); reMap.put("jungle_glass_pane", JUNGLE_WINDOW_PANE.getId()); reMap.put("piston_pole", PISTON_EXTENSION_POLE.getId()); -// reMap.put("shadow_steel_sword", ); - reMap.put("lapis_plate", LAPIS_SHEET.getId()); reMap.put("crushed_copper", CRUSHED_COPPER.getId()); reMap.put("empty_blueprint", SCHEMATIC.getId()); -// reMap.put("shadow_steel_mattock", ); -// reMap.put("rose_quartz_sword", ); reMap.put("gold_sheet", GOLDEN_SHEET.getId()); reMap.put("flour", WHEAT_FLOUR.getId()); -// reMap.put("encased_shaft", ); reMap.put("blueprint_and_quill", SCHEMATIC_AND_QUILL.getId()); reMap.put("crushed_iron", CRUSHED_IRON.getId()); -// reMap.put("blazing_axe", ); reMap.put("slot_cover", CRAFTER_SLOT_COVER.getId()); reMap.put("blueprint", SCHEMATIC.getId()); reMap.put("symmetry_wand", WAND_OF_SYMMETRY.getId()); reMap.put("terrain_zapper", WORLDSHAPER.getId()); -// reMap.put("blazing_sword", ); -// reMap.put("zinc_handle", HAND_CRANK.getId()); -// reMap.put("rose_quartz_axe", ); -// reMap.put("shadow_steel_pickaxe", ); reMap.put("crushed_zinc", CRUSHED_ZINC.getId()); -// reMap.put("rose_quartz_pickaxe", ); -// reMap.put("blazing_pickaxe", ); reMap.put("property_filter", ATTRIBUTE_FILTER.getId()); -// reMap.put("blazing_shovel", ); reMap.put("crushed_gold", CRUSHED_GOLD.getId()); reMap.put("obsidian_dust", POWDERED_OBSIDIAN.getId()); -// reMap.put("rose_quartz_shovel", ); } @SubscribeEvent public static void onRemapBlocks(RegistryEvent.MissingMappings event) { - ModContainer mod = ModList.get() - .getModContainerById(Create.ID) - .orElse(null); - if (mod == null) - return; - event.setModContainer(mod); - ImmutableList> mappings = event.getMappings(); - - for (RegistryEvent.MissingMappings.Mapping mapping : mappings) { + for (RegistryEvent.MissingMappings.Mapping mapping : event.getMappings(Create.ID)) { 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); } } } @@ -212,24 +176,29 @@ public class RemapHelper { @SubscribeEvent public static void onRemapItems(RegistryEvent.MissingMappings event) { - ModContainer mod = ModList.get() - .getModContainerById(Create.ID) - .orElse(null); - if (mod == null) - return; - event.setModContainer(mod); - ImmutableList> mappings = event.getMappings(); - - for (RegistryEvent.MissingMappings.Mapping mapping : mappings) { + for (RegistryEvent.MissingMappings.Mapping mapping : event.getMappings(Create.ID)) { 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); } } } } + + @SubscribeEvent + public static void onRemapFluids(RegistryEvent.MissingMappings event) { + for (Mapping mapping : event.getMappings(Create.ID)) { + if (mapping.key.getPath() + .equals("milk")) + mapping.remap(ForgeMod.MILK.get()); + else if (mapping.key.getPath() + .equals("flowing_milk")) + mapping.remap(ForgeMod.FLOWING_MILK.get()); + } + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/ServerSpeedProvider.java b/src/main/java/com/simibubi/create/foundation/utility/ServerSpeedProvider.java index 45e7e224b..28038851a 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ServerSpeedProvider.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ServerSpeedProvider.java @@ -32,9 +32,9 @@ public class ServerSpeedProvider { @OnlyIn(Dist.CLIENT) public static void clientTick() { if (Minecraft.getInstance() - .isSingleplayer() + .hasSingleplayerServer() && Minecraft.getInstance() - .isGamePaused()) + .isPaused()) return; modifier.tick(); clientTimer++; diff --git a/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java b/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java index d1191082d..70ccfb950 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java +++ b/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Predicate; @@ -13,6 +14,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import com.simibubi.create.AllTags; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.compat.dynamictrees.DynamicTree; import net.minecraft.block.BambooBlock; import net.minecraft.block.Block; @@ -36,6 +39,17 @@ import net.minecraft.world.World; public class TreeCutter { public static final Tree NO_TREE = new Tree(Collections.emptyList(), Collections.emptyList()); + public static boolean canDynamicTreeCutFrom(Block startBlock) { + return Mods.DYNAMICTREES.runIfInstalled(() -> () -> DynamicTree.isDynamicBranch(startBlock)).orElse(false); + } + + @Nonnull + public static Optional findDynamicTree(Block startBlock, BlockPos pos) { + if (canDynamicTreeCutFrom(startBlock)) + return Mods.DYNAMICTREES.runIfInstalled(() -> () -> new DynamicTree(pos)); + return Optional.empty(); + } + /** * Finds a tree at the given pos. Block at the position should be air * @@ -54,11 +68,11 @@ public class TreeCutter { List frontier = new LinkedList<>(); // Bamboo, Sugar Cane, Cactus - BlockState stateAbove = reader.getBlockState(pos.up()); + BlockState stateAbove = reader.getBlockState(pos.above()); if (isVerticalPlant(stateAbove)) { - logs.add(pos.up()); + logs.add(pos.above()); for (int i = 1; i < 256; i++) { - BlockPos current = pos.up(i); + BlockPos current = pos.above(i); if (!isVerticalPlant(reader.getBlockState(current))) break; logs.add(current); @@ -69,13 +83,13 @@ public class TreeCutter { // Chorus if (isChorus(stateAbove)) { - frontier.add(pos.up()); + frontier.add(pos.above()); while (!frontier.isEmpty()) { BlockPos current = frontier.remove(0); visited.add(current); logs.add(current); for (Direction direction : Iterate.directions) { - BlockPos offset = current.offset(direction); + BlockPos offset = current.relative(direction); if (visited.contains(offset)) continue; if (!isChorus(reader.getBlockState(offset))) @@ -92,7 +106,7 @@ public class TreeCutter { return NO_TREE; visited.add(pos); - BlockPos.getAllInBox(pos.add(-1, 0, -1), pos.add(1, 1, 1)) + BlockPos.betweenClosedStream(pos.offset(-1, 0, -1), pos.offset(1, 1, 1)) .forEach(p -> frontier.add(new BlockPos(p))); // Find all logs @@ -128,15 +142,15 @@ public class TreeCutter { if (isGenericLeaf) leaves.add(currentPos); - int distance = !isLeaf ? 0 : blockState.get(LeavesBlock.DISTANCE); + int distance = !isLeaf ? 0 : blockState.getValue(LeavesBlock.DISTANCE); for (Direction direction : Iterate.directions) { - BlockPos offset = currentPos.offset(direction); + BlockPos offset = currentPos.relative(direction); if (visited.contains(offset)) continue; BlockState state = reader.getBlockState(offset); BlockPos subtract = offset.subtract(pos); int horizontalDistance = Math.max(Math.abs(subtract.getX()), Math.abs(subtract.getZ())); - if (isLeaf(state) && state.get(LeavesBlock.DISTANCE) > distance + if (isLeaf(state) && state.getValue(LeavesBlock.DISTANCE) > distance || isNonDecayingLeaf(state) && horizontalDistance < 4) frontier.add(offset); } @@ -175,7 +189,7 @@ public class TreeCutter { Set visited = new HashSet<>(); List frontier = new LinkedList<>(); frontier.add(pos); - frontier.add(pos.up()); + frontier.add(pos.above()); int posY = pos.getY(); while (!frontier.isEmpty()) { @@ -185,7 +199,7 @@ public class TreeCutter { if (!isLog(reader.getBlockState(currentPos))) continue; - if (!lowerLayer && !pos.equals(currentPos.down()) && isLog(reader.getBlockState(currentPos.down()))) + if (!lowerLayer && !pos.equals(currentPos.below()) && isLog(reader.getBlockState(currentPos.below()))) return false; for (Direction direction : Iterate.directions) { @@ -193,7 +207,7 @@ public class TreeCutter { continue; if (direction == Direction.UP && !lowerLayer) continue; - BlockPos offset = currentPos.offset(direction); + BlockPos offset = currentPos.relative(direction); if (visited.contains(offset)) continue; frontier.add(offset); @@ -205,21 +219,21 @@ public class TreeCutter { } private static void addNeighbours(BlockPos pos, List frontier, Set visited) { - BlockPos.getAllInBox(pos.add(-1, -1, -1), pos.add(1, 1, 1)) + BlockPos.betweenClosedStream(pos.offset(-1, -1, -1), pos.offset(1, 1, 1)) .filter(((Predicate) visited::contains).negate()) .forEach(p -> frontier.add(new BlockPos(p))); } private static boolean isLog(BlockState state) { - return state.isIn(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(state); + return state.is(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(state); } private static boolean isNonDecayingLeaf(BlockState state) { - return state.isIn(BlockTags.WART_BLOCKS) || state.getBlock() == Blocks.SHROOMLIGHT; + return state.is(BlockTags.WART_BLOCKS) || state.getBlock() == Blocks.SHROOMLIGHT; } private static boolean isLeaf(BlockState state) { - return state.contains(LeavesBlock.DISTANCE); + return state.hasProperty(LeavesBlock.DISTANCE); } public static class Tree extends AbstractBlockBreakQueue { 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..7d273f44e 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java @@ -12,6 +12,7 @@ import net.minecraft.nbt.DoubleNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Mirror; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Quaternion; @@ -21,6 +22,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) { @@ -33,8 +35,7 @@ public class VecHelper { public static Vector3d rotateCentered(Vector3d vec, double deg, Axis axis) { Vector3d shift = getCenterOf(BlockPos.ZERO); - return VecHelper.rotate(vec.subtract(shift), deg, axis) - .add(shift); + return VecHelper.rotate(vec.subtract(shift), deg, axis).add(shift); } public static Vector3d rotate(Vector3d vec, double deg, Axis axis) { @@ -59,16 +60,51 @@ public class VecHelper { return vec; } + public static Vector3d mirrorCentered(Vector3d vec, Mirror mirror) { + Vector3d shift = getCenterOf(BlockPos.ZERO); + return VecHelper.mirror(vec.subtract(shift), mirror).add(shift); + } + + public static Vector3d mirror(Vector3d vec, Mirror mirror) { + if (mirror == null || mirror == Mirror.NONE) + return vec; + if (vec == Vector3d.ZERO) + return vec; + + double x = vec.x; + double y = vec.y; + double z = vec.z; + + if (mirror == Mirror.LEFT_RIGHT) + return new Vector3d(x, y, -z); + if (mirror == Mirror.FRONT_BACK) + return new Vector3d(-x, y, z); + return vec; + } + + public static Vector3d lookAt(Vector3d vec, Vector3d fwd) { + fwd = fwd.normalize(); + Vector3d up = new Vector3d(0,1,0); + double dot = fwd.dot(up); + if (Math.abs(dot) > 1 - 1.0E-3) + up = new Vector3d(0, 0, dot > 0 ? 1 : -1); + Vector3d right = fwd.cross(up).normalize(); + up = right.cross(fwd).normalize(); + double x = vec.x * right.x + vec.y * up.x + vec.z * fwd.x; + double y = vec.x * right.y + vec.y * up.y + vec.z * fwd.y; + double z = vec.x * right.z + vec.y * up.z + vec.z * fwd.z; + return new Vector3d(x, y, z); + } + public static boolean isVecPointingTowards(Vector3d vec, Direction direction) { - return Vector3d.of(direction.getDirectionVec()) - .dotProduct(vec.normalize()) > 0; - // return new Vector3d(direction.getDirectionVec()).distanceTo(vec.normalize()) < .75; + return Vector3d.atLowerCornerOf(direction.getNormal()) + .dot(vec.normalize()) > 0.125; // slight tolerance to activate perpendicular movement actors } public static Vector3d getCenterOf(Vector3i pos) { - if (pos.equals(Vector3i.NULL_VECTOR)) + if (pos.equals(Vector3i.ZERO)) return CENTER_OF_ORIGIN; - return Vector3d.of(pos) + return Vector3d.atLowerCornerOf(pos) .add(.5f, .5f, .5f); } @@ -83,14 +119,14 @@ public class VecHelper { } public static Vector3d axisAlingedPlaneOf(Direction face) { - return axisAlingedPlaneOf(Vector3d.of(face.getDirectionVec())); + return axisAlingedPlaneOf(Vector3d.atLowerCornerOf(face.getNormal())); } public static ListNBT writeNBT(Vector3d vec) { ListNBT listnbt = new ListNBT(); - listnbt.add(DoubleNBT.of(vec.x)); - listnbt.add(DoubleNBT.of(vec.y)); - listnbt.add(DoubleNBT.of(vec.z)); + listnbt.add(DoubleNBT.valueOf(vec.x)); + listnbt.add(DoubleNBT.valueOf(vec.y)); + listnbt.add(DoubleNBT.valueOf(vec.z)); return listnbt; } @@ -105,11 +141,11 @@ public class VecHelper { } public static int getCoordinate(Vector3i pos, Axis axis) { - return axis.getCoordinate(pos.getX(), pos.getY(), pos.getZ()); + return axis.choose(pos.getX(), pos.getY(), pos.getZ()); } public static float getCoordinate(Vector3d vec, Axis axis) { - return (float) axis.getCoordinate(vec.x, vec.y, vec.z); + return (float) axis.choose(vec.x, vec.y, vec.z); } public static boolean onSameAxis(BlockPos pos1, BlockPos pos2, Axis axis) { @@ -140,7 +176,7 @@ public class VecHelper { public static Vector3d project(Vector3d vec, Vector3d ontoVec) { if (ontoVec.equals(Vector3d.ZERO)) return Vector3d.ZERO; - return ontoVec.scale(vec.dotProduct(ontoVec) / ontoVec.lengthSquared()); + return ontoVec.scale(vec.dot(ontoVec) / ontoVec.lengthSqr()); } @Nullable @@ -152,8 +188,8 @@ public class VecHelper { lineDirection = lineDirection.normalize(); Vector3d diff = origin.subtract(sphereCenter); - double lineDotDiff = lineDirection.dotProduct(diff); - double delta = lineDotDiff * lineDotDiff - (diff.lengthSquared() - radius * radius); + double lineDotDiff = lineDirection.dot(diff); + double delta = lineDotDiff * lineDotDiff - (diff.lengthSqr() - radius * radius); if (delta < 0) return null; double t = -lineDotDiff + MathHelper.sqrt(delta); @@ -166,52 +202,52 @@ public class VecHelper { * The (centered) location on the screen of the given 3d point in the world. * Result is (dist right of center screen, dist up from center screen, if < 0, then in front of view plane) */ - ActiveRenderInfo ari = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); - Vector3d camera_pos = ari.getProjectedView(); - Quaternion camera_rotation_conj = ari.getRotation() + ActiveRenderInfo ari = Minecraft.getInstance().gameRenderer.getMainCamera(); + Vector3d camera_pos = ari.getPosition(); + Quaternion camera_rotation_conj = ari.rotation() .copy(); - camera_rotation_conj.conjugate(); + camera_rotation_conj.conj(); Vector3f result3f = new Vector3f((float) (camera_pos.x - target.x), (float) (camera_pos.y - target.y), (float) (camera_pos.z - target.z)); - result3f.func_214905_a(camera_rotation_conj); + result3f.transform(camera_rotation_conj); // ----- compensate for view bobbing (if active) ----- // the following code adapted from GameRenderer::applyBobbing (to invert it) Minecraft mc = Minecraft.getInstance(); - if (mc.gameSettings.viewBobbing) { - Entity renderViewEntity = mc.getRenderViewEntity(); + if (mc.options.bobView) { + Entity renderViewEntity = mc.getCameraEntity(); if (renderViewEntity instanceof PlayerEntity) { PlayerEntity playerentity = (PlayerEntity) renderViewEntity; - float distwalked_modified = playerentity.distanceWalkedModified; + float distwalked_modified = playerentity.walkDist; - float f = distwalked_modified - playerentity.prevDistanceWalkedModified; + float f = distwalked_modified - playerentity.walkDistO; float f1 = -(distwalked_modified + f * partialTicks); - float f2 = MathHelper.lerp(partialTicks, playerentity.prevCameraYaw, playerentity.cameraYaw); - Quaternion q2 = new Quaternion(Vector3f.POSITIVE_X, + float f2 = MathHelper.lerp(partialTicks, playerentity.oBob, playerentity.bob); + Quaternion q2 = new Quaternion(Vector3f.XP, Math.abs(MathHelper.cos(f1 * (float) Math.PI - 0.2F) * f2) * 5.0F, true); - q2.conjugate(); - result3f.func_214905_a(q2); + q2.conj(); + result3f.transform(q2); Quaternion q1 = - new Quaternion(Vector3f.POSITIVE_Z, MathHelper.sin(f1 * (float) Math.PI) * f2 * 3.0F, true); - q1.conjugate(); - result3f.func_214905_a(q1); + new Quaternion(Vector3f.ZP, MathHelper.sin(f1 * (float) Math.PI) * f2 * 3.0F, true); + q1.conj(); + result3f.transform(q1); Vector3f bob_translation = new Vector3f((MathHelper.sin(f1 * (float) Math.PI) * f2 * 0.5F), (-Math.abs(MathHelper.cos(f1 * (float) Math.PI) * f2)), 0.0f); - bob_translation.setY(-bob_translation.getY()); // this is weird but hey, if it works + bob_translation.setY(-bob_translation.y()); // this is weird but hey, if it works result3f.add(bob_translation); } } // ----- adjust for fov ----- - float fov = (float) mc.gameRenderer.getFOVModifier(ari, partialTicks, true); + float fov = (float) mc.gameRenderer.getFov(ari, partialTicks, true); float half_height = (float) mc.getWindow() - .getScaledHeight() / 2; - float scale_factor = half_height / (result3f.getZ() * (float) Math.tan(Math.toRadians(fov / 2))); - return new Vector3d(-result3f.getX() * scale_factor, result3f.getY() * scale_factor, result3f.getZ()); + .getGuiScaledHeight() / 2; + float scale_factor = half_height / (result3f.z() * (float) Math.tan(Math.toRadians(fov / 2))); + return new Vector3d(-result3f.x() * scale_factor, result3f.y() * scale_factor, result3f.z()); } } 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/VoxelShaper.java b/src/main/java/com/simibubi/create/foundation/utility/VoxelShaper.java index 31e9645ac..7b9b35e71 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VoxelShaper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VoxelShaper.java @@ -57,11 +57,11 @@ public class VoxelShaper { } public static Direction axisAsFace(Axis axis) { - return Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); + return Direction.get(AxisDirection.POSITIVE, axis); } protected static float horizontalAngleFromDirection(Direction direction) { - return (float) ((Math.max(direction.getHorizontalIndex(), 0) & 3) * 90); + return (float) ((Math.max(direction.get2DDataValue(), 0) & 3) * 90); } protected static VoxelShaper forDirectionsWithRotation(VoxelShape shape, Direction facing, @@ -79,7 +79,7 @@ public class VoxelShaper { return shape; return rotatedCopy(shape, usingValues.apply(from) - .inverse() + .reverse() .add(usingValues.apply(to))); } @@ -90,7 +90,7 @@ public class VoxelShaper { MutableObject result = new MutableObject<>(VoxelShapes.empty()); Vector3d center = new Vector3d(8, 8, 8); - shape.forEachBox((x1, y1, z1, x2, y2, z2) -> { + shape.forAllBoxes((x1, y1, z1, x2, y2, z2) -> { Vector3d v1 = new Vector3d(x1, y1, z1).scale(16) .subtract(center); Vector3d v2 = new Vector3d(x2, y2, z2).scale(16) @@ -106,7 +106,7 @@ public class VoxelShaper { v2 = VecHelper.rotate(v2, (float) rotation.z, Axis.Z) .add(center); - VoxelShape rotated = Block.makeCuboidShape(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z); + VoxelShape rotated = Block.box(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z); result.setValue(VoxelShapes.or(result.getValue(), rotated)); }); 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..20555bdb3 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java +++ b/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java @@ -4,20 +4,19 @@ 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; +import javax.annotation.Nonnull; import net.minecraft.world.IWorld; +import net.minecraftforge.common.util.NonNullFunction; public class WorldAttached { static List> allMaps = new ArrayList<>(); Map attached; - private Supplier factory; + private final NonNullFunction factory; - public WorldAttached(Supplier factory) { + public WorldAttached(NonNullFunction factory) { this.factory = factory; attached = new HashMap<>(); allMaps.add(attached); @@ -27,12 +26,12 @@ public class WorldAttached { allMaps.forEach(m -> m.remove(world)); } - @Nullable + @Nonnull public T get(IWorld world) { T t = attached.get(world); if (t != null) return t; - T entry = factory.get(); + T entry = factory.apply(world); put(world, entry); return entry; } @@ -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/WorldHelper.java b/src/main/java/com/simibubi/create/foundation/utility/WorldHelper.java index 3cd375ea9..2f256a42b 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/WorldHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/WorldHelper.java @@ -6,8 +6,8 @@ import net.minecraft.world.IWorld; public class WorldHelper { public static ResourceLocation getDimensionID(IWorld world) { - return world.getRegistryManager() - .get(Registry.DIMENSION_TYPE_KEY) - .getKey(world.getDimension()); + return world.registryAccess() + .registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY) + .getKey(world.dimensionType()); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/animation/LerpedFloat.java b/src/main/java/com/simibubi/create/foundation/utility/animation/LerpedFloat.java index 087929bb0..bd15f8dcc 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/animation/LerpedFloat.java +++ b/src/main/java/com/simibubi/create/foundation/utility/animation/LerpedFloat.java @@ -55,14 +55,14 @@ public class LerpedFloat { public boolean updateChaseSpeed(double speed) { float prevSpeed = this.chaseSpeed; this.chaseSpeed = (float) speed; - return !MathHelper.epsilonEquals(prevSpeed, speed); + return !MathHelper.equal(prevSpeed, speed); } public void tickChaser() { previousValue = value; if (chaseFunction == null) return; - if (MathHelper.epsilonEquals((double) value, chaseTarget)) { + if (MathHelper.equal((double) value, chaseTarget)) { value = chaseTarget; return; } @@ -83,7 +83,7 @@ public class LerpedFloat { } public boolean settled() { - return MathHelper.epsilonEquals((double) previousValue, value); + return MathHelper.equal((double) previousValue, value); } public float getChaseTarget() { diff --git a/src/main/java/com/simibubi/create/foundation/utility/animation/PhysicalFloat.java b/src/main/java/com/simibubi/create/foundation/utility/animation/PhysicalFloat.java index d56f8e35f..26ae9a246 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/animation/PhysicalFloat.java +++ b/src/main/java/com/simibubi/create/foundation/utility/animation/PhysicalFloat.java @@ -11,6 +11,7 @@ public class PhysicalFloat { float previousSpeed; float speed; + float limit = Float.NaN; float mass; @@ -41,6 +42,11 @@ public class PhysicalFloat { return addForce(new Force.Zeroing((float) g)); } + public PhysicalFloat withLimit(float limit) { + this.limit = limit; + return this; + } + public void tick() { previousSpeed = speed; previousValue = value; @@ -53,6 +59,10 @@ public class PhysicalFloat { forces.removeIf(Force::finished); + if (Float.isFinite(limit)) { + speed = MathHelper.clamp(speed, -limit, limit); + } + value += speed; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockParams.java b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockParams.java index b83e7f13d..01c6ddc6c 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockParams.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockParams.java @@ -23,7 +23,7 @@ public class GhostBlockParams { } public static GhostBlockParams of(Block block) { - return of(block.getDefaultState()); + return of(block.defaultBlockState()); } public GhostBlockParams at(BlockPos pos) { 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..f55febbb2 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.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import net.minecraft.block.BlockState; @@ -53,24 +53,24 @@ public abstract class GhostBlockRenderer { private static class DefaultGhostBlockRenderer extends GhostBlockRenderer { public void render(MatrixStack ms, SuperRenderTypeBuffer buffer, GhostBlockParams params) { - ms.push(); + ms.pushPose(); BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRendererDispatcher(); + .getBlockRenderer(); - IBakedModel model = dispatcher.getModelForState(params.state); + IBakedModel model = dispatcher.getBlockModel(params.state); - RenderType layer = RenderTypeLookup.getEntityBlockLayer(params.state, false); + RenderType layer = RenderTypeLookup.getRenderType(params.state, false); IVertexBuilder vb = buffer.getEarlyBuffer(layer); BlockPos pos = params.pos; ms.translate(pos.getX(), pos.getY(), pos.getZ()); - dispatcher.getBlockModelRenderer() - .renderModel(ms.peek(), vb, params.state, model, 1f, 1f, 1f, 0xF000F0, OverlayTexture.DEFAULT_UV, + dispatcher.getModelRenderer() + .renderModel(ms.last(), vb, params.state, model, 1f, 1f, 1f, 0xF000F0, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); - ms.pop(); + ms.popPose(); } } @@ -80,17 +80,17 @@ public abstract class GhostBlockRenderer { public void render(MatrixStack ms, SuperRenderTypeBuffer buffer, GhostBlockParams params) { // prepare - ms.push(); + ms.pushPose(); // RenderSystem.pushMatrix(); Minecraft mc = Minecraft.getInstance(); - BlockRendererDispatcher dispatcher = mc.getBlockRendererDispatcher(); + BlockRendererDispatcher dispatcher = mc.getBlockRenderer(); - IBakedModel model = dispatcher.getModelForState(params.state); + IBakedModel model = dispatcher.getBlockModel(params.state); // RenderType layer = RenderTypeLookup.getEntityBlockLayer(params.state); - RenderType layer = RenderType.getTranslucent(); + RenderType layer = RenderType.translucent(); IVertexBuilder vb = buffer.getEarlyBuffer(layer); BlockPos pos = params.pos; @@ -101,14 +101,14 @@ public abstract class GhostBlockRenderer { ms.translate(-.5, -.5, -.5); // dispatcher.getBlockModelRenderer().renderModel(ms.peek(), vb, params.state, model, 1f, 1f, 1f, 0xF000F0, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); - renderModel(params, ms.peek(), vb, params.state, model, 1f, 1f, 1f, - WorldRenderer.getLightmapCoordinates(mc.world, pos), OverlayTexture.DEFAULT_UV, + renderModel(params, ms.last(), vb, params.state, model, 1f, 1f, 1f, + WorldRenderer.getLightColor(mc.level, pos), OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); // buffer.draw(); // clean // RenderSystem.popMatrix(); - ms.pop(); + ms.popPose(); } @@ -139,7 +139,7 @@ public abstract class GhostBlockRenderer { float f; float f1; float f2; - if (bakedquad.hasTintIndex()) { + if (bakedquad.isTinted()) { f = MathHelper.clamp(p_228803_2_, 0.0F, 1.0F); f1 = MathHelper.clamp(p_228803_3_, 0.0F, 1.0F); f2 = MathHelper.clamp(p_228803_4_, 0.0F, 1.0F); @@ -159,17 +159,17 @@ public abstract class GhostBlockRenderer { static void quad(float alpha, IVertexBuilder vb, MatrixStack.Entry p_227890_1_, BakedQuad p_227890_2_, float[] p_227890_3_, float p_227890_4_, float p_227890_5_, float p_227890_6_, int[] p_227890_7_, int p_227890_8_) { - int[] aint = p_227890_2_.getVertexData(); - Vector3i Vector3i = p_227890_2_.getFace() - .getDirectionVec(); + int[] aint = p_227890_2_.getVertices(); + Vector3i Vector3i = p_227890_2_.getDirection() + .getNormal(); Vector3f vector3f = new Vector3f((float) Vector3i.getX(), (float) Vector3i.getY(), (float) Vector3i.getZ()); - Matrix4f matrix4f = p_227890_1_.getModel(); - vector3f.transform(p_227890_1_.getNormal()); + Matrix4f matrix4f = p_227890_1_.pose(); + vector3f.transform(p_227890_1_.normal()); int vertexSize = DefaultVertexFormats.BLOCK.getIntegerSize(); int j = aint.length / vertexSize; try (MemoryStack memorystack = MemoryStack.stackPush()) { - ByteBuffer bytebuffer = memorystack.malloc(DefaultVertexFormats.BLOCK.getSize()); + ByteBuffer bytebuffer = memorystack.malloc(DefaultVertexFormats.BLOCK.getVertexSize()); IntBuffer intbuffer = bytebuffer.asIntBuffer(); for (int k = 0; k < j; ++k) { @@ -191,9 +191,9 @@ public abstract class GhostBlockRenderer { float f10 = bytebuffer.getFloat(20); Vector4f vector4f = new Vector4f(f, f1, f2, 1.0F); vector4f.transform(matrix4f); - vb.applyBakedNormals(vector3f, bytebuffer, p_227890_1_.getNormal()); - vb.vertex(vector4f.getX(), vector4f.getY(), vector4f.getZ(), r, g, b, alpha, f9, f10, p_227890_8_, - l, vector3f.getX(), vector3f.getY(), vector3f.getZ()); + vb.applyBakedNormals(vector3f, bytebuffer, p_227890_1_.normal()); + vb.vertex(vector4f.x(), vector4f.y(), vector4f.z(), r, g, b, alpha, f9, f10, p_227890_8_, + l, vector3f.x(), vector3f.y(), vector3f.z()); } } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlocks.java b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlocks.java index 1ef7f0c01..240afe3a4 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlocks.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlocks.java @@ -4,7 +4,7 @@ import java.util.HashMap; import java.util.Map; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.block.BlockState; import net.minecraft.util.math.MathHelper; diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java index 9839b890d..059fbbc2b 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java @@ -2,8 +2,8 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; -import com.simibubi.create.foundation.renderState.RenderTypes; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.RenderTypes; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; @@ -27,10 +27,10 @@ public class AABBOutline extends Outline { } public void renderBB(MatrixStack ms, SuperRenderTypeBuffer buffer, AxisAlignedBB bb) { - Vector3d projectedView = Minecraft.getInstance().gameRenderer.getActiveRenderInfo() - .getProjectedView(); + Vector3d projectedView = Minecraft.getInstance().gameRenderer.getMainCamera() + .getPosition(); boolean noCull = bb.contains(projectedView); - bb = bb.grow(noCull ? -1 / 128d : 1 / 128d); + bb = bb.inflate(noCull ? -1 / 128d : 1 / 128d); noCull |= params.disableCull; Vector3d xyz = new Vector3d(bb.minX, bb.minY, bb.minZ); diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java index 1f91f886f..9e17f3e39 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java @@ -9,8 +9,8 @@ import java.util.Set; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllSpecialTextures; -import com.simibubi.create.foundation.renderState.RenderTypes; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.RenderTypes; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.RenderType; @@ -32,17 +32,17 @@ public class BlockClusterOutline extends Outline { @Override public void render(MatrixStack ms, SuperRenderTypeBuffer buffer, float pt) { for (MergeEntry edge : cluster.visibleEdges) { - Vector3d start = Vector3d.of(edge.pos); - Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, edge.axis); - renderAACuboidLine(ms, buffer, start, Vector3d.of(edge.pos.offset(direction))); + Vector3d start = Vector3d.atLowerCornerOf(edge.pos); + Direction direction = Direction.get(AxisDirection.POSITIVE, edge.axis); + renderAACuboidLine(ms, buffer, start, Vector3d.atLowerCornerOf(edge.pos.relative(direction))); } for (MergeEntry face : cluster.visibleFaces.keySet()) { AxisDirection axisDirection = cluster.visibleFaces.get(face); - Direction direction = Direction.getFacingFromAxis(axisDirection, face.axis); + Direction direction = Direction.get(axisDirection, face.axis); BlockPos pos = face.pos; if (axisDirection == AxisDirection.POSITIVE) - pos = pos.offset(direction.getOpposite()); + pos = pos.relative(direction.getOpposite()); renderBlockFace(ms, buffer, pos, direction); } } @@ -57,7 +57,7 @@ public class BlockClusterOutline extends Outline { IVertexBuilder builder = buffer.getLateBuffer(translucentType); Vector3d center = VecHelper.getCenterOf(pos); - Vector3d offset = Vector3d.of(face.getDirectionVec()); + Vector3d offset = Vector3d.atLowerCornerOf(face.getNormal()); Vector3d plane = VecHelper.axisAlingedPlaneOf(offset); Axis axis = face.getAxis(); @@ -66,7 +66,7 @@ public class BlockClusterOutline extends Outline { .add(offset); int deg = face.getAxisDirection() - .getOffset() * 90; + .getStep() * 90; Vector3d a1 = plane.add(center); plane = VecHelper.rotate(plane, deg, axis); Vector3d a2 = plane.add(center); @@ -92,9 +92,9 @@ public class BlockClusterOutline extends Outline { // 6 FACES for (Axis axis : Axis.values()) { - Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); + Direction direction = Direction.get(AxisDirection.POSITIVE, axis); for (int offset : new int[] { 0, 1 }) { - MergeEntry entry = new MergeEntry(axis, pos.offset(direction, offset)); + MergeEntry entry = new MergeEntry(axis, pos.relative(direction, offset)); if (visibleFaces.remove(entry) == null) visibleFaces.put(entry, offset == 0 ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE); } @@ -111,13 +111,13 @@ public class BlockClusterOutline extends Outline { if (axis2 == axis3) continue; - Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis2); - Direction direction2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis3); + Direction direction = Direction.get(AxisDirection.POSITIVE, axis2); + Direction direction2 = Direction.get(AxisDirection.POSITIVE, axis3); for (int offset : new int[] { 0, 1 }) { - BlockPos entryPos = pos.offset(direction, offset); + BlockPos entryPos = pos.relative(direction, offset); for (int offset2 : new int[] { 0, 1 }) { - entryPos = entryPos.offset(direction2, offset2); + entryPos = entryPos.relative(direction2, offset2); MergeEntry entry = new MergeEntry(axis, entryPos); if (!visibleEdges.remove(entry)) visibleEdges.add(entry); diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java index d70ef3189..66d0140fc 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; @@ -13,8 +13,8 @@ public class ChasingAABBOutline extends AABBOutline { public ChasingAABBOutline(AxisAlignedBB bb) { super(bb); - prevBB = bb.grow(0); - targetBB = bb.grow(0); + prevBB = bb.inflate(0); + targetBB = bb.inflate(0); } public void target(AxisAlignedBB target) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java index 6085a76a6..5b16d2b66 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; 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..22a8f86bc 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 @@ -4,15 +4,15 @@ import java.util.Optional; import javax.annotation.Nullable; +import com.jozufozu.flywheel.util.transform.MatrixTransformStack; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack.Entry; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllSpecialTextures; -import com.simibubi.create.foundation.renderState.RenderTypes; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.RenderTypes; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; +import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -36,22 +36,22 @@ public abstract class Outline { public void renderCuboidLine(MatrixStack ms, SuperRenderTypeBuffer buffer, Vector3d start, Vector3d end) { Vector3d diff = end.subtract(start); float hAngle = AngleHelper.deg(MathHelper.atan2(diff.x, diff.z)); - float hDistance = (float) diff.mul(1, 0, 1) + float hDistance = (float) diff.multiply(1, 0, 1) .length(); float vAngle = AngleHelper.deg(MathHelper.atan2(hDistance, diff.y)) - 90; - ms.push(); - MatrixStacker.of(ms) + ms.pushPose(); + MatrixTransformStack.of(ms) .translate(start) .rotateY(hAngle).rotateX(vAngle); renderAACuboidLine(ms, buffer, Vector3d.ZERO, new Vector3d(0, 0, diff.length())); - ms.pop(); + ms.popPose(); } public void renderAACuboidLine(MatrixStack ms, SuperRenderTypeBuffer buffer, Vector3d start, Vector3d end) { float lineWidth = params.getLineWidth(); if (lineWidth == 0) return; - + IVertexBuilder builder = buffer.getBuffer(RenderTypes.getOutlineSolid()); Vector3d diff = end.subtract(start); @@ -65,7 +65,7 @@ public abstract class Outline { Vector3d extension = diff.normalize() .scale(lineWidth / 2); Vector3d plane = VecHelper.axisAlingedPlaneOf(diff); - Direction face = Direction.getFacingFromVector(diff.x, diff.y, diff.z); + Direction face = Direction.getNearest(diff.x, diff.y, diff.z); Axis axis = face.getAxis(); start = start.subtract(extension); @@ -98,16 +98,16 @@ public abstract class Outline { putQuad(ms, builder, b4, b3, b2, b1, face); putQuad(ms, builder, a1, a2, a3, a4, face.getOpposite()); Vector3d vec = a1.subtract(a4); - face = Direction.getFacingFromVector(vec.x, vec.y, vec.z); + face = Direction.getNearest(vec.x, vec.y, vec.z); putQuad(ms, builder, a1, b1, b2, a2, face); vec = VecHelper.rotate(vec, -90, axis); - face = Direction.getFacingFromVector(vec.x, vec.y, vec.z); + face = Direction.getNearest(vec.x, vec.y, vec.z); putQuad(ms, builder, a2, b2, b3, a3, face); vec = VecHelper.rotate(vec, -90, axis); - face = Direction.getFacingFromVector(vec.x, vec.y, vec.z); + face = Direction.getNearest(vec.x, vec.y, vec.z); putQuad(ms, builder, a3, b3, b4, a4, face); vec = VecHelper.rotate(vec, -90, axis); - face = Direction.getFacingFromVector(vec.x, vec.y, vec.z); + face = Direction.getNearest(vec.x, vec.y, vec.z); putQuad(ms, builder, a4, b4, b1, a1, face); } @@ -128,27 +128,27 @@ public abstract class Outline { int i = 15 << 20 | 15 << 4; int j = i >> 16 & '\uffff'; int k = i & '\uffff'; - Entry peek = ms.peek(); - Vector3d rgb = params.rgb; + Entry peek = ms.last(); + Color rgb = params.rgb; if (transformNormals == null) - transformNormals = peek.getNormal(); + transformNormals = peek.normal(); int xOffset = 0; int yOffset = 0; int zOffset = 0; if (normal != null) { - xOffset = normal.getXOffset(); - yOffset = normal.getYOffset(); - zOffset = normal.getZOffset(); + xOffset = normal.getStepX(); + yOffset = normal.getStepY(); + zOffset = normal.getStepZ(); } - builder.vertex(peek.getModel(), (float) pos.x, (float) pos.y, (float) pos.z) - .color((float) rgb.x, (float) rgb.y, (float) rgb.z, params.alpha) - .texture(u, v) - .overlay(OverlayTexture.DEFAULT_UV) - .light(j, k) - .normal(peek.getNormal(), xOffset, yOffset, zOffset) + builder.vertex(peek.pose(), (float) pos.x, (float) pos.y, (float) pos.z) + .color(rgb.getRedAsFloat(), rgb.getGreenAsFloat(), rgb.getBlueAsFloat(), rgb.getAlphaAsFloat() * params.alpha) + .uv(u, v) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(j, k) + .normal(peek.normal(), xOffset, yOffset, zOffset) .endVertex(); transformNormals = null; @@ -169,7 +169,7 @@ public abstract class Outline { protected boolean disableNormals; protected float alpha; protected int lightMapU, lightMapV; - protected Vector3d rgb; + protected Color rgb; private float lineWidth; public OutlineParams() { @@ -177,7 +177,7 @@ public abstract class Outline { alpha = 1; lineWidth = 1 / 32f; fadeLineWidth = true; - rgb = ColorHelper.getRGB(0xFFFFFF); + rgb = Color.WHITE; int i = 15 << 20 | 15 << 4; lightMapU = i >> 16 & '\uffff'; @@ -187,7 +187,12 @@ public abstract class Outline { // builder public OutlineParams colored(int color) { - rgb = ColorHelper.getRGB(color); + rgb = new Color(color, false); + return this; + } + + public OutlineParams colored(Color c) { + rgb = c.copy(); return this; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java index 64ae8334f..776663486 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java @@ -8,7 +8,7 @@ import java.util.Optional; import java.util.Set; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; import com.simibubi.create.foundation.utility.outliner.LineOutline.EndChasingLineOutline; import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams; 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..63ec2aace 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 @@ -65,7 +65,7 @@ public interface IPlacementHelper { PlacementOffset offset = getOffset(player, world, state, pos, ray); if (heldItem.getItem() instanceof BlockItem) { BlockItem blockItem = (BlockItem) heldItem.getItem(); - offset = offset.withGhostState(blockItem.getBlock().getDefaultState()); + offset = offset.withGhostState(blockItem.getBlock().defaultBlockState()); } return offset; } @@ -89,22 +89,22 @@ public interface IPlacementHelper { } static void renderArrow(Vector3d center, Vector3d target, Direction arrowPlane, double distanceFromCenter) { Vector3d direction = target.subtract(center).normalize(); - Vector3d facing = Vector3d.of(arrowPlane.getDirectionVec()); + Vector3d facing = Vector3d.atLowerCornerOf(arrowPlane.getNormal()); Vector3d start = center.add(direction); - Vector3d offset = direction.scale(distanceFromCenter-1); - Vector3d offsetA = direction.crossProduct(facing).normalize().scale(.25); - Vector3d offsetB = facing.crossProduct(direction).normalize().scale(.25); + Vector3d offset = direction.scale(distanceFromCenter - 1); + Vector3d offsetA = direction.cross(facing).normalize().scale(.25); + Vector3d offsetB = facing.cross(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(); } @@ -141,7 +141,7 @@ public interface IPlacementHelper { Vector3d centerToHit = hit.subtract(VecHelper.getCenterOf(pos)); return Arrays.stream(Iterate.directions) .filter(includeDirection) - .map(dir -> Pair.of(dir, Vector3d.of(dir.getDirectionVec()).distanceTo(centerToHit))) + .map(dir -> Pair.of(dir, Vector3d.atLowerCornerOf(dir.getNormal()).distanceTo(centerToHit))) .sorted(Comparator.comparingDouble(Pair::getSecond)) .map(Pair::getFirst) .collect(Collectors.toList()); diff --git a/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementHelpers.java b/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementHelpers.java index 09f98b72f..25903ef46 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementHelpers.java +++ b/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementHelpers.java @@ -78,30 +78,30 @@ public class PlacementHelpers { @OnlyIn(Dist.CLIENT) private static void checkHelpers() { Minecraft mc = Minecraft.getInstance(); - ClientWorld world = mc.world; + ClientWorld world = mc.level; if (world == null) return; - if (!(mc.objectMouseOver instanceof BlockRayTraceResult)) + if (!(mc.hitResult instanceof BlockRayTraceResult)) return; - BlockRayTraceResult ray = (BlockRayTraceResult) mc.objectMouseOver; + BlockRayTraceResult ray = (BlockRayTraceResult) mc.hitResult; if (mc.player == null) return; - if (mc.player.isSneaking())//for now, disable all helpers when sneaking TODO add helpers that respect sneaking but still show position + if (mc.player.isShiftKeyDown())//for now, disable all helpers when sneaking TODO add helpers that respect sneaking but still show position return; for (Hand hand : Hand.values()) { - ItemStack heldItem = mc.player.getHeldItem(hand); + ItemStack heldItem = mc.player.getItemInHand(hand); List filteredForHeldItem = helpers.stream().filter(helper -> helper.matchesItem(heldItem)).collect(Collectors.toList()); if (filteredForHeldItem.isEmpty()) continue; - BlockPos pos = ray.getPos(); + BlockPos pos = ray.getBlockPos(); BlockState state = world.getBlockState(pos); List filteredForState = filteredForHeldItem.stream().filter(helper -> helper.matchesState(state)).collect(Collectors.toList()); @@ -145,7 +145,7 @@ public class PlacementHelpers { @SubscribeEvent @OnlyIn(Dist.CLIENT) - public static void onRender(RenderGameOverlayEvent.Pre event) { + public static void onRender(RenderGameOverlayEvent.Post event) { if (event.getType() != RenderGameOverlayEvent.ElementType.CROSSHAIRS) return; @@ -155,8 +155,8 @@ public class PlacementHelpers { if (player != null && animationTick > 0) { MainWindow res = event.getWindow(); - float screenY = res.getScaledHeight() / 2f; - float screenX = res.getScaledWidth() / 2f; + float screenY = res.getGuiScaledHeight() / 2f; + float screenX = res.getGuiScaledWidth() / 2f; float progress = getCurrentAlpha(); drawDirectionIndicator(event.getMatrixStack(), event.getPartialTicks(), screenX, screenY, progress); @@ -178,12 +178,12 @@ public class PlacementHelpers { Vector3d target = new Vector3d(projTarget.x, projTarget.y, 0); if (projTarget.z > 0) { - target = target.inverse(); + target = target.reverse(); } Vector3d norm = target.normalize(); Vector3d ref = new Vector3d(0, 1, 0); - float targetAngle = AngleHelper.deg(Math.acos(norm.dotProduct(ref))); + float targetAngle = AngleHelper.deg(Math.acos(norm.dot(ref))); angle.withSpeed(0.25f); @@ -210,24 +210,24 @@ public class PlacementHelpers { } private static void fadedArrow(MatrixStack ms, float centerX, float centerY, float r, float g, float b, float a, float length, float snappedAngle) { - ms.push(); + ms.pushPose(); RenderSystem.disableTexture(); RenderSystem.enableBlend(); RenderSystem.disableAlphaTest(); RenderSystem.defaultBlendFunc(); RenderSystem.shadeModel(GL11.GL_SMOOTH); - ms.translate(centerX, centerY, 0); - ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle.get(0))); + ms.translate(centerX, centerY, 5); + ms.mulPose(Vector3f.ZP.rotationDegrees(angle.get(0))); //RenderSystem.rotatef(snappedAngle, 0, 0, 1); double scale = AllConfigs.CLIENT.indicatorScale.get(); RenderSystem.scaled(scale, scale, 1); Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferbuilder = tessellator.getBuffer(); + BufferBuilder bufferbuilder = tessellator.getBuilder(); bufferbuilder.begin(GL11.GL_POLYGON, DefaultVertexFormats.POSITION_COLOR); - Matrix4f mat = ms.peek().getModel(); + Matrix4f mat = ms.last().pose(); bufferbuilder.vertex(mat, 0, - (10 + length), 0).color(r, g, b, a).endVertex(); @@ -239,24 +239,25 @@ public class PlacementHelpers { bufferbuilder.vertex(mat, 6, -6, 0).color(r, g, b, 0f).endVertex(); bufferbuilder.vertex(mat, 9, -3, 0).color(r, g, b, 0f).endVertex(); - tessellator.draw(); + tessellator.end(); RenderSystem.shadeModel(GL11.GL_FLAT); RenderSystem.disableBlend(); RenderSystem.enableAlphaTest(); RenderSystem.enableTexture(); - ms.pop(); + ms.popPose(); } private static void textured(MatrixStack ms, float centerX, float centerY, float alpha, float snappedAngle) { - ms.push(); + ms.pushPose(); RenderSystem.enableTexture(); AllGuiTextures.PLACEMENT_INDICATOR_SHEET.bind(); RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); RenderSystem.enableAlphaTest(); RenderSystem.defaultBlendFunc(); RenderSystem.shadeModel(GL11.GL_SMOOTH); - ms.translate(centerX, centerY, 0); + ms.translate(centerX, centerY, 50); float scale = AllConfigs.CLIENT.indicatorScale.get().floatValue() * .75f; ms.scale(scale, scale, 1); ms.scale(12, 12, 1); @@ -270,20 +271,20 @@ public class PlacementHelpers { float th = tex_size; Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEXTURE); + BufferBuilder buffer = tessellator.getBuilder(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX); - Matrix4f mat = ms.peek().getModel(); - buffer.vertex(mat, -1, -1, 0).color(1f, 1f, 1f, alpha).texture(tx, ty).endVertex(); - buffer.vertex(mat, -1, 1, 0).color(1f, 1f, 1f, alpha).texture(tx, ty + th).endVertex(); - buffer.vertex(mat, 1, 1, 0).color(1f, 1f, 1f, alpha).texture(tx + tw, ty + th).endVertex(); - buffer.vertex(mat, 1, -1, 0).color(1f, 1f, 1f, alpha).texture(tx + tw, ty).endVertex(); + Matrix4f mat = ms.last().pose(); + buffer.vertex(mat, -1, -1, 0).color(1f, 1f, 1f, alpha).uv(tx, ty).endVertex(); + buffer.vertex(mat, -1, 1, 0).color(1f, 1f, 1f, alpha).uv(tx, ty + th).endVertex(); + buffer.vertex(mat, 1, 1, 0).color(1f, 1f, 1f, alpha).uv(tx + tw, ty + th).endVertex(); + buffer.vertex(mat, 1, -1, 0).color(1f, 1f, 1f, alpha).uv(tx + tw, ty).endVertex(); - tessellator.draw(); + tessellator.end(); RenderSystem.shadeModel(GL11.GL_FLAT); RenderSystem.disableBlend(); - ms.pop(); + ms.popPose(); } } 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..4ab7ef08f 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,26 +102,29 @@ 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.isClientSide) + return ActionResultType.SUCCESS; + ItemUseContext context = new ItemUseContext(player, hand, ray); BlockPos newPos = new BlockPos(pos); - if (!world.isBlockModifiable(player, newPos)) + if (!world.mayInteract(player, newPos)) return ActionResultType.PASS; - BlockState state = stateTransform.apply(blockItem.getBlock().getDefaultState()); - if (state.contains(BlockStateProperties.WATERLOGGED)) { + BlockState state = stateTransform.apply(blockItem.getBlock().defaultBlockState()); + if (state.hasProperty(BlockStateProperties.WATERLOGGED)) { FluidState fluidState = world.getFluidState(newPos); - state = state.with(BlockStateProperties.WATERLOGGED, fluidState.getFluid() == Fluids.WATER); + state = state.setValue(BlockStateProperties.WATERLOGGED, fluidState.getType() == Fluids.WATER); } - BlockSnapshot snapshot = BlockSnapshot.create(world.getRegistryKey(), world, newPos); - world.setBlockState(newPos, state); + BlockSnapshot snapshot = BlockSnapshot.create(world.dimension(), world, newPos); + world.setBlockAndUpdate(newPos, state); BlockEvent.EntityPlaceEvent event = new BlockEvent.EntityPlaceEvent(snapshot, IPlacementHelper.ID, player); if (MinecraftForge.EVENT_BUS.post(event)) { @@ -131,18 +134,15 @@ public class PlacementOffset { BlockState newState = world.getBlockState(newPos); SoundType soundtype = newState.getSoundType(world, newPos, player); - world.playSound(player, newPos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); + world.playSound(null, newPos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); - player.addStat(Stats.ITEM_USED.get(blockItem)); - - if (world.isRemote) - return ActionResultType.SUCCESS; + player.awardStat(Stats.ITEM_USED.get(blockItem)); if (player instanceof ServerPlayerEntity) - CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, newPos, context.getItem()); + CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, newPos, context.getItemInHand()); if (!player.isCreative()) - context.getItem().shrink(1); + context.getItemInHand().shrink(1); return ActionResultType.SUCCESS; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/placement/util/PoleHelper.java b/src/main/java/com/simibubi/create/foundation/utility/placement/util/PoleHelper.java index f362531d3..8488daf3a 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/placement/util/PoleHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/placement/util/PoleHelper.java @@ -41,12 +41,12 @@ public abstract class PoleHelper> implements IPlacementH } public int attachedPoles(World world, BlockPos pos, Direction direction) { - BlockPos checkPos = pos.offset(direction); + BlockPos checkPos = pos.relative(direction); BlockState state = world.getBlockState(checkPos); int count = 0; while (matchesAxis(state, direction.getAxis())) { count++; - checkPos = checkPos.offset(direction); + checkPos = checkPos.relative(direction); state = world.getBlockState(checkPos); } return count; @@ -59,7 +59,7 @@ public abstract class PoleHelper> implements IPlacementH @Override public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) { - List directions = IPlacementHelper.orderedByDistance(pos, ray.getHitVec(), dir -> dir.getAxis() == axisFunction.apply(state)); + List directions = IPlacementHelper.orderedByDistance(pos, ray.getLocation(), dir -> dir.getAxis() == axisFunction.apply(state)); for (Direction dir : directions) { int range = AllConfigs.SERVER.curiosities.placementAssistRange.get(); if (player != null) { @@ -71,11 +71,11 @@ public abstract class PoleHelper> implements IPlacementH if (poles >= range) continue; - BlockPos newPos = pos.offset(dir, poles + 1); + BlockPos newPos = pos.relative(dir, poles + 1); BlockState newState = world.getBlockState(newPos); if (newState.getMaterial().isReplaceable()) - return PlacementOffset.success(newPos, bState -> bState.with(property, state.get(property))); + return PlacementOffset.success(newPos, bState -> bState.setValue(property, state.getValue(property))); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/recipe/IRecipeTypeInfo.java b/src/main/java/com/simibubi/create/foundation/utility/recipe/IRecipeTypeInfo.java new file mode 100644 index 000000000..bf347471f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/recipe/IRecipeTypeInfo.java @@ -0,0 +1,15 @@ +package com.simibubi.create.foundation.utility.recipe; + +import net.minecraft.item.crafting.IRecipeSerializer; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.util.ResourceLocation; + +public interface IRecipeTypeInfo { + + ResourceLocation getId(); + + > T getSerializer(); + + > T getType(); + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java index 901ca5dc6..95123ff19 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java +++ b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java @@ -31,7 +31,7 @@ public class RecipeConditions { } public static Predicate> outputMatchesFilter(FilteringBehaviour filtering) { - return r -> filtering.test(r.getRecipeOutput()); + return r -> filtering.test(r.getResultItem()); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/DummyStatusListener.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/DummyStatusListener.java new file mode 100644 index 000000000..b963a236c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/DummyStatusListener.java @@ -0,0 +1,18 @@ +package com.simibubi.create.foundation.utility.worldWrappers; + +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.chunk.listener.IChunkStatusListener; + +public class DummyStatusListener implements IChunkStatusListener { + + @Override + public void updateSpawnPos(ChunkPos p_219509_1_) {} + + @Override + public void onStatusChange(ChunkPos p_219508_1_, ChunkStatus p_219508_2_) {} + + @Override + public void stop() {} + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/PlacementSimulationServerWorld.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/PlacementSimulationServerWorld.java index 60b82a4e5..18ce49c0c 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/PlacementSimulationServerWorld.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/PlacementSimulationServerWorld.java @@ -21,23 +21,23 @@ public class PlacementSimulationServerWorld extends WrappedServerWorld { } @Override - public boolean setBlockState(BlockPos pos, BlockState newState, int flags) { - blocksAdded.put(pos.toImmutable(), newState); + public boolean setBlock(BlockPos pos, BlockState newState, int flags) { + blocksAdded.put(pos.immutable(), newState); return true; } @Override - public boolean setBlockState(BlockPos pos, BlockState state) { - return setBlockState(pos, state, 0); + public boolean setBlockAndUpdate(BlockPos pos, BlockState state) { + return setBlock(pos, state, 0); } @Override - public boolean hasBlockState(BlockPos pos, Predicate condition) { + public boolean isStateAtPosition(BlockPos pos, Predicate condition) { return condition.test(getBlockState(pos)); } @Override - public boolean isBlockPresent(BlockPos pos) { + public boolean isLoaded(BlockPos pos) { return true; } @@ -50,7 +50,7 @@ public class PlacementSimulationServerWorld extends WrappedServerWorld { public BlockState getBlockState(BlockPos pos) { if (blocksAdded.containsKey(pos)) return blocksAdded.get(pos); - return Blocks.AIR.getDefaultState(); + return Blocks.AIR.defaultBlockState(); } } 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..57a1462b6 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,20 +33,31 @@ 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<>(); } @Override - public WorldLightManager getLightingProvider() { + public WorldLightManager getLightEngine() { 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.onBlockEmissionIncrease(pos, light); + } + } + } + public void setTileEntities(Collection tileEntities) { tesAdded.clear(); - tileEntities.forEach(te -> tesAdded.put(te.getPos(), te)); + tileEntities.forEach(te -> tesAdded.put(te.getBlockPos(), te)); } public void clear() { @@ -52,37 +65,38 @@ public class PlacementSimulationWorld extends WrappedWorld implements IFlywheelW } @Override - public boolean setBlockState(BlockPos pos, BlockState newState, int flags) { + public boolean setBlock(BlockPos pos, BlockState newState, int flags) { + blocksAdded.put(pos, newState); - SectionPos sectionPos = SectionPos.from(pos); - - if (spannedChunks.add(sectionPos)) { + SectionPos sectionPos = SectionPos.of(pos); + if (spannedSections.add(sectionPos)) { lighter.updateSectionStatus(sectionPos, false); } - lighter.checkBlock(pos); + if ((flags & 128) == 0) { + lighter.checkBlock(pos); + } - blocksAdded.put(pos, newState); return true; } @Override - public boolean setBlockState(BlockPos pos, BlockState state) { - return setBlockState(pos, state, 0); + public boolean setBlockAndUpdate(BlockPos pos, BlockState state) { + return setBlock(pos, state, 0); } @Override - public TileEntity getTileEntity(BlockPos pos) { + public TileEntity getBlockEntity(BlockPos pos) { return tesAdded.get(pos); } @Override - public boolean hasBlockState(BlockPos pos, Predicate condition) { + public boolean isStateAtPosition(BlockPos pos, Predicate condition) { return condition.test(getBlockState(pos)); } @Override - public boolean isBlockPresent(BlockPos pos) { + public boolean isLoaded(BlockPos pos) { return true; } @@ -92,7 +106,7 @@ public class PlacementSimulationWorld extends WrappedWorld implements IFlywheelW } public BlockState getBlockState(int x, int y, int z) { - return getBlockState(scratch.setPos(x, y, z)); + return getBlockState(scratch.set(x, y, z)); } @Override @@ -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.defaultBlockState(); } - } diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/RayTraceWorld.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/RayTraceWorld.java index 3a15cc1e7..eb608d262 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/RayTraceWorld.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/RayTraceWorld.java @@ -20,8 +20,8 @@ public class RayTraceWorld implements IBlockReader { } @Override - public TileEntity getTileEntity(BlockPos pos) { - return template.getTileEntity(pos); + public TileEntity getBlockEntity(BlockPos pos) { + return template.getBlockEntity(pos); } @Override 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..7d68691b1 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; @@ -37,12 +38,12 @@ public class WrappedChunkProvider extends AbstractChunkProvider { @Nullable @Override - public IBlockReader getChunkForLight(int x, int z) { + public IBlockReader getChunkForLighting(int x, int z) { return getChunk(x, z); } @Override - public IBlockReader getWorld() { + public IBlockReader getLevel() { return world; } @@ -52,22 +53,22 @@ 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)); } @Override - public String makeString() { + public String gatherStats() { return "WrappedChunkProvider"; } @Override - public WorldLightManager getLightManager() { - return world.getLightingProvider(); + public WorldLightManager getLightEngine() { + return world.getLightEngine(); } } 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..4e497fdc7 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 @@ -38,7 +38,7 @@ public class WrappedClientWorld extends ClientWorld { protected World world; private WrappedClientWorld(World world) { - super(mc.getConnection(), mc.world.getWorldInfo(), world.getRegistryKey(), world.getDimension(), mc.getConnection().viewDistance, world.getProfilerSupplier(), mc.worldRenderer, world.isDebugWorld(), world.getBiomeAccess().seed); + super(mc.getConnection(), mc.level.getLevelData(), world.dimension(), world.dimensionType(), mc.getConnection().serverChunkRadius, world.getProfilerSupplier(), mc.levelRenderer, world.isDebug(), world.getBiomeManager().biomeZoomSeed); this.world = world; } @@ -47,8 +47,13 @@ public class WrappedClientWorld extends ClientWorld { } @Override - public boolean isBlockLoaded(BlockPos pos) { - return world.isBlockLoaded(pos); + public boolean hasChunkAt(BlockPos pos) { + return world.hasChunkAt(pos); + } + + @Override + public boolean isLoaded(BlockPos pos) { + return world.isLoaded(pos); } @Override @@ -70,13 +75,13 @@ public class WrappedClientWorld extends ClientWorld { @Override - public int getLightLevel(LightType type, BlockPos pos) { - return world.getLightLevel(type, pos); + public int getBrightness(LightType type, BlockPos pos) { + return world.getBrightness(type, pos); } @Override - public int getLightValue(BlockPos pos) { - return world.getLightValue(pos); + public int getLightEmission(BlockPos pos) { + return world.getLightEmission(pos); } @Override @@ -86,13 +91,13 @@ public class WrappedClientWorld extends ClientWorld { @Nullable @Override - public T getClosestEntity(List p_217361_1_, EntityPredicate p_217361_2_, @Nullable LivingEntity p_217361_3_, double p_217361_4_, double p_217361_6_, double p_217361_8_) { - return world.getClosestEntity(p_217361_1_, p_217361_2_, p_217361_3_, p_217361_4_, p_217361_6_, p_217361_8_); + public T getNearestEntity(List p_217361_1_, EntityPredicate p_217361_2_, @Nullable LivingEntity p_217361_3_, double p_217361_4_, double p_217361_6_, double p_217361_8_) { + return world.getNearestEntity(p_217361_1_, p_217361_2_, p_217361_3_, p_217361_4_, p_217361_6_, p_217361_8_); } @Override - public int getColor(BlockPos p_225525_1_, ColorResolver p_225525_2_) { - return world.getColor(p_225525_1_, p_225525_2_); + public int getBlockTint(BlockPos p_225525_1_, ColorResolver p_225525_2_) { + return world.getBlockTint(p_225525_1_, p_225525_2_); } // FIXME: Emissive Lighting might not light stuff properly @@ -109,18 +114,18 @@ public class WrappedClientWorld extends ClientWorld { } @Override - public void addOptionalParticle(IParticleData p_195589_1_, double p_195589_2_, double p_195589_4_, double p_195589_6_, double p_195589_8_, double p_195589_10_, double p_195589_12_) { - world.addOptionalParticle(p_195589_1_, p_195589_2_, p_195589_4_, p_195589_6_, p_195589_8_, p_195589_10_, p_195589_12_); + public void addAlwaysVisibleParticle(IParticleData p_195589_1_, double p_195589_2_, double p_195589_4_, double p_195589_6_, double p_195589_8_, double p_195589_10_, double p_195589_12_) { + world.addAlwaysVisibleParticle(p_195589_1_, p_195589_2_, p_195589_4_, p_195589_6_, p_195589_8_, p_195589_10_, p_195589_12_); } @Override - public void addOptionalParticle(IParticleData p_217404_1_, boolean p_217404_2_, double p_217404_3_, double p_217404_5_, double p_217404_7_, double p_217404_9_, double p_217404_11_, double p_217404_13_) { - world.addOptionalParticle(p_217404_1_, p_217404_2_, p_217404_3_, p_217404_5_, p_217404_7_, p_217404_9_, p_217404_11_, p_217404_13_); + public void addAlwaysVisibleParticle(IParticleData p_217404_1_, boolean p_217404_2_, double p_217404_3_, double p_217404_5_, double p_217404_7_, double p_217404_9_, double p_217404_11_, double p_217404_13_) { + world.addAlwaysVisibleParticle(p_217404_1_, p_217404_2_, p_217404_3_, p_217404_5_, p_217404_7_, p_217404_9_, p_217404_11_, p_217404_13_); } @Override - public void playSound(double p_184134_1_, double p_184134_3_, double p_184134_5_, SoundEvent p_184134_7_, SoundCategory p_184134_8_, float p_184134_9_, float p_184134_10_, boolean p_184134_11_) { - world.playSound(p_184134_1_, p_184134_3_, p_184134_5_, p_184134_7_,p_184134_8_, p_184134_9_, p_184134_10_, p_184134_11_); + public void playLocalSound(double p_184134_1_, double p_184134_3_, double p_184134_5_, SoundEvent p_184134_7_, SoundCategory p_184134_8_, float p_184134_9_, float p_184134_10_, boolean p_184134_11_) { + world.playLocalSound(p_184134_1_, p_184134_3_, p_184134_5_, p_184134_7_,p_184134_8_, p_184134_9_, p_184134_10_, p_184134_11_); } @Override @@ -130,8 +135,8 @@ public class WrappedClientWorld extends ClientWorld { @Nullable @Override - public TileEntity getTileEntity(BlockPos p_175625_1_) { - return world.getTileEntity(p_175625_1_); + public TileEntity getBlockEntity(BlockPos p_175625_1_) { + return world.getBlockEntity(p_175625_1_); } public World getWrappedWorld() { return world; diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedServerWorld.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedServerWorld.java index ec967e3d7..8104de717 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedServerWorld.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedServerWorld.java @@ -37,48 +37,50 @@ public class WrappedServerWorld extends ServerWorld { protected World world; public WrappedServerWorld(World world) { - // Replace null with world.getChunkProvider().chunkManager.field_219266_t ? We had null in 1.15 - super(world.getServer(), Util.getServerExecutor(), getLevelSaveFromWorld(world), (IServerWorldInfo) world.getWorldInfo(), world.getRegistryKey(), world.getDimension(), null, ((ServerChunkProvider) world.getChunkProvider()).getChunkGenerator(), world.isDebugWorld(), world.getBiomeAccess().seed, Collections.EMPTY_LIST, false); //, world.field_25143); + super(world.getServer(), Util.backgroundExecutor(), getLevelSaveFromWorld(world), + (IServerWorldInfo) world.getLevelData(), world.dimension(), world.dimensionType(), + new DummyStatusListener(), ((ServerChunkProvider) world.getChunkSource()).getGenerator(), world.isDebug(), + world.getBiomeManager().biomeZoomSeed, Collections.emptyList(), false); this.world = world; } @Override - public float getCelestialAngleRadians(float p_72826_1_) { + public float getSunAngle(float p_72826_1_) { return 0; } - + @Override - public int getLight(BlockPos pos) { + public int getMaxLocalRawBrightness(BlockPos pos) { return 15; } @Override - public void notifyBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState, int flags) { - world.notifyBlockUpdate(pos, oldState, newState, flags); + public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { + world.sendBlockUpdated(pos, oldState, newState, flags); } @Override - public ServerTickList getPendingBlockTicks() { - ITickList tl = world.getPendingBlockTicks(); + public ServerTickList getBlockTicks() { + ITickList tl = world.getBlockTicks(); if (tl instanceof ServerTickList) return (ServerTickList) tl; - return super.getPendingBlockTicks(); + return super.getBlockTicks(); } @Override - public ServerTickList getPendingFluidTicks() { - ITickList tl = world.getPendingFluidTicks(); + public ServerTickList getLiquidTicks() { + ITickList tl = world.getLiquidTicks(); if (tl instanceof ServerTickList) return (ServerTickList) tl; - return super.getPendingFluidTicks(); + return super.getLiquidTicks(); } @Override - public void playEvent(PlayerEntity player, int type, BlockPos pos, int data) { + public void levelEvent(PlayerEntity player, int type, BlockPos pos, int data) { } @Override - public List getPlayers() { + public List players() { return Collections.emptyList(); } @@ -88,12 +90,12 @@ public class WrappedServerWorld extends ServerWorld { } @Override - public void playMovingSound(PlayerEntity p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_, + public void playSound(PlayerEntity p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_, SoundCategory p_217384_4_, float p_217384_5_, float p_217384_6_) { } @Override - public Entity getEntityByID(int id) { + public Entity getEntity(int id) { return null; } @@ -103,22 +105,22 @@ public class WrappedServerWorld extends ServerWorld { } @Override - public boolean addEntity(Entity entityIn) { - entityIn.setWorld(world); - return world.addEntity(entityIn); + public boolean addFreshEntity(Entity entityIn) { + entityIn.setLevel(world); + return world.addFreshEntity(entityIn); } @Override - public void registerMapData(MapData mapDataIn) { + public void setMapData(MapData mapDataIn) { } @Override - public int getNextMapId() { + public int getFreeMapId() { return 0; } @Override - public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) { + public void destroyBlockProgress(int breakerId, BlockPos pos, int progress) { } @Override @@ -127,16 +129,16 @@ public class WrappedServerWorld extends ServerWorld { } @Override - public ITagCollectionSupplier getTags() { - return world.getTags(); + public ITagCollectionSupplier getTagManager() { + return world.getTagManager(); } @Override - public Biome getGeneratorStoredBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_) { - return world.getGeneratorStoredBiome(p_225604_1_, p_225604_2_, p_225604_3_); + public Biome getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_) { + return world.getUncachedNoiseBiome(p_225604_1_, p_225604_2_, p_225604_3_); } private static SaveFormat.LevelSave getLevelSaveFromWorld(World world) { - return ObfuscationReflectionHelper.getPrivateValue(MinecraftServer.class, world.getServer(), "field_71310_m"); + return ObfuscationReflectionHelper.getPrivateValue(MinecraftServer.class, world.getServer(), "field_71310_m"); // storageSource } } 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..46b8cdcf6 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,11 +35,11 @@ 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, - world.isRemote, world.isDebugWorld(), 0); + super((ISpawnWorldInfo) world.getLevelData(), world.dimension(), world.dimensionType(), world::getProfiler, + world.isClientSide, world.isDebug(), 0); this.world = world; this.provider = provider; } @@ -48,65 +48,65 @@ public class WrappedWorld extends World { this(world, null); } - public World getWorld() { + public World getLevel() { return world; } - + @Override - public WorldLightManager getLightingProvider() { - return world.getLightingProvider(); + public WorldLightManager getLightEngine() { + return world.getLightEngine(); } - + @Override public BlockState getBlockState(@Nullable BlockPos pos) { return world.getBlockState(pos); } @Override - public boolean hasBlockState(@Nullable BlockPos p_217375_1_, @Nullable Predicate p_217375_2_) { - return world.hasBlockState(p_217375_1_, p_217375_2_); + public boolean isStateAtPosition(@Nullable BlockPos p_217375_1_, @Nullable Predicate p_217375_2_) { + return world.isStateAtPosition(p_217375_1_, p_217375_2_); } @Override - public TileEntity getTileEntity(@Nullable BlockPos pos) { - return world.getTileEntity(pos); + public TileEntity getBlockEntity(@Nullable BlockPos pos) { + return world.getBlockEntity(pos); } @Override - public boolean setBlockState(@Nullable BlockPos pos, @Nullable BlockState newState, int flags) { - return world.setBlockState(pos, newState, flags); + public boolean setBlock(@Nullable BlockPos pos, @Nullable BlockState newState, int flags) { + return world.setBlock(pos, newState, flags); } @Override - public int getLight(BlockPos pos) { + public int getMaxLocalRawBrightness(BlockPos pos) { return 15; } @Override - public void notifyBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState, int flags) { - world.notifyBlockUpdate(pos, oldState, newState, flags); + public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { + world.sendBlockUpdated(pos, oldState, newState, flags); } @Override - public ITickList getPendingBlockTicks() { - return world.getPendingBlockTicks(); + public ITickList getBlockTicks() { + return world.getBlockTicks(); } @Override - public ITickList getPendingFluidTicks() { - return world.getPendingFluidTicks(); + public ITickList getLiquidTicks() { + return world.getLiquidTicks(); } @Override - public AbstractChunkProvider getChunkProvider() { + public AbstractChunkProvider getChunkSource() { return provider; } @Override - public void playEvent(@Nullable PlayerEntity player, int type, BlockPos pos, int data) {} + public void levelEvent(@Nullable PlayerEntity player, int type, BlockPos pos, int data) {} @Override - public List getPlayers() { + public List players() { return Collections.emptyList(); } @@ -115,11 +115,11 @@ public class WrappedWorld extends World { SoundCategory category, float volume, float pitch) {} @Override - public void playMovingSound(@Nullable PlayerEntity p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_, + public void playSound(@Nullable PlayerEntity p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_, SoundCategory p_217384_4_, float p_217384_5_, float p_217384_6_) {} @Override - public Entity getEntityByID(int id) { + public Entity getEntity(int id) { return null; } @@ -129,23 +129,23 @@ public class WrappedWorld extends World { } @Override - public boolean addEntity(@Nullable Entity entityIn) { + public boolean addFreshEntity(@Nullable Entity entityIn) { if (entityIn == null) return false; - entityIn.setWorld(world); - return world.addEntity(entityIn); + entityIn.setLevel(world); + return world.addFreshEntity(entityIn); } @Override - public void registerMapData(MapData mapDataIn) {} + public void setMapData(MapData mapDataIn) {} @Override - public int getNextMapId() { - return world.getNextMapId(); + public int getFreeMapId() { + return world.getFreeMapId(); } @Override - public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {} + public void destroyBlockProgress(int breakerId, BlockPos pos, int progress) {} @Override public Scoreboard getScoreboard() { @@ -158,36 +158,36 @@ public class WrappedWorld extends World { } @Override - public ITagCollectionSupplier getTags() { - return world.getTags(); + public ITagCollectionSupplier getTagManager() { + return world.getTagManager(); } @Override - public Biome getGeneratorStoredBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_) { - return world.getGeneratorStoredBiome(p_225604_1_, p_225604_2_, p_225604_3_); + public Biome getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_) { + return world.getUncachedNoiseBiome(p_225604_1_, p_225604_2_, p_225604_3_); } @Override - public DynamicRegistries getRegistryManager() { - return world.getRegistryManager(); + public DynamicRegistries registryAccess() { + return world.registryAccess(); } @Override - public float getBrightness(Direction p_230487_1_, boolean p_230487_2_) { - return world.getBrightness(p_230487_1_, p_230487_2_); + public float getShade(Direction p_230487_1_, boolean p_230487_2_) { + return world.getShade(p_230487_1_, p_230487_2_); } @Override - public void markChunkDirty(BlockPos p_175646_1_, TileEntity p_175646_2_) { + public void blockEntityChanged(BlockPos p_175646_1_, TileEntity p_175646_2_) { } @Override - public boolean isBlockLoaded(BlockPos p_175667_1_) { + public boolean hasChunkAt(BlockPos p_175667_1_) { return true; } @Override - public void updateComparatorOutputLevel(BlockPos p_175666_1_, Block p_175666_2_) { + public void updateNeighbourForOutputSignal(BlockPos p_175666_1_, Block p_175666_2_) { return; } } 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..e5a963e2b --- /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 java.util.List; +import java.util.function.Predicate; + +import javax.annotation.Nullable; + +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; + +public class EmptierChunk extends Chunk { + + public EmptierChunk() { + super(null, null, null); + } + + public BlockState getBlockState(BlockPos p_180495_1_) { + return Blocks.VOID_AIR.defaultBlockState(); + } + + @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.defaultFluidState(); + } + + @Nullable + public WorldLightManager getLightEngine() { + return null; + } + + public int getLightEmission(BlockPos p_217298_1_) { + return 0; + } + + public void addEntity(Entity p_76612_1_) { } + + public void removeEntity(Entity p_76622_1_) { } + + public void removeEntity(Entity p_76608_1_, int p_76608_2_) { } + + @Nullable + public TileEntity getBlockEntity(BlockPos p_177424_1_, Chunk.CreateEntityType p_177424_2_) { + return null; + } + + public void addBlockEntity(TileEntity p_150813_1_) { } + + public void setBlockEntity(BlockPos p_177426_1_, TileEntity p_177426_2_) { } + + public void removeBlockEntity(BlockPos p_177425_1_) { } + + public void markUnsaved() { } + + public void getEntities(@Nullable Entity p_177414_1_, AxisAlignedBB p_177414_2_, List p_177414_3_, Predicate p_177414_4_) { } + + public void getEntitiesOfClass(Class p_177430_1_, AxisAlignedBB p_177430_2_, List p_177430_3_, Predicate p_177430_4_) { } + + public boolean isEmpty() { + return true; + } + + public boolean isYSpaceEmpty(int p_76606_1_, int p_76606_2_) { + return true; + } + + public ChunkHolder.LocationType getFullStatus() { + return ChunkHolder.LocationType.BORDER; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunk.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunk.java index c7bd8101d..6eaa14f87 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunk.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunk.java @@ -55,7 +55,7 @@ public class WrappedChunk implements IChunk { } @Override - public Stream getLightSources() { + public Stream getLights() { return world.blocksAdded .entrySet() .stream() @@ -84,7 +84,7 @@ public class WrappedChunk implements IChunk { } @Override - public void addTileEntity(BlockPos p_177426_1_, TileEntity p_177426_2_) { + public void setBlockEntity(BlockPos p_177426_1_, TileEntity p_177426_2_) { } @@ -94,12 +94,12 @@ public class WrappedChunk implements IChunk { } @Override - public Set getTileEntitiesPos() { + public Set getBlockEntitiesPos() { return null; } @Override - public Collection> func_217311_f() { + public Collection> getHeightmaps() { return null; } @@ -109,12 +109,12 @@ public class WrappedChunk implements IChunk { } @Override - public Heightmap getHeightmap(Heightmap.Type p_217303_1_) { + public Heightmap getOrCreateHeightmapUnprimed(Heightmap.Type p_217303_1_) { return null; } @Override - public int getTopBlockY(Heightmap.Type p_201576_1_, int p_201576_2_, int p_201576_3_) { + public int getHeight(Heightmap.Type p_201576_1_, int p_201576_2_, int p_201576_3_) { return 0; } @@ -130,49 +130,49 @@ public class WrappedChunk implements IChunk { @Nullable @Override - public BiomeContainer getBiomeArray() { + public BiomeContainer getBiomes() { return null; } @Override - public void setModified(boolean p_177427_1_) { + public void setUnsaved(boolean p_177427_1_) { } @Override - public boolean isModified() { + public boolean isUnsaved() { return false; } @Override - public void removeTileEntity(BlockPos p_177425_1_) { + public void removeBlockEntity(BlockPos p_177425_1_) { } @Override - public ShortList[] getPackedPositions() { + public ShortList[] getPostProcessing() { return new ShortList[0]; } @Nullable @Override - public CompoundNBT getDeferredTileEntity(BlockPos p_201579_1_) { + public CompoundNBT getBlockEntityNbt(BlockPos p_201579_1_) { return null; } @Nullable @Override - public CompoundNBT func_223134_j(BlockPos p_223134_1_) { + public CompoundNBT getBlockEntityNbtForSaving(BlockPos p_223134_1_) { return null; } @Override - public ITickList getBlocksToBeTicked() { + public ITickList getBlockTicks() { return null; } @Override - public ITickList getFluidsToBeTicked() { + public ITickList getLiquidTicks() { return null; } @@ -192,18 +192,18 @@ public class WrappedChunk implements IChunk { } @Override - public boolean hasLight() { + public boolean isLightCorrect() { return needsLight; } @Override - public void setLight(boolean needsLight) { + public void setLightCorrect(boolean needsLight) { this.needsLight = needsLight; } @Nullable @Override - public TileEntity getTileEntity(BlockPos pos) { + public TileEntity getBlockEntity(BlockPos pos) { return null; } @@ -218,42 +218,42 @@ public class WrappedChunk implements IChunk { } @Override - public void addStructureReference(Structure arg0, long arg1) { + public void addReferenceForFeature(Structure arg0, long arg1) { } @Override - public Map, LongSet> getStructureReferences() { + public Map, LongSet> getAllReferences() { return null; } @Override - public LongSet getStructureReferences(Structure arg0) { + public LongSet getReferencesForFeature(Structure arg0) { return null; } @Override - public StructureStart getStructureStart(Structure arg0) { + public StructureStart getStartForFeature(Structure arg0) { return null; } @Override - public void setStructureReferences(Map, LongSet> arg0) { + public void setAllReferences(Map, LongSet> arg0) { } @Override - public void setStructureStart(Structure arg0, StructureStart arg1) { + public void setStartForFeature(Structure arg0, StructureStart arg1) { } @Override - public void setStructureStarts(Map, StructureStart> p_201612_1_) { + public void setAllStarts(Map, StructureStart> p_201612_1_) { } @Override - public Map, StructureStart> getStructureStarts() { + public Map, StructureStart> getAllStarts() { return null; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunkSection.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunkSection.java index e5e90594d..26282a22b 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunkSection.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunkSection.java @@ -14,9 +14,9 @@ public class WrappedChunkSection extends ChunkSection { public WrappedChunkSection(WrappedChunk owner, int yBase) { super(yBase); this.owner = owner; - this.xStart = owner.pos.getXStart(); + this.xStart = owner.pos.getMinBlockX(); this.yStart = yBase; - this.zStart = owner.pos.getZStart(); + this.zStart = owner.pos.getMinBlockZ(); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/AllWorldFeatures.java b/src/main/java/com/simibubi/create/foundation/worldgen/AllWorldFeatures.java index 3eab6cd93..9113dd70a 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/AllWorldFeatures.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/AllWorldFeatures.java @@ -77,7 +77,7 @@ public class AllWorldFeatures { if (event.getCategory() == Category.NETHER) return; event.getGeneration() - .feature(GenerationStage.Decoration.UNDERGROUND_ORES, entry.getFeature()); + .addFeature(GenerationStage.Decoration.UNDERGROUND_ORES, entry.getFeature()); }); } diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenDecorator.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenDecorator.java index b9c6509ad..86cfb3fe9 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenDecorator.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenDecorator.java @@ -18,7 +18,7 @@ public class ConfigDrivenDecorator extends SimplePlacement getPositions(Random r, ConfigDrivenOreFeatureConfig config, BlockPos pos) { + protected Stream place(Random r, ConfigDrivenOreFeatureConfig config, BlockPos pos) { float frequency = config.getFrequency(); int floored = MathHelper.floor(frequency); diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenFeatureEntry.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenFeatureEntry.java index e89ff388e..0d6eeb8ce 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenFeatureEntry.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenFeatureEntry.java @@ -49,11 +49,11 @@ public class ConfigDrivenFeatureEntry extends ConfigBase { private ConfiguredFeature createFeature() { ConfigDrivenOreFeatureConfig config = - new ConfigDrivenOreFeatureConfig(FillerBlockType.BASE_STONE_OVERWORLD, block.get() - .getDefaultState(), id); + new ConfigDrivenOreFeatureConfig(FillerBlockType.NATURAL_STONE, block.get() + .defaultBlockState(), id); - return ConfigDrivenOreFeature.INSTANCE.configure(config) - .decorate(ConfigDrivenDecorator.INSTANCE.configure(config)); + return ConfigDrivenOreFeature.INSTANCE.configured(config) + .decorated(ConfigDrivenDecorator.INSTANCE.configured(config)); } public void addToConfig(ForgeConfigSpec.Builder builder) { diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreFeature.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreFeature.java index 959452655..b93026dc8 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreFeature.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreFeature.java @@ -22,7 +22,7 @@ public class ConfigDrivenOreFeature extends Feature CODEC = RecordCodecBuilder.create((p_236568_0_) -> { - return p_236568_0_.group(RuleTest.field_25012.fieldOf("target") + return p_236568_0_.group(RuleTest.CODEC.fieldOf("target") .forGetter((p_236570_0_) -> { return p_236570_0_.target; }), BlockState.CODEC.fieldOf("state") diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/OxidizingBlock.java b/src/main/java/com/simibubi/create/foundation/worldgen/OxidizingBlock.java index 74345a8a3..d58fa40a6 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/OxidizingBlock.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/OxidizingBlock.java @@ -29,35 +29,35 @@ public class OxidizingBlock extends Block { public OxidizingBlock(Properties properties, float chance) { super(properties); this.chance = chance; - setDefaultState(getDefaultState().with(OXIDIZATION, 0)); + registerDefaultState(defaultBlockState().setValue(OXIDIZATION, 0)); } @Override - protected void fillStateContainer(Builder builder) { - super.fillStateContainer(builder.add(OXIDIZATION)); + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(OXIDIZATION)); } @Override - public boolean ticksRandomly(BlockState state) { - return super.ticksRandomly(state) || state.get(OXIDIZATION) < 7; + public boolean isRandomlyTicking(BlockState state) { + return super.isRandomlyTicking(state) || state.getValue(OXIDIZATION) < 7; } @Override public void randomTick(BlockState state, ServerWorld worldIn, BlockPos pos, Random random) { if (worldIn.getRandom() .nextFloat() <= chance) { - int currentState = state.get(OXIDIZATION); + int currentState = state.getValue(OXIDIZATION); boolean canIncrease = false; LinkedList neighbors = new LinkedList<>(); for (Direction facing : Iterate.directions) { - BlockPos neighbourPos = pos.offset(facing); + BlockPos neighbourPos = pos.relative(facing); if (!worldIn.isAreaLoaded(neighbourPos, 0)) continue; - if (!worldIn.isBlockPresent(neighbourPos)) + if (!worldIn.isLoaded(neighbourPos)) continue; BlockState neighborState = worldIn.getBlockState(neighbourPos); - if (neighborState.contains(OXIDIZATION) && neighborState.get(OXIDIZATION) != 0) { - neighbors.add(neighborState.get(OXIDIZATION)); + if (neighborState.hasProperty(OXIDIZATION) && neighborState.getValue(OXIDIZATION) != 0) { + neighbors.add(neighborState.getValue(OXIDIZATION)); } if (BlockHelper.hasBlockSolidSide(neighborState, worldIn, neighbourPos, facing.getOpposite())) { continue; @@ -69,20 +69,20 @@ public class OxidizingBlock extends Block { .mapToInt(v -> v) .average(); if (average.orElse(7d) >= currentState) - worldIn.setBlockState(pos, state.with(OXIDIZATION, Math.min(currentState + 1, 7))); + worldIn.setBlockAndUpdate(pos, state.setValue(OXIDIZATION, Math.min(currentState + 1, 7))); } } } @Override - public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, + public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult blockRayTraceResult) { - if (state.get(OXIDIZATION) > 0 && player.getHeldItem(hand) + if (state.getValue(OXIDIZATION) > 0 && player.getItemInHand(hand) .getItem() instanceof SandPaperItem) { if (!player.isCreative()) - player.getHeldItem(hand) - .damageItem(1, player, p -> p.sendBreakAnimation(p.getActiveHand())); - world.setBlockState(pos, state.with(OXIDIZATION, 0)); + player.getItemInHand(hand) + .hurtAndBreak(1, player, p -> p.broadcastBreakEvent(p.getUsedItemHand())); + world.setBlockAndUpdate(pos, state.setValue(OXIDIZATION, 0)); return ActionResultType.SUCCESS; } return ActionResultType.PASS; 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..b2ed3b126 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,27 +1,37 @@ -modLoader="javafml" -loaderVersion="[34,)" -#issueTrackerURL="" +modLoader="javafml" +loaderVersion="[36,)" +issueTrackerURL="https://github.com/Creators-of-Create/Create/issues" license="MIT" -[[mods]] +[[mods]] modId="create" -version="${file.jarVersion}" -displayName="Create" +version="v0.3.2e" +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.''' -[[dependencies.create]] +[[dependencies.create]] modId="forge" - mandatory=true - versionRange="[35.1.16,)" + mandatory=true + versionRange="[36.2.0,)" ordering="NONE" side="BOTH" [[dependencies.create]] modId="minecraft" mandatory=true - versionRange="[1.16.4,1.17)" + versionRange="[1.16.5,1.17)" ordering="NONE" - side="BOTH" \ No newline at end of file + side="BOTH" + +[[dependencies.create]] + modId="flywheel" + mandatory=true + versionRange="[1.16-0.2.3,1.16-0.3)" + ordering="AFTER" + side="BOTH" 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/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/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..02e90fb66 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 = vec4(v.color.rgb / diffuse(v.normal), v.color.a); #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/advancements.json b/src/main/resources/assets/create/lang/default/advancements.json index 4ee6b87de..1f35ae1b2 100644 --- a/src/main/resources/assets/create/lang/default/advancements.json +++ b/src/main/resources/assets/create/lang/default/advancements.json @@ -127,8 +127,8 @@ "advancement.create.flywheel.desc": "Successfully connect an engine to the Flywheel.", "advancement.create.overstress_flywheel": "High levels of Stress", "advancement.create.overstress_flywheel.desc": "Overstress a Furnace Engine.", - "advancement.create.integrated_circuit": "Complex Calculation", - "advancement.create.integrated_circuit.desc": "Assemble an Integrated Circuit.", + "advancement.create.precision_mechanism": "Complex Curiosities", + "advancement.create.precision_mechanism.desc": "Assemble a Precision Mechanism.", "advancement.create.mechanical_arm": "Busy Hands!", "advancement.create.mechanical_arm.desc": "Craft a Mechanical Arm, select in- and outputs, place it down and give it power; then watch as it does all the work for you.", "advancement.create.musical_arm": "Play Me My Theme Tune!", @@ -144,7 +144,7 @@ "advancement.create.blaze_cake": "Sugar Rush", "advancement.create.blaze_cake.desc": "Bake your blaze burner a special cake.", - "advancement.create.chromatic_compound": "Bipolar Minerals", + "advancement.create.chromatic_compound": "Mysterious Minerals", "advancement.create.chromatic_compound.desc": "Create a Bar of Chromatic Compound.", "advancement.create.shadow_steel": "Void Returner", "advancement.create.shadow_steel.desc": "Create Shadow Steel, a metal bar of nothingness.", @@ -157,6 +157,8 @@ "advancement.create.wand_of_symmetry.desc": "Craft a Staff of Symmetry.", "advancement.create.extendo_grip": "Boioioing!", "advancement.create.extendo_grip.desc": "Get hold of an Extendo Grip.", + "advancement.create.potato_cannon": "Fwoomp!", + "advancement.create.potato_cannon.desc": "Defeat an enemy with your Potato Cannon.", "advancement.create.dual_extendo_grip": "Ultimate Boing-age", "advancement.create.dual_extendo_grip.desc": "Dual wield Extendo Grips for super-human reach.", diff --git a/src/main/resources/assets/create/lang/default/messages.json b/src/main/resources/assets/create/lang/default/messages.json index 22a691d46..7d13f1069 100644 --- a/src/main/resources/assets/create/lang/default/messages.json +++ b/src/main/resources/assets/create/lang/default/messages.json @@ -4,14 +4,30 @@ "itemGroup.create.palettes": "Create Palettes", "death.attack.create.crush": "%1$s was processed by Crushing Wheels", - "death.attack.create.fan_fire": "%1$s was burned to death by hot air", - "death.attack.create.fan_lava": "%1$s was burned to death by lava fan", + "death.attack.create.crush.player": "%1$s was thrown into Crushing Wheels by %2$s", + "death.attack.create.fan_fire": "%1$s got smoked by an Encased Fan", + "death.attack.create.fan_fire.player": "%1$s was thrown into a smoker by %2$s", + "death.attack.create.fan_lava": "%1$s was incinerated by an Encased Fan", + "death.attack.create.fan_lava.player": "%1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "%1$s was impaled by a Mechanical Drill", + "death.attack.create.mechanical_drill.player": "%1$s was thrown in front of a Drill by %2$s", "death.attack.create.mechanical_saw": "%1$s got cut in half by a Mechanical Saw", + "death.attack.create.mechanical_saw.player": "%1$s was thrown into a Saw by %2$s", + "death.attack.create.potato_cannon": "%1$s was shot by %2$s's Potato Cannon", + "death.attack.create.potato_cannon.item": "%1$s was shot by %2$s using %3$s", "death.attack.create.cuckoo_clock_explosion": "%1$s was blown up by tampered cuckoo clock", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s was blown up by tampered cuckoo clock", "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.ponder_index": "Ponder Index", + "create.menu.only_ingame": "Available in the Pause Menu", + "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 +53,23 @@ "create.recipe.spout_filling": "Filling by Spout", "create.recipe.draining": "Item Draining", - "create.recipe.processing.chance": "%1$s%% Chance", + "create.recipe.sequenced_assembly": "Sequenced Assembly", + "create.recipe.assembly.next": "Next: %1$s", + "create.recipe.assembly.step": "Step %1$s:", + "create.recipe.assembly.progress": "Progress: %1$s/%2$s", + "create.recipe.assembly.pressing": "Process in Press", + "create.recipe.assembly.spout_filling_fluid": "Spout %1$s", + "create.recipe.assembly.deploying_item": "Deploy %1$s", + "create.recipe.assembly.cutting": "Cut with Saw", + "create.recipe.assembly.repeat": "Repeat Sequence %1$s Times", + "create.recipe.assembly.junk": "Random salvage", + + "create.recipe.processing.chance": "%1$s%% Chance", + "create.recipe.deploying.not_consumed": "Not Consumed", "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", @@ -65,7 +93,8 @@ "create.action.saveToFile": "Save", "create.action.discard": "Discard", - "create.keyinfo.toolmenu": "Focus Tool Menu", + "create.keyinfo.toolmenu": "Focus Schematic Overlay", + "create.keyinfo.toolbelt": "Access Nearby Toolboxes", "create.keyinfo.scrollup": "Simulate Mousewheel Up (inworld)", "create.keyinfo.scrolldown": "Simulate Mousewheel Down (inworld)", @@ -77,6 +106,12 @@ "create.gui.toolmenu.focusKey": "Hold [%1$s] to Focus", "create.gui.toolmenu.cycle": "[SCROLL] to Cycle", + + "create.toolbox.unequip": "Unequip: %1$s", + "create.toolbox.outOfRange": "Toolbox of held item not in Range", + "create.toolbox.detach": "Stop tracking and keep item", + "create.toolbox.depositAll": "Return items to nearby Toolboxes", + "create.toolbox.depositBox": "Return items to Toolbox", "create.gui.symmetryWand.mirrorType": "Mirror", "create.gui.symmetryWand.orientation": "Orientation", @@ -116,11 +151,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 +173,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 +211,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 +324,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,23 +365,19 @@ "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", "create.item_attributes.consumable.inverted": "cannot be eaten", - "create.item_attributes.smeltable": "can be Smelted", - "create.item_attributes.smeltable.inverted": "cannot be Smelted", - "create.item_attributes.washable": "can be Washed", - "create.item_attributes.washable.inverted": "cannot be Washed", - "create.item_attributes.smokable": "can be Smoked", - "create.item_attributes.smokable.inverted": "cannot be Smoked", - "create.item_attributes.crushable": "can be Crushed", - "create.item_attributes.crushable.inverted": "cannot be Crushed", - "create.item_attributes.blastable": "is smeltable in Blast Furnace", - "create.item_attributes.blastable.inverted": "is not smeltable in Blast Furnace", + "create.item_attributes.fluid_container": "can store fluids", + "create.item_attributes.fluid_container.inverted": "cannot store fluids", "create.item_attributes.enchanted": "is enchanted", "create.item_attributes.enchanted.inverted": "is unenchanted", + "create.item_attributes.max_enchanted": "is enchanted at max level", + "create.item_attributes.max_enchanted.inverted": "is not enchanted at max level", + "create.item_attributes.renamed": "has a custom name", + "create.item_attributes.renamed.inverted": "does not have a custom name", "create.item_attributes.damaged": "is damaged", "create.item_attributes.damaged.inverted": "is not damaged", "create.item_attributes.badly_damaged": "is heavily damaged", @@ -357,19 +388,33 @@ "create.item_attributes.equipable.inverted": "cannot be equipped", "create.item_attributes.furnace_fuel": "is furnace fuel", "create.item_attributes.furnace_fuel.inverted": "is not furnace fuel", + "create.item_attributes.washable": "can be Washed", + "create.item_attributes.washable.inverted": "cannot be Washed", + "create.item_attributes.crushable": "can be Crushed", + "create.item_attributes.crushable.inverted": "cannot be Crushed", + "create.item_attributes.smeltable": "can be Smelted", + "create.item_attributes.smeltable.inverted": "cannot be Smelted", + "create.item_attributes.smokable": "can be Smoked", + "create.item_attributes.smokable.inverted": "cannot be Smoked", + "create.item_attributes.blastable": "is smeltable in Blast Furnace", + "create.item_attributes.blastable.inverted": "is not smeltable in Blast Furnace", + + "create.item_attributes.shulker_level": "is shulker %1$s", + "create.item_attributes.shulker_level.inverted": "is shulker not %1$s", + "create.item_attributes.shulker_level.full": "full", + "create.item_attributes.shulker_level.empty": "empty", + "create.item_attributes.shulker_level.partial": "partially filled", + "create.item_attributes.in_tag": "is tagged %1$s", "create.item_attributes.in_tag.inverted": "is not tagged %1$s", "create.item_attributes.in_item_group": "is in group '%1$s'", "create.item_attributes.in_item_group.inverted": "is not in group '%1$s'", "create.item_attributes.added_by": "was added by %1$s", "create.item_attributes.added_by.inverted": "was not added by %1$s", - "create.item_attributes.has_enchant": "is enchanted with %1$s", "create.item_attributes.has_enchant.inverted": "is not enchanted with %1$s", "create.item_attributes.color": "is dyed %1$s", "create.item_attributes.color.inverted": "is not dyed %1$s", - "create.item_attributes.max_enchanted": "is enchanted at max level", - "create.item_attributes.max_enchanted.inverted": "is not enchanted at max level", "create.item_attributes.has_fluid": "contains %1$s", "create.item_attributes.has_fluid.inverted": "does not contain %1$s", "create.item_attributes.has_name": "has the custom name %1$s", @@ -384,15 +429,15 @@ "create.item_attributes.book_copy_second.inverted": "is not a second-generation copy", "create.item_attributes.book_copy_tattered": "is a tattered mess", "create.item_attributes.book_copy_tattered.inverted": "is not a tattered mess", - "create.item_attributes.astralsorcery_crystal": "has crystal attribute %1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "does not have crystal attribute %1$s", - "create.item_attributes.astralsorcery_constellation": "is attuned to %1$s", - "create.item_attributes.astralsorcery_constellation.inverted": "is not attuned to %1$s", - "create.item_attributes.astralsorcery_perk_gem": "has perk attribute %1$s", - "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.item_attributes.astralsorcery_constellation": "is attuned to %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "is not attuned to %1$s", + "create.item_attributes.astralsorcery_crystal": "has crystal attribute %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "does not have crystal attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem": "has perk attribute %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "does not have perk attribute %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 +473,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)", @@ -464,6 +509,28 @@ "create.tooltip.chute.fans_pull_down": "Fans pull from Below", "create.tooltip.chute.contains": "Contains: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "Currently distributing:", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "Right-Click to retrieve", + + "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.potato_cannon.ammo.attack_damage": "%1$s Attack Damage", + "create.potato_cannon.ammo.reload_ticks": "%1$s Reload Ticks", + "create.potato_cannon.ammo.knockback": "%1$s Knockback", + "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 +556,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..1148bb09a 100644 --- a/src/main/resources/assets/create/lang/default/tooltips.json +++ b/src/main/resources/assets/create/lang/default/tooltips.json @@ -8,88 +8,21 @@ "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", - "block.create.hose_pulley.tooltip.behaviour1": "_Raises_ or _Lowers_ the hose, location of the hose determines up to which _height extraction_ or _filling_ will act.", - "block.create.hose_pulley.tooltip.condition2": "When Fluids pulled from Pulley", - "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.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.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.", - + "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 +33,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", @@ -116,9 +49,18 @@ "item.create.tree_fertilizer.tooltip.behaviour1": "Grows Trees _regardless_ of their _spacing conditions_", "item.create.extendo_grip.tooltip": "EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "Boioioing! Greatly _increases reach distance_ of the wielder.", + "item.create.extendo_grip.tooltip.summary": "Boioioing! Greatly _increases reach distance_ of the wielder. Can be powered with Air Pressure from a _Copper_ _Backtank_", "item.create.extendo_grip.tooltip.condition1": "When in Off-Hand", "item.create.extendo_grip.tooltip.behaviour1": "Increases _reach distance_ of items used in the _Main-Hand_.", + "item.create.extendo_grip.tooltip.condition2": "While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.behaviour2": "_No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", + + "item.create.potato_cannon.tooltip": "POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.condition1": "When R-Clicked", + "item.create.potato_cannon.tooltip.behaviour1": "_Shoots_ a suitable item from your _Inventory_.", + "item.create.potato_cannon.tooltip.condition2": "While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.behaviour2": "_No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.filter.tooltip": "FILTER", "item.create.filter.tooltip.summary": "_Controls outputs_ and _inputs_ of logistical devices with more _precision_, matching them against a _set of items_ or several _nested filters_.", @@ -126,7 +68,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 +117,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,67 +135,112 @@ "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.toolbox.tooltip": "TOOLBOX", + "block.create.toolbox.tooltip.summary": "Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", + "block.create.toolbox.tooltip.condition1": "When Picked Up", + "block.create.toolbox.tooltip.behaviour1": "_Retains_ Inventory _Contents_.", + "block.create.toolbox.tooltip.condition2": "When placed in Range", + "block.create.toolbox.tooltip.behaviour2": "_Nearby_ _Players_ can hold the _Toolbox_ _Keybind_ to access its contents _Remotely_.", + "block.create.toolbox.tooltip.condition3": "When R-Clicked", + "block.create.toolbox.tooltip.behaviour3": "Opens the _Container Interface_.", + "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.summary": "Toggles a Redstone signal based on the amount of _Stored Items_ or _Fluids_ 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_.", + "block.create.content_observer.tooltip.summary": "_Detects Items_ or _Fluids_ inside _containers_, _pipes_ or _conveyors_ matching a configured _filter_.", + "block.create.content_observer.tooltip.condition1": "When observing a Container", + "block.create.content_observer.tooltip.behaviour1": "Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", + "block.create.content_observer.tooltip.condition2": "When observing a Funnel", + "block.create.content_observer.tooltip.behaviour2": "Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", "block.create.adjustable_crate.tooltip": "ADJUSTABLE CRATE", "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", "block.create.creative_crate.tooltip.behaviour1": "Anything _extracting_ from this container will provide an _endless supply_ of the item specified. Items _inserted_ into this crate will be _voided._", + "item.create.creative_blaze_cake.tooltip": "CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip.summary": "A very special treat for _Blaze Burners_ that allows _controlling their heat level_. After eating this cake, Blaze Burners will _never run out of fuel_.", + "item.create.creative_blaze_cake.tooltip.condition1": "R-Click on Blaze Burner", + "item.create.creative_blaze_cake.tooltip.behaviour1": "_Locks_ the Blaze Burner's heat level. If used again, _cycles_ the Blaze Burner's heat level.", + "block.create.controller_rail.tooltip": "CONTROLLER RAIL", "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.linked_controller.tooltip.condition4": "R-Click on Lectern", + "item.create.linked_controller.tooltip.behaviour4": "Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", + + "item.create.diving_helmet.tooltip": "DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "Together with a _Copper_ _Backtank_, allows the wielder 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": "Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder 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." - + + "block.create.peculiar_bell.tooltip": "PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + + "block.create.haunted_bell.tooltip": "HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "A _Cursed Bell_ haunted by lost souls of the Nether.", + "block.create.haunted_bell.tooltip.condition1": "When Held or Rang", + "block.create.haunted_bell.tooltip.behaviour1": "Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn." + } diff --git a/src/main/resources/assets/create/lang/es_es.json b/src/main/resources/assets/create/lang/es_es.json index c8e41ac46..504694aab 100644 --- a/src/main/resources/assets/create/lang/es_es.json +++ b/src/main/resources/assets/create/lang/es_es.json @@ -13,7 +13,7 @@ "block.create.andesite_bricks": "Ladrillos de andesita", "block.create.andesite_bricks_slab": "Losa de ladrillos de andesita", "block.create.andesite_bricks_stairs": "Escaleras de ladrillos de andesita", - "block.create.andesite_bricks_wall": "Pared de ladrillos de andesita", + "block.create.andesite_bricks_wall": "Muro de ladrillos de andesita", "block.create.andesite_casing": "Revestidor de andesita", "block.create.andesite_cobblestone": "Adoquín de andesita", "block.create.andesite_cobblestone_slab": "Losa de adoquín de andesita", @@ -27,10 +27,12 @@ "block.create.belt": "Cinta", "block.create.birch_window": "Ventana de abedul", "block.create.birch_window_pane": "Panel de ventana de abedul", + "block.create.black_nixie_tube": "Tubo Nixie negro", "block.create.black_sail": "Vela negra", "block.create.black_seat": "Asiento negro", "block.create.black_valve_handle": "Asa de válvula negra", "block.create.blaze_burner": "Quemador de Blaze", + "block.create.blue_nixie_tube": "Tubo Nixie azul", "block.create.blue_sail": "Vela azul", "block.create.blue_seat": "Asiento azul", "block.create.blue_valve_handle": "Asa de válvula azul", @@ -40,6 +42,7 @@ "block.create.brass_encased_shaft": "Eje revestido de latón", "block.create.brass_funnel": "Embudo de latón", "block.create.brass_tunnel": "Túnel de latón", + "block.create.brown_nixie_tube": "Tubo Nixie marrón", "block.create.brown_sail": "Vela marrón", "block.create.brown_seat": "Asiento marrón", "block.create.brown_valve_handle": "Asa de válvula marrón", @@ -52,23 +55,27 @@ "block.create.chiseled_weathered_limestone": "Piedra caliza erosionada cincelada", "block.create.chocolate": "Chocolate", "block.create.chute": "Ducto", - "block.create.clockwork_bearing": "Rodamiento de reloj", + "block.create.clockwork_bearing": "Rodamiento tipo reloj", "block.create.clutch": "Embrague", - "block.create.cogwheel": "Rueda dentada", + "block.create.cogwheel": "Engranaje pequeño", "block.create.content_observer": "Observador de contenidos", "block.create.controller_rail": "Raíl de control", + "block.create.copper_backtank": "Depósito trasero de cobre", "block.create.copper_block": "Bloque de cobre", "block.create.copper_casing": "Revestidor de caliza", - "block.create.copper_ore": "Mineral de cobre", + "block.create.copper_ore": "Mena de cobre", "block.create.copper_shingles": "Bloque de tejas de cobre", "block.create.copper_tiles": "Bloque de baldosas de cobre", "block.create.copper_valve_handle": "Asa de válvula de cobre", "block.create.creative_crate": "Caja creativa", "block.create.creative_fluid_tank": "Tanque de fluidos creativo", "block.create.creative_motor": "Motor creativo", + "block.create.crimson_window": "Ventana carmesí", + "block.create.crimson_window_pane": "Panel de ventana carmesí", "block.create.crushing_wheel": "Rueda trituradora", "block.create.crushing_wheel_controller": "Controlador de Rueda trituradora", - "block.create.cuckoo_clock": "Reloj Cucú", + "block.create.cuckoo_clock": "Reloj de cuco", + "block.create.cyan_nixie_tube": "Tubo Nixie cian", "block.create.cyan_sail": "Vela cian", "block.create.cyan_seat": "Asiento cian", "block.create.cyan_valve_handle": "Asa de válvula cian", @@ -78,32 +85,32 @@ "block.create.dark_scoria_bricks": "Ladrillos de escoria oscura", "block.create.dark_scoria_bricks_slab": "Losa de ladrillos de escoria oscura", "block.create.dark_scoria_bricks_stairs": "Escaleras de ladrillos de escoria oscura", - "block.create.dark_scoria_bricks_wall": "Pared de ladrillos de escoria oscura", + "block.create.dark_scoria_bricks_wall": "Muro de ladrillos de escoria oscura", "block.create.dark_scoria_cobblestone": "Adoquines de escoria oscura", "block.create.dark_scoria_cobblestone_slab": "Losa de adoquines de escoria oscura", "block.create.dark_scoria_cobblestone_stairs": "Escaleras de adoquines de escoria oscura", - "block.create.dark_scoria_cobblestone_wall": "Pared de adoquines de escoria oscura", + "block.create.dark_scoria_cobblestone_wall": "Muro de adoquines de escoria oscura", "block.create.dark_scoria_pillar": "Pilar de escoria oscura", "block.create.deployer": "Desplegador", "block.create.depot": "Depósito", "block.create.diorite_bricks": "Ladrillos de diorita", "block.create.diorite_bricks_slab": "Losa de ladrillos de diorita", "block.create.diorite_bricks_stairs": "Escaleras de ladrillos de diorita", - "block.create.diorite_bricks_wall": "Pared de ladrillos de diorita", + "block.create.diorite_bricks_wall": "Muro de ladrillos de diorita", "block.create.diorite_cobblestone": "Adoquín de diorita", "block.create.diorite_cobblestone_slab": "Losa de adoquínes de diorita", "block.create.diorite_cobblestone_stairs": "Escaleras de adoquines de diorita", - "block.create.diorite_cobblestone_wall": "Pared de adoquines de diorita", + "block.create.diorite_cobblestone_wall": "Muro de adoquines de diorita", "block.create.diorite_pillar": "Pilar de diorita", "block.create.dolomite": "Dolomita", "block.create.dolomite_bricks": "Ladrillos de dolomita", "block.create.dolomite_bricks_slab": "Losa de ladrillos de dolomita", "block.create.dolomite_bricks_stairs": "Escaleras de ladrillos de dolomita", - "block.create.dolomite_bricks_wall": "Pared de ladrillos de dolomita", + "block.create.dolomite_bricks_wall": "Muro de ladrillos de dolomita", "block.create.dolomite_cobblestone": "Adoquín de dolomita", "block.create.dolomite_cobblestone_slab": "Losa de adoquín de dolomita", "block.create.dolomite_cobblestone_stairs": "Escaleras de adoquines de dolomita", - "block.create.dolomite_cobblestone_wall": "Pared de adoquines de dolomita", + "block.create.dolomite_cobblestone_wall": "Muro de adoquines de dolomita", "block.create.dolomite_pillar": "Pilar de dolomita", "block.create.encased_chain_drive": "Cadena de transmisión revestida", "block.create.encased_fan": "Ventilador revestido", @@ -111,39 +118,39 @@ "block.create.fancy_andesite_bricks": "Ladrillos de andesita elegantes", "block.create.fancy_andesite_bricks_slab": "Ladrillos de andesita elegantes", "block.create.fancy_andesite_bricks_stairs": "Escaleras de ladrillos de andesita elegantes", - "block.create.fancy_andesite_bricks_wall": "Pared de ladrillos de andesita elegantes", + "block.create.fancy_andesite_bricks_wall": "Muro de ladrillos de andesita elegantes", "block.create.fancy_dark_scoria_bricks": "Ladrillos de escoria oscura elegantes", "block.create.fancy_dark_scoria_bricks_slab": "Losa de ladrillos de escoria oscura elegantes", "block.create.fancy_dark_scoria_bricks_stairs": "Escalera de ladrillos de escoria oscura elegantes", - "block.create.fancy_dark_scoria_bricks_wall": "Pared de ladrillos de escoria oscura elegantes", + "block.create.fancy_dark_scoria_bricks_wall": "Muro de ladrillos de escoria oscura elegantes", "block.create.fancy_diorite_bricks": "Ladrillos de diorita elegantes", "block.create.fancy_diorite_bricks_slab": "Losa de ladrillos de diorita elegantes", "block.create.fancy_diorite_bricks_stairs": "Escaleras de ladrillos de diorita elegantes", - "block.create.fancy_diorite_bricks_wall": "Pared de ladrillos de diorita elegantes", + "block.create.fancy_diorite_bricks_wall": "Muro de ladrillos de diorita elegantes", "block.create.fancy_dolomite_bricks": "Ladrillos de dolomita elegantes", "block.create.fancy_dolomite_bricks_slab": "Losa de ladrillos de dolomita elegantes", "block.create.fancy_dolomite_bricks_stairs": "Escaleras de ladrillos de dolomita elegantes", - "block.create.fancy_dolomite_bricks_wall": "Pared de ladrillos de dolomita elegantes", + "block.create.fancy_dolomite_bricks_wall": "Muro de ladrillos de dolomita elegantes", "block.create.fancy_gabbro_bricks": "Ladrillos de gabro elegantes", "block.create.fancy_gabbro_bricks_slab": "Losa de ladrillos de gabro elegantes", "block.create.fancy_gabbro_bricks_stairs": "Escaleras de ladrillos de gabro elegantes", - "block.create.fancy_gabbro_bricks_wall": "Pared de ladrillos de gabro elegantes", + "block.create.fancy_gabbro_bricks_wall": "Muro de ladrillos de gabro elegantes", "block.create.fancy_granite_bricks": "Ladrillos de granito elegantes", "block.create.fancy_granite_bricks_slab": "Losa de ladrillos de granito elegantes", "block.create.fancy_granite_bricks_stairs": "Escaleras de ladrillos de granito elegantes", - "block.create.fancy_granite_bricks_wall": "Pared de ladrillos de granito elegantes", + "block.create.fancy_granite_bricks_wall": "Muro de ladrillos de granito elegantes", "block.create.fancy_limestone_bricks": "Ladrillos de piedra caliza elegantes", "block.create.fancy_limestone_bricks_slab": "Losa de ladrillos de piedra caliza elegantes", "block.create.fancy_limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza elegantes", - "block.create.fancy_limestone_bricks_wall": "Pared de ladrillos de piedra caliza elegantes", + "block.create.fancy_limestone_bricks_wall": "Muro de ladrillos de piedra caliza elegantes", "block.create.fancy_scoria_bricks": "Ladrillos de escoria elegantes", "block.create.fancy_scoria_bricks_slab": "Losa de ladrillos de escoria elegantes", "block.create.fancy_scoria_bricks_stairs": "Escaleras de ladrillos de escoria elegantes", - "block.create.fancy_scoria_bricks_wall": "Pared de ladrillos de escoria elegantes", + "block.create.fancy_scoria_bricks_wall": "Muro de ladrillos de escoria elegantes", "block.create.fancy_weathered_limestone_bricks": "Ladrillos de piedra de caliza erosionada elegantes", "block.create.fancy_weathered_limestone_bricks_slab": "Losa de ladrillos de caliza erosionada elegantes", "block.create.fancy_weathered_limestone_bricks_stairs": "Escaleras de ladrillos de caliza erosionada elegantes", - "block.create.fancy_weathered_limestone_bricks_wall": "Pared de ladrillos de caliza erosionada elegantes", + "block.create.fancy_weathered_limestone_bricks_wall": "Muro de ladrillos de caliza erosionada elegantes", "block.create.fluid_pipe": "Tubería de fluidos de cobre", "block.create.fluid_tank": "Depósito de fluidos", "block.create.fluid_valve": "Válvula de fluidos", @@ -155,13 +162,13 @@ "block.create.gabbro_bricks": "Ladrillos de gabro", "block.create.gabbro_bricks_slab": "Losa de ladrillos de gabro", "block.create.gabbro_bricks_stairs": "Escaleras de ladrillos de gabro", - "block.create.gabbro_bricks_wall": "Pared de ladrillos de gabro", + "block.create.gabbro_bricks_wall": "Muro de ladrillos de gabro", "block.create.gabbro_cobblestone": "Adoquín de gabro", "block.create.gabbro_cobblestone_slab": "Losa de adoquínes de gabro", "block.create.gabbro_cobblestone_stairs": "Escaleras de adoquínes de gabro", - "block.create.gabbro_cobblestone_wall": "Pared de adoquínes de gabro", + "block.create.gabbro_cobblestone_wall": "Muro de adoquínes de gabro", "block.create.gabbro_pillar": "Pilar de gabro", - "block.create.gantry_pinion": "Piñón de grúa", + "block.create.gantry_carriage": "Carro de grúa", "block.create.gantry_shaft": "Eje de grúa", "block.create.gearbox": "Caja de transmisión", "block.create.gearshift": "Caja de cambios", @@ -169,27 +176,30 @@ "block.create.granite_bricks": "Ladrillos de granito", "block.create.granite_bricks_slab": "Losa de ladrillos de granito", "block.create.granite_bricks_stairs": "Escaleras de ladrillos de granito", - "block.create.granite_bricks_wall": "Pared de ladrillos de granito", + "block.create.granite_bricks_wall": "Muro de ladrillos de granito", "block.create.granite_cobblestone": "Adoquín de granito", "block.create.granite_cobblestone_slab": "Losa de adoquínes de granito", "block.create.granite_cobblestone_stairs": "Escaleras de adoquínes de granito", - "block.create.granite_cobblestone_wall": "Pared de adoquínes de granito", + "block.create.granite_cobblestone_wall": "Muro de adoquínes de granito", "block.create.granite_pillar": "Pilar de granito", + "block.create.gray_nixie_tube": "Tubo Nixie gris", "block.create.gray_sail": "Vela gris", "block.create.gray_seat": "Asiento gris", "block.create.gray_valve_handle": "Asa de válvula gris", + "block.create.green_nixie_tube": "Tubo Nixie verde", "block.create.green_sail": "Vela verde", "block.create.green_seat": "Asiento verde", "block.create.green_valve_handle": "Asa de válvula verde", "block.create.hand_crank": "Manivela", + "block.create.haunted_bell": "Campana encantada", "block.create.honey": "Miel", "block.create.horizontal_framed_glass": "Cristal con marco horizontal", "block.create.horizontal_framed_glass_pane": "Panel de cristal con marco horizontal", "block.create.hose_pulley": "Polea de manguera", - "block.create.item_drain": "Drenador de elementos", + "block.create.item_drain": "Drenador de objetos", "block.create.jungle_window": "Ventana de jungla", "block.create.jungle_window_pane": "Panel de ventana de jungla", - "block.create.large_cogwheel": "Rueda dentada grande", + "block.create.large_cogwheel": "Engranaje grande", "block.create.layered_andesite": "Andesita estratificada", "block.create.layered_dark_scoria": "Escoria oscura estratificada", "block.create.layered_diorite": "Diorita estratificada", @@ -199,12 +209,16 @@ "block.create.layered_limestone": "Piedra caliza estratificada", "block.create.layered_scoria": "Escoria estratificada", "block.create.layered_weathered_limestone": "Caliza erosionada estratificada", + "block.create.lectern_controller": "Controlador de atril", + "block.create.light_blue_nixie_tube": "Tubo Nixie azul claro", "block.create.light_blue_sail": "Vela azul claro", "block.create.light_blue_seat": "Asiento azul claro", "block.create.light_blue_valve_handle": "Asa de válvula azul claro", + "block.create.light_gray_nixie_tube": "Tubo Nixie gris claro", "block.create.light_gray_sail": "Vela gris claro", "block.create.light_gray_seat": "Asiento gris claro", "block.create.light_gray_valve_handle": "Asa de válvula gris claro", + "block.create.lime_nixie_tube": "Tubo Nixie lima", "block.create.lime_sail": "Vela lima", "block.create.lime_seat": "Asiento lima", "block.create.lime_valve_handle": "Asa de válvula lima", @@ -213,20 +227,21 @@ "block.create.limestone_bricks": "Ladrillos de piedra caliza", "block.create.limestone_bricks_slab": "Losa de ladrillos de piedra caliza", "block.create.limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza", - "block.create.limestone_bricks_wall": "Pared de ladrillos de piedra caliza", + "block.create.limestone_bricks_wall": "Muro de ladrillos de piedra caliza", "block.create.limestone_cobblestone": "Adoquínes de piedra caliza", "block.create.limestone_cobblestone_slab": "Losa de adoquines de piedra caliza", "block.create.limestone_cobblestone_stairs": "Escaleras de adoquines de piedra caliza", - "block.create.limestone_cobblestone_wall": "Pared de adoquines de piedra caliza", + "block.create.limestone_cobblestone_wall": "Muro de adoquines de piedra caliza", "block.create.limestone_pillar": "Pilar de piedra caliza", "block.create.linear_chassis": "Chasis lineal", "block.create.lit_blaze_burner": "Quemador de Blaze encendido", + "block.create.magenta_nixie_tube": "Tubo Nixie magenta", "block.create.magenta_sail": "Vela magenta", "block.create.magenta_seat": "Asiento magenta", "block.create.magenta_valve_handle": "Asa de válvula magenta", "block.create.mechanical_arm": "Brazo mecánico", "block.create.mechanical_bearing": "Rodamiento mecánico", - "block.create.mechanical_crafter": "Autoensamblador mecánico", + "block.create.mechanical_crafter": "Ensamblador mecánico", "block.create.mechanical_drill": "Taladro mecánico", "block.create.mechanical_harvester": "Cosechadora mecánica", "block.create.mechanical_mixer": "Mezcladora mecánica", @@ -248,7 +263,7 @@ "block.create.mossy_limestone": "Caliza musgosa", "block.create.mossy_scoria": "Escoria musgosa", "block.create.mossy_weathered_limestone": "Caliza erosionada musgosa", - "block.create.mysterious_cuckoo_clock": "Reloj cucú", + "block.create.mysterious_cuckoo_clock": "Reloj de cuco", "block.create.natural_scoria": "Escoria natural", "block.create.nixie_tube": "Tubo Nixie", "block.create.nozzle": "Boquilla", @@ -271,39 +286,41 @@ "block.create.paved_andesite": "Andesita pavimentada", "block.create.paved_andesite_slab": "Losa de andesita pavimentada", "block.create.paved_andesite_stairs": "Escaleras de andesita pavimentada", - "block.create.paved_andesite_wall": "Pared de andesita pavimentada", + "block.create.paved_andesite_wall": "Muro de andesita pavimentada", "block.create.paved_dark_scoria": "Escoria oscura pavimentada", "block.create.paved_dark_scoria_slab": "Losa de escoria oscura pavimentada", "block.create.paved_dark_scoria_stairs": "Escaleras de escoria oscura pavimentada", - "block.create.paved_dark_scoria_wall": "Pared de escoria oscura pavimentad", + "block.create.paved_dark_scoria_wall": "Muro de escoria oscura pavimentad", "block.create.paved_diorite": "Diorita pavimentada", "block.create.paved_diorite_slab": "Losa de diorita pavimentada", "block.create.paved_diorite_stairs": "Escaleras de diorita pavimentada", - "block.create.paved_diorite_wall": "Pared de diorita pavimentad", + "block.create.paved_diorite_wall": "Muro de diorita pavimentad", "block.create.paved_dolomite": "Dolomita pavimentada", "block.create.paved_dolomite_slab": "Losa de dolomita pavimentada", "block.create.paved_dolomite_stairs": "Escaleras de dolomita pavimentada", - "block.create.paved_dolomite_wall": "Pared de dolomita pavimentada", + "block.create.paved_dolomite_wall": "Muro de dolomita pavimentada", "block.create.paved_gabbro": "Gabro pavimentado", "block.create.paved_gabbro_slab": "Losa de gabro pavimentado", "block.create.paved_gabbro_stairs": "Escaleras de gabro pavimentado", - "block.create.paved_gabbro_wall": "Pared de gabro pavimentado", + "block.create.paved_gabbro_wall": "Muro de gabro pavimentado", "block.create.paved_granite": "Granito pavimentado", "block.create.paved_granite_slab": "Losa de granito pavimentado", "block.create.paved_granite_stairs": "Escaleras de granito pavimentado", - "block.create.paved_granite_wall": "Pared de granito pavimentado", + "block.create.paved_granite_wall": "Muro de granito pavimentado", "block.create.paved_limestone": "Piedra caliza pavimentada", "block.create.paved_limestone_slab": "Losa de piedra caliza pavimentada", "block.create.paved_limestone_stairs": "Escaleras de piedra caliza pavimentada", - "block.create.paved_limestone_wall": "Pared de piedra caliza pavimentada", + "block.create.paved_limestone_wall": "Muro de piedra caliza pavimentada", "block.create.paved_scoria": "Escoria pavimentada", "block.create.paved_scoria_slab": "Losa de escoria pavimentada", "block.create.paved_scoria_stairs": "Escaleras de escoria pavimentada", - "block.create.paved_scoria_wall": "Pared de escoria pavimentada", + "block.create.paved_scoria_wall": "Muro de escoria pavimentada", "block.create.paved_weathered_limestone": "Piedra caliza erosionada pavimentada", "block.create.paved_weathered_limestone_slab": "Losa de piedra caliza erosionada pavimentada", "block.create.paved_weathered_limestone_stairs": "Escaleras de piedra caliza erosionada pavimentada", - "block.create.paved_weathered_limestone_wall": "Pared de piedra caliza erosionada pavimentada", + "block.create.paved_weathered_limestone_wall": "Muro de piedra caliza erosionada pavimentada", + "block.create.peculiar_bell": "Campana peculiar", + "block.create.pink_nixie_tube": "Tubo Nixie rosa", "block.create.pink_sail": "Vela rosa", "block.create.pink_seat": "Asiento rosa", "block.create.pink_valve_handle": "Asa de válvula rosa", @@ -311,62 +328,64 @@ "block.create.polished_dark_scoria": "Escoria oscura pulida", "block.create.polished_dark_scoria_slab": "Losa de escoria oscura pulida", "block.create.polished_dark_scoria_stairs": "Escaleras de escoria oscura pulida", - "block.create.polished_dark_scoria_wall": "Pared de escoria oscura pulida", + "block.create.polished_dark_scoria_wall": "Muro de escoria oscura pulida", "block.create.polished_dolomite": "Dolomita pulida", "block.create.polished_dolomite_slab": "Losa de dolomita pulida", "block.create.polished_dolomite_stairs": "Escaleras de dolomita pulidas", - "block.create.polished_dolomite_wall": "Pared de dolomita pulida", + "block.create.polished_dolomite_wall": "Muro de dolomita pulida", "block.create.polished_gabbro": "Gabro pulido", "block.create.polished_gabbro_slab": "Losa de gabro pulido", "block.create.polished_gabbro_stairs": "Escaleras de gabro pulido", - "block.create.polished_gabbro_wall": "Pared de gabro pulido", + "block.create.polished_gabbro_wall": "Muro de gabro pulido", "block.create.polished_limestone": "Piedra caliza pulida", "block.create.polished_limestone_slab": "Losa de piedra caliza pulida", "block.create.polished_limestone_stairs": "Escaleras de piedra caliza pulidas", - "block.create.polished_limestone_wall": "Pared de piedra caliza pulida", + "block.create.polished_limestone_wall": "Muro de piedra caliza pulida", "block.create.polished_scoria": "Escoria pulida", "block.create.polished_scoria_slab": "Losa de escoria pulida", "block.create.polished_scoria_stairs": "Escaleras de losa pulida", - "block.create.polished_scoria_wall": "Pared de escoria pulida", + "block.create.polished_scoria_wall": "Muro de escoria pulida", "block.create.polished_weathered_limestone": "Piedra caliza erosionada pulida", "block.create.polished_weathered_limestone_slab": "Losa de piedra caliza erosionada pulida", "block.create.polished_weathered_limestone_stairs": "Escaleras de piedra caliza erosionada pulida", - "block.create.polished_weathered_limestone_wall": "Pared de piedra caliza erosionada pulida", + "block.create.polished_weathered_limestone_wall": "Muro de piedra caliza erosionada pulida", "block.create.portable_fluid_interface": "Interfaz de fluidos portátil", "block.create.portable_storage_interface": "Interfaz de almacenamiento portátil", "block.create.powered_latch": "Palanca motorizada", "block.create.powered_toggle_latch": "Palanca de cierre motorizada", "block.create.pulley_magnet": "Imán de la polea", - "block.create.pulse_repeater": "Repetidor de pulsos de Redstone", + "block.create.pulse_repeater": "Repetidor de pulsos de redstone", + "block.create.purple_nixie_tube": "Tubo Nixie morado", "block.create.purple_sail": "Vela morada", "block.create.purple_seat": "Asiento morado", "block.create.purple_valve_handle": "Asa de válvula morada", "block.create.radial_chassis": "Chasis radial", + "block.create.red_nixie_tube": "Tubo Nixie rojo", "block.create.red_sail": "Vela roja", "block.create.red_seat": "Asiento rojo", "block.create.red_valve_handle": "Asa de válvula roja", - "block.create.redstone_contact": "Contacto de Redstone", - "block.create.redstone_link": "Enlace de Redstone", - "block.create.refined_radiance_casing": "Revestidor de radiante", + "block.create.redstone_contact": "Contacto de redstone", + "block.create.redstone_link": "Enlace de redstone", + "block.create.refined_radiance_casing": "Revestidor radiante", "block.create.reinforced_rail": "Raíl reforzado", "block.create.rope": "Cuerda", "block.create.rope_pulley": "Polea de cuerda", - "block.create.rotation_speed_controller": "Controlador de velocidad de rotación", + "block.create.rotation_speed_controller": "Controlador de velocidad rotacional", "block.create.sail_frame": "Marco de vela", "block.create.schematic_table": "Tabla de esquemas", - "block.create.schematicannon": "Schematicannon", + "block.create.schematicannon": "Cañón de esquemas", "block.create.scoria": "Escoria", "block.create.scoria_bricks": "Ladrillos de escoria", "block.create.scoria_bricks_slab": "Losa de ladrillos de escoria", "block.create.scoria_bricks_stairs": "Escaleras de ladrillos de escoria", - "block.create.scoria_bricks_wall": "Pared de ladrillos de escoria", + "block.create.scoria_bricks_wall": "Muro de ladrillos de escoria", "block.create.scoria_cobblestone": "Adoquín de escoria", "block.create.scoria_cobblestone_slab": "Losa de adoquínes de escoria", "block.create.scoria_cobblestone_stairs": "Escaleras de adoquines de escoria", - "block.create.scoria_cobblestone_wall": "Pared de adoquines de escoria", + "block.create.scoria_cobblestone_wall": "Muro de adoquines de escoria", "block.create.scoria_pillar": "Pilar de escoria", "block.create.secondary_linear_chassis": "Chasis lineal secundario", - "block.create.sequenced_gearshift": "Palanca de cambios secuencial", + "block.create.sequenced_gearshift": "Caja de cambios secuencial", "block.create.shadow_steel_casing": "Revestidor sombrío", "block.create.shaft": "Eje", "block.create.smart_chute": "Ducto inteligente", @@ -375,6 +394,7 @@ "block.create.spout": "Surtidor", "block.create.spruce_window": "Ventana de abeto", "block.create.spruce_window_pane": "Panel de ventana de abeto", + "block.create.sticker": "Sticker", "block.create.sticky_mechanical_piston": "Pistón mecánico pegajoso", "block.create.stockpile_switch": "Interruptor de acopio", "block.create.stressometer": "Estresómetro", @@ -383,57 +403,70 @@ "block.create.turntable": "Plataforma giratoria mecánica", "block.create.vertical_framed_glass": "Vidrio esmaltado vertical", "block.create.vertical_framed_glass_pane": "Panel de vidrio esmaltado vertical", + "block.create.warped_window": "Ventana distorsionada", + "block.create.warped_window_pane": "Panel de ventana distorsionada", "block.create.water_wheel": "Rueda hidráulica mecánica", "block.create.weathered_limestone": "Piedra caliza erosionada", "block.create.weathered_limestone_bricks": "Ladrillos de piedra caliza erosionada", "block.create.weathered_limestone_bricks_slab": "Losa de piedra caliza erosionada", "block.create.weathered_limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza erosionada", - "block.create.weathered_limestone_bricks_wall": "Pared de ladrillos de piedra caliza erosionada", + "block.create.weathered_limestone_bricks_wall": "Muro de ladrillos de piedra caliza erosionada", "block.create.weathered_limestone_cobblestone": "Adoquín de piedra caliza erosionada", "block.create.weathered_limestone_cobblestone_slab": "Losa de adoquín de piedra caliza erosionada", "block.create.weathered_limestone_cobblestone_stairs": "Escaleras de adoquín de piedra caliza erosionada", - "block.create.weathered_limestone_cobblestone_wall": "Pared de adoquínes de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone_wall": "Muro de adoquínes de piedra caliza erosionada", "block.create.weathered_limestone_pillar": "Pilar de piedra caliza erosionada", + "block.create.weighted_ejector": "Eyector de peso", + "block.create.white_nixie_tube": "Tubo Nixie blanco", "block.create.white_sail": "Vela blanca", "block.create.white_seat": "Asiento blanco", "block.create.white_valve_handle": "Asa de válvula blanco", "block.create.windmill_bearing": "Rodamiento del molino de viento", "block.create.wooden_bracket": "Soporte de madera para ejes", + "block.create.yellow_nixie_tube": "Tubo Nixie amarillo", "block.create.yellow_sail": "Vela amarilla", "block.create.yellow_seat": "Asiento amarillo", "block.create.yellow_valve_handle": "Asa de válvula amarillo", "block.create.zinc_block": "Bloque de zinc", - "block.create.zinc_ore": "Mineral de zinc", + "block.create.zinc_ore": "Mena de zinc", + + "enchantment.create.capacity": "Capacidad", + "enchantment.create.potato_recovery": "Recuperación de patatas", "entity.create.contraption": "Artilugio", + "entity.create.crafting_blueprint": "Plano de elaboración", "entity.create.gantry_contraption": "Artilugio de grúa", + "entity.create.potato_projectile": "Proyectil de patata", "entity.create.seat": "Asiento", "entity.create.stationary_contraption": "Artilugio estacionario", - "entity.create.super_glue": "Super Pegamento", + "entity.create.super_glue": "Pegamento", - "fluid.create.milk": "Leche", "fluid.create.potion": "Poción", "fluid.create.tea": "Té del Constructor", "item.create.andesite_alloy": "Aleación de andesita", "item.create.attribute_filter": "Filtro de atributos", "item.create.bar_of_chocolate": "Barra de chocolate", - "item.create.belt_connector": "Correa", - "item.create.blaze_cake": "Pastel de Blaze", - "item.create.blaze_cake_base": "Base de Pastel de Blaze", + "item.create.belt_connector": "Correa mecánica", + "item.create.blaze_cake": "Pastel de blaze", + "item.create.blaze_cake_base": "Base de pastel de blaze", "item.create.brass_hand": "Mano de latón", "item.create.brass_ingot": "Lingote de latón", "item.create.brass_nugget": "Pepita de latón", "item.create.brass_sheet": "Lámina de latón", "item.create.builders_tea": "Té del Constructor", "item.create.chest_minecart_contraption": "Artilugio de vagoneta con cofre", - "item.create.chocolate_bucket": "Cubo de chocolate", + "item.create.chocolate_bucket": "Cubo con chocolate", + "item.create.chocolate_glazed_berries": "Bayas glaseadas con chocolate", "item.create.chromatic_compound": "Compuesto cromático", - "item.create.cinder_flour": "Harina de ceniza", + "item.create.cinder_flour": "Harina del Nether", + "item.create.copper_backtank": "Depósito trasero de cobre", "item.create.copper_ingot": "Lingote de cobre", "item.create.copper_nugget": "Pepita de cobre", "item.create.copper_sheet": "Lámina de cobre", - "item.create.crafter_slot_cover": "Tapa de ranura del Autoensamblador mecánico", + "item.create.crafter_slot_cover": "Tapa de ranura del ensamblador mecánico", + "item.create.crafting_blueprint": "Plano de elaboración", + "item.create.creative_blaze_cake": "´Pastel de blaze creativo", "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", @@ -448,36 +481,42 @@ "item.create.crushed_tin_ore": "Mineral de estaño molido", "item.create.crushed_uranium_ore": "Mineral de uranio molido", "item.create.crushed_zinc_ore": "Mineral de zinc molido", - "item.create.deforester": "Deforestador", + "item.create.diving_boots": "Botas de buceo", + "item.create.diving_helmet": "Casco de buceo", "item.create.dough": "Masilla", "item.create.electron_tube": "Tubo de electrones", - "item.create.empty_blaze_burner": "Quemador de Blaze vacío", + "item.create.empty_blaze_burner": "Quemador de blaze vacío", "item.create.empty_schematic": "Esquema vacío", "item.create.extendo_grip": "Agarre extendido", "item.create.filter": "Filtro", "item.create.furnace_minecart_contraption": "Artilugio de vagoneta de horno", - "item.create.goggles": "Gafas del Ingeniero", + "item.create.goggles": "Gafas del constructor", "item.create.golden_sheet": "Lámina de oro", - "item.create.handheld_blockzapper": "Blockzapper", - "item.create.handheld_worldshaper": "Worldshaper", - "item.create.honey_bucket": "Cubo de miel", - "item.create.integrated_circuit": "Chip de circuito integrado", + "item.create.handheld_worldshaper": "Worldshaper Creativo", + "item.create.honey_bucket": "Cubo con miel", + "item.create.honeyed_apple": "Manzana con miel", + "item.create.incomplete_cogwheel": "Engranaje pequeño incompleto", + "item.create.incomplete_large_cogwheel": "Engranaje grande incompleto", + "item.create.incomplete_precision_mechanism": "Mecanismo de precisión incompleto", "item.create.iron_sheet": "Lámina de hierro", - "item.create.lapis_sheet": "Lámina de lapislázuli", + "item.create.linked_controller": "Controlador enlazado", "item.create.minecart_contraption": "Artilugio de vagoneta", "item.create.minecart_coupling": "Acoplamiento de vagoneta", "item.create.polished_rose_quartz": "Cuarzo rosado pulido", - "item.create.powdered_obsidian": "Obsidiana en polvo", + "item.create.potato_cannon": "Cañón de patatas", + "item.create.powdered_obsidian": "Polvo de obsidiana", + "item.create.precision_mechanism": "Mecanismo de precisión", "item.create.propeller": "Hélice", "item.create.red_sand_paper": "Papel de lija rojo", "item.create.refined_radiance": "Resplandor refinado", "item.create.rose_quartz": "Cuarzo rosado", "item.create.sand_paper": "Papel de lija", "item.create.schematic": "Esquema", - "item.create.schematic_and_quill": "Esquema y Pluma", + "item.create.schematic_and_quill": "Esquema y pluma", "item.create.shadow_steel": "Acero sombrío", - "item.create.super_glue": "Super Pegamento", - "item.create.tree_fertilizer": "Fertilizador de árboles", + "item.create.super_glue": "Pegamento", + "item.create.sweet_roll": "Pan dulce", + "item.create.tree_fertilizer": "Fertilizante para árboles", "item.create.vertical_gearbox": "Caja de transmisión vertical", "item.create.wand_of_symmetry": "Varita de simetría", "item.create.wheat_flour": "Harina de trigo", @@ -490,25 +529,25 @@ "_": "->------------------------] Advancements [------------------------<-", "advancement.create.root": "Bienvenido a Create", - "advancement.create.root.desc": "¡Es hora de empezar a construir increíbles Artilugios!", - "advancement.create.andesite_alloy": "Aliteraciones en abundancia", + "advancement.create.root.desc": "¡Es hora de empezar a construir increíbles artilugios!", + "advancement.create.andesite_alloy": "Aleaciones en abundancia", "advancement.create.andesite_alloy.desc": "Los materiales de Create tienen nombres extraños, la aleación de andesita es uno de ellos.", - "advancement.create.its_alive": "Está Vivo!", - "advancement.create.its_alive.desc": "Vea cómo gira su primer componente cinético.", + "advancement.create.its_alive": "¡Está vivo!", + "advancement.create.its_alive.desc": "Mira cómo gira tu primer componente cinético.", "advancement.create.shifting_gears": "Cambiando de marcha", - "advancement.create.shifting_gears.desc": "Conecta una rueda dentada grande a una pequeña, lo que te permitirá cambiar la velocidad de tu artilugio.", + "advancement.create.shifting_gears.desc": "Conecta un engranaje grande a uno pequeño, lo que te permitirá cambiar la velocidad de tu artilugio.", "advancement.create.overstressed": "Sobrecargado", "advancement.create.overstressed.desc": "Experimenta los límites del estrés.", "advancement.create.belt": "Paseo de algas", "advancement.create.belt.desc": "Conectar dos ejes con una correa.", - "advancement.create.tunnel": "Cúbrete!", - "advancement.create.tunnel.desc": "Embellece tu correa con un Túnel.", + "advancement.create.tunnel": "¡Cúbrete!", + "advancement.create.tunnel.desc": "Embellece tu correa con un túnel.", "advancement.create.splitter_tunnel": "Divide y vencerás", "advancement.create.splitter_tunnel.desc": "Crear un divisor con un grupo de túneles de latón.", "advancement.create.chute": "Caída en picado", "advancement.create.chute.desc": "Coloque un ducto, la contrapartida vertical de la cinta.", "advancement.create.upward_chute": "Abducción aérea", - "advancement.create.upward_chute.desc": "Observe cómo un objeto lanzado vuela hacia un paracaídas impulsado por un ventilador.", + "advancement.create.upward_chute.desc": "Observe cómo un objeto lanzado vuela dentro de un ducto impulsado por un ventilador.", "advancement.create.belt_funnel": "Colgantes con forma de embudo", "advancement.create.belt_funnel.desc": "Coloca un embudo lateral encima de una cinta o depósito para crear un tipo especial.", "advancement.create.belt_funnel_kiss": "Los loros y las aletas", @@ -516,81 +555,81 @@ "advancement.create.fan": "Maestro mecánico del aire", "advancement.create.fan.desc": "Monta la corriente de aire proporcionada por un ventilador revestido.", "advancement.create.fan_lava": "Calentador geotérmico", - "advancement.create.fan_lava.desc": "Quedar atrapado en una corriente de aire que funde las cosas.", + "advancement.create.fan_lava.desc": "Queda atrapado en una corriente de aire que funde las cosas.", "advancement.create.fan_water": "Lavado de la ropa", - "advancement.create.fan_water.desc": "Quedar atrapado en una corriente de aire que lava las cosas.", + "advancement.create.fan_water.desc": "Queda atrapado en una corriente de aire que lava las cosas.", "advancement.create.fan_smoke": "Fuelle mecánico", - "advancement.create.fan_smoke.desc": "Quedar atrapado en una corriente de aire que humea los artículos.", + "advancement.create.fan_smoke.desc": "Queda atrapado en una corriente de aire que humea los objetos.", "advancement.create.wrench": "Configurar convenientemente", "advancement.create.wrench.desc": "Crea una llave inglesa para ayudarte a construir tus artilugios.", - "advancement.create.goggles": "Stress-O-Vision", - "advancement.create.goggles.desc": "Crea unas Gafas del Ingeniero para ayudarte a obtener más información cinética de los componentes.", - "advancement.create.speedometer": "Pero, ¿con qué rapidez exactamente??", - "advancement.create.speedometer.desc": "Coloca y alimenta un Velocímetro. Míralo a través de las gafas para leer su valor exacto.", + "advancement.create.goggles": "Estresóvisión", + "advancement.create.goggles.desc": "Crea unas gafas del constructor para ayudarte a obtener más información cinética de los componentes.", + "advancement.create.speedometer": "Pero, ¿con qué rapidez exactamente?", + "advancement.create.speedometer.desc": "Coloca y alimenta un velocímetro. Míralo a través de las gafas para leer su valor exacto.", "advancement.create.stressometer": "Pero, ¿cuán estresado exactamente??", - "advancement.create.stressometer.desc": "Coloca y alimenta un Estresómetro. Míralo a través de las gafas para leer su valor exacto.", - "advancement.create.aesthetics": "Boom, Estética!", - "advancement.create.aesthetics.desc": "Colocar los soportes en un eje, tubo y rueda dentada.", - "advancement.create.reinforced": "Boom, Reforzado!", - "advancement.create.reinforced.desc": "Utilizar bloques de revestimiento en un eje, un tubo y una cinta.", + "advancement.create.stressometer.desc": "Coloca y alimenta un estresómetro. Míralo a través de las gafas para leer su valor exacto.", + "advancement.create.aesthetics": "Boom, ¡Estética!", + "advancement.create.aesthetics.desc": "Coloca soportes en ejes, ductos y engranajes.", + "advancement.create.reinforced": "Boom, ¡Reforzado!", + "advancement.create.reinforced.desc": "Utiliza bloques de revestimiento en un eje, un ducto y una cinta.", "advancement.create.water_wheel": "Aprovechar la hidráulica", - "advancement.create.water_wheel.desc": "Coloca una Rueda hidráulica e intenta hacerla girar.", + "advancement.create.water_wheel.desc": "Coloca una rueda hidráulica e intenta hacerla girar.", "advancement.create.chocolate_wheel": "Potencia de buen gusto", - "advancement.create.chocolate_wheel.desc": "Hacer funcionar una rueda de agua con chocolate fundido.", - "advancement.create.lava_wheel": "Rueda de Magma", + "advancement.create.chocolate_wheel.desc": "Haz funcionar una rueda de agua con chocolate fundido.", + "advancement.create.lava_wheel": "Rueda de magma", "advancement.create.lava_wheel.desc": "Esto no debió haber funcionado.", "advancement.create.cuckoo": "¿Es el momento?", - "advancement.create.cuckoo.desc": "Presenciar cómo un Reloj de cucú anuncia la hora de acostarse.", + "advancement.create.cuckoo.desc": "Presencia cómo un reloj de cuco anuncia la hora de acostarse.", "advancement.create.millstone": "Triturador de bolsillo", - "advancement.create.millstone.desc": "Colocar y alimentar una Piedra de molino.", + "advancement.create.millstone.desc": "Coloca y alimenta una piedra de molino.", "advancement.create.windmill": "Una suave brisa", - "advancement.create.windmill.desc": "Montar un molino de viento.", + "advancement.create.windmill.desc": "Monta un molino de viento.", "advancement.create.maxed_windmill": "Una fuerte brisa", - "advancement.create.maxed_windmill.desc": "Montar un molino de viento de máxima intensidad.", + "advancement.create.maxed_windmill.desc": "Monta un molino de viento con máxima intensidad.", "advancement.create.andesite_casing": "La edad de la andesita", "advancement.create.andesite_casing.desc": "Utiliza un poco de aleación de andesita y madera para crear un revestimiento básico.", "advancement.create.mechanical_drill": "Interruptores fijos", - "advancement.create.mechanical_drill.desc": "Colocar y alimentar un taladro mecánico.", + "advancement.create.mechanical_drill.desc": "Coloca y alimenta un taladro mecánico.", "advancement.create.press": "¡La prensa se pone en marcha!", "advancement.create.press.desc": "Activa una prensa mecánica y utilízala para crear algunas láminas.", "advancement.create.polished_rose_quartz": "Diamantes rosas", "advancement.create.polished_rose_quartz.desc": "Utiliza un trozo de papel de lija para pulir el cuarzo rosa hasta que se vuelva transparente.", "advancement.create.electron_tube": "Beep Boop", - "advancement.create.electron_tube.desc": "Haz algunos Tubos de Electrones, útiles en la fabricación de maquinaria menos primitiva.", + "advancement.create.electron_tube.desc": "Haz algunos tubos de electrones, útiles en la fabricación de maquinaria menos primitiva.", "advancement.create.mechanical_saw": "Picado estacionario", - "advancement.create.mechanical_saw.desc": "Colocar y alimentar una sierra mecánica.", + "advancement.create.mechanical_saw.desc": "Coloca y alimenta una sierra mecánica.", "advancement.create.basin": "Funcionamiento de la cuenca", - "advancement.create.basin.desc": "Coloca una Cuenca e intenta arrojar objetos en ella.", + "advancement.create.basin.desc": "Coloca una cuenca e intenta arrojar objetos en ella.", "advancement.create.mixer": "Mezcla de colores", - "advancement.create.mixer.desc": "Coloque una batidora mecánica sobre el lavabo, enciéndala y empiece a mezclar algunos ingredientes.", + "advancement.create.mixer.desc": "Coloca una batidora mecánica sobre el lavabo, enciéndala y empiece a mezclar algunos ingredientes.", "advancement.create.blaze_burner": "Una chimenea viva", - "advancement.create.blaze_burner.desc": "Obtener un Quemador de Blaze.", + "advancement.create.blaze_burner.desc": "Obtiene un quemador de blaze.", "advancement.create.compact": "Compactación automática", - "advancement.create.compact.desc": "Utiliza una prensa y una palangana para compactar algunos elementos.", + "advancement.create.compact.desc": "Utiliza una prensa y una cuenca para compactar algunos objetos.", "advancement.create.brass": "Aleaciones reales", - "advancement.create.brass.desc": "Utiliza Cobre molido y Zinc molido para crear algo de latón.", + "advancement.create.brass.desc": "Utiliza cobre molido y zinc molido para crear algo de latón.", "advancement.create.brass_casing": "La Edad de Latón", "advancement.create.brass_casing.desc": "Utiliza el latón recién obtenido y algo de madera para crear un revestimiento más avanzado.", "advancement.create.copper_casing": "La Edad de Cobre", "advancement.create.copper_casing.desc": "Utiliza algunas láminas de cobre y madera para crear algunos revestimientos de cobre.", "advancement.create.spout": "Sploosh", - "advancement.create.spout.desc": "Observar el llenado de un elemento fluido usando una boquilla.", + "advancement.create.spout.desc": "Observa el llenado de un fluido usando una boquilla.", "advancement.create.spout_potion": "Cervecera global", "advancement.create.spout_potion.desc": "Mira cómo un pico llena una botella con líquido de poción.", "advancement.create.chocolate": "Un mundo de imaginación", - "advancement.create.chocolate.desc": "Obtener un cubo de chocolate fundido.", + "advancement.create.chocolate.desc": "Obtiene un cubo con chocolate fundido.", "advancement.create.item_drain": "Drenaje de la ropa", - "advancement.create.item_drain.desc": "Ver cómo se vacía un elemento fluido mediante una drenadora de elementos.", - "advancement.create.chained_item_drain": "Déjalo rodar!", - "advancement.create.chained_item_drain.desc": "Observa cómo un objeto rueda por varios drenadores de elementos encadenados.", + "advancement.create.item_drain.desc": "Ve cómo se vacía un fluido mediante un drenador de objetos.", + "advancement.create.chained_item_drain": "¡Déjalo rodar!", + "advancement.create.chained_item_drain.desc": "Observa cómo un objeto rueda por varios drenadores de objetos encadenados.", "advancement.create.glass_pipe": "Espía del flujo", - "advancement.create.glass_pipe.desc": "Observe cómo se propaga el fluido a través de una tubería de fluidos con ventanas. Las tuberías de fluido rectas se convierten en ventanas cuando se utiliza una llave en ellas.", + "advancement.create.glass_pipe.desc": "Observa cómo se propaga el fluido a través de un tubo de fluidos con ventanas. Los tubos de fluido rectos se convierten en ventanas cuando se utiliza una llave inglesa en ellas.", "advancement.create.pipe_collision": "No cruzar nunca los arroyos", "advancement.create.pipe_collision.desc": "Vea cómo se unen dos fluidos en su red de tuberías.", "advancement.create.pipe_spill": "¡Hay una fuga!", "advancement.create.pipe_spill.desc": "Observe cómo un extremo abierto de una tubería toma o deposita fluidos en el mundo.", "advancement.create.hose_pulley": "Vertidos industriales", - "advancement.create.hose_pulley.desc": "Bajar una polea de manguera y ver cómo se vacía o se llena un cuerpo de líquido.", + "advancement.create.hose_pulley.desc": "Baja una polea de manguera y ve cómo se vacía o se llena un cuerpo de líquido.", "advancement.create.infinite_water": "Drenando el océano", "advancement.create.infinite_water.desc": "Bombea de una masa de agua lo suficientemente grande como para ser considerada infinita.", "advancement.create.infinite_lava": "Drenaje del núcleo de los planetas", @@ -598,55 +637,51 @@ "advancement.create.infinite_chocolate": "Ahogándose en la imaginación", "advancement.create.infinite_chocolate.desc": "Bombea desde una masa de chocolate fundido lo suficientemente grande como para ser considerado infinito.", "advancement.create.crafter": "Montaje automatizado", - "advancement.create.crafter.desc": "Coloca y alimenta algunos autoensambladores.", + "advancement.create.crafter.desc": "Coloca y alimenta algunos ensambladores.", "advancement.create.clockwork_bearing": "Artilugio a la hora", - "advancement.create.clockwork_bearing.desc": "Ensamblar una estructura montada sobre un rodamiento de relojería.", + "advancement.create.clockwork_bearing.desc": "Ensamblar una estructura montada sobre un rodamiento tipo reloj.", "advancement.create.nixie_tube": "Signos de estilo", - "advancement.create.nixie_tube.desc": "Obtener y colocar un par de Tubos Nixie.", + "advancement.create.nixie_tube.desc": "Obtener y colocar un par de tubos nixie.", "advancement.create.deployer": "Picar, colocar y atacar", - "advancement.create.deployer.desc": "Coloca y potencia un Desplegador, el reflejo perfecto de ti mismo.", + "advancement.create.deployer.desc": "Coloca y potencia un desplegador, el reflejo perfecto de ti mismo.", "advancement.create.speed_controller": "Los ingenieros lo odian!", - "advancement.create.speed_controller.desc": "Coloque un regulador de velocidad de rotación, el dispositivo definitivo para cambiar de marcha.", + "advancement.create.speed_controller.desc": "Coloca un controlador de velocidad rotacional, el dispositivo definitivo para cambiar de marcha.", "advancement.create.flywheel": "El corazón de la fábrica", - "advancement.create.flywheel.desc": "Conectar con éxito un motor a la rueda de inercia.", + "advancement.create.flywheel.desc": "Conecta con éxito un motor a la rueda de inercia.", "advancement.create.overstress_flywheel": "Altos niveles de estrés", - "advancement.create.overstress_flywheel.desc": "Sobrecargar un Motor de Horno.", - "advancement.create.integrated_circuit": "Cálculos complejos", - "advancement.create.integrated_circuit.desc": "Ensamblar un chip de circuito integrado.", - "advancement.create.mechanical_arm": "Manos ocupadas!", + "advancement.create.overstress_flywheel.desc": "Sobrecarga un motor de horno.", + "advancement.create.precision_mechanism": "Curiosidades complejas", + "advancement.create.precision_mechanism.desc": "Monta un mecanismo de precisión.", + "advancement.create.mechanical_arm": "¡Manos ocupadas!", "advancement.create.mechanical_arm.desc": "Crea un brazo mecánico, selecciona las entradas y salidas, colócalo en el suelo y dale energía; luego observa cómo hace todo el trabajo por ti.", - "advancement.create.musical_arm": "Tócame la melodía!", - "advancement.create.musical_arm.desc": "Vea cómo un brazo mecánico maneja su Jukebox.", + "advancement.create.musical_arm": "¡Tócame la melodía!", + "advancement.create.musical_arm.desc": "Vea cómo un brazo mecánico maneja su tocadiscos.", "advancement.create.arm_many_targets": "Organize-o-Tron", - "advancement.create.arm_many_targets.desc": "Programar un brazo mecánico con diez o más posiciones de salida.", + "advancement.create.arm_many_targets.desc": "Programa un brazo mecánico con diez o más posiciones de salida.", "advancement.create.arm_blaze_burner": "Combust-o-Tron", - "advancement.create.arm_blaze_burner.desc": "Instruya un brazo mecánico para alimentar su Quemador de Blaze.", + "advancement.create.arm_blaze_burner.desc": "Instruya un brazo mecánico para alimentar su quemador de blaze.", "advancement.create.fist_bump": "¡Pégale, hermano!", - "advancement.create.fist_bump.desc": "Hacer que dos Desplegadores se den un puñetazo.", + "advancement.create.fist_bump.desc": "Haz que dos desplegadores se den un puñetazo.", "advancement.create.crushing_wheel": "Un par de gigantes", - "advancement.create.crushing_wheel.desc": "Crea algunas Ruedas de trituración para descomponer más materiales de forma más eficaz.", + "advancement.create.crushing_wheel.desc": "Crea algunas ruedas de trituración para descomponer más materiales de forma más eficaz.", "advancement.create.blaze_cake": "Fiebre del azúcar", - "advancement.create.blaze_cake.desc": "Hornea en tu Quemador de Blaze un pastel especial.", - "advancement.create.chromatic_compound": "Minerales bipolares", - "advancement.create.chromatic_compound.desc": "Crea una Barra de Compuesto Cromático.", + "advancement.create.blaze_cake.desc": "Hornea en tu quemador de blaze un pastel especial.", + "advancement.create.chromatic_compound": "Minerales misteriosos", + "advancement.create.chromatic_compound.desc": "Crea una barra de compuesto cromático.", "advancement.create.shadow_steel": "Retorno del vacío", - "advancement.create.shadow_steel.desc": "Crea Acero Sombrío, una barra de metal de la nada.", + "advancement.create.shadow_steel.desc": "Crea acero sombrío, una barra de metal de la nada.", "advancement.create.refined_radiance": "Brillante e inspirador", - "advancement.create.refined_radiance.desc": "Crea un Resplandor refinado, una poderosa sustancia cromática.", + "advancement.create.refined_radiance.desc": "Crea un resplandor refinado, una poderosa sustancia cromática.", "advancement.create.chromatic_age": "La edad cromática", "advancement.create.chromatic_age.desc": "Crear bloques de revestimiento de la luz y la oscuridad.", - "advancement.create.zapper": "Construir con estilo", - "advancement.create.zapper.desc": "Construye un Blockzapper. Una pistola láser radiante que te ayuda a construir.", - "advancement.create.upgraded_zapper": "Radiante sobrecarga", - "advancement.create.upgraded_zapper.desc": "Crear y activar un Blockzapper totalmente mejorado.", "advancement.create.wand_of_symmetry": "Espejos radiantes", "advancement.create.wand_of_symmetry.desc": "Crear un bastón de simetría.", - "advancement.create.deforester": "Picado radiante", - "advancement.create.deforester.desc": "Crea un Deforestador y despídete del bosque local.", - "advancement.create.extendo_grip": "Boioioing!", - "advancement.create.extendo_grip.desc": "Hazte con un Agarre extentido.", + "advancement.create.extendo_grip": "¡Boioioing!", + "advancement.create.extendo_grip.desc": "Hazte con un agarre extentido.", + "advancement.create.potato_cannon": "Fwoomp!", + "advancement.create.potato_cannon.desc": "Derrota a un enemigo con tu cañón de patatas.", "advancement.create.dual_extendo_grip": "La última edad del boing", - "advancement.create.dual_extendo_grip.desc": "Doble Empuñadura extendida para un alcance sobrehumano.", + "advancement.create.dual_extendo_grip.desc": "Doble empuñadura extendida para un alcance sobrehumano.", "advancement.create.eob": "Fin de la beta", "advancement.create.eob.desc": "Espere más contenido aquí en el futuro. <3", @@ -656,16 +691,32 @@ "itemGroup.create.base": "Create", "itemGroup.create.palettes": "Paletas", - "death.attack.create.crush": "%1$s se procesó por las Ruedas de trituración", + "death.attack.create.crush": "%1$s se procesó en las ruedas de trituración", + "death.attack.create.crush.player": "%1$s fue arrojado a las ruedas de trituración por %2$s", "death.attack.create.fan_fire": "%1$s murió quemado por el aire caliente", + "death.attack.create.fan_fire.player": "%1$s fue arrojado a un ahumador por %2$s", "death.attack.create.fan_lava": "%1$s murió quemado por un abanico de lava", + "death.attack.create.fan_lava.player": "%1$s fue arrojado a una fundición por %2$s", "death.attack.create.mechanical_drill": "%1$s fue empalado por un taladro mecánico", + "death.attack.create.mechanical_drill.player": "%1$s fue lanzado frente a un taladro por %2$s", "death.attack.create.mechanical_saw": "%1$s fue cortado por la mitad por una sierra mecánica", - "death.attack.create.cuckoo_clock_explosion": "%1$s fue volado por los aires por un reloj cucú manipulado", + "death.attack.create.mechanical_saw.player": "%1$s fue arrojado a una sierra por %2$s", + "death.attack.create.potato_cannon": "%1$s fue disparado por el cañón de patatas de %2$s's", + "death.attack.create.potato_cannon.item": "%1$s fue disparado por %2$s utilizando %3$s", + "death.attack.create.cuckoo_clock_explosion": "%1$s fue volado por los aires por un reloj de cuco manipulado", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s fue volado por un reloj de cuco manipulado", - "create.block.deployer.damage_source_name": "un Desplegador rebelde", + "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": "Regresar al menú", + "create.menu.configure": "Configurar...", + "create.menu.ponder_index": "Índice", + "create.menu.only_ingame": "Disponible en el menú de pausa", + "create.menu.project_page": "Página del proyecto", + "create.menu.report_bugs": "Reportar problemas", + "create.menu.support": "Apóyenos", + "create.recipe.crushing": "Trituración", "create.recipe.milling": "Fresado", "create.recipe.fan_washing": "Lavado a granel", @@ -676,6 +727,7 @@ "create.recipe.fan_blasting.fan": "Ventilador detrás de la lava", "create.recipe.pressing": "Prensando", "create.recipe.mixing": "Mezclando", + "create.recipe.deploying": "Desplegando", "create.recipe.automatic_shapeless": "Elaboración automatizada de productos sin forma", "create.recipe.automatic_brewing": "Elaboración de cerveza automatizada", "create.recipe.packing": "Compactando", @@ -685,11 +737,20 @@ "create.recipe.automatic_shaped": "Elaboración automatizada de productos con forma", "create.recipe.block_cutting": "Corte de bloques", "create.recipe.wood_cutting": "Corte de maderas", - "create.recipe.blockzapper_upgrade": "Blockzapper", "create.recipe.sandpaper_polishing": "Pulido con papel de lija", "create.recipe.mystery_conversion": "Conversión misteriosa", "create.recipe.spout_filling": "Llenar por el pico", - "create.recipe.draining": "Drenador de elementos", + "create.recipe.draining": "Drenador de objetos", + "create.recipe.sequenced_assembly": "Montaje secuenciado", + "create.recipe.assembly.next": "Siguiente: %1$s", + "create.recipe.assembly.step": "Fase %1$s:", + "create.recipe.assembly.progress": "Progreso: %1$s/%2$s", + "create.recipe.assembly.pressing": "Proceso en prensa", + "create.recipe.assembly.spout_filling_fluid": "Pico %1$s", + "create.recipe.assembly.deploying_item": "Despliegue %1$s", + "create.recipe.assembly.cutting": "Corte con sierra", + "create.recipe.assembly.repeat": "Repetir la secuencia %1$s veces", + "create.recipe.assembly.junk": "Basura aleatoria", "create.recipe.processing.chance": "%1$s%% Chance", "create.recipe.heat_requirement.none": "No es necesario calentar", "create.recipe.heat_requirement.heated": "Calentado", @@ -706,7 +767,7 @@ "create.generic.unit.seconds": "Segundos", "create.generic.unit.minutes": "Minutos", "create.generic.unit.rpm": "RPM", - "create.generic.unit.stress": "su", + "create.generic.unit.stress": "SU(unidades de estrés)", "create.generic.unit.degrees": "°", "create.generic.unit.millibuckets": "%1$smB", "create.generic.clockwise": "En el sentido de las agujas del reloj", @@ -723,11 +784,11 @@ "create.keyinfo.scrolldown": "Simular usar la rueda del ratón hacia abajo (en el mundo)", "create.gui.scrollInput.defaultTitle": "Seleccione una opción:", - "create.gui.scrollInput.scrollToModify": "Usa la rueda del ratón para Modificar", + "create.gui.scrollInput.scrollToModify": "Usa la rueda del ratón para modificar", "create.gui.scrollInput.scrollToAdjustAmount": "Usa la rueda del ratón para ajustar la cantidad", - "create.gui.scrollInput.scrollToSelect": "Usa la rueda del ratón para Seleccionar", - "create.gui.scrollInput.shiftScrollsFaster": "Shift para usar la rueda del ratón más rápido", - "create.gui.toolmenu.focusKey": "Mantenga [%1$s] para enfocar", + "create.gui.scrollInput.scrollToSelect": "Usa la rueda del ratón para seleccionar", + "create.gui.scrollInput.shiftScrollsFaster": "Mayús izdo para usar la rueda del ratón más rápido", + "create.gui.toolmenu.focusKey": "Mantén [%1$s] para enfocar", "create.gui.toolmenu.cycle": "[RUEDA DEL RATÓN] para el ciclo", "create.gui.symmetryWand.mirrorType": "Espejado", "create.gui.symmetryWand.orientation": "Orientación", @@ -742,21 +803,17 @@ "create.orientation.alongZ": "A lo largo de Z", "create.orientation.alongX": "A lo largo de X", - "create.gui.blockzapper.title": "Blockzapper", - "create.gui.blockzapper.replaceMode": "Modo de sustitución", - "create.gui.blockzapper.searchDiagonal": "Seguir las diagonales", - "create.gui.blockzapper.searchFuzzy": "Ignorar los bordes del material", - "create.gui.blockzapper.range": "Alcance del margen de maniobra", - "create.gui.blockzapper.needsUpgradedAmplifier": "Requiere un amplificador mejorado", - "create.gui.blockzapper.patternSection": "Patrón", - "create.gui.blockzapper.pattern.solid": "Sólido", - "create.gui.blockzapper.pattern.checkered": "Tablero de ajedrez", - "create.gui.blockzapper.pattern.inversecheckered": "Tablero de ajedrez invertido", - "create.gui.blockzapper.pattern.chance25": "25% Roll", - "create.gui.blockzapper.pattern.chance50": "50% Roll", - "create.gui.blockzapper.pattern.chance75": "75% Roll", - "create.gui.terrainzapper.title": "Worldshaper", - "create.gui.terrainzapper.placement": "Colocación", + "create.gui.terrainzapper.title": "Blockzapper", + "create.gui.terrainzapper.searchDiagonal": "Seguir diagonales", + "create.gui.terrainzapper.searchFuzzy": "Ignorar los bordes del material", + "create.gui.terrainzapper.patternSection": "Patrón", + "create.gui.terrainzapper.pattern.solid": "Sólido", + "create.gui.terrainzapper.pattern.checkered": "Tablero de ajedrez", + "create.gui.terrainzapper.pattern.inversecheckered": "Tablero de ajedrez invertido", + "create.gui.terrainzapper.pattern.chance25": "25% Roll", + "create.gui.terrainzapper.pattern.chance50": "50% Roll", + "create.gui.terrainzapper.pattern.chance75": "75% Roll", + "create.gui.terrainzapper.placement": "Ubicación", "create.gui.terrainzapper.placement.merged": "Fusionado", "create.gui.terrainzapper.placement.attached": "Adjuntado", "create.gui.terrainzapper.placement.inserted": "Insertado", @@ -764,28 +821,19 @@ "create.gui.terrainzapper.brush.cuboid": "Cuboide", "create.gui.terrainzapper.brush.sphere": "Esfera", "create.gui.terrainzapper.brush.cylinder": "Cilindro", + "create.gui.terrainzapper.brush.surface": "Superficie", + "create.gui.terrainzapper.brush.cluster": "Grupo", "create.gui.terrainzapper.tool": "Herramienta", "create.gui.terrainzapper.tool.fill": "Llenar", - "create.gui.terrainzapper.tool.place": "Sitio", - "create.gui.terrainzapper.tool.replace": "Sustituir", - "create.gui.terrainzapper.tool.clear": "Borrar", - "create.gui.terrainzapper.tool.overlay": "Superposición", + "create.gui.terrainzapper.tool.place": "Ubicar", + "create.gui.terrainzapper.tool.replace": "Reemplazar", + "create.gui.terrainzapper.tool.clear": "Eliminar", + "create.gui.terrainzapper.tool.overlay": "Superponer", "create.gui.terrainzapper.tool.flatten": "Aplanar", - "create.terrainzapper.shiftRightClickToSet": "Shift+Clic con el botón derecho para seleccionar una forma", - - "create.blockzapper.usingBlock": "Utilizando: %1$s", - "create.blockzapper.componentUpgrades": "Mejoras de componentes:", - "create.blockzapper.component.body": "Cuerpo", - "create.blockzapper.component.amplifier": "Amplificador", - "create.blockzapper.component.accelerator": "Acelerador", - "create.blockzapper.component.retriever": "Recuperador", - "create.blockzapper.component.scope": "Mira telescópica", - "create.blockzapper.componentTier.none": "Ninguno", - "create.blockzapper.componentTier.brass": "Latón", - "create.blockzapper.componentTier.chromatic": "Cromático", - "create.blockzapper.leftClickToSet": "Clic izquierdo en un bloque para establecer el material", - "create.blockzapper.empty": "Sin bloques!", + "create.terrainzapper.shiftRightClickToSet": "Mayús izdo + clic derecho para seleccionar una forma", + "create.terrainzapper.usingBlock": "Usando: %1$s", + "create.terrainzapper.leftClickToSet": "Clic izquierdo a un bloque para establecer el material", "create.minecart_coupling.two_couplings_max": "Las vagonetas no pueden tener más de dos enganches cada una", "create.minecart_coupling.unloaded": "Algunas partes de su tren parecen estar en chunks no cargados", @@ -811,8 +859,8 @@ "create.contraptions.clockwork.hour_first_24": "La manecilla del día primero", "create.logistics.filter": "Filtro", - "create.logistics.recipe_filter": "Filtro de recetas", - "create.logistics.fluid_filter": "Filtro de fluidos", + "create.logistics.recipe_filter": "Filtro para recetas", + "create.logistics.fluid_filter": "Filtro para fluidos", "create.logistics.firstFrequency": "Freq. #1", "create.logistics.secondFrequency": "Freq. #2", "create.logistics.filter.apply": "Filtro aplicado a %1$s.", @@ -823,12 +871,14 @@ "create.gui.goggles.kinetic_stats": "Estadísticas cinéticas:", "create.gui.goggles.at_current_speed": "con la velocidad actual", "create.gui.goggles.pole_length": "Longitud del poste:", + "create.gui.goggles.fluid_container": "Información sobre el contenedor de fluidos:", + "create.gui.goggles.fluid_container.capacity": "Capacidad: ", "create.gui.assembly.exception": "Este artilugio no se pudo montar:", "create.gui.assembly.exception.unmovableBlock": "Bloque inamovible (%4$s) en [%1$s,%2$s,%3$s]", "create.gui.assembly.exception.chunkNotLoaded": "El bloque en [%1$s,%2$s,%3$s] no estaba en un chunk cargado", "create.gui.assembly.exception.structureTooLarge": "Hay demasiados bloques incluídos en el artilugio.\nEl máximo configurado es: %1$s", "create.gui.assembly.exception.tooManyPistonPoles": "Hay demasiadas Pértigas de extensión conectadas a este Pistón.\nEl máximo configurado es: %1$s", - "create.gui.assembly.exception.noPistonPoles": "Faltan pértigas de extensión para el Pistón", + "create.gui.assembly.exception.noPistonPoles": "Faltan pértigas de extensión para el pistón", "create.gui.assembly.exception.not_enough_sails": "La estructura adjunta no incluye suficientes bloques tipo vela: %1$s\nSe requiere un mínimo de %2$s", "create.gui.gauge.info_header": "Información sobre el medidor:", "create.gui.speedometer.title": "Velocidad de rotación", @@ -837,7 +887,7 @@ "create.gui.stressometer.overstressed": "Sobrecargado", "create.gui.stressometer.no_rotation": "Sin rotación", "create.gui.contraptions.not_fast_enough": "Parece que este %1$s no está girando con _suficiente_ velocidad_.", - "create.gui.contraptions.network_overstressed": "Parece que este artilugio está _sobrecargado_. Añade más fuentes o _desacelera_ los componentes con un _impacto_ de alto estrés.", + "create.gui.contraptions.network_overstressed": "Parece que este artilugio está _sobrecargado_. Añade más fuentes o _desacelera_ los componentes con un _impacto de estrés alto_.", "create.gui.adjustable_crate.title": "Caja ajustable", "create.gui.adjustable_crate.storageSpace": "Espacio de almacenamiento", "create.gui.stockpile_switch.title": "Interruptor de acopio", @@ -857,7 +907,7 @@ "create.gui.sequenced_gearshift.instruction.delay.duration": "Duración", "create.gui.sequenced_gearshift.instruction.end.descriptive": "Fin", "create.gui.sequenced_gearshift.instruction.end": "Fin", - "create.gui.sequenced_gearshift.instruction.await.descriptive": "En espera de un Pulso de Redstone", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "En espera de un pulso de redstone", "create.gui.sequenced_gearshift.instruction.await": "En espera", "create.gui.sequenced_gearshift.speed": "Velocidad, Dirección", "create.gui.sequenced_gearshift.speed.forward": "Velocidad de entrada, hacia adelante", @@ -868,7 +918,7 @@ "create.schematicAndQuill.dimensions": "Tamaño del esquema: %1$sx%2$sx%3$s", "create.schematicAndQuill.firstPos": "Primera posición fijada.", "create.schematicAndQuill.secondPos": "Segunda posición fijada.", - "create.schematicAndQuill.noTarget": "Mantenga [Ctrl] para seleccionar los bloques del aire.", + "create.schematicAndQuill.noTarget": "Mantén [Ctrl] para seleccionar los bloques del aire.", "create.schematicAndQuill.abort": "Selección eliminada.", "create.schematicAndQuill.title": "Nombre del esquema:", "create.schematicAndQuill.convert": "Guardar y desplegar inmediatamente", @@ -884,7 +934,7 @@ "create.schematic.rotation.cw270": "En el sentido de las agujas del reloj 270", "create.schematic.mirror": "Espejado", "create.schematic.mirror.none": "Ninguno", - "create.schematic.mirror.frontBack": "Delante-detrás", + "create.schematic.mirror.frontBack": "Delante-Detrás", "create.schematic.mirror.leftRight": "Izquierda-Derecha", "create.schematic.tool.deploy": "Despliegue", "create.schematic.tool.move": "Mover XZ", @@ -893,27 +943,27 @@ "create.schematic.tool.print": "Imprimir", "create.schematic.tool.flip": "Voltear", "create.schematic.tool.deploy.description.0": "Mueve la estructura a un lugar.", - "create.schematic.tool.deploy.description.1": "Haga clic con el botón derecho del ratón en el suelo para colocar.", - "create.schematic.tool.deploy.description.2": "Mantenga [Ctrl] para seleccionar a una distancia fija.", - "create.schematic.tool.deploy.description.3": "[Ctrl]-Rueda del ratón para cambiar la distancia.", + "create.schematic.tool.deploy.description.1": "Haz clic con el botón derecho del ratón en el suelo para colocarla.", + "create.schematic.tool.deploy.description.2": "Mantén [Ctrl] para seleccionar a una distancia fija.", + "create.schematic.tool.deploy.description.3": "[Ctrl] + [RUEDA DEL RATÓN] para cambiar la distancia.", "create.schematic.tool.move.description.0": "Desplaza el esquema horizontalmente.", - "create.schematic.tool.move.description.1": "Apunta al Esquema y [CTRL]-Rueda del ratón para ponerlo.", + "create.schematic.tool.move.description.1": "Apunta al esquema y [Ctrl] + [RUEDA DEL RATÓN] para ponerlo.", "create.schematic.tool.move.description.2": "", "create.schematic.tool.move.description.3": "", "create.schematic.tool.movey.description.0": "Desplaza el esquema verticalmente..", - "create.schematic.tool.movey.description.1": "[CTRL]-Rueda del ratón para moverlo hacia arriba/abajo.", + "create.schematic.tool.movey.description.1": "[Ctrl] + [RUEDA DEL RATÓN] para moverlo hacia arriba/abajo.", "create.schematic.tool.movey.description.2": "", "create.schematic.tool.movey.description.3": "", "create.schematic.tool.rotate.description.0": "Gira el esquema alrededor de su centro.", - "create.schematic.tool.rotate.description.1": "[CTRL]-Rueda del ratón para girar 90 grados.", + "create.schematic.tool.rotate.description.1": "[Ctrl] + [RUEDA DEL RATÓN] para girar 90 grados.", "create.schematic.tool.rotate.description.2": "", "create.schematic.tool.rotate.description.3": "", "create.schematic.tool.print.description.0": "Sitúa instantáneamente la estructura en el mundo.", "create.schematic.tool.print.description.1": "[Clic derecho] para confirmar la colocación en el lugar actual.", "create.schematic.tool.print.description.2": "Esta herramienta es sólo para el Modo Creativo.", "create.schematic.tool.print.description.3": "", - "create.schematic.tool.flip.description.0": "Voltea el Esquema a lo largo de la cara que seleccione.", - "create.schematic.tool.flip.description.1": "Apunta al esquema y [CTRL]-Rueda del ratón para voltearlo.", + "create.schematic.tool.flip.description.0": "Voltea el esquema a lo largo de la cara que seleccione.", + "create.schematic.tool.flip.description.1": "Apunta al esquema y [Ctrl] + [RUEDA DEL RATÓN] para voltearlo.", "create.schematic.tool.flip.description.2": "", "create.schematic.tool.flip.description.3": "", @@ -927,8 +977,8 @@ "create.gui.schematicTable.availableSchematics": "Esquemas disponibles", "create.gui.schematicTable.noSchematics": "No hay esquemas guardados", "create.gui.schematicTable.uploading": "Subiendo...", - "create.gui.schematicTable.finished": "Subida finalizada!", - "create.gui.schematicannon.title": "Schematicannon", + "create.gui.schematicTable.finished": "¡Subida finalizada!", + "create.gui.schematicannon.title": "Cañón de esquemas", "create.gui.schematicannon.listPrinter": "Lista de control de la impresora", "create.gui.schematicannon.gunpowderLevel": "Pólvora %1$s%%", "create.gui.schematicannon.shotsRemaining": "Disparos restantes: %1$s", @@ -946,16 +996,16 @@ "create.gui.schematicannon.slot.listPrinter": "Coloque los libros aquí para imprimir una lista de comprobación para su esquema", "create.gui.schematicannon.slot.schematic": "Añada su esquema aquí. Asegúrese de que se despliega en un lugar específico.", "create.gui.schematicannon.option.skipMissing.description": "Si el cañón no encuentra un bloque necesario para su colocación, continuará en la siguiente ubicación.", - "create.gui.schematicannon.option.skipTileEntities.description": "El cañón evitará reemplazar los bloques que contienen datos, como los Cofres.", + "create.gui.schematicannon.option.skipTileEntities.description": "El cañón evitará reemplazar los bloques que contienen datos, como los cofres.", "create.gui.schematicannon.option.dontReplaceSolid.description": "El cañón nunca sustituirá ningún bloque sólido en su zona de trabajo, sólo los no sólidos y el aire.", "create.gui.schematicannon.option.replaceWithSolid.description": "El cañón sólo reemplazará los bloques sólidos en su área de trabajo si el esquema contiene un bloque sólido en la ubicación.", "create.gui.schematicannon.option.replaceWithAny.description": "El cañón reemplazará los bloques sólidos en su área de trabajo si el esquema contiene algún bloque en la ubicación.", - "create.gui.schematicannon.option.replaceWithEmpty.description": "El cañón eliminará todos los bloques de su zona de trabajo, incluidos los sustituidos por Aire.", + "create.gui.schematicannon.option.replaceWithEmpty.description": "El cañón eliminará todos los bloques de su zona de trabajo, incluidos los sustituidos por aire.", "create.schematicannon.status.idle": "Inactivo", "create.schematicannon.status.ready": "Listo", "create.schematicannon.status.running": "Funcionando", - "create.schematicannon.status.finished": "Finished", + "create.schematicannon.status.finished": "Finalizado", "create.schematicannon.status.paused": "Pausado", "create.schematicannon.status.stopped": "Detenido", "create.schematicannon.status.noGunpowder": "Sin pólvora", @@ -974,9 +1024,9 @@ "create.materialChecklist.blocksNotLoaded": "* Descargo de Responsabilidad *\n\nLa lista de materiales puede ser inexacta debido a que no se han cargado los chunks pertinentes.", "create.gui.filter.deny_list": "Lista de denegados", - "create.gui.filter.deny_list.description": "Los elementos pasan si NO coinciden con ninguno de los anteriores. Una lista de denegación vacía acepta todo.", + "create.gui.filter.deny_list.description": "Los objetos pasan si NO coinciden con ninguno de los anteriores. Una lista de denegación vacía acepta todo.", "create.gui.filter.allow_list": "Lista de permitidos", - "create.gui.filter.allow_list.description": "Los elementos pasan si coinciden con alguno de los anteriores. Una lista de permitidos vacía rechaza todo.", + "create.gui.filter.allow_list.description": "Los objetos pasan si coinciden con alguno de los anteriores. Una lista de permitidos vacía rechaza todo.", "create.gui.filter.respect_data": "Respetar datos", "create.gui.filter.respect_data.description": "Los objetos sólo coinciden si su durabilidad, encantos y otros atributos también coinciden.", "create.gui.filter.ignore_data": "Ignorar datos", @@ -1014,8 +1064,17 @@ "create.item_attributes.in_item_group.inverted": "no está en el grupo '%1$s'", "create.item_attributes.added_by": "fue añadido por %1$s", "create.item_attributes.added_by.inverted": "no fue añadida por %1$s", + "create.item_attributes.shulker_level": "es shulker %1$s", + "create.item_attributes.shulker_level.inverted": "no es shulker %1$s", + "create.item_attributes.shulker_level.full": "lleno", + "create.item_attributes.shulker_level.empty": "vacío", + "create.item_attributes.shulker_level.partial": "parcialmente lleno", "create.item_attributes.has_enchant": "está encantado con %1$s", "create.item_attributes.has_enchant.inverted": "no está encantado con %1$s", + "create.item_attributes.color": "Está teñido %1$s", + "create.item_attributes.color.inverted": "No está teñido %1$s", + "create.item_attributes.max_enchanted": "está encantado en el nivel máximo", + "create.item_attributes.max_enchanted.inverted": "no está encantado en el nivel máximo", "create.item_attributes.has_fluid": "contiene %1$s", "create.item_attributes.has_fluid.inverted": "no contiene %1$s", "create.item_attributes.has_name": "tiene el nombre personalizado %1$s", @@ -1044,16 +1103,16 @@ "create.gui.attribute_filter.add_attribute": "Añadir atributo a la lista", "create.gui.attribute_filter.add_inverted_attribute": "Añadir atributo invertido a la Lista", "create.gui.attribute_filter.allow_list_disjunctive": "Lista de permitidos (Cualquiera)", - "create.gui.attribute_filter.allow_list_disjunctive.description": "Los elementos pasan si tienen alguno de los atributos seleccionados", + "create.gui.attribute_filter.allow_list_disjunctive.description": "Los objetos pasan si tienen alguno de los atributos seleccionados", "create.gui.attribute_filter.allow_list_conjunctive": "Lista de permitidos (Todos)", - "create.gui.attribute_filter.allow_list_conjunctive.description": "Los elementos pasan sólo si tienen TODOS los atributos seleccionados", + "create.gui.attribute_filter.allow_list_conjunctive.description": "Los objetos pasan sólo si tienen TODOS los atributos seleccionados", "create.gui.attribute_filter.deny_list": "Lista de denegados", - "create.gui.attribute_filter.deny_list.description": "Los elementos pasan si NO tienen ninguno de los atributos seleccionados", + "create.gui.attribute_filter.deny_list.description": "Los objetos pasan si NO tienen ninguno de los atributos seleccionados", "create.gui.attribute_filter.add_reference_item": "Añadir elemento de referencia", - "create.tooltip.holdKey": "Mantener [%1$s]", - "create.tooltip.holdKeyOrKey": "Mantener [%1$s] o [%2$s]", - "create.tooltip.keyShift": "Shift", + "create.tooltip.holdForDescription": "Mantén [%1$s] para mas información", + "create.tooltip.holdForControls": "Mantén [%1$s] para ver los controles", + "create.tooltip.keyShift": "Mayús izdo.", "create.tooltip.keyCtrl": "Ctrl", "create.tooltip.speedRequirement": "Requisitos de velocidad: %1$s", "create.tooltip.speedRequirement.none": "Ninguno", @@ -1068,20 +1127,25 @@ "create.tooltip.capacityProvided.low": "Pequeña", "create.tooltip.capacityProvided.medium": "Media", "create.tooltip.capacityProvided.high": "Grande", - "create.tooltip.capacityProvided.asGenerator": "(Como generador)", - "create.tooltip.generationSpeed": "Genera en %1$s %2$s", + "create.tooltip.generationSpeed": "Generada en %1$s %2$s", "create.tooltip.analogStrength": "Fuerza analógica: %1$s/15", - "create.mechanical_arm.extract_from": "Extraer elementos de %1$s", - "create.mechanical_arm.deposit_to": "Depositar elementos en %1$s", + "create.mechanical_arm.extract_from": "Extraer objetos de %1$s", + "create.mechanical_arm.deposit_to": "Depositar objetos en %1$s", "create.mechanical_arm.summary": "El brazo mecánico tiene %1$s entrada(s) y %2$s salida(s)", "create.mechanical_arm.points_outside_range": "%1$s punto(s) de interacción seleccionado(s) eliminado(s) debido a las limitaciones de rango", + "create.weighted_ejector.target_set": "Objetivo seleccionado", + "create.weighted_ejector.target_not_valid": "Expulsión al bloque adyacente (el objetivo no era válido)", + "create.weighted_ejector.no_target": "Expulsión al bloque adyacente (no se ha seleccionado ningún objetivo)", + "create.weighted_ejector.targeting": "Expulsión a [%1$s,%2$s,%3$s]", + "create.weighted_ejector.stack_size": "Tamaño de la pila expulsada", + "create.logistics.when_multiple_outputs_available": "Cuando hay múltiples salidas disponibles", "create.mechanical_arm.selection_mode.round_robin": "Round Robin", "create.mechanical_arm.selection_mode.forced_round_robin": "Round Robin forzado", - "create.mechanical_arm.selection_mode.prefer_first": "Preferir el primer objetivo", + "create.mechanical_arm.selection_mode.prefer_first": "Preferir el primero", "create.tunnel.selection_mode.split": "División", "create.tunnel.selection_mode.forced_split": "División forzada", @@ -1092,27 +1156,44 @@ "create.tunnel.selection_mode.synchronize": "Sincronizar entradas", "create.tooltip.chute.header": "Información del ducto", - "create.tooltip.chute.items_move_down": "Los elementos se mueven hacia abajo", - "create.tooltip.chute.items_move_up": "Los elementos se mueven hacia arriba", + "create.tooltip.chute.items_move_down": "Los objetos se mueven hacia abajo", + "create.tooltip.chute.items_move_up": "Los objetos se mueven hacia arriba", "create.tooltip.chute.no_fans_attached": "No hay ventiladores adjuntos", "create.tooltip.chute.fans_push_up": "Los ventiladores empujan desde abajo", "create.tooltip.chute.fans_push_down": "Los ventiladores empujan desde arriba", "create.tooltip.chute.fans_pull_up": "Los ventiladores tiran desde arriba", "create.tooltip.chute.fans_pull_down": "Los ventiladores tiran desde abajo", "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "Actualmente distribuye:", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "Haga clic derecho para recuperar", - "create.hint.hose_pulley.title": "Suministro sin fondo", - "create.hint.hose_pulley": "La masa de fluido objetivo se considera infinita", - "create.hint.mechanical_arm_no_targets.title": "No hay objetivos", - "create.hint.mechanical_arm_no_targets": "Parece que a este _brazo mecánico_ no se le ha asignado ningún _objetivo._ Selecciona correas, depósitos, embudos y otros bloques haciendo _clic derecho_ sobre ellos mientras _sostienes_ el _brazo mecánico_ en tu _mano_.", - "create.hint.horizontal_funnel.title": "Embudos horizontales", - "create.hint.horizontal_funnel": "No puede transferir entre inventarios _directamente_. Intenta pasar una _correa_ o un _depósito_ por debajo de tu embudo para extraer artículos de los inventarios", - "create.hint.upward_funnel.title": "Embudos hacia arriba", - "create.hint.upward_funnel": "sólo pueden transferir objetos insertados por _brazos_, y _ductos_ impulsados por ventilador, o elementos _lanzados_ hacia ellos. Intenta construir algunos _ductos_ si quieres mover tus objetos _verticalmente_", - "create.hint.empty_bearing.title": "Rodamiento de reloj", - "create.hint.empty_bearing": "_Haz clic con el botón derecho del ratón_ en el rodamiento con la _mano vacía_ para _adherir_ la estructura que acabas de construir delante de él", - "create.hint.full_deployer.title": "Desbordamiento de elementos del desplegador", - "create.hint.full_deployer": "Parece que este _Desplegador_ contiene _elementos_ en exceso que necesitan ser _extraídos._ Usa un _tolva,_embudo_ u otro medio para liberarlo de su desbordamiento.", + "create.linked_controller.bind_mode": "Modo de enlace activo", + "create.linked_controller.press_keybind": "Presiona %1$s, %2$s, %3$s, %4$s, %5$s o %6$s, para vincular esta frecuencia a la tecla correspondiente", + "create.linked_controller.key_bound": "Frecuencia ligada a %1$s", + "create.linked_controller.frequency_slot_1": "Enlace de teclas: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "Enlace de teclas: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "Ranura para ingredientes", + "create.crafting_blueprint.filter_items_viable": "Los objetos del filtro avanzado son viables", + "create.crafting_blueprint.display_slot": "Ranura de pantalla", + "create.crafting_blueprint.inferred": "A partir de la receta", + "create.crafting_blueprint.manually_assigned": "Asignado manualmente", + "create.crafting_blueprint.secondary_display_slot": "Ranura de pantalla secundaria", + "create.crafting_blueprint.optional": "Opcional", + + "create.potato_cannon.ammo.attack_damage": "%1$s Daño de ataque", + "create.potato_cannon.ammo.reload_ticks": "%1$s Recarga por Ticks", + "create.potato_cannon.ammo.knockback": "%1$s Golpe de efecto", + + "create.hint.hose_pulley.title": "Suministro ilimitado", + "create.hint.hose_pulley": "La masa de fluido objetivo se considera infinita.", + "create.hint.mechanical_arm_no_targets.title": "Sin objetivos", + "create.hint.mechanical_arm_no_targets": "Parece que a este _brazo mecánico_ no se le ha asignado ningún objetivo. Selecciona _correas_, _depósitos_, _embudos_ y otros bloques haciendo clic derecho sobre ellos mientras _sostienes_ el _brazo mecánico_ en tu mano..", + "create.hint.empty_bearing.title": "Actualización del rodamiento", + "create.hint.empty_bearing": "Haz clic derecho sobre el rodamiento con la _mano vacía_ para _adjuntar_ la estructura que acabas de construir delante de él.", + "create.hint.full_deployer.title": "Exceso de objetos en el desplegador", + "create.hint.full_deployer": "Parece que este _desplegador_ contiene _exceso_ de objetos que necesitan ser _extraídos._ Usa una _tolva_, _embudo_ u otro medio para liberarlo de su excedente.", "create.gui.config.overlay1": "Hola :)", "create.gui.config.overlay2": "Esta es una muestra de la superposición", @@ -1127,20 +1208,51 @@ "create.command.killTPSCommand.status.slowed_by.0": "[Crear]: El tick del servidor está actualmente ralentizado en %s ms :o", "create.command.killTPSCommand.status.slowed_by.1": "[Crear]: El tick del servidor está ralentizado en %s ms ahora >:)", "create.command.killTPSCommand.status.slowed_by.2": "[Create]: El tick del servidor ha vuelto a su velocidad normal :D", - "create.command.killTPSCommand.status.usage.0": "[Create]: usar /killtps stop para que el servidor vuelva a la velocidad normal", - "create.command.killTPSCommand.status.usage.1": "[Create]: usar /killtps start para ralentizar artificialmente el tick del servidor", + "create.command.killTPSCommand.status.usage.0": "[Create]: usa /killtps stop para que el servidor vuelva a la velocidad normal", + "create.command.killTPSCommand.status.usage.1": "[Create]: usa /killtps start para ralentizar artificialmente el tick del servidor", "create.command.killTPSCommand.argument.tickTime": "tickTime", - "create.subtitle.schematicannon_launch_block": "Disparos de Schematicannon", - "create.subtitle.schematicannon_finish": "Acabados de Schematicannon", - "create.subtitle.slime_added": "Slime aplastado", - "create.subtitle.mechanical_press_activation": "La Prensa Mecánica se activa", - "create.subtitle.mechanical_press_item_break": "Clanks de metal", - "create.subtitle.blockzapper_place": "Los bloques se colocan en su sitio", - "create.subtitle.blockzapper_confirm": "Ding afirmativo", - "create.subtitle.blockzapper_deny": "Boop declinante", - "create.subtitle.block_funnel_eat": "CHOMPS del embudo", - "create.subtitle.blaze_munch": "Blaze mastica felizmente", + "create.contraption.minecart_contraption_too_big": "Este artilugio de vagoneta parece demasiado grande para recogerlo", + "create.contraption.minecart_contraption_illegal_pickup": "Una fuerza mística está atando este artilugio de vagoneta al mundo", + + + "_": "->------------------------] Subtitles [------------------------<-", + + "create.subtitle.contraption_disassemble": "", + "create.subtitle.peculiar_bell_use": "", + "create.subtitle.mixing": "", + "create.subtitle.mechanical_press_activation_belt": "", + "create.subtitle.fwoomp": "", + "create.subtitle.worldshaper_place": "", + "create.subtitle.crushing_1": "", + "create.subtitle.depot_slide": "", + "create.subtitle.saw_activate_stone": "", + "create.subtitle.blaze_munch": "", + "create.subtitle.funnel_flap": "", + "create.subtitle.schematicannon_finish": "", + "create.subtitle.haunted_bell_use": "", + "create.subtitle.scroll_value": "", + "create.subtitle.crafter_craft": "", + "create.subtitle.controller_put": "", + "create.subtitle.cranking": "", + "create.subtitle.wrench_remove": "", + "create.subtitle.cogs": "", + "create.subtitle.slime_added": "", + "create.subtitle.wrench_rotate": "", + "create.subtitle.potato_hit": "", + "create.subtitle.saw_activate_wood": "", + "create.subtitle.haunted_bell_convert": "", + "create.subtitle.deployer_polish": "", + "create.subtitle.deny": "", + "create.subtitle.controller_click": "", + "create.subtitle.schematicannon_launch_block": "", + "create.subtitle.copper_armor_equip": "", + "create.subtitle.controller_take": "Lectern empties", + "create.subtitle.mechanical_press_activation": "", + "create.subtitle.contraption_assemble": "", + "create.subtitle.crafter_click": "", + "create.subtitle.depot_plop": "", + "create.subtitle.confirm": "", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1151,654 +1263,1042 @@ "item.create.example_item.tooltip.behaviour1": "Entonces este elemento hace esto. (los comportamientos se muestran en el turno)", "item.create.example_item.tooltip.condition2": "Y cuando esto", "item.create.example_item.tooltip.behaviour2": "Puedes añadir tantos comportamientos como quieras", - "item.create.example_item.tooltip.control1": "Cuando se pulsa Ctrl", + "item.create.example_item.tooltip.control1": "Cuando se pulsa [Ctrl]", "item.create.example_item.tooltip.action1": "Se muestran estos controles", - "block.create.andesite_encased_shaft.tooltip": "EJE REVESTIDO DE ANDESITA", - "block.create.andesite_encased_shaft.tooltip.summary": "Elemento _sólo para el modo creativo_. Reviste los _ejes_ en el mundo usando _revestimiento de andesita_. Los bloques de revestimiento _no se consumirán_.", - - "block.create.brass_encased_shaft.tooltip": "EJE REVESTIDO DE LATÓN", - "block.create.brass_encased_shaft.tooltip.summary": "Elemento _sólo para el modo creativo_. Reviste los _ejes_ en el mundo usando _revestimiento de latón_. Los bloques de revestimiento _no se consumirán_.", - "block.create.wooden_bracket.tooltip": "SOPORTE DE MADERA PARA EJES", - "block.create.wooden_bracket.tooltip.summary": "Decora tus _Ejes_, _Ruedas dentadas_ y _Ductos_ con un refuerzo acogedor y de madera.", + "block.create.wooden_bracket.tooltip.summary": "Decora tus _ejes_, _engranajes_ y _ductos_ con un acogedor refuerzo de madera.", "block.create.metal_bracket.tooltip": "SOPORTE DE METAL PARA EJES", - "block.create.metal_bracket.tooltip.summary": "Decora tus _Ejes_, _Ruedas dentadas_ y _Ductos_ con un poco de refuerzo industrial robusto.", - - "block.create.andesite_casing.tooltip": "REVESTIDOR DE ANDESITA", - "block.create.andesite_casing.tooltip.summary": "Máquina de revestimiento simple con una variedad de usos. Seguro para la decoración. Puede utilizarse para _revestir ejes_ y _cintas._", - - "block.create.andesite_funnel.tooltip": "EMBUDO DE ANDESITA", - "block.create.andesite_funnel.tooltip.summary": "Un componente de transferencia de elementos en general, que hace la transición de éstos entre los medios de transporte. Se puede controlar con una _señal de Redstone_.", - "block.create.andesite_funnel.tooltip.condition1": "Comportamiento general", - "block.create.andesite_funnel.tooltip.behaviour1": "La cara _abierta_ _recogerá los objetos molidos_ en el espacio del bloque que tiene delante y los _insertará_ en cualquier contenedor del lado opuesto del embudo", - "block.create.andesite_funnel.tooltip.condition2": "Cuando se montan en cintas, depósitos y similares", - "block.create.andesite_funnel.tooltip.behaviour2": "_Recoge_ o _Coloca_ los elementos en el componente montado, desde o hacia el inventario _detrás_ de sí mismo. Siempre que el embudo tenga una direccionalidad específica, puede invertirse utilizando una Llave.", - "block.create.andesite_funnel.tooltip.condition3": "Cuando se encuentra verticalmente entre dos inventarios", - "block.create.andesite_funnel.tooltip.behaviour3": "Transferirá los artículos hacia abajo, como una tolva sin búfer.", - - "block.create.andesite_tunnel.tooltip": "TÚNEL DE ANDESITA", - "block.create.andesite_tunnel.tooltip.summary": "¡Una cubierta protectora para sus _cintas_!. El _Túnel de Andesita_ puede separar un elemento de una pila cuando se coloca otra cinta o depósito al lado de la cinta principal.", - "block.create.andesite_tunnel.tooltip.control1": "Click derecho con la Llave Inglesa en el lateral", - "block.create.andesite_tunnel.tooltip.action1": "_Ajusta las persianas de las ventanas_ si el túnel tiene una ventana en esa cara.", - - "block.create.brass_funnel.tooltip": "EMBUDO DE LATÓN", - "block.create.brass_funnel.tooltip.summary": "Un componente de transferencia de elementos en general, que hace la transición de éstos entre los medios de transporte. Se puede controlar con una _señal de Redstone_. Viene con un práctico _filtro_.", - "block.create.brass_funnel.tooltip.condition1": "Comportamiento General", - "block.create.brass_funnel.tooltip.behaviour1": "La cara _abierta_ _recogerá los objetos molidos_ en el espacio del bloque que tiene delante y los _insertará_ en cualquier contenedor del lado opuesto del embudo.", - "block.create.brass_funnel.tooltip.condition2": "Cuando se montan en cintas, depósitos y similares", - "block.create.brass_funnel.tooltip.behaviour2": "_Recoge_ o _Coloca_ los elementos en el componente montado, desde o hacia el inventario _detrás_ de sí mismo. Siempre que el embudo tenga una direccionalidad específica, puede invertirse utilizando una Llave Inglesa.", - "block.create.brass_funnel.tooltip.condition3": "Cuando se encuentra verticalmente entre dos inventarios", - "block.create.brass_funnel.tooltip.behaviour3": "Transfiere los artículos hacia abajo, como una tolva sin búfer.", - - "block.create.brass_tunnel.tooltip": "TÚNEL DE LATÓN", - "block.create.brass_tunnel.tooltip.summary": "Una cubierta protectora elegante para sus _cintas_. Los _Túneles de latón_ también vienen con una serie de opciones de _Filtración_ y _División_ para sus artículos.", - "block.create.brass_tunnel.tooltip.condition1": "Cuando se colocan uno al lado del otro", - "block.create.brass_tunnel.tooltip.behaviour1": "Los túneles de latón se conectan entre sí y permiten redirigir el contenido de una cinta a otra.", - "block.create.brass_tunnel.tooltip.condition2": "Filtrado", - "block.create.brass_tunnel.tooltip.behaviour2": "Los _Túneles de latón_ vienen con filtros tanto para la _Entrada_ como para la _Salida_. Si un _Elemento_ no está permitido desde la salida filtrada de un _Túnel_ será transferido a la salida de un _Túnel_ conectado.", - "block.create.brass_tunnel.tooltip.condition3": "Dividiendo", - "block.create.brass_tunnel.tooltip.behaviour3": "Los _Túneles de latón_ pueden ser configurados para cambiar el método en el que los _Elementos_ son ordenados en los _Túneles_ conectados.", - "block.create.brass_tunnel.tooltip.control1": "Cuando haces click derecho con una Llave Inglesa", - "block.create.brass_tunnel.tooltip.action1": "_Ajusta las persianas de las ventanas_ si el túnel tiene una ventana en esa cara.", - "block.create.brass_tunnel.tooltip.control2": "Usa la rueda del ratón con la Llave Inglesa en la parte superior", - "block.create.brass_tunnel.tooltip.action2": "Cambiar el método de división de los _Túneles_ conectados.", - - "block.create.copper_casing.tooltip": "REVESTIDOR DE COBRE", - "block.create.copper_casing.tooltip.summary": "Robusta máquina de revestimientos con una gran variedad de usos. Seguro para la decoración.", - "block.create.copper_casing.tooltip.condition1": "Cuando se utiliza en una tubería de fluidos", - "block.create.copper_casing.tooltip.behaviour1": "_Reviste_ la _Tubería de fluidos_ con _Revestimiento de cobre_. Las tuberías de fluidos revestidas _bloquean sus conexiones_ en su lugar, dejando de reaccionar a los cambios en las tuberías vecinas.", - - "block.create.encased_fluid_pipe.tooltip": "TUBO DE FLUIDOS REFORZADO", - "block.create.encased_fluid_pipe.tooltip.summary": "Un tubo de fluidos reforzado con más cobre.", - - "block.create.copper_valve_handle.tooltip": "ASA DE VÁLVULA DE COBRE", - "block.create.copper_valve_handle.tooltip.summary": "Una precisa _fuente_ de _fuerza de rotación_ que requiere la interacción de los jugadores. ¡Ten cuidado de no agotarte!", - "block.create.copper_valve_handle.tooltip.condition1": "Cuando se utiliza", - "block.create.copper_valve_handle.tooltip.behaviour1": "Proporciona _Fuerza de rotación_ a un artilugio acoplado. _Shift_ para _invertir_ la rotación.", + "block.create.metal_bracket.tooltip.summary": "Decora tus _ejes_, _engranajes_ y _ductos_ con un poco de robusto refuerzo industrial.", "block.create.seat.tooltip": "ASIENTO", - "block.create.seat.tooltip.summary": "¡Siéntate y disfruta del viaje! Anclará a un jugador en un _contrafuerte_ en movimiento. También es ideal para los muebles estáticos. Viene en una variedad de colores.", - "block.create.seat.tooltip.condition1": "Click derecho en el asiento", - "block.create.seat.tooltip.behaviour1": "Sienta al jugador en el _Asiento_. Pulsa shift izquierdo para dejar el _Asiento_.", - - "block.create.chute.tooltip": "DUCTO", - "block.create.chute.tooltip.summary": "_Recoge_ y _Transporta_ elementos en vertical o en diagonal. Puede tanto coger como colocar objetos en _contenedores de objetos_. También puede interactuar con los ductos desde el lateral utilizando _tolvas_ o _embudos montados_.", - "block.create.chute.tooltip.condition1": "Cuando se alimenta con un ventilador", - "block.create.chute.tooltip.behaviour1": "Los ductos accionados por ventilador pueden transportar _elementos_ hacia arriba, y aspirar _elementos_ de los _depósitos_ y de las _cintas_.", - - "block.create.depot.tooltip": "DEPÓSITO", - "block.create.depot.tooltip.summary": "Un lugar práctico para colocar sus _elementos_. Proporciona un punto de interacción para varias máquinas", - "block.create.depot.tooltip.condition1": "Click derecho en el depósito", - "block.create.depot.tooltip.behaviour1": "Coloca o toma un _Elemento_ del _Depósito_. Los _Bloques_ y los _Artilugios_ que interactúan con una _cinta_ también funcionan en un _Depósito_.", + "block.create.seat.tooltip.summary": "¡Siéntate y disfruta del viaje! Anclará a un jugador en un artilugio en movimiento. También es ideal para muebles estáticos. Viene en una variedad de colores.", + "block.create.seat.tooltip.condition1": "Cuando se hace clic derecho en el asiento", + "block.create.seat.tooltip.behaviour1": "Sienta al jugador en el _asiento_. Pulsa Mayús izdo para dejar el asiento.", "item.create.blaze_cake.tooltip": "PASTEL DE BLAZE", - "item.create.blaze_cake.tooltip.summary": "Un delicioso regalo para sus esforzados _Quemadores de blaze_. Los pone en marcha!.", - - "item.create.empty_blaze_burner.tooltip": "QUEMADOR DE BLAZE VACÍO", - "item.create.empty_blaze_burner.tooltip.summary": "Un pequeño hogar de hierro para tus amigos fogosos. Estoy seguro de que podrías darles un buen uso.", - "item.create.empty_blaze_burner.tooltip.condition1": "Cuando se utiliza en un Blaze o en un generador de Blaze", - "item.create.empty_blaze_burner.tooltip.behaviour1": "_Captura_ un Blaze en el elemento", - - "block.create.fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS DE COBRE", - "block.create.fluid_pipe.tooltip.summary": "Se utiliza para mover _fluidos_. Necesita una _bomba mecánica_ para que el _fluido_ se mueva.", - "block.create.fluid_pipe.tooltip.condition1": "Transferencia de fluidos", - "block.create.fluid_pipe.tooltip.behaviour1": "Puede conectarse a _contenedores de fluidos_ como _depósitos_ o _cuencas_. Los extremos expuestos de los _tubos_ también pueden drenar o colocar bloques de fluido. ¡Cuidado con las fugas!", - "block.create.fluid_pipe.tooltip.control1": "Cuando haces clic derecho con una Llave Inglesa", - "block.create.fluid_pipe.tooltip.action1": "Coloca una ventana en la tubería si está disponible", - - "block.create.hose_pulley.tooltip": "POLEA DE MANGUERA", - "block.create.hose_pulley.tooltip.summary": "Se utiliza para _colocar_ o _drenar_ grandes _cuerpos fluidos_ en el mundo", - "block.create.hose_pulley.tooltip.condition1": "Cuando se alimenta por cinética", - "block.create.hose_pulley.tooltip.behaviour1": "_Sube_ o _baja_ la manguera, la ubicación de la manguera determina hasta qué _altura de extracción_ o _llenado_ actuará.", - "block.create.hose_pulley.tooltip.condition2": "Cuando los fluidos se extraen de la polea", - "block.create.hose_pulley.tooltip.behaviour2": "Comienza a _tomar bloques de fluidos_ del cuerpo al que se bajó el extremo de la manguera. Los cuerpos muy _grandes_ de fluidos se _considerarán infinitos_.", - "block.create.hose_pulley.tooltip.condition3": "Cuando los fluidos son empujados a la polea", - "block.create.hose_pulley.tooltip.behaviour3": "Comienza a _llenar de fluido_ el mundo hasta la _altura_ de los extremos de la _manguera_", - - "block.create.fluid_tank.tooltip": "TANQUE DE FLUIDOS", - "block.create.fluid_tank.tooltip.summary": "Almacena todos tus _líquidos_ favoritos. Escala en anchura y altura.", - "block.create.fluid_tank.tooltip.condition1": "Cuando se hace click derecho con la Llave Inglesa", - "block.create.fluid_tank.tooltip.behaviour1": "Cambia la ventana opcional", - - "block.create.creative_fluid_tank.tooltip": "TANQUE DE FLUIDOS CREATIVO", - "block.create.creative_fluid_tank.tooltip.summary": "Este _Tanque de Fluidos_ permite la replicación infinita de cualquier Fluido. Escala en anchura y altura.", - "block.create.creative_fluid_tank.tooltip.condition1": "Cuando hay fluido en el tanque", - "block.create.creative_fluid_tank.tooltip.behaviour1": "Todo lo que se _extraiga_ de este tanque proporcionará un _suministro ilimitado_ del fluido especificado. Los fluidos _insertados_ en este tanque serán _evitados._", - "block.create.creative_fluid_tank.tooltip.condition2": "Cuando se hace clic derecho con una Llave Inglesa", - "block.create.creative_fluid_tank.tooltip.behaviour2": "Cambia la ventana opcional", - - "block.create.fluid_valve.tooltip": "VALVULA DE FLUIDOS", - "block.create.fluid_valve.tooltip.summary": "Detiene el flujo de un fluido por una tubería", - "block.create.fluid_valve.tooltip.condition1": "Flujo controlable", - "block.create.fluid_valve.tooltip.behaviour1": "La _fuerza de rotación_ aplicada obligará a la _válvula_ a cerrarse, cesando el flujo de _fluidos_. Invierta la dirección de la _fuerza de rotación_ para volver a abrir la válvula", - - "block.create.mechanical_pump.tooltip": "BOMBA MECÁNICA", - "block.create.mechanical_pump.tooltip.summary": "Toma la _fuerza de rotación_ y la utiliza para mover el _fluido_ a lo largo de un _tubo_. Tiene un rango máximo de efecto en ambas direcciones. (16 bloques por defecto)", - "block.create.mechanical_pump.tooltip.condition1": "Flujo de fluido", - "block.create.mechanical_pump.tooltip.behaviour1": "La _fuerza de rotación_ aplicada crea una presión que obliga al _fluido_ a pasar por la red de _tuberías_. Invierte la dirección de la _fuerza de rotación_ para cambiar la dirección en la que fluye el _fluido_", - "block.create.mechanical_pump.tooltip.control1": "Pulsando con el botón derecho del ratón con la Llave Inglesa", - "block.create.mechanical_pump.tooltip.action1": "Invierte la dirección de la _bomba_, cambiando la dirección por defecto del flujo", - - "block.create.smart_fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS INTELIGENTE", - "block.create.smart_fluid_pipe.tooltip.summary": "Una _tubería de fluidos_ con un filtro. Puede especificar qué _fluidos_ pasan por ella", - "block.create.smart_fluid_pipe.tooltip.condition1": "Cuando se introducen fluidos en ella", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "Las tuberías inteligentes que reciban fluidos que no coincidan con su filtro bloquearán el flujo", - "block.create.smart_fluid_pipe.tooltip.condition2": "Cuando es adyacente a un contenedor de fluido", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "Las tuberías inteligentes que _inicien_ un _flujo_ desde cualquier contenedor sólo extraerán fluidos que _coincidan_ con su _filtro._", - - "block.create.spout.tooltip": "SURTIDOR", - "block.create.spout.tooltip.summary": "Un inyector para rellenar tus elementos de _fluidos._", - "block.create.spout.tooltip.condition1": "Transferencia de fluidos", - "block.create.spout.tooltip.behaviour1": "Cuando se coloca un _contenedor de fluidos_ como un _cubo_ o una _botella_ debajo, el caño intentará rellenarlo con su propio _fluido_ almacenado", - "block.create.spout.tooltip.condition2": "Automatización de fluidos", - "block.create.spout.tooltip.behaviour2": "El caño colocado encima de una _cinta_ o _depósito_ reaccionará automáticamente con un contenedor de fluidos_ que pase por debajo", - - "block.create.item_drain.tooltip": "DRENADOR DE ELEMENTOS", - "block.create.item_drain.tooltip.summary": "Un depósito rallado para vaciar tus _artículos fluidos._", - "block.create.item_drain.tooltip.condition1": "Transferencia de fluidos", - "block.create.item_drain.tooltip.behaviour1": "Cuando un _contenedor de fluidos_, como un _cubo_ o una _botella_, se inserta desde el lateral, el desagüe intentará vaciarlo en su propio _contenedor de fluidos_. El artículo será entonces expulsado por el lado opuesto", - - "block.create.mechanical_arm.tooltip": "BRAZO MECÁNICO", - "block.create.mechanical_arm.tooltip.summary": "Artilugio avanzado para reubicar _elementos_", - "block.create.mechanical_arm.tooltip.condition1": "Transferencia de elementos", - "block.create.mechanical_arm.tooltip.behaviour1": "Puede tomar o colocar objetos en cualquier _inventario_ accesible_, como _Cintas_, _Depósitos_, _Embudos_ y _Autoensambladores_", - "block.create.mechanical_arm.tooltip.control1": "Mientras está en la mano", - "block.create.mechanical_arm.tooltip.action1": "Haz clic con el botón derecho en un _objeto accesible del inventario_ para establecerlo como _fuente_ para el _brazo mecánico_. Haz clic con el botón derecho del ratón dos veces para establecerlo como _destino_", - "block.create.mechanical_arm.tooltip.control2": "Usa la rueda del ratón con la Llave Inglesa", - "block.create.mechanical_arm.tooltip.action2": "Establece el comportamiento de orden de los _items_ emitidos por el _brazo mecánico_", + "item.create.blaze_cake.tooltip.summary": "Un delicioso regalo para sus esforzados _quemadores de blaze_. ¡Los pone en marcha!.", "item.create.wand_of_symmetry.tooltip": "VARITA DE SIMETRÍA", - "item.create.wand_of_symmetry.tooltip.summary": "Refleja perfectamente la colocación de bloques en los planos configurados", + "item.create.wand_of_symmetry.tooltip.summary": "Refleja perfectamente la colocación de bloques en los planos configurados.", "item.create.wand_of_symmetry.tooltip.condition1": "Mientras está en el inventario rápido", - "item.create.wand_of_symmetry.tooltip.behaviour1": "Permanece activo", - "item.create.wand_of_symmetry.tooltip.control1": "Click derecho en el suelo", - "item.create.wand_of_symmetry.tooltip.action1": "_Crea_ o _Mueve_ el Espejo", - "item.create.wand_of_symmetry.tooltip.control2": "Click derecho en el aire", - "item.create.wand_of_symmetry.tooltip.action2": "_Quita_ el Espejo activo", - "item.create.wand_of_symmetry.tooltip.control3": "Click derecho mientras se agacha", - "item.create.wand_of_symmetry.tooltip.action3": "Abre la _Interfaz de Configuración_", - - "item.create.handheld_blockzapper.tooltip": "BLOCKZAPPER", - "item.create.handheld_blockzapper.tooltip.summary": "Novedoso artefacto para colocar o intercambiar bloques a distancia", - "item.create.handheld_blockzapper.tooltip.control1": "Click izquierdo en un bloque", - "item.create.handheld_blockzapper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo", - "item.create.handheld_blockzapper.tooltip.control2": "Click derecho en un bloque", - "item.create.handheld_blockzapper.tooltip.action2": "_Coloca_ o _Reemplaza_ el bloque objetivo", - "item.create.handheld_blockzapper.tooltip.control3": "Click derecho mientras se agacha", - "item.create.handheld_blockzapper.tooltip.action3": "Abre la _Interfaz de Configuración_", + "item.create.wand_of_symmetry.tooltip.behaviour1": "Permanece activo.", + "item.create.wand_of_symmetry.tooltip.control1": "Cuando se hace clic derecho en el suelo", + "item.create.wand_of_symmetry.tooltip.action1": "_Crea_ o _mueve_ el espejo.", + "item.create.wand_of_symmetry.tooltip.control2": "Cuando se hace clic derecho en el aire", + "item.create.wand_of_symmetry.tooltip.action2": "_Quita_ el espejo activo.", + "item.create.wand_of_symmetry.tooltip.control3": "Mayús izdo + clic derecho", + "item.create.wand_of_symmetry.tooltip.action3": "Abre la interfaz de configuración.", "item.create.handheld_worldshaper.tooltip": "WORLDSHAPER", - "item.create.handheld_worldshaper.tooltip.summary": "Práctica herramienta para crear _paisajes_ y _características del terreno_", - "item.create.handheld_worldshaper.tooltip.control1": "Click izquierdo en un bloque", - "item.create.handheld_worldshaper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo", - "item.create.handheld_worldshaper.tooltip.control2": "Click derecho en un bloque", + "item.create.handheld_worldshaper.tooltip.summary": "Práctica herramienta para crear _paisajes_ y _características del terreno_.", + "item.create.handheld_worldshaper.tooltip.control1": "Cuando se hace clic izquierdo en un bloque", + "item.create.handheld_worldshaper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo.", + "item.create.handheld_worldshaper.tooltip.control2": "Cuando se hace clic derecho en un bloque", "item.create.handheld_worldshaper.tooltip.action2": "Aplica el _pincel_ y la _herramienta_ actualmente seleccionadas en el lugar deseado.", - "item.create.handheld_worldshaper.tooltip.control3": "Click derecho mientras se agacha", - "item.create.handheld_worldshaper.tooltip.action3": "Abre la _Interfaz de Configuración_", + "item.create.handheld_worldshaper.tooltip.control3": "Mayús izdo + clic derecho", + "item.create.handheld_worldshaper.tooltip.action3": "Abre la interfaz de configuración.", "item.create.tree_fertilizer.tooltip": "FERTILIZANTE PARA ÁRBOLES", - "item.create.tree_fertilizer.tooltip.summary": "Una potente combinación de minerales adecuada para acelerar el crecimiento de los tipos de árboles más comunes", + "item.create.tree_fertilizer.tooltip.summary": "Una potente combinación de minerales adecuada para acelerar el crecimiento de los tipos de árboles más comunes.", "item.create.tree_fertilizer.tooltip.condition1": "Cuando se utiliza en un árbol joven", - "item.create.tree_fertilizer.tooltip.behaviour1": "Hace crecer los árboles _independientemente_ de sus condiciones de _espacio_", - - "item.create.deforester.tooltip": "DEFORESTADOR", - "item.create.deforester.tooltip.summary": "Un hacha _radiante_ capaz de talar árboles en una fracción de segundo", + "item.create.tree_fertilizer.tooltip.behaviour1": "Hace crecer los árboles _independientemente_ de sus condiciones de _espacio_.", "item.create.extendo_grip.tooltip": "AGARRE EXTENDIDO", - "item.create.extendo_grip.tooltip.summary": "¡Boioioing! Aumenta enormemente la _distancia de alcance_ del portador", + "item.create.extendo_grip.tooltip.summary": "¡Boioioing! Aumenta enormemente la _distancia de alcance_ del portador. Se puede alimentar con la presión de aire de un _depósito trasero de cobre_", "item.create.extendo_grip.tooltip.condition1": "Cuando está fuera de la mano", - "item.create.extendo_grip.tooltip.behaviour1": "Aumenta la _distancia de alcance_ de los objetos usados en la _mano principal_", + "item.create.extendo_grip.tooltip.behaviour1": "Aumenta la _distancia de alcance_ de los objetos usados en la _mano principal_.", + "item.create.extendo_grip.tooltip.condition2": "Mientras se usa un depósito trasero de cobre", + "item.create.extendo_grip.tooltip.behaviour2": "No se utilizará _durabilidad_. En su lugar, la _presión del aire_ se drena desde el tanque", + + "item.create.potato_cannon.tooltip": "CANÓN DE PATATAS", + "item.create.potato_cannon.tooltip.summary": "Fwoomp! Lanza tus verduras caseras a tus enemigos. Se puede alimentar con la presión de aire de un _depósito trasero de cobre_", + "item.create.potato_cannon.tooltip.condition1": "Cuando se usa clic derecho", + "item.create.potato_cannon.tooltip.behaviour1": "_Dispara_ un objeto adecuado desde tu inventario_.", + "item.create.potato_cannon.tooltip.condition2": "Mientras se usa un depósito trasero de cobre", + "item.create.potato_cannon.tooltip.behaviour2": "No se utilizará _durabilidad_. En su lugar, la _presión del aire_ se drena desde el tanque", "item.create.filter.tooltip": "FILTRO", - "item.create.filter.tooltip.summary": "Controla las salidas_ y _entradas_ de los dispositivos logísticos con más _precisión_, comparándolas con un _conjunto de elementos_ o varios _filtros anidados_", - "item.create.filter.tooltip.condition1": "Cuando está en la ranura del filtro", - "item.create.filter.tooltip.behaviour1": "Controla_ el flujo del elemento según su _configuración_", + "item.create.filter.tooltip.summary": "Controla las _salidas_ y _entradas_ de los _dispositivos logísticos_ con más precisión, comparándolas con un _conjunto de objetos_ o varios _filtros anidados_.", + "item.create.filter.tooltip.condition1": "Cuando está en la ranura de filtros", + "item.create.filter.tooltip.behaviour1": "Controla el flujo de objetos según su _configuración_.", "item.create.filter.tooltip.condition2": "Cuando se hace clic derecho", - "item.create.filter.tooltip.behaviour2": "Abre la interfaz de _configuración_", + "item.create.filter.tooltip.behaviour2": "Abre la interfaz de configuración.", "item.create.attribute_filter.tooltip": "FILTRO DE ATRIBUTOS", - "item.create.attribute_filter.tooltip.summary": "Controla las salidas_ y las _entradas_ de los dispositivos logísticos con más _precisión_, comparándolas con un _conjunto de _atributos_ y _categorías_ de artículos", - "item.create.attribute_filter.tooltip.condition1": "Cuando está en la ranura del filtro", - "item.create.attribute_filter.tooltip.behaviour1": "Controla el flujo del elemento según su _configuración_", + "item.create.attribute_filter.tooltip.summary": "Controla las _salidas_ y las _entradas_ de los _dispositivos logísticos_ con más precisión, comparándolas con un _conjunto de atributos_ y _categorías_ de objetos.", + "item.create.attribute_filter.tooltip.condition1": "Cuando está en la ranura de filtros", + "item.create.attribute_filter.tooltip.behaviour1": "Controla el flujo de objetos según su _configuración_.", "item.create.attribute_filter.tooltip.condition2": "Cuando se hace clic derecho", - "item.create.attribute_filter.tooltip.behaviour2": "Abre la interfaz de _configuración_", + "item.create.attribute_filter.tooltip.behaviour2": "Abre la interfaz de configuración.", "item.create.empty_schematic.tooltip": "ESQUEMA VACÍO", - "item.create.empty_schematic.tooltip.summary": "Se utiliza como ingrediente de las recetas y para escribir en la _tabla de esquemas_", + "item.create.empty_schematic.tooltip.summary": "Se utiliza como 'ingrediente' de las recetas y para escribir en la _tabla de esquemas_.", "item.create.schematic.tooltip": "ESQUEMA", - "item.create.schematic.tooltip.summary": "Contiene una estructura para ser posicionada y colocada en el mundo. Posiciona el holograma como se desee y utiliza un _Esquematicannon_ para construirlo", - "item.create.schematic.tooltip.condition1": "Cuando se mantiene", - "item.create.schematic.tooltip.behaviour1": "Se puede posicionar utilizando las herramientas en pantalla", - "item.create.schematic.tooltip.control1": "Click derecho mientras se agacha", - "item.create.schematic.tooltip.action1": "Abre una _Interfaz_ para introducir las _Coordenadas_ exactas", + "item.create.schematic.tooltip.summary": "Contiene una estructura para ser posicionada y colocada en el mundo. Posiciona el holograma como desees y utiliza un _cañón de esquemas_ para construirla.", + "item.create.schematic.tooltip.condition1": "Cuando se sostiene en la mano", + "item.create.schematic.tooltip.behaviour1": "Se puede posicionar utilizando las herramientas en pantalla.", + "item.create.schematic.tooltip.control1": "Mayús izdo + clic derecho", + "item.create.schematic.tooltip.action1": "Abre una _interfaz_ para introducir las _coordenadas_ exactas.", "item.create.schematic_and_quill.tooltip": "ESQUEMA Y PLUMA", - "item.create.schematic_and_quill.tooltip.summary": "Se utiliza para guardar una estructura de tu mundo en un archivo .nbt", + "item.create.schematic_and_quill.tooltip.summary": "Se utiliza para guardar una estructura de tu mundo en un archivo .nbt.", "item.create.schematic_and_quill.tooltip.condition1": "Paso 1", - "item.create.schematic_and_quill.tooltip.behaviour1": "Selecciona dos puntos de esquina usando click derecho", + "item.create.schematic_and_quill.tooltip.behaviour1": "Selecciona dos puntos de esquina usando clic derecho.", "item.create.schematic_and_quill.tooltip.condition2": "Paso 2", - "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrl-Rueda del ratón_ en las caras para ajustar el tamaño. Click derecho de nuevo para guardar", - "item.create.schematic_and_quill.tooltip.control1": "Click derecho", - "item.create.schematic_and_quill.tooltip.action1": "Seleccionar un punto de esquina / confirmar guardar", - "item.create.schematic_and_quill.tooltip.control2": "Al mantener Ctrl", - "item.create.schematic_and_quill.tooltip.action2": "Seleccionar puntos en _medio del aire_. Rueda del ratón para ajustar la distancia", - "item.create.schematic_and_quill.tooltip.control3": "Click derecho mientras se agacha", - "item.create.schematic_and_quill.tooltip.action3": "Reinicia_ y elimina la selección", + "item.create.schematic_and_quill.tooltip.behaviour2": "[Ctrl] + [RUEDA DEL RATÓN] en las caras para ajustar el tamaño. Clic derecho de nuevo para guardar.", + "item.create.schematic_and_quill.tooltip.control1": "Cuando se hace clic derecho", + "item.create.schematic_and_quill.tooltip.action1": "Selecciona un punto de esquina / confirmar guardar.", + "item.create.schematic_and_quill.tooltip.control2": "Cuando mantiene [Ctrl]", + "item.create.schematic_and_quill.tooltip.action2": "Selecciona puntos en _medio del aire_. Rueda del ratón para ajustar la distancia.", + "item.create.schematic_and_quill.tooltip.control3": "Mayús izdo + clic derecho", + "item.create.schematic_and_quill.tooltip.action3": "_Reinicia_ y elimina la selección.", - "block.create.schematicannon.tooltip": "ESQUEMATICAÑÓN", - "block.create.schematicannon.tooltip.summary": "Dispara bloques para recrear un _Esquema_ desplegado en el Mundo. Utiliza elementos de los inventarios adyacentes y _Pólvora_ como combustible.", - "block.create.schematicannon.tooltip.control1": "Cuando se hace clic derecho", - "block.create.schematicannon.tooltip.action1": "Abre la _Interfaz_ de configuración", + "block.create.schematicannon.tooltip": "CAÑÓN DE ESQUEMAS", + "block.create.schematicannon.tooltip.summary": "Dispara bloques para recrear un _esquema_ desplegado en el mundo. Utiliza objetos de los inventarios adyacentes y _pólvora_ como combustible.", + "block.create.schematicannon.tooltip.condition1": "Cuando se hace clic derecho", + "block.create.schematicannon.tooltip.behaviour1": "Abre la interfaz.", "block.create.schematic_table.tooltip": "TABLA DE ESQUEMAS", - "block.create.schematic_table.tooltip.summary": "Escribe los esquemas guardados en un _esquema vacío_", + "block.create.schematic_table.tooltip.summary": "Escribe los esquemas guardados en un _esquema vacío_.", "block.create.schematic_table.tooltip.condition1": "Cuando se da un esquema vacío", - "block.create.schematic_table.tooltip.behaviour1": "Carga un archivo elegido de la carpeta de esquemas", + "block.create.schematic_table.tooltip.behaviour1": "Carga un archivo elegido de la carpeta de esquemas.", - "block.create.shaft.tooltip": "EJE", - "block.create.shaft.tooltip.summary": "_Retransmite la rotación_ en línea recta", - - "block.create.cogwheel.tooltip": "RUEDA DENTADA", - "block.create.cogwheel.tooltip.summary": "_Retransmite la rotación_ en línea recta, y a las _ruedas dentadas_ adyacentes", - - "block.create.large_cogwheel.tooltip": "RUEDA DENTADA GRANDE", - "block.create.large_cogwheel.tooltip.summary": "Una versión más grande de la _Rueda dentada_, que permite _cambiar_ la _Velocidad de Rotación_ cuando se conecta a su contraparte más pequeña", - - "block.create.encased_shaft.tooltip": "EJE REVESTIDO", - "block.create.encased_shaft.tooltip.summary": "_Retransmite la rotación_ en línea recta. Adecuado para propagar la Rotación a través de Muros", - - "block.create.gearbox.tooltip": "CAJA DE TRANSMISIÓN", - "block.create.gearbox.tooltip.summary": "_Retransmite la rotación_ en _cuatro direcciones_. Invierte las conexiones rectas", - - "block.create.gearshift.tooltip": "CAJA DE CAMBIOS", - "block.create.gearshift.tooltip.summary": "Un control para alternar la dirección de rotación de los ejes conectados", - "block.create.gearshift.tooltip.condition1": "Cuando se alimenta", - "block.create.gearshift.tooltip.behaviour1": "_Invierte_ la rotación de salida", - - "block.create.clutch.tooltip": "Embrague", - "block.create.clutch.tooltip.summary": "Un control para conectar/desconectar la rotación de los ejes conectados", - "block.create.clutch.tooltip.condition1": "Cuando se acciona", - "block.create.clutch.tooltip.behaviour1": "_Detiene_ el transporte de la rotación al otro lado", - - "block.create.encased_chain_drive.tooltip": "CADENA DE TRANSMISIÓN REVESTIDA", - "block.create.encased_chain_drive.tooltip.summary": "_Retransmite la rotación_ en línea recta y a las cadenas de transmisión adyacentes. Las cadenas de transmisión se conectan en un grupo cuando se colocan junto a otra en cualquier cara sin eje. Su orientación no tiene que coincidir", - "block.create.encased_chain_drive.tooltip.condition1": "Cuando se conecta", - "block.create.encased_chain_drive.tooltip.behaviour1": "Los bloques conectados transmitirán la _velocidad de rotación_ y la dirección de este componente", - - "block.create.adjustable_chain_gearshift.tooltip": "CADENA DE TRANSMISIÓN AJUSTABLE", - "block.create.adjustable_chain_gearshift.tooltip.summary": "_Retransmite el giro_ en línea recta y a las _cadenas adyacentes_. El Redstone analógo proporcionada a este bloque controlará qué tamaño de rueda motriz se acopla a las cadenas de transmisión adyacentes", - "block.create.adjustable_chain_gearshift.tooltip.condition1": "Control de Redstone", - "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "_Sin señal_, los accionamientos de cadena adyacentes transmitirán la _misma velocidad._ Con una señal de _fuerza completa_, los accionamientos de cadena adyacentes transmitirán exactamente _el doble de su velocidad._ Cualquier cosa entre medias dará resultados entre 1-2x su velocidad", - - "item.create.belt_connector.tooltip": "CORREA", - "item.create.belt_connector.tooltip.summary": "Conecta dos o más _ejes_ con una _Correa_. Los ejes conectados tendrán exactamente la misma velocidad y dirección de rotación. La correa puede actuar como _Transportador_ para _Estados_ y _Entidades_", - "item.create.belt_connector.tooltip.control1": "Click derecho en el eje", - "item.create.belt_connector.tooltip.action1": "Selecciona el eje como una polea de la correa. Los dos ejes seleccionados tienen que estar _alineados_ ya sea _Verticalmente_, _Horizontalmente_ o _Diagonalmente_ hacia la dirección de la correa", - "item.create.belt_connector.tooltip.control2": "Click derecho mientras te agachas", - "item.create.belt_connector.tooltip.action2": "_Reinicia_ la primera posición seleccionada para la correa", - - "item.create.goggles.tooltip": "GAFAS DEL INGENIERO", - "item.create.goggles.tooltip.summary": "Un par de gafas para aumentar tu visión con útil información _cinética_", + "item.create.goggles.tooltip": "GAFAS DEL CONSTRUCTOR", + "item.create.goggles.tooltip.summary": "Un par de gafas para aumentar tu visión con útil información _cinética_.", "item.create.goggles.tooltip.condition1": "Cuando se llevan puestas", - "item.create.goggles.tooltip.behaviour1": "Muestra _indicadores de color_ correspondientes al _Nivel de velocidad_ de un componente cinético colocado, así como el _Impacto de estrés_ y la _Capacidad_ de los componentes individuales.", - "item.create.goggles.tooltip.condition2": "Al mirar el medidor", - "item.create.goggles.tooltip.behaviour2": "Muestra información detallada sobre _Velocidad_ o _Estrés_ de la red a la que está conectado el medidor", + "item.create.goggles.tooltip.behaviour1": "Muestra _indicadores de color_ correspondientes al _nivel de velocidad_ de un componente cinético colocado, así como el _impacto de estrés_ y la _carga_ de los componentes individuales.", + "item.create.goggles.tooltip.condition2": "Al mirar un medidor", + "item.create.goggles.tooltip.behaviour2": "Muestra información detallada sobre _velocidad_ o _estrés_ de la red a la que está conectado el medidor.", + "item.create.goggles.tooltip.condition3": "Al mirar un contenedor de fluidos", + "item.create.goggles.tooltip.behaviour3": "Muestra información detallada sobre la _carga_ del bloque y los _líquidos_ almacenados en su interior.", "item.create.wrench.tooltip": "LLAVE INGLESA", - "item.create.wrench.tooltip.summary": "Una herramienta útil para trabajar en artilugios cinéticos. Se puede utilizar para _Rotar_, _Desmantelar_ y para _Configurar_ componentes", - "item.create.wrench.tooltip.control1": "Click con el botón derecho en un bloque cinético", - "item.create.wrench.tooltip.action1": "_Rota los componentes_ hacia o desde la cara con la que ha interactuado", - "item.create.wrench.tooltip.control2": "Click derecho mientras te agachas", - "item.create.wrench.tooltip.action2": "Desmonta los componentes cinéticos_ y los devuelve a _tu inventario_", - - "block.create.creative_motor.tooltip": "MOTOR CREATIVO", - "block.create.creative_motor.tooltip.summary": "Una fuente configurable de _Fuerza Rotativa_", - - "block.create.water_wheel.tooltip": "RUEDA HIDRÁULICA MECÁNICA", - "block.create.water_wheel.tooltip.summary": "Proporciona _Fuerza de rotación_ tomada de las _Corrientes de agua_ adyacentes", - - "block.create.encased_fan.tooltip": "VENTILADOR REVESTIDO", - "block.create.encased_fan.tooltip.summary": "Convierte la _fuerza de rotación_ en _corrientes de aire_ y viceversa. Tiene una gran variedad de usos", - "block.create.encased_fan.tooltip.condition1": "Cuando es alimentado por Redstone", - "block.create.encased_fan.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a partir de cualquier _fuente de calor_ inmediatamente inferior. El ventilador debe estar orientado hacia abajo", - "block.create.encased_fan.tooltip.condition2": "Cuando es impulsado por la cinética", - "block.create.encased_fan.tooltip.behaviour2": "_Empuja_ o _Tira_ de Entidades, dependiendo de la velocidad de Rotación entrante", - "block.create.encased_fan.tooltip.condition3": "Al soplar a través de bloques especiales", - "block.create.encased_fan.tooltip.behaviour3": "Se emiten partículas de _Líquidos_ y _Fuego_ en el flujo de aire. Esto puede utilizarse para _procesar objetos_", + "item.create.wrench.tooltip.summary": "Una herramienta útil para trabajar en artilugios cinéticos. Se puede utilizar para _rotar_, _desmantelar_ y para _configurar_ componentes.", + "item.create.wrench.tooltip.control1": "Cuando se hace clic derecho en un bloque cinético", + "item.create.wrench.tooltip.action1": "Rota los componentes hacia o desde la cara con la que ha interactuado.", + "item.create.wrench.tooltip.control2": "Mayús izdo + clic derecho", + "item.create.wrench.tooltip.action2": "Desmonta los _componentes cinéticos_ y los devuelve a tu inventario_.", "block.create.nozzle.tooltip": "BOQUILLA", - "block.create.nozzle.tooltip.summary": "Se acopla a la parte delantera de un _ventilador revestido_ para distribuir su efecto sobre las entidades en _todas las direcciones_", - - "block.create.hand_crank.tooltip": "MANIVELA", - "block.create.hand_crank.tooltip.summary": "Una sencilla _fuente_ de _fuerza de rotación_ que requiere la interacción de los jugadores. Ten cuidado de no agotarte!", - "block.create.hand_crank.tooltip.condition1": "Cuando se usa", - "block.create.hand_crank.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a un artilugio acoplado. _Se puede revertir_ la rotación", + "block.create.nozzle.tooltip.summary": "Se acopla a la parte delantera de un _ventilador revestido_ para distribuir su efecto sobre las entidades en _todas las direcciones_.", "block.create.cuckoo_clock.tooltip": "RELOJ DE CUCO", - "block.create.cuckoo_clock.tooltip.summary": "Fina artesanía para _decorar_ un espacio y _contar el tiempo_", + "block.create.cuckoo_clock.tooltip.summary": "Fina artesanía para decorar un espacio y contar el tiempo.", "block.create.cuckoo_clock.tooltip.condition1": "Cuando es alimentado por cinética", - "block.create.cuckoo_clock.tooltip.behaviour1": "Muestra la _hora actual_ y toca una melodía dos veces al día. Se activa_ una vez al _mediodía_ y al anochecer, en cuanto _los jugadores pueden dormir_", + "block.create.cuckoo_clock.tooltip.behaviour1": "Muestra la _hora actual_ y toca una melodía dos veces al día. Se activa una vez al mediodía y al anochecer, _en cuanto los jugadores pueden dormir_.", "block.create.turntable.tooltip": "PLATAFORMA GIRATORIA", - "block.create.turntable.tooltip.summary": "Convierte la _fuerza de rotación_ en un refinado mareo", - - "block.create.millstone.tooltip": "PIEDRA DEL MOLINO", - "block.create.millstone.tooltip.summary": "Un componente cinético adecuado para _moler_ materiales insertados. Puede ser alimentado por una rueda dentada adyacente o conectándose al eje de la parte inferior. Los resultados tienen que ser extraídos del componente", - "block.create.millstone.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.millstone.tooltip.behaviour1": "Comienza a aplicar _recetas de fresado_ a cualquier elemento insertado desde el lateral o la parte superior del bloque", - "block.create.millstone.tooltip.condition2": "Cuando se hace clic derecho", - "block.create.millstone.tooltip.behaviour2": "Recoge las salidas manualmente", - - "block.create.crushing_wheel.tooltip": "RUEDA DE TRITURACIÓN", - "block.create.crushing_wheel.tooltip.summary": "Grandes ruedas giratorias que _rompen_ cualquier cosa", - "block.create.crushing_wheel.tooltip.condition1": "Cuando se une a otra rueda trituradora", - "block.create.crushing_wheel.tooltip.behaviour1": "Forma una máquina trituradora para procesar una variedad de cosas. Los dientes de las ruedas tienen que conectarse y moverse con la _misma velocidad_ en _direcciones opuestas_", - - "block.create.mechanical_press.tooltip": "PRENSA MECÁNICA", - "block.create.mechanical_press.tooltip.summary": "Un pistón de fuerza para comprimir los objetos que tiene debajo. Requiere una _fuerza de rotación_ constante", - "block.create.mechanical_press.tooltip.condition1": "Cuando es impulsado por Redstone", - "block.create.mechanical_press.tooltip.behaviour1": "Comienza a _comprimir_ los objetos que caen debajo", - "block.create.mechanical_press.tooltip.condition2": "Cuando está por encima de una cinta", - "block.create.mechanical_press.tooltip.behaviour2": "Comprime _automáticamente_ los elementos de derivación en la cinta", - "block.create.mechanical_press.tooltip.condition3": "Cuando está por encima de la Cuenca", - "block.create.mechanical_press.tooltip.behaviour3": "Comienza a _compactar artículos_ en la cuenca siempre que estén presentes todos los ingredientes necesarios", - - "block.create.basin.tooltip": "CUENCA", - "block.create.basin.tooltip.summary": "Un práctico _contenedor de elementos_ utilizado en el procesamiento con la _Mezcladora mecánica_ y la _Prensa mecánica_. Soporta _Comparadores de Redstone_. Viene con un práctico filtro que especifica qué elementos deben crearse en esta cuenca", - "block.create.basin.tooltip.condition1": "Salida automática", - "block.create.basin.tooltip.behaviour1": "Cuando los _inventarios abiertos_ como cintas, otras cuencas, depósitos, desagües de fluidos y otros están _bajo un lado_ de una cuenca, recibirán automáticamente cualquier _salida de artículos/fluidos_ creada en la cuenca. Esto es útil para la automatización", - - "block.create.blaze_burner.tooltip": "QUEMADOR DE BLAZE", - "block.create.blaze_burner.tooltip.summary": "Un bloque donde se aloja un blaze domado para calentar una cuenca", - "block.create.blaze_burner.tooltip.condition1": "Cuando se coloca debajo de una cuenca", - "block.create.blaze_burner.tooltip.behaviour1": "Proporciona _calor_ a las recetas de la cuenca", - "block.create.blaze_burner.tooltip.condition2": "Cuando se utiliza el combustible en el Quemador de Blaze", - "block.create.blaze_burner.tooltip.behaviour2": "Aumenta el tiempo de combustión restante en el tiempo de combustión del horno del elemento utilizado. Consume el objeto. Utiliza _Torta de Blaze_ para altas temperaturas", - - "block.create.reinforced_rail.tooltip": "RAÍL REFORZADO", - "block.create.reinforced_rail.tooltip.summary": "Raíl estabilizado con madera, _no necesita soportes_", - - "block.create.mechanical_mixer.tooltip": "MEZCLADOR MECÁNICO", - "block.create.mechanical_mixer.tooltip.summary": "Un batidor cinético que proporciona recetas de elaboración automatizada de múltiples ingredientes. Requiere una _fuerza de rotación_ constante y una _cuenca_ colocada debajo (con un espacio intermedio)", - "block.create.mechanical_mixer.tooltip.condition1": "Cuando está por encima de la Cuenca", - "block.create.mechanical_mixer.tooltip.behaviour1": "Comienza a mezclar los elementos en la cuenca siempre que estén presentes todos los ingredientes necesarios. Para evitar recetas no deseadas, utilice la ranura del filtro de la cuenca o reduzca la fuerza de rotación hasta que se hayan añadido todos los ingredientes deseados", - - "block.create.mechanical_crafter.tooltip": "AUTOENSAMBLADOR MECÁNICO", - "block.create.mechanical_crafter.tooltip.summary": "Un ensamblador cinético para _automatizar_ cualquier receta de _crafteo_ con forma. Coloca _múltiples en una cuadrícula_ correspondiente a tu receta, y _organiza sus cintas_ para crear un _flujo_ que salga de la cuadrícula en uno de los Autoensambladores", - "block.create.mechanical_crafter.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.mechanical_crafter.tooltip.behaviour1": "_Empieza el proceso de creación_ en cuanto _todos los crafters_ de la parrilla hayan recibido un objeto_", - "block.create.mechanical_crafter.tooltip.condition2": "Con pulso de Redstone", - "block.create.mechanical_crafter.tooltip.behaviour2": "_Fuerza_ el inicio del proceso de _creación_ con todos los _artículos_ dados actualmente en la parrilla", - "block.create.mechanical_crafter.tooltip.control1": "Cuando se arranca por delante", - "block.create.mechanical_crafter.tooltip.action1": "_Circula la dirección_ hacia la que un autoensamblador individual _mueve sus objetos_. Para formar una cuadrícula de trabajo, _organiza las cintas en un flujo_ que mueva todos los objetos hacia un autoensamblador final. El autoensamblador final debe _apuntar hacia fuera_ de la rejilla", - "block.create.mechanical_crafter.tooltip.control2": "Cuando se arranca hacia atrás", - "block.create.mechanical_crafter.tooltip.action2": "Conecta_ el _inventario de entrada_ de los autoensambladores adyacentes. Usa esto para _combinar ranuras_ en la cuadrícula de trabajo y _guardar el la entrada de trabajo_", - - "block.create.furnace_engine.tooltip": "MOTOR DEL HORNO", - "block.create.furnace_engine.tooltip.summary": "Una poderosa fuente de _fuerza de rotación/torque_ que requiere un _horno en funcionamiento_ para funcionar", - "block.create.furnace_engine.tooltip.condition1": "Cuando se conecta a un horno encendido", - "block.create.furnace_engine.tooltip.behaviour1": "_Empieza a alimentar_ un _Horno_ colocado delante de él (a 1m de distancia). Utiliza un Alto Horno para obtener mayores velocidades", - - "block.create.flywheel.tooltip": "RUEDA DE INERCIA", - "block.create.flywheel.tooltip.summary": "Una gran rueda metálica para _conducir y estabilizar_ la fuerza generada por un _motor conectado_. Las ruedas de inercia se conectan a los motores si están a _1m de distancia_ y en un _ángulo de 90º_ entre ellos", - "block.create.flywheel.tooltip.condition1": "Cuando está unida a un motor en marcha", - "block.create.flywheel.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a un artilugio conectado en función de la fuerza y la velocidad del generador", - - "block.create.portable_storage_interface.tooltip": "INTERFAZ DE ALMACENAMIENTO PORTÁTIL", - "block.create.portable_storage_interface.tooltip.summary": "Un punto de intercambio portátil para _mover elementos_ hacia y desde una _estructura_ movida por un pistón, rodamiento, vagoneta o polea. Para cumplirse dos interfaces tienen que _enfrentarse_ y estar separadas _1-2 bloques_", - "block.create.portable_storage_interface.tooltip.condition1": "Mientras se mueve", - "block.create.portable_storage_interface.tooltip.behaviour1": "Interactúa con las _interfaces de almacenamiento portátil_ estacionarias para transferir elementos hacia o desde el artilugio. Los componentes que se inserten o extraigan de la _interfaz estacionaria_ interactuarán con los inventarios del artilugio _directamente._ La estructura se detendrá brevemente mientras se intercambian los elementos.", - "block.create.portable_storage_interface.tooltip.condition2": "Cuando es alimentado por Redstone", - "block.create.portable_storage_interface.tooltip.behaviour2": "Desactiva_ cualquier conexión activa inmediatamente", - - "block.create.portable_fluid_interface.tooltip": "INTERFAZ DE FLUIDO PORTÁTIL", - "block.create.portable_fluid_interface.tooltip.summary": "Punto de intercambio portátil para _mover fluidos_ hacia y desde una _estructura_ movida por un pistón, rodamiento, vagoneta o polea. Para cumplirse dos interfaces tienen que _enfrentarse_ y estar separadas _1-2 bloques_", - "block.create.portable_fluid_interface.tooltip.condition1": "Mientras se mueve", - "block.create.portable_fluid_interface.tooltip.behaviour1": "Interactúa con las _interfaces de almacenamiento portátiles_ estacionarias para transferir fluidos hacia o desde el artilugio. Las tuberías que se inserten en la _interfaz estacionaria_ o se extraigan de ella interactuarán con los depósitos del artilugio _directamente._ La estructura se paralizará brevemente mientras se intercambian fluidos.", - "block.create.portable_fluid_interface.tooltip.condition2": "Cuando se alimenta con Redstone", - "block.create.portable_fluid_interface.tooltip.behaviour2": "_Desconecta_ cualquier conexión activa inmediatamente", - - "block.create.rotation_speed_controller.tooltip": "CONTROLADOR DE VELOCIDAD DE ROTACIÓN", - "block.create.rotation_speed_controller.tooltip.summary": "Un _relé_ configurable_ capaz de acelerar o ralentizar el componente de destino a cualquier velocidad deseada", - "block.create.rotation_speed_controller.tooltip.condition1": "Cuando se adjunta a una rueda dentada grande", - "block.create.rotation_speed_controller.tooltip.behaviour1": "Transmite la fuerza de rotación entrante a la rueda, intentando _igualar_ la _velocidad_ a la que está configurada. La _rueda mecánica_ tiene que estar _adherida en la parte superior_ del controlador", - - "block.create.mechanical_piston.tooltip": "PISTÓN MECÁNICO", - "block.create.mechanical_piston.tooltip.summary": "Una versión más avanzada del _Pistón_. Utiliza la _Fuerza de rotación_ para mover con precisión las estructuras que tiene delante. las pértigas de extensión del pistón_ en la parte trasera definen el _alcance_ de este dispositivo. Sin las extensiones, el pistón no se moverá. Utiliza _Chasis_ o _Bloques de Slime_ para mover más de una línea de bloques", - "block.create.mechanical_piston.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.mechanical_piston.tooltip.behaviour1": "Comienza a mover la estructura adjunta. La velocidad y la dirección se correlacionan con la velocidad de rotación entrante", - - "block.create.piston_extension_pole.tooltip": "PÉRTIGA DE EXTENSIÓN", - "block.create.piston_extension_pole.tooltip.summary": "Amplía la gama de _Pistones mecánicos_", - "block.create.piston_extension_pole.tooltip.condition1": "Cuando se acopla a un pistón mecánico", - "block.create.piston_extension_pole.tooltip.behaviour1": "Extiende el alcance de un pistón en 1 bloque", - - "block.create.mechanical_bearing.tooltip": "RODAMIENTO MECÁNICO", - "block.create.mechanical_bearing.tooltip.summary": "Se utiliza para girar _estructuras más grandes_ con fuerza de rotación", - "block.create.mechanical_bearing.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.mechanical_bearing.tooltip.behaviour1": "Inicia la rotación de los bloques adjuntos. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque", - - "block.create.windmill_bearing.tooltip": "RODAMIENTO DEL MOLINO DE VIENTO", - "block.create.windmill_bearing.tooltip.summary": "Se utiliza para aprovechar la _fuerza de rotación_ del viento. Coloca tu propio diseño y mira cómo gira!", - "block.create.windmill_bearing.tooltip.condition1": "Al hacer clic con el botón derecho", - "block.create.windmill_bearing.tooltip.behaviour1": "Comienza a proporcionar _Fuerza de rotación_ generada por la rotación de su estructura adjunta. La estructura tiene que incluir bloques de vela o lana adecuados. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque.", - - "block.create.sail_frame.tooltip": "MARCO DE VELA", - "block.create.sail_frame.tooltip.summary": "Un útil bloque de construcción y fuente de energía cinética cuando forma parte de una estructura montada sobre un _Rodamiento de molino_", - - "block.create.white_sail.tooltip": "VELA BLANCA", - "block.create.white_sail.tooltip.summary": "Un útil bloque de construcción y fuente de energía cinética cuando forma parte de una estructura montada en un _Rodamiento de molino_. Viene en una variedad de colores", - "block.create.white_sail.tooltip.condition1": "Cuando se hace clic con el botón derecho del ratón con tinte", - "block.create.white_sail.tooltip.behaviour1": "Cambia el color de la vela", - - "block.create.clockwork_bearing.tooltip": "RODAMIENTO DE RELOJ", - "block.create.clockwork_bearing.tooltip.summary": "Una versión avanzada del _rodamiento mecánico_ para hacer girar hasta dos _manecillas de reloj_ según la _hora actual_ en el _juego_", - "block.create.clockwork_bearing.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.clockwork_bearing.tooltip.behaviour1": "Comienza a girar la estructura adjunta hacia la _hora actual_. Si existe una segunda estructura independiente delante de la primera, servirá de _manecilla de las horas_", - - "block.create.sequenced_gearshift.tooltip": "CAMBIO DE MARCHAS SECUENCIADO", - "block.create.sequenced_gearshift.tooltip.summary": "Un _componente de utilidad programable_, que puede cambiar su _rendimiento rotacional_ según hasta _5 instrucciones consecutivas._ Utilízalo para alimentar Rodamientos Mecánicos, Pistones o Poleas con más control sobre la sincronización y la velocidad. Puede ser menos preciso a velocidades más altas", - "block.create.sequenced_gearshift.tooltip.condition1": "Cuando es impulsado por Redstone", - "block.create.sequenced_gearshift.tooltip.behaviour1": "_Ejecuta_ las instrucciones programadas en función de la velocidad de entrada", - "block.create.sequenced_gearshift.tooltip.condition2": "Cuando se hace clic derecho", - "block.create.sequenced_gearshift.tooltip.behaviour2": "Abre la _interfaz de configuración._", - - "block.create.cart_assembler.tooltip": "ENSAMBLADOR DE VAGONETAS", - "block.create.cart_assembler.tooltip.summary": "Cuando se coloca en un _Raíl_, puede _ensamblar_ y _desensamblar_ estructuras móviles en las vagonetas que pasan. Consulta [Ctrl] para conocer el comportamiento específico del tipo de raíl", - "block.create.cart_assembler.tooltip.condition1": "Artilugio de vagoneta simple", - "block.create.cart_assembler.tooltip.behaviour1": "Con un _miembro único_, las estructuras se anclarán y girarán en _una sola vagoneta_. Utilice una _Llave Inglesa_ para especificar el _comportamiento de rotación_ deseado", - "block.create.cart_assembler.tooltip.condition2": "Artilugio de vagonetas", - "block.create.cart_assembler.tooltip.behaviour2": "Dos ensambladores de vagonetas _conectadas por_ una _estructura_, una vez que ambos contengan una vagoneta, las conectará con un artilugio montado _entre los dos_. La estructura se comportará de forma similar a un _acoplador de vagonetas_", - "block.create.cart_assembler.tooltip.control1": "Cuando se coloca sobre un Rail", - "block.create.cart_assembler.tooltip.action1": "_Se monta_ en las vagonetas que pasan _cuando está alimentado_, _se desmonta_ en caso contrario", - "block.create.cart_assembler.tooltip.control2": "Cuando se coloca sobre un raíl energizado", - "block.create.cart_assembler.tooltip.action2": "Monta y _acelera_ las vagonetas _cuando está alimentado_, desmonta y _sostiene_ en caso contrario", - "block.create.cart_assembler.tooltip.control3": "Cuando se coloca sobre el raíl detector", - "block.create.cart_assembler.tooltip.action3": "_Monta vagonetas sin montar_, _desmonta vagonetas montadas_", - "block.create.cart_assembler.tooltip.control4": "Cuando se coloca sobre el raíl activador", - "block.create.cart_assembler.tooltip.action4": "Desmonta_ vagonetas cuando se activa", - - "block.create.rope_pulley.tooltip": "POLEA DE CUERDA", - "block.create.rope_pulley.tooltip.summary": "Mueve verticalmente los _bloques_ y _estructuras_ adjuntos. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque", - "block.create.rope_pulley.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.rope_pulley.tooltip.behaviour1": "Comienza a mover la estructura adjunta. La velocidad y la dirección se correlacionan con la velocidad de rotación entrante", - - "block.create.linear_chassis.tooltip": "CHASIS LINEAL", - "block.create.linear_chassis.tooltip.summary": "Bloque base configurable que conecta estructuras para el movimiento", - "block.create.linear_chassis.tooltip.condition1": "Cuando se mueve", - "block.create.linear_chassis.tooltip.behaviour1": "_Mueve_ todos los _Chasis adjuntos_ con la misma orientación, y una columna de Bloques dentro de su rango. Los bloques sólo serán arrastrados si la cara del chasis es _Pegajosa_ (Ver [Ctrl])", - "block.create.linear_chassis.tooltip.condition2": "Con Llave Inglesa", - "block.create.linear_chassis.tooltip.behaviour2": "Configura el _rango_ para este bloque de chasis. Mantenga pulsada la tecla CTRL para modificar también el rango de todos los bloques de chasis adjuntos", - "block.create.linear_chassis.tooltip.control1": "Cuando se hace clic derecho con slime", - "block.create.linear_chassis.tooltip.action1": "Hace que la cara sobre la que se ha hecho clic sea _pegajosa_. Cuando se mueva, el chasis _tirará_ de los bloques adjuntos, independientemente de la dirección del movimiento", - - "block.create.secondary_linear_chassis.tooltip": "CHASIS LINEAL SECUNDARIO", - "block.create.secondary_linear_chassis.tooltip.summary": "Un segundo tipo de _Chasis lineal_ que no se conecta al otro", - - "block.create.radial_chassis.tooltip": "CHASIS RADIAL", - "block.create.radial_chassis.tooltip.summary": "Bloque base configurable que conecta estructuras para el movimiento", - "block.create.radial_chassis.tooltip.condition1": "Cuando se mueve", - "block.create.radial_chassis.tooltip.behaviour1": "_Mueve_ todos los _Chasis_ adjuntos en una columna, y un cilindro de bloques a su alrededor. Los bloques que lo rodean sólo se mueven cuando están dentro del rango y están adheridos a un lado pegajoso (Ver [Ctrl]).", - "block.create.radial_chassis.tooltip.condition2": "Con Llave Inglesa", - "block.create.radial_chassis.tooltip.behaviour2": "Configura el _rango_ para este bloque de chasis. Mantenga pulsada la tecla CTRL para modificar también el rango de todos los bloques de chasis adjuntos", - "block.create.radial_chassis.tooltip.control1": "Cuando se hace clic derecho con slime", - "block.create.radial_chassis.tooltip.action1": "Hace que la cara sobre la que se ha hecho clic sea _pegajosa_. Cuando el chasis se mueve, todos los bloques designados unidos a la cara pegajosa se mueven con él", - - "block.create.mechanical_drill.tooltip": "TALADRO MECÁNICO", - "block.create.mechanical_drill.tooltip.summary": "Un dispositivo mecánico adecuado para _romper bloques_. Se puede mover con _pistones mecánicos_, _rodamientos_ u otros controladores", - "block.create.mechanical_drill.tooltip.condition1": "Cuando se mueve con cinética", - "block.create.mechanical_drill.tooltip.behaviour1": "Actúa como un rompebloques _estacionario_. También _hace daño a las entidades_ en su área efectiva", - "block.create.mechanical_drill.tooltip.condition2": "Mientras se mueve", - "block.create.mechanical_drill.tooltip.behaviour2": "Rompe los bloques con los que colisiona el taladro", - - "block.create.mechanical_harvester.tooltip": "COSECHADORA MECÁNICA", - "block.create.mechanical_harvester.tooltip.summary": "Una cosechadora mecánica adecuada para la automatización de cultivos a mediana escala. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros controladores", - "block.create.mechanical_harvester.tooltip.condition1": "Mientras se mueve", - "block.create.mechanical_harvester.tooltip.behaviour1": "_Corta_ todos los _cultivos maduros_ con los que la cuchilla colisiona y los restablece a su estado de crecimiento inicial", - - "block.create.mechanical_plough.tooltip": "ARADO MECÁNICO", - "block.create.mechanical_plough.tooltip.summary": "Un arado mecánico tiene varios usos. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros mandos", - "block.create.mechanical_plough.tooltip.condition1": "Mientras se mueve", - "block.create.mechanical_plough.tooltip.behaviour1": "_Rompe bloques_ con los que _no se puede colisionar_, como antorchas, raíles o capas de nieve. _Aplica_ su _movimiento_ a las _entidades_ sin dañarlas. _Labra bloques de tierra_ como si se usara una azada en ellos", - - "block.create.mechanical_saw.tooltip": "SIERRA MECÁNICA", - "block.create.mechanical_saw.tooltip.summary": "Adecuada para _cortar árboles_ de forma eficaz y para _cortar bloques_ en sus homólogos carpinteros. Se puede mover mediante _pistones mecánicos_ o _rodamientos_", - "block.create.mechanical_saw.tooltip.condition1": "Cuando está orientado hacia arriba", - "block.create.mechanical_saw.tooltip.behaviour1": "Aplica las recetas _Serrar_ y _Estallar_ a los objetos que se dejan caer o se introducen en ella. Cuando hay varias salidas posibles, las recorre a menos que se asigne un _filtro_", - "block.create.mechanical_saw.tooltip.condition2": "Cuando se orienta horizontalmente", - "block.create.mechanical_saw.tooltip.behaviour2": "Rompe los troncos_ que tiene delante. Si el tronco soportaba un árbol por sí mismo, el _árbol se derrumbará_ lejos de la sierra", - "block.create.mechanical_saw.tooltip.condition3": "Mientras se mueve", - "block.create.mechanical_saw.tooltip.behaviour3": "_Corta_ todos los _Árboles_ con los que colisiona la sierra", + "block.create.turntable.tooltip.summary": "Convierte la _fuerza rotacional_ en un refinado mareo.", "block.create.stockpile_switch.tooltip": "INTERRUPTOR DE ACOPIO", - "block.create.stockpile_switch.tooltip.summary": "Activa una señal de Redstone en función de la cantidad de _Artículos almacenados_ en el Contenedor adjunto. Viene con un práctico filtro. A diferencia de un _Comparador,_ el _Interruptor de acopio_ permite la configuración de _Umbrales,_ a partir de los cuales se invierten las señales", - "block.create.stockpile_switch.tooltip.condition1": "Cuando haces click derecho", - "block.create.stockpile_switch.tooltip.behaviour1": "Abre la _Interfaz de Configuración_", + "block.create.stockpile_switch.tooltip.summary": "Activa una señal de redstone en función de la cantidad de _objetos almacenados_ en el _contenedor_ adjunto. Viene con un práctico filtro. A diferencia de un _comparador, el _interruptor de acopio_ permite la configuración de _umbrales_, a partir de los cuales se invierten las señales.", + "block.create.stockpile_switch.tooltip.condition1": "Cuando se hace clic derecho", + "block.create.stockpile_switch.tooltip.behaviour1": "Abre la interfaz de configuración.", "block.create.content_observer.tooltip": "OBSERVADOR DE CONTENIDO", - "block.create.content_observer.tooltip.summary": "_Detecta artículos_ dentro de _contenedores_ y _transportadores_ que coinciden con un _filtro_ configurado. Mientras el _inventario_, la _cinta_ o la _canaleta_ observados contengan_ un artículo que coincida, este componente emitirá una _señal de Redstone_. Cuando un _túnel observado transfiere_ un artículo coincidente, este componente emitirá un _Pulso de Redstone_", - - "block.create.redstone_link.tooltip": "ENLACE DE REDSTONE", - "block.create.redstone_link.tooltip.summary": "Puntos finales para conexiones _Inalámbricas Redstone_. Se pueden asignar _frecuencias_ utilizando cualquier elemento. El alcance de la señal es limitado, aunque razonablemente lejano", - "block.create.redstone_link.tooltip.condition1": "Cuando se alimenta", - "block.create.redstone_link.tooltip.behaviour1": "Recibir enlaces de la misma _Frecuencia_ producirá una señal de Redstone", - "block.create.redstone_link.tooltip.control1": "Cuando se hace Clic derecho con un ítem", - "block.create.redstone_link.tooltip.action1": "Establece la _Frecuencia_ a ese elemento. Se pueden utilizar un total de _dos elementos diferentes_ en combinación para definir una Frecuencia", - "block.create.redstone_link.tooltip.control2": "Cuando se hace clic derecho mientras se agacha", - "block.create.redstone_link.tooltip.action2": "Cambia entre el modo _Receptor_ y _Transmisor_", - - "block.create.nixie_tube.tooltip": "TUBO NIXIE", - "block.create.nixie_tube.tooltip.summary": "Un elegante _visualizador_ de _números y texto_ potenciados por Redstone", - "block.create.nixie_tube.tooltip.condition1": "Cuando se alimenta", - "block.create.nixie_tube.tooltip.behaviour1": "Muestra el valor actual de la _Fuerza de la señal Redstone_", - "block.create.nixie_tube.tooltip.condition2": "Con etiqueta de nombre", - "block.create.nixie_tube.tooltip.behaviour2": "Mostrar el _contenido_ de su _etiqueta de nombre_ con varios tubos nixie _ordenados_ en una _línea_", - - "block.create.redstone_contact.tooltip": "CONTACTO DE REDSTONE", - "block.create.redstone_contact.tooltip.summary": "Solo emite energía de Redstone por parejas. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros controladores", - "block.create.redstone_contact.tooltip.condition1": "Cuando se enfrenta a otro Contacto", - "block.create.redstone_contact.tooltip.behaviour1": "Proporciona una _señal de Redstone_", - "block.create.redstone_contact.tooltip.condition2": "Mientras se mueve", - "block.create.redstone_contact.tooltip.behaviour2": "Activa todos los contactos estacionarios que pasa", + "block.create.content_observer.tooltip.summary": "_Detecta objetos_ dentro de _contenedores_ y _transportadores_ que coincidan con un _filtro_ configurado. Mientras el _inventario_, la _cinta_ o la _canaleta_ observados _contengan_ un objeto que coincida, este componente emitirá una _señal de redstone_. Cuando un embudo observado _transfiere_ un objeto coincidente, este componente emitirá un _pulso de redstone_.", "block.create.adjustable_crate.tooltip": "CAJA AJUSTABLE", - "block.create.adjustable_crate.tooltip.summary": "Este _Contenedor de Artículos_ permite el control manual de su capacidad. Puede contener hasta _16 pilas_ de cualquier objeto. Soporta _Comparadores de Redstone_", - "block.create.adjustable_crate.tooltip.control1": "Cuando haces click derecho", - "block.create.adjustable_crate.tooltip.action1": "Abre la _Interfaz_", + "block.create.adjustable_crate.tooltip.summary": "Este _contenedor de objetos_ permite el control manual de su capacidad. Puede contener hasta _16 pilas_ de cualquier objeto. Soporta _comparadores de redstone_.", + "block.create.adjustable_crate.tooltip.condition1": "Cuando se hace clic derecho", + "block.create.adjustable_crate.tooltip.behaviour1": "Abre la interfaz.", "block.create.creative_crate.tooltip": "CAJA CREATIVA", - "block.create.creative_crate.tooltip.summary": "Este _Contenedor de Almacenamiento_ permite la replicación infinita de cualquier elemento. Colócalo junto a un _Schematicannon_ para eliminar cualquier requisito de material", - "block.create.creative_crate.tooltip.condition1": "Cuando el artículo está en la ranura del filtro", - "block.create.creative_crate.tooltip.behaviour1": "Todo lo que se _extraiga_ de este contenedor proporcionará un _suministro ilimitado_ del elemento especificado. Los elementos _insertados_ en esta caja serán _evitados._", + "block.create.creative_crate.tooltip.summary": "Este _contenedor de objetos_ permite la replicación infinita de cualquier elemento. Colócalo junto a un _cañón de esquemas_ para eliminar cualquier requisito de material.", + "block.create.creative_crate.tooltip.condition1": "Cuando el elemento está en la ranura para filtros", + "block.create.creative_crate.tooltip.behaviour1": "Todo lo que se _extraiga_ de este contenedor proporcionará un suministro _ilimitado_ del elemento especificado. Los objetos _insertados_ en esta caja serán _evitados_.", - "block.create.deployer.tooltip": "DESPLEGADOR", - "block.create.deployer.tooltip.summary": "_Lanza_, _Usa_ y _Activa_. Esta máquina intentará _imitar_ a un _jugador_ en la medida de lo posible. Puede _tomar_ y _depositar objetos_ en su propio _inventario_. Los objetos guardados deben ser _insertados_ y _extraídos_ del bloque directamente", - "block.create.deployer.tooltip.condition1": "Cuando se alimenta de cinética", - "block.create.deployer.tooltip.behaviour1": "Extiende su brazo y se _activa_ en el espacio del bloque _2m por delante_ de sí mismo", - "block.create.deployer.tooltip.condition2": "Click derecho con la Llave Inglesa", - "block.create.deployer.tooltip.behaviour2": "Activa el modo puñetazo. En el _modo puñetazo_, el Desplegador intentará usar su objeto para _romper bloques_ o _herir entidades_", - "block.create.deployer.tooltip.condition3": "Cuando se asigna el filtro", - "block.create.deployer.tooltip.behaviour3": "El desplegador no se activará a menos que el elemento retenido _coincida_ con el _filtro._ Los elementos que no coincidan no podrán ser insertados; los elementos retenidos que coincidan con el filtro no podrán ser extraídos.", - - "block.create.brass_casing.tooltip": "REVESTIDOR DE LATÓN", - "block.create.brass_casing.tooltip.summary": "Resistente máquina revestidora con una gran variedad de usos. Segura para la decoración. Se puede utilizar para _revestir ejes_ y _cintas._", - - "block.create.pulse_repeater.tooltip": "REPETIDOR DE PULSOS DE REDSTONE", - "block.create.pulse_repeater.tooltip.summary": "Un circuito sencillo para cortar las señales de Redstone que pasan a una longitud de _1 tick_", - - "block.create.adjustable_repeater.tooltip": "REPETIDOR AJUSTABLE", - "block.create.adjustable_repeater.tooltip.summary": "Un avanzado _repetidor de Redstone_ con un _retraso configurable_ de hasta 30 minutos", - - "block.create.adjustable_pulse_repeater.tooltip": "REPETIDOR DE PULSO AJUSTABLE", - "block.create.adjustable_pulse_repeater.tooltip.summary": "Un _repetidor de pulsos_ con un _retardo configurable_ de hasta 30 minutos", - - "block.create.analog_lever.tooltip": "PALANCA ANALÓGICA", - "block.create.analog_lever.tooltip.summary": "Una palanca con un control más _preciso_ sobre su fuerza de _señal_ emitida", - - "block.create.powered_toggle_latch.tooltip": "PALANCA MECANIZADA", - "block.create.powered_toggle_latch.tooltip.summary": "Una palanca que puede ser accionada por un _Pulso de Redstone_", - - "block.create.powered_latch.tooltip": "PALANCA DE CIERRE MECANIZADA", - "block.create.powered_latch.tooltip.summary": "Una palanca que puede ser controlada por _señales de Redstone_. Una señal en la _trasera la habilita_, una señal desde el _lado la reinicia_", + "item.create.creative_blaze_cake.tooltip": "PASTEL CREATIVO", + "item.create.creative_blaze_cake.tooltip.summary": "Un regalo muy especial para los _Quemadores de Blaze_ que permite _controlar su nivel de calor_. Después de comer este pastel, los Quemadores de blaze _nunca se quedarán sin combustible_.", + "item.create.creative_blaze_cake.tooltip.condition1": "Click derecho en un Quemador de blaze", + "item.create.creative_blaze_cake.tooltip.behaviour1": "Bloquea el nivel de calor del Quemador de blaze. Si se utiliza de nuevo, _cicla_ el nivel de calor del Quemador de blaze.", "block.create.controller_rail.tooltip": "RAÍL DE CONTROL", - "block.create.controller_rail.tooltip.summary": "Un _raíl energizado unidireccional_ capaz de _controlar con precisión_ la _velocidad de movimiento_ de una vagoneta", - "block.create.controller_rail.tooltip.condition1": "Cuando es impulsado por Redstone", - "block.create.controller_rail.tooltip.behaviour1": "_Acelera_ o _Desacelera_ pasando _vagonetas_ correspondientes a la _fuerza de la señal_. Propaga la energía de Redstone a los Raíles de control adyacentes. Al alimentar dos Raíles de control con diferentes intensidades, los carriles entre ellos interpolarán su señal", - - "block.create.speedometer.tooltip": "VELOCÍMETRO", - "block.create.speedometer.tooltip.summary": "Mide y muestra la _velocidad de rotación_ de los componentes cinéticos acoplados. Es compatible con _comparadores de Redstone_", - "block.create.speedometer.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.speedometer.tooltip.behaviour1": "Indica un color correspondiente al nivel de velocidad. El _Verde_ indica Lento, el _Azul_ Moderado y el _Púrpura_ Rápido. Algunos componentes mecánicos requieren un nivel de velocidad suficiente para funcionar correctamente", - - "block.create.stressometer.tooltip": "ESTRESÓMETRO", - "block.create.stressometer.tooltip.summary": "Mide y muestra el _estrés global_ de la red cinética adjunta. Es compatible con _comparadores de Redstone_", - "block.create.stressometer.tooltip.condition1": "Cuando se alimenta con cinética", - "block.create.stressometer.tooltip.behaviour1": "Indica un color correspondiente al nivel de estrés. Las redes demasiado estresadas dejarán de moverse. El estrés puede aliviarse añadiendo más _fuentes de rotación_ a la red", + "block.create.controller_rail.tooltip.summary": "Un raíl energizado _unidireccional_ capaz de _controlar con precisión_ la _velocidad de movimiento_ de una vagoneta.", + "block.create.controller_rail.tooltip.condition1": "Cuando es alimentado con redstone", + "block.create.controller_rail.tooltip.behaviour1": "_Acelera_ o _desacelera_ pasando _vagonetas_ correspondientes a la _fuerza de la señal_. Propaga la energía de redstone a los raíles de control adyacentes. Al alimentar dos raíles de control con diferentes intensidades, los carriles entre ellos interpolarán su señal.", "item.create.sand_paper.tooltip": "PAPEL DE LIJA", - "item.create.sand_paper.tooltip.summary": "Un papel rugoso que se puede utilizar para _pulir materiales_. Se puede aplicar automáticamente con el Desplegador", + "item.create.sand_paper.tooltip.summary": "Un papel rugoso que se puede utilizar para _pulir materiales_. Se puede aplicar automáticamente con el _desplegador_.", "item.create.sand_paper.tooltip.condition1": "Cuando se usa", - "item.create.sand_paper.tooltip.behaviour1": "Aplica el pulido a los objetos sostenidos en la _mano libre_ o tirados en el _suelo_ cuando se _miran_", - - "item.create.super_glue.tooltip": "SÚPER PEGAMENTO", - "item.create.super_glue.tooltip.summary": "Pega un bloque a otro y serán inseparables para siempre", - "item.create.super_glue.tooltip.condition1": "Cuando se usa", - "item.create.super_glue.tooltip.behaviour1": "Hace que la cara _clicada_ de un bloque sea _pegajosa_. Los bloques unidos a caras pegajosas serán _arrastrados_ cuando se muevan por _pistones mecánicos_, _rodamientos_ y otros controladores", - "item.create.super_glue.tooltip.condition2": "Cuando se sostiene en la mano", - "item.create.super_glue.tooltip.behaviour2": "_Adjunta automáticamente_ los bloques colocados desde la mano principal al _lado_ contra el que fueron _colocados._", + "item.create.sand_paper.tooltip.behaviour1": "Aplica un pulido a los objetos sostenidos en la _mano libre_ o tirados en el _suelo_ cuando se _miran_.", "item.create.builders_tea.tooltip": "TÉ DEL CONSTRUCTOR", - "item.create.builders_tea.tooltip.summary": "La bebida perfecta para empezar el día- _Motivante_ y _Saturante._", + "item.create.builders_tea.tooltip.summary": "La bebida perfecta para empezar el día. Motivante y saturante.", "item.create.refined_radiance.tooltip": "RESPLANDOR REFINADO", - "item.create.refined_radiance.tooltip.summary": "Material cromático forjado a partir de _luz absorbida_", + "item.create.refined_radiance.tooltip.summary": "Un material cromático forjado a partir de la _luz absorbida_.", + "item.create.refined_radiance.tooltip.condition1": "Trabajo en progreso", + "item.create.refined_radiance.tooltip.behaviour1": "Los usos para este material estarán disponibles en un próximo lanzamiento.", "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.summary": "Un material cromático forjado en el _vacío_.", + "item.create.shadow_steel.tooltip.condition1": "Trabajo en curso", + "item.create.shadow_steel.tooltip.behaviour1": "Los usos de este material estarán disponibles en una futura versión.", + + "item.create.linked_controller.tooltip": "CONTROLADOR ENLAZADO", + "item.create.linked_controller.tooltip.summary": "Permite el control manual de las frecuencias de _enlaces de redstone_ asignadas a sus seis botones.", + "item.create.linked_controller.tooltip.condition1": "Al hacer clic derecho", + "item.create.linked_controller.tooltip.behaviour1": "Activa el _controlador_. Los _controles de movimiento_ se adquieren mientras está activo.", + "item.create.linked_controller.tooltip.condition2": "Al usar Mayús izdo + clic derecho", + "item.create.linked_controller.tooltip.behaviour2": "Abre la interfaz de configuración manual.", + "item.create.linked_controller.tooltip.condition3": "Al usar clic derecho en un receptor de enlaces de redstone", + "item.create.linked_controller.tooltip.behaviour3": "Activa el _modo de vinculación_, pulsa uno de los _seis controles_ para vincularlo a la _frecuencia de los enlaces_.", + "item.create.linked_controller.tooltip.condition4": "Clic derecho en un atril", + "item.create.linked_controller.tooltip.behaviour4": "Coloca el controlador en el atril para facilitar su activación. (Clic derecho + mayús izq. para recuperarlo)", + + "item.create.diving_helmet.tooltip": "CASCO DE BUCEO", + "item.create.diving_helmet.tooltip.summary": "Junto con un _depósito trasero de cobre_, permite que el usuario pueda respirar bajo el agua durante un tiempo prolongado.", + "item.create.diving_helmet.tooltip.condition1": "Cuando se lleva puesto", + "item.create.diving_helmet.tooltip.behaviour1": "Proporciona el efecto de _respiración acuática_, drenando lentamente la presión de aire del _depósito trasero_.", + + "item.create.copper_backtank.tooltip": "DEPÓSITO TRASERO DE COBRE", + "item.create.copper_backtank.tooltip.summary": "Un tanque portátil para transportar _aire presurizado_.", + "item.create.copper_backtank.tooltip.condition1": "Cuando se lleva puesto", + "item.create.copper_backtank.tooltip.behaviour1": "Proporciona _aire presurizado_ a los equipos que lo requieran.", + "item.create.copper_backtank.tooltip.condition2": "Cuando se coloca y es alimentado por cinética", + "item.create.copper_backtank.tooltip.behaviour2": "Recoge _aire presurizado_ a un ritmo que depende de la velocidad rotacional.", + + "item.create.diving_boots.tooltip": "BOTAS DE BUCEO", + "item.create.diving_boots.tooltip.summary": "Un par de _botas_ pesadas, que permiten atravesar mejor el suelo del océano.", + "item.create.diving_boots.tooltip.condition1": "Cuando se llevan puestas", + "item.create.diving_boots.tooltip.behaviour1": "El portador se hunde rápido y no puede nadar. Concede la capacidad de caminar y saltar bajo el agua. Al portador no le afectarán las _correas mecánicas.", + + "item.create.crafting_blueprint.tooltip": "PLANO DE ELABORACIÓN", + "item.create.crafting_blueprint.tooltip.summary": "Colocado en una pared, puede utilizarse para especificar la disposición de los ingredientes para facilitar la elaboración manual. Cada ranura representa una receta", + "item.create.crafting_blueprint.condition1": "Al hacer clic derecho en una ranura vacía", + "item.create.crafting_blueprint.behaviour1": "Abre un menú que permite configurar una receta y los objetos a mostrar.", + "item.create.crafting_blueprint.condition2": "Al hacer clic derecho en una ranura configurada", + "item.create.crafting_blueprint.behaviour2": "Aplica la receta configurada con los ingredientes que se encuentran en tu inventario. Se puede utilizar para fabricar hasta una pila de objetos.", "item.create.minecart_coupling.tooltip": "ENSAMBLADOR DE VAGONETAS", - "item.create.minecart_coupling.tooltip.summary": "_Encadena_ todas tus _Vagonetas_ o _Artilugios de vagoneta_ para formar un majestuoso Tren", - "item.create.minecart_coupling.tooltip.condition1": "Cuando se utiliza en Vagonetas", - "item.create.minecart_coupling.tooltip.behaviour1": "_Acopla_ dos Vagonetas, intentando mantenerlas a una _distancia constante_ mientras se mueven", + "item.create.minecart_coupling.tooltip.summary": "_Encadena_ todas tus _vagonetas_ o _artilugios de vagoneta_ para formar un majestuoso _tren_.", + "item.create.minecart_coupling.tooltip.condition1": "Cuando se utiliza en vagonetas", + "item.create.minecart_coupling.tooltip.behaviour1": "_Acopla_ dos vagonetas, intentando mantenerlas a una _distancia constante_ mientras se mueven.", - "item.create.crafter_slot_cover.tooltip": "TAPA DE RANURA DEL AUTOENSAMBLADOR", - "item.create.crafter_slot_cover.tooltip.summary": "Se utiliza para marcar a un _Autoensamblador_ una ranura vacía en una receta. Los autoensambladores no tienen que formar necesariamente una cuadrícula completa. Esto es útil cuando hay recetas en las que los _ingredientes están en diagonal_ entre sí", + "block.create.peculiar_bell.tooltip": "CAMPANA PECULIAR", + "block.create.peculiar_bell.tooltip.summary": "Una campana decorativa de latón. Al colocarla sobre un _Fuego del alma_ o una _Fogata del alma_ puede producirse una transformación espeluznante...", - "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", + "block.create.haunted_bell.tooltip": "CAMPANA ENCANTADA", + "block.create.haunted_bell.tooltip.summary": "Una _campana maldita_ perseguida por las almas perdidas del Nether", + "block.create.haunted_bell.tooltip.condition1": "Cuando se sostiene o suena", + "block.create.haunted_bell.tooltip.behaviour1": "Resalta los _puntos sin luz_ cercanos en los que pueden aparecer las _criaturas hostiles_.", + + + "_": "->------------------------] Ponder Content [------------------------<-", + + "create.ponder.hold_to_ponder": "Mantén [%1$s] para considerar", + "create.ponder.subject": "Tema de esta escena", + "create.ponder.pondering": "Considerando sobre...", + "create.ponder.identify_mode": "Identificando modo activo.\nDespausea con [%1$s]", + "create.ponder.associated": "Entradas asociadas", + "create.ponder.close": "Cerrar", + "create.ponder.identify": "Identificar", + "create.ponder.next": "Escena siguiente", + "create.ponder.previous": "Escena previa", + "create.ponder.replay": "Repetición", + "create.ponder.think_back": "Volver atrás", + "create.ponder.slow_text": "Lectura cómoda", + "create.ponder.exit": "Salir", + "create.ponder.welcome": "Bienvenido al instructivo de Create", + "create.ponder.categories": "Categorías disponibles", + "create.ponder.index_description": "Haga clic en uno de los iconos para conocer sus objetos y bloques asociados", + "create.ponder.index_title": "Índice", + "create.ponder.shared.rpm16": "16 RPM", + "create.ponder.shared.behaviour_modify_wrench": "Este comportamiento puede modificarse mediante una llave inglesa", + "create.ponder.shared.storage_on_contraption": "Los inventarios unidos al artilugio recogerán sus producciones automáticamente", + "create.ponder.shared.sneak_and": "Mayús izdo. +", + "create.ponder.shared.rpm8": "8 RPM", + "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm32": "32 RPM", + "create.ponder.shared.rpm16_source": "Fuente: 16 RPM", + "create.ponder.shared.movement_anchors": "Con la ayuda de un chasis o pegamento, se pueden mover estructuras más grandes.", + "create.ponder.tag.redstone": "Componentes lógicos", + "create.ponder.tag.redstone.description": "Componentes que ayudan a la ingeniería de redstone", + "create.ponder.tag.contraption_assembly": "Utilidades para adjuntar bloques", + "create.ponder.tag.contraption_assembly.description": "Herramientas y componentes utilizados para montar estructuras con movimiento, como un artilugio animado", + "create.ponder.tag.fluids": "Manipuladores de fluidos", + "create.ponder.tag.fluids.description": "Componentes que ayudan a transportar y utilizar fluidos", + "create.ponder.tag.decoration": "Estética", + "create.ponder.tag.decoration.description": "Componentes utilizados principalmente con fines decorativos", + "create.ponder.tag.windmill_sails": "Velas para los rodamientos de los molinos de viento", + "create.ponder.tag.windmill_sails.description": "Bloques que cuentan para la fuerza de un artefacto de molino de viento cuando se ensamblan. Cada uno de ellos tiene la misma eficacia al hacerlo.", + "create.ponder.tag.arm_targets": "Objetivos para los brazos mecánicos", + "create.ponder.tag.arm_targets.description": "Componentes que pueden seleccionarse como entradas o salidas del brazo mecánico", + "create.ponder.tag.kinetic_appliances": "Dispositivos cinéticos", + "create.ponder.tag.kinetic_appliances.description": "Componentes que utilizan la fuerza rotacional", + "create.ponder.tag.kinetic_sources": "Fuentes cinéticas", + "create.ponder.tag.kinetic_sources.description": "Componentes que generan fuerza rotacional", + "create.ponder.tag.movement_anchor": "Anclas de movimiento", + "create.ponder.tag.movement_anchor.description": "Componentes que permiten crear artilugios en movimiento, animando una estructura anexa de diversas maneras", + "create.ponder.tag.kinetic_relays": "Transmisores cinéticos", + "create.ponder.tag.kinetic_relays.description": "Componentes que ayudan a transmitir la fuerza rotacional en otro lugar", + "create.ponder.tag.contraption_actor": "Actores del artilugio", + "create.ponder.tag.contraption_actor.description": "Componentes que exponen un comportamiento especial cuando están unidos a un artilugio en movimiento", + "create.ponder.tag.creative": "Modo creativo", + "create.ponder.tag.creative.description": "Componentes que no suelen estar disponibles para el Modo Supervivencia", + "create.ponder.tag.logistics": "Transporte de objetos", + "create.ponder.tag.logistics.description": "Componentes que ayudan a desplazar los objetos", + + "create.ponder.adjustable_pulse_repeater.header": "Controlar señales mediante repetidores de pulsos ajustables", + "create.ponder.adjustable_pulse_repeater.text_1": "Los repetidores de pulsos ajustables emiten un pulso corto con un retardo", + "create.ponder.adjustable_pulse_repeater.text_2": "Con la rueda del ratón se puede configurar el tiempo de carga", + "create.ponder.adjustable_pulse_repeater.text_3": "Los retrasos configurados pueden ser de hasta 30 minutos", + + "create.ponder.adjustable_repeater.header": "Controlar señales mediante repetidores ajustables", + "create.ponder.adjustable_repeater.text_1": "Los repetidores ajustables se comportan de forma similar a los repetidores normales", + "create.ponder.adjustable_repeater.text_2": "Se cargan durante un tiempo determinado...", + "create.ponder.adjustable_repeater.text_3": "...y se enfrían durante el mismo tiempo", + "create.ponder.adjustable_repeater.text_4": "Con la rueda del ratón se puede configurar el tiempo de carga", + "create.ponder.adjustable_repeater.text_5": "Los retrasos configurados pueden variar hasta 30 minutos", + + "create.ponder.analog_lever.header": "Controlar señales mediante la palanca analógica", + "create.ponder.analog_lever.text_1": "Las palancas analógicas son una fuente compacta y precisa de energía de redstone", + "create.ponder.analog_lever.text_2": "Haz clic derecho para aumentar su potencia analógica", + "create.ponder.analog_lever.text_3": "Usa Mayús izdo + clic derecho para volver a disminuir su potencia", + + "create.ponder.andesite_tunnel.header": "Usar túneles de andesita", + "create.ponder.andesite_tunnel.text_1": "Los túneles de andesita se pueden utilizar para tapar las correas", + "create.ponder.andesite_tunnel.text_2": "Siempre que un túnel de andesita tenga conexiones a los lados...", + "create.ponder.andesite_tunnel.text_3": "...dividirá exactamente un elemento de cualquier pila que pase", + "create.ponder.andesite_tunnel.text_4": "El resto continuará su camino", + + "create.ponder.basin.header": "Procesar objetos en la cuenca", + "create.ponder.basin.text_1": "Una cuenca puede contener objetos y fluidos para su procesamiento", + "create.ponder.basin.text_2": "Después de un paso de procesamamiento, las cuencas intentan descargar por debajo a un lado de ellas", + "create.ponder.basin.text_3": "Cuando un ingrediente válido está presente, la cuenca mostrará un conducto de salida", + "create.ponder.basin.text_4": "Aquí se pueden aplicar varias opciones", + "create.ponder.basin.text_5": "Las salidas serán capturadas por el inventario que está por debajo", + "create.ponder.basin.text_6": "Sin conducto de salida, la cuenca retendrá los objetos creados en su procesamiento", + "create.ponder.basin.text_7": "Esto puede ser útil si las salidas deben ser reutilizadas como ingredientes", + "create.ponder.basin.text_8": "Las salidas deseadas tendrán que ser extraídas de la cuenca", + "create.ponder.basin.text_9": "Podría ser necesario un filtro para evitar sacar los objetos no procesados", + + "create.ponder.bearing_modes.header": "Modos de movimiento del rodamiento mecánico", + "create.ponder.bearing_modes.text_1": "Cuando se detenga, el rodamiento mecánico colocará la estructura en el ángulo más cercano alineado con la cuadrícula", + "create.ponder.bearing_modes.text_2": "Se puede configurar para que nunca vuelva a los bloques sólidos, o sólo cerca del ángulo en el que comenzó", + + "create.ponder.belt_casing.header": "Correas revestidas", + "create.ponder.belt_casing.text_1": "Se puede utilizar revestidor de latón o andesita para decorar las correas", + "create.ponder.belt_casing.text_2": "Se puede utilizar una llave inglesa para quitar el revestimiento", + + "create.ponder.belt_connector.header": "El uso de las correas mecánicas", + "create.ponder.belt_connector.text_1": "Al hacer clic derecho en dos ejes con una correa mecánica se conectarán entre sí", + "create.ponder.belt_connector.text_2": "Las selecciones accidentales pueden ser canceladas con Mayús izdo + clic derecho", + "create.ponder.belt_connector.text_3": "Se pueden añadir ejes adicionales en toda la correa", + "create.ponder.belt_connector.text_4": "Los ejes conectados a través de correas girarán con velocidad y dirección idénticas", + "create.ponder.belt_connector.text_5": "Los ejes añadidos se pueden quitar con la llave inglesa", + "create.ponder.belt_connector.text_6": "Las correas mecánicas se pueden teñir con fines estéticos", + + "create.ponder.belt_directions.header": "Orientaciones válidas para las correas mecánicas", + "create.ponder.belt_directions.text_1": "Las correas mecánicas no pueden conectarse en direcciones arbitrarias", + "create.ponder.belt_directions.text_2": "1. Pueden conectarse horizontalmente", + "create.ponder.belt_directions.text_3": "2. Pueden conectarse en diagonal", + "create.ponder.belt_directions.text_4": "3. Pueden conectarse verticalmente", + "create.ponder.belt_directions.text_5": "4. Y pueden conectar ejes verticales horizontalmente", + "create.ponder.belt_directions.text_6": "Estas son todas las direcciones posibles. Pueden abarcar cualquier longitud entre 2 y 20 bloques", + + "create.ponder.belt_transport.header": "El uso de las correas mecánicas para la logística", + "create.ponder.belt_transport.text_1": "Las correas mecánicas transportan objetos y otras entidades", + "create.ponder.belt_transport.text_2": "Haz clic derecho con la mano vacía para sacar objetos de una 'cinta'", + + "create.ponder.blaze_burner.header": "Alimentar quemadores de blaze", + "create.ponder.blaze_burner.text_1": "Los quemadores de blaze pueden proporcionar calor a los objetos procesados en una cuenca", + "create.ponder.blaze_burner.text_2": "Para ello, el blaze tiene que ser alimentado con objetos inflamables", + "create.ponder.blaze_burner.text_3": "Con un pastel de blaze, el quemador puede alcanzar un mayor nivel de calor", + "create.ponder.blaze_burner.text_4": "El proceso de alimentación puede automatizarse utilizando desplegadores o brazos mecánicos", + + "create.ponder.brass_funnel.header": "El embudo de latón", + "create.ponder.brass_funnel.text_1": "Los embudos de andesita sólo pueden extraer objetos individuales", + "create.ponder.brass_funnel.text_2": "Los embudos de latón pueden extraer hasta una pila completa", + "create.ponder.brass_funnel.text_3": "Usar la rueda de desplazamiento del ratón en la ranura para filtros permite un control preciso del tamaño de la pila extraída.", + "create.ponder.brass_funnel.text_4": "El uso de objetos en la ranura de filtrado restringirá el embudo para transferir sólo las pilas que coincidan.", + + "create.ponder.brass_tunnel.header": "Usar túneles de latón", + "create.ponder.brass_tunnel.text_1": "Los túneles de latón pueden utilizarse para tapar las correas", + "create.ponder.brass_tunnel.text_2": "Tienen ranuras de filtro en cada lado abierto", + "create.ponder.brass_tunnel.text_3": "Los filtros en las conexiones de entrada simplemente bloquean los objetos que no coincidan", + "create.ponder.brass_tunnel.text_4": "Los filtros en las conexiones de salida pueden utilizarse para ordenar los objetos por tipo", + "create.ponder.brass_tunnel.text_5": "Siempre que un objeto de paso tenga múltiples salidas válidas, el modo de distribución decidirá cómo manejarlo", + "create.ponder.brass_tunnel.text_6": "Los túneles de latón en bandas paralelas formarán un grupo", + "create.ponder.brass_tunnel.text_7": "Los objetos entrantes se distribuirán ahora por todas las salidas conectadas", + "create.ponder.brass_tunnel.text_8": "Para ello, los objetos también pueden insertarse en el bloque del túnel directamente", + + "create.ponder.brass_tunnel_modes.header": "Modos de distribución del túnel de latón", + "create.ponder.brass_tunnel_modes.text_1": "Mediante una llave inglesa se puede configurar el comportamiento de distribución de los túneles de latón", + "create.ponder.brass_tunnel_modes.text_10": "'Sincronizar entradas' es una configuración única de los túneles de latón", + "create.ponder.brass_tunnel_modes.text_11": "Las entradas sólo pueden pasar si cada túnel del grupo tiene una en espera", + "create.ponder.brass_tunnel_modes.text_12": "Esto asegura que todas las correas afectadas suministren objetos al mismo tiempo", + "create.ponder.brass_tunnel_modes.text_2": "El modo División intentará distribuir la pila uniformemente entre las salidas disponibles", + "create.ponder.brass_tunnel_modes.text_3": "Si una salida no puede tomar más objetos, se saltará", + "create.ponder.brass_tunnel_modes.text_4": "El modo División forzada nunca saltará las salidas, y en su lugar esperará hasta que estén libres", + "create.ponder.brass_tunnel_modes.text_5": "El modo Round Robin mantiene las pilas enteras, y recorre las salidas de forma iterativa", + "create.ponder.brass_tunnel_modes.text_6": "Una vez más, si una salida no puede aceptar más objetos, se saltará", + "create.ponder.brass_tunnel_modes.text_7": "El modo Round Robin forzado nunca omite salidas", + "create.ponder.brass_tunnel_modes.text_8": "El modo Preferir el más cercano prioriza las salidas más cercanas a la ubicación de entrada de los objetos", + "create.ponder.brass_tunnel_modes.text_9": "El modo Aleatorizar distribuirá pilas enteras a salidas elegidas al azar", + + "create.ponder.cart_assembler.header": "Mover estructuras usando ensambladores de vagonetas", + "create.ponder.cart_assembler.text_1": "Los ensambladores de vagonetas montan estructuras adjuntas a las vagonetas que pasan", + "create.ponder.cart_assembler.text_2": "Sin una señal de redstone, desmonta los artilugios de vagoneta que pasan de nuevo en bloques", + "create.ponder.cart_assembler.text_3": "El uso de una llave inglesa en una vagoneta te permitirá llevar el artilugio a otro lugar", + + "create.ponder.cart_assembler_dual.header": "Ensamblajes de artilugios de vagoneta", + "create.ponder.cart_assembler_dual.text_1": "Siempre que dos ensambladores de vagoneta compartan una estructura adjunta...", + "create.ponder.cart_assembler_dual.text_2": "...al alimentar a cualquiera de ellos se creará un artilugio de vagoneta", + "create.ponder.cart_assembler_dual.text_3": "Las vagonetas se comportarán como las conectadas a través del acoplamiento de vagoneta", + + "create.ponder.cart_assembler_modes.header": "Configurar la orientación de los artilugios de vagonetas", + "create.ponder.cart_assembler_modes.text_1": "Los artilugios de vagonetas girarán para orientarse hacia el movimiento de sus vagonetas", + "create.ponder.cart_assembler_modes.text_2": "Esta flecha indica qué lado de la estructura se considerará la parte delantera", + "create.ponder.cart_assembler_modes.text_3": "Si el ensamblador está configurado para bloquear la rotación, la orientación de los artilugios nunca cambiará", + + "create.ponder.cart_assembler_rails.header": "Otros tipos de vagonetas y raíles", + "create.ponder.cart_assembler_rails.text_1": "Los ensambladores de vagonetas en raíles normales no afectarán el movimiento de las vagonetas que pasen", + "create.ponder.cart_assembler_rails.text_2": "Cuando se encuentre en un raíl motorizado o en un raíl de control, las vagonetas se mantendrán en su sitio hasta que sea motorizado", + "create.ponder.cart_assembler_rails.text_3": "Se pueden utilizar otros tipos de vagonetas como anclaje", + "create.ponder.cart_assembler_rails.text_4": "Los artilugios de vagonetas de horno se mantendrán alimentados a sí mismos, sacando combustible de cualquier inventario adjunto", + + "create.ponder.chain_drive.header": "Transmitir fuerza rotacional con las cadenas de transmisión", + "create.ponder.chain_drive.text_1": "Las cadenas de transmisión transmiten la rotación entre sí en fila", + "create.ponder.chain_drive.text_2": "Todos los ejes conectados así girarán en la misma dirección", + "create.ponder.chain_drive.text_3": "Cualquier parte de la fila puede girar 90 grados usando una llave inglesa", + + "create.ponder.chain_gearshift.header": "Controlar la velocidad de rotación con la cadena de transmisión ajustable", + "create.ponder.chain_gearshift.text_1": "Las cadenas de transmisión ajustables sin alimentación se comportan exactamente como las cadenas de transmisión", + "create.ponder.chain_gearshift.text_2": "Cuando están alimentadas, la velocidad transmitida a las demás cadenas de transmisión de la fila se duplica", + "create.ponder.chain_gearshift.text_3": "Siempre que la cadena de transmisión alimentada no esté en el origen, su velocidad se reducirá a la mitad", + "create.ponder.chain_gearshift.text_4": "En ambos casos, las cadenas de transmisión de la fila siempre funcionan a 2 veces la velocidad de la cadena de transmisión alimentada", + "create.ponder.chain_gearshift.text_5": "Utilizando señales analógicas, la relación puede ajustarse con mayor precisión, entre 1 y 2", + "create.ponder.chain_gearshift.text_6": "12 RPM", + + "create.ponder.chute.header": "Transportar objetos hacia abajo a través de ductos", + "create.ponder.chute.text_1": "Los ductos pueden transportar objetos verticalmente desde y hacia los inventarios", + "create.ponder.chute.text_2": "Usando la llave inglesa, se puede crear una ventana", + "create.ponder.chute.text_3": "Colocar ductos apuntando a las caras laterales de otro lo hará en diagonal", + + "create.ponder.chute_upward.header": "Transportar objetos hacia arriba mediante ductos", + "create.ponder.chute_upward.text_1": "Usando ventiladores revestidos en la parte superior o inferior, un ducto puede transportar objetos hacia arriba", + "create.ponder.chute_upward.text_2": "Al inspeccionar los ductos con las gafas del constructor, se revela información sobre la dirección del movimiento", + "create.ponder.chute_upward.text_3": "En el extremo 'bloqueado', los objetos tendrán que ser insertados/tomados de los lados", + + "create.ponder.clockwork_bearing.header": "Animar estructuras con rodamientos tipo reloj", + "create.ponder.clockwork_bearing.text_1": "Los rodamientos tipo reloj se fijan a los bloques que tienen delante", + "create.ponder.clockwork_bearing.text_2": "Al recibir fuerza rotacional, la estructura girará según la hora del día", + "create.ponder.clockwork_bearing.text_3": "3:00", + "create.ponder.clockwork_bearing.text_4": "4:00", + "create.ponder.clockwork_bearing.text_5": "Haz clic derecho en el rodamiento para iniciar o detener la animación de la estructura", + "create.ponder.clockwork_bearing.text_6": "Delante de la manecilla de las horas se puede añadir una segunda estructura", + "create.ponder.clockwork_bearing.text_7": "Asegúrese de que las dos estructuras no están unidas entre sí con pegamento o algo similar", + "create.ponder.clockwork_bearing.text_8": "La segunda estructura ahora girará como el minutero", + + "create.ponder.clutch.header": "Controlar la fuerza rotacional mediante un embrague", + "create.ponder.clutch.text_1": "Los embragues transmitirán la rotación en línea recta", + "create.ponder.clutch.text_2": "Cuando se alimentan con redstone, rompen la conexión", + + "create.ponder.cog_speedup.header": "Cambiar de marchas con engranajes", + "create.ponder.cog_speedup.text_1": "Los engranajes grandes y pequeños pueden conectarse en diagonal", + "create.ponder.cog_speedup.text_2": "Al cambiar de engranajes grandes a pequeños, la velocidad rotacional se duplicará", + "create.ponder.cog_speedup.text_3": "Inversamente, la velocidad rotacional se reducirá a la mitad", + + "create.ponder.cogwheel.header": "Transmitir fuerza rotacional mediante engranajes", + "create.ponder.cogwheel.text_1": "Los engranajes transmitirán la rotación a otros engranajes adyacentes", + "create.ponder.cogwheel.text_2": "Los ejes adyacentes conectados así, girarán en direcciones opuestas", + + "create.ponder.creative_fluid_tank.header": "Tanque de fluídos creativo", + "create.ponder.creative_fluid_tank.text_1": "Los depósitos de fluidos creativos pueden utilizarse para proporcionar un suministro de fluidos sin fondo", + "create.ponder.creative_fluid_tank.text_2": "Haga clic con el botón derecho en un elemento que contenga fluido para configurarlo", + "create.ponder.creative_fluid_tank.text_3": "Las redes de tuberías pueden ahora extraer sin cesar el fluido asignado del depósito", + "create.ponder.creative_fluid_tank.text_4": "Cualquier fluido empujado de vuelta a un tanque de fluido creativo será anulado", + + "create.ponder.creative_motor.header": "Generar fuerza rotacional con motores creativos", + "create.ponder.creative_motor.text_1": "Los motores creativos son una fuente compacta y configurable de fuerza rotacional", + "create.ponder.creative_motor.text_2": "Usar la rueda de desplazamiento del ratón en su parte trasera cambia las RPM de la salida rotacional", + + "create.ponder.crushing_wheels.header": "Procesar objetos con las ruedas trituradoras", + "create.ponder.crushing_wheels.text_1": "Un par de ruedas trituradoras pueden moler objetos de forma muy eficaz", + "create.ponder.crushing_wheels.text_2": "Su fuerza rotacional tiene que hacerlas girar una contra otra", + "create.ponder.crushing_wheels.text_3": "Los objetos lanzados o insertados en la parte superior serán procesados", + "create.ponder.crushing_wheels.text_4": "Los objetos también pueden ser insertados y recogidos a través de medios automatizados", + + "create.ponder.deployer.header": "Usar el desplegador", + "create.ponder.deployer.text_1": "Dada la fuerza rotacional, un desplegador puede imitar las interacciones de los jugadores", + "create.ponder.deployer.text_10": "Haz clic derecho en el frente para darle un objeto a utilizar", + "create.ponder.deployer.text_11": "Los objetos también pueden ser insertados automáticamente", + "create.ponder.deployer.text_12": "Los desplegadores llevan una ranura de filtro", + "create.ponder.deployer.text_13": "Cuando se establece un filtro, sólo se activa mientras se mantiene un elemento coincidente", + "create.ponder.deployer.text_14": "Ahora sólo se pueden insertar los objetos que coincidan con el filtro...", + "create.ponder.deployer.text_15": "...y sólo se extraerán los objetos que no coincidan", + "create.ponder.deployer.text_2": "Siempre interactuará con la posición 2 bloques delante de sí mismo", + "create.ponder.deployer.text_3": "Los bloques situados directamente delante no lo obstruirán", + "create.ponder.deployer.text_4": "Los desplegadores pueden:", + "create.ponder.deployer.text_5": "Colocar bloques,", + "create.ponder.deployer.text_6": "Usar objetos,", + "create.ponder.deployer.text_7": "Activar bloques,", + "create.ponder.deployer.text_8": "Cosechar bloques", + "create.ponder.deployer.text_9": "Y atacar criaturas", + + "create.ponder.deployer_contraption.header": "Usar desplegadores en artilugios", + "create.ponder.deployer_contraption.text_1": "Siempre que los desplegadores se muevan como parte de un artilugio animado...", + "create.ponder.deployer_contraption.text_2": "Se activan en cada ubicación visitada, utilizando objetos de los inventarios de cualquier parte del artilugio", + "create.ponder.deployer_contraption.text_3": "La ranura para filtros se puede utilizar para especificar qué objetos tirar", + + "create.ponder.deployer_modes.header": "Modos del desplegador", + "create.ponder.deployer_modes.text_1": "Por defecto, un desplegador imita la interacción del clic derecho del ratón", + "create.ponder.deployer_modes.text_2": "Usando una llave inglesa, se puede configurar para imitar un clic izquierdo en su lugar", + + "create.ponder.deployer_processing.header": "Procesar objetos mediante desplegadores", + "create.ponder.deployer_processing.text_1": "Con un objeto de sujeción ajustado, los desplegadores pueden procesar los objetos proporcionados por debajo de ellos", + "create.ponder.deployer_processing.text_2": "Los objetos de entrada pueden soltarse o colocarse en un depósito bajo el desplegador", + "create.ponder.deployer_processing.text_3": "Cuando los objetos se proporcionan en una 'cinta'...", + "create.ponder.deployer_processing.text_4": "El desplegador los retendrá y procesará automáticamente", + + "create.ponder.deployer_redstone.header": "Controlar desplegadores con redstone", + "create.ponder.deployer_redstone.text_1": "Al controlar los desplegadores con redstone, éstos no se activarán", + "create.ponder.deployer_redstone.text_2": "Antes de detenerse, el desplegador terminará cualquier ciclo iniciado", + "create.ponder.deployer_redstone.text_3": "Por lo tanto, un pulso negativo puede ser utilizado para desencadenar exactamente un ciclo de activación", + + "create.ponder.depot.header": "Usar depósitos", + "create.ponder.depot.text_1": "Los depósitos pueden servir como objetos 'fijos' de la correa", + "create.ponder.depot.text_2": "Haz clic derecho para colocar o eliminar manualmente objetos del mismo", + "create.ponder.depot.text_3": "Al igual que las correas mecánicas, pueden proporcionar objetos para su procesamiento", + "create.ponder.depot.text_4": "...así como proporcionar objetos a los brazos mecánicos", + + "create.ponder.empty_blaze_burner.header": "Usar quemadores de blaze vacíos", + "create.ponder.empty_blaze_burner.text_1": "Haz clic derecho en un blaze con el quemador vacío para capturarlo", + "create.ponder.empty_blaze_burner.text_2": "Alternativamente, los blaze pueden ser recogidos de sus spawners directamente", + "create.ponder.empty_blaze_burner.text_3": "Ahora tienes una fuente de calor ideal para varias máquinas", + "create.ponder.empty_blaze_burner.text_4": "Por motivos estéticos, los quemadores de blaze vacíos también se pueden encender con pedernal y acero", + "create.ponder.empty_blaze_burner.text_5": "La llama puede transformarse utilizando un objeto con alma", + "create.ponder.empty_blaze_burner.text_6": "Sin embargo, no son adecuados para la calefacción industrial", + + "create.ponder.encased_fluid_pipe.header": "Revestir tuberías de fluídos", + "create.ponder.encased_fluid_pipe.text_1": "El revestidor de cobre puede utilizarse para decorar las tuberías de fluidos", + "create.ponder.encased_fluid_pipe.text_2": "Además de estar ocultas, las tuberías revestidas están bloqueadas en su estado de conectividad", + "create.ponder.encased_fluid_pipe.text_3": "Ya no reaccionará a los bloques vecinos que se añadan o eliminen", + + "create.ponder.fan_direction.header": "El flujo de aire de los ventiladores revestidos", + "create.ponder.fan_direction.text_1": "Los ventiladores revestidos utilizan la fuerza rotacional para crear una corriente de aire", + "create.ponder.fan_direction.text_2": "La fuerza y la dirección del flujo dependen de la fuerza rotacional suministrada", + + "create.ponder.fan_processing.header": "Procesar objetos mediante ventiladores revestidos", + "create.ponder.fan_processing.text_1": "Al pasar por lava, el flujo de aire se calienta", + "create.ponder.fan_processing.text_2": "Los objetos capturados en la zona serán fundidos", + "create.ponder.fan_processing.text_3": "Los artículos de comida arrojados aquí serán incinerados", + "create.ponder.fan_processing.text_4": "En su lugar, se debería utilizar una instalación de ahumado, usando fuego", + "create.ponder.fan_processing.text_5": "Los flujos de aire que pasan por el agua crean una instalación de lavado", + "create.ponder.fan_processing.text_6": "Se puede hacer un nuevo e interesante procesamiento con él", + "create.ponder.fan_processing.text_7": "La velocidad del ventilador NO afecta a la velocidad de procesamiento, sólo a su rango", + "create.ponder.fan_processing.text_8": "El procesamiento del ventilador también puede aplicarse a los objetos de los depósitos y las correas", + + "create.ponder.fan_source.header": "Generar fuerza rotacional mediante ventiladores revestidos", + "create.ponder.fan_source.text_1": "Los ventiladores orientados hacia una fuente de calor pueden proporcionar fuerza rotacional", + "create.ponder.fan_source.text_2": "Cuando se les da una señal de redstone, los ventiladores comenzarán a proporcionar fuerza", + + "create.ponder.fluid_pipe_flow.header": "Transportar fluidos mediante tuberías de cobre", + "create.ponder.fluid_pipe_flow.text_1": "Las tuberías de fluidos pueden conectar dos o más fuentes y objetivos de fluidos", + "create.ponder.fluid_pipe_flow.text_2": "Utilizando una llave, se puede dar a un segmento de tubo recto una ventana", + "create.ponder.fluid_pipe_flow.text_3": "Las tuberías con ventanas no se conectarán a ningún otro segmento de tubería adyacente", + "create.ponder.fluid_pipe_flow.text_4": "Accionadas por bombas mecánicas, las tuberías pueden transportar fluidos", + "create.ponder.fluid_pipe_flow.text_5": "Al principio no se extrae ningún líquido", + "create.ponder.fluid_pipe_flow.text_6": "Una vez que el flujo los conecta, los puntos finales transfieren gradualmente su contenido", + "create.ponder.fluid_pipe_flow.text_7": "Así, los bloques de tuberías nunca contienen 'físicamente' ningún fluido", + + "create.ponder.fluid_pipe_interaction.header": "Drenaje y llenado de contenedores de fluidos", + "create.ponder.fluid_pipe_interaction.text_1": "Los puntos finales de una red de tuberías pueden interactuar con una variedad de bloques", + "create.ponder.fluid_pipe_interaction.text_2": "Cualquier bloque con capacidad para almacenar fluidos puede ser llenado o vaciado", + "create.ponder.fluid_pipe_interaction.text_3": "Los bloques de origen justo delante de un extremo abierto pueden ser recogidos...", + "create.ponder.fluid_pipe_interaction.text_4": "...mientras que el derrame en espacios vacíos puede crear fuentes de fluidos", + "create.ponder.fluid_pipe_interaction.text_5": "Las tuberías también pueden extraer fluidos de un puñado de otros bloques directamente", + + "create.ponder.fluid_tank_sizes.header": "Dimensiones de un depósito de fluidos", + "create.ponder.fluid_tank_sizes.text_1": "Los depósitos de fluidos pueden combinarse para aumentar la capacidad total", + "create.ponder.fluid_tank_sizes.text_2": "Su cuadrado base puede tener hasta 3 bloques de ancho...", + "create.ponder.fluid_tank_sizes.text_3": "...y crecen en altura en más de 30 capas adicionales", + "create.ponder.fluid_tank_sizes.text_4": "Con una llave inglesa, se puede cambiar la ventana de un tanque", + + "create.ponder.fluid_tank_storage.header": "Almacenar fluidos en depósitos de fluidos", + "create.ponder.fluid_tank_storage.text_1": "Los depósitos de fluidos pueden utilizarse para almacenar grandes cantidades de fluidos", + "create.ponder.fluid_tank_storage.text_2": "Las redes de tuberías pueden empujar y arrastrar fluidos desde cualquier lado", + "create.ponder.fluid_tank_storage.text_3": "El fluido contenido puede ser medido por un Comparador", + "create.ponder.fluid_tank_storage.text_4": "Sin embargo, en el Modo Supervivencia no se pueden añadir o tomar fluidos manualmente", + "create.ponder.fluid_tank_storage.text_5": "Puede utilizar cuencas, drenadores de objetos y tuberías para vaciar o llenar objetos que contengan líquido", + + "create.ponder.flywheel.header": "Generar fuerza rotacional con la rueda de inercia", + "create.ponder.flywheel.text_1": "Las ruedas de inercia son necesarias para generar fuerza rotacional con el motor de horno", + "create.ponder.flywheel.text_2": "La fuerza rotacional proporcionada tiene una capacidad de estrés muy grande", + "create.ponder.flywheel.text_3": "El uso de un alto horno duplicará la eficiencia del motor", + + "create.ponder.funnel_compat.header": "Compatibilidades con el embudo", + "create.ponder.funnel_compat.text_1": "Los embudos deberían interactuar bien con un puñado de otros componentes", + "create.ponder.funnel_compat.text_2": "Sierras verticales", + "create.ponder.funnel_compat.text_3": "Depósitos", + "create.ponder.funnel_compat.text_4": "Drenadores de objetos", + + "create.ponder.funnel_direction.header": "Dirección de la transferencia", + "create.ponder.funnel_direction.text_1": "Colocado normalmente, extrae objetos del inventario", + "create.ponder.funnel_direction.text_2": "Colocado mientras pulsa Mayús izdo, pone objetos en el inventario", + "create.ponder.funnel_direction.text_3": "Usando una llave inglesa, el embudo puede ser volteado después de su colocación", + "create.ponder.funnel_direction.text_4": "Se aplicarán las mismas reglas para la mayoría de las orientaciones", + "create.ponder.funnel_direction.text_5": "Los embudos en las correas extraerán/insertarán dependiendo de su dirección de movimiento", + + "create.ponder.funnel_intro.header": "Usar embudos", + "create.ponder.funnel_intro.text_1": "Los embudos son ideales para transferir objetos desde y hacia los inventarios", + + "create.ponder.funnel_redstone.header": "Embudos alimentados con redstone", + "create.ponder.funnel_redstone.text_1": "La energía de redstone impedirá la actuación de cualquier embudo", + + "create.ponder.funnel_transfer.header": "Transferencia directa", + "create.ponder.funnel_transfer.text_1": "Los embudos no pueden transferir nunca entre inventarios cerrados directamente", + "create.ponder.funnel_transfer.text_2": "Los ductos o los ductos inteligentes podrían ser más adecuados para estos fines", + "create.ponder.funnel_transfer.text_3": "Lo mismo se aplica para el movimiento horizontal. Una correa mecánica debería ayudar aquí", + + "create.ponder.furnace_engine.header": "Generar fuerza rotacional con el motor de horno", + "create.ponder.furnace_engine.text_1": "Los motores de horno generan fuerza rotacional mientras su horno adjunto está funcionando", + "create.ponder.furnace_engine.text_2": "La fuerza rotacional proporcionada tiene una capacidad de estrés muy grande", + "create.ponder.furnace_engine.text_3": "El uso de un alto horno duplicará la eficiencia del motor", + + "create.ponder.gantry_carriage.header": "Usar carros de grúa", + "create.ponder.gantry_carriage.text_1": "Los carros de grúa pueden montarse y deslizarse a lo largo de un eje de grúa", + "create.ponder.gantry_carriage.text_2": "Las instalaciones de grúa pueden mover bloques adjuntos", + + "create.ponder.gantry_cascaded.header": "Grúas en cascada", + "create.ponder.gantry_cascaded.text_1": "Los ejes de grúas se unen a un carro de grúa sin necesidad de pegamento", + "create.ponder.gantry_cascaded.text_2": "Lo mismo se aplica a los carros de grúa en los ejes de grúas desplazados", + "create.ponder.gantry_cascaded.text_3": "Así, un sistema de grúas puede estar en cascada para cubrir múltiples ejes de movimiento", + + "create.ponder.gantry_direction.header": "Dirección del movimiento de la grúa", + "create.ponder.gantry_direction.text_1": "Los ejes de grúa pueden tener orientaciones opuestas", + "create.ponder.gantry_direction.text_2": "La dirección de movimiento de los carros de grúa depende de la orientación de sus ejes", + "create.ponder.gantry_direction.text_3": "...así como de su sentido de rotación", + "create.ponder.gantry_direction.text_4": "Se aplican las mismas reglas para la rotación propagada", + + "create.ponder.gantry_redstone.header": "Propagación de la potencia de la grúa", + "create.ponder.gantry_redstone.text_1": "Los ejes de grúa alimentados con redstone dejan de mover sus carros", + "create.ponder.gantry_redstone.text_2": "En su lugar, su fuerza rotacional se transmite al eje de salida de los carros", + + "create.ponder.gantry_shaft.header": "Usar ejes de grúa", + "create.ponder.gantry_shaft.text_1": "Los ejes de grúa forman la base de una instalación de grúas. Los carros adjuntos se moverán a lo largo de ellos", + "create.ponder.gantry_shaft.text_2": "Las instalaciones de grúas pueden mover los bloques adjuntos", + + "create.ponder.gearbox.header": "Transmitir fuerza rotacional mediante cajas de transmisión", + "create.ponder.gearbox.text_1": "Saltar entre ejes de rotación puede volverse voluminoso rápidamente", + "create.ponder.gearbox.text_2": "Una caja de transmisión es el equivalente más compacto de esta configuración", + "create.ponder.gearbox.text_3": "Los ejes giran en las direcciones reflejadas...", + "create.ponder.gearbox.text_4": "...esto quiere decir que las conexiones rectas se invierten", + + "create.ponder.gearshift.header": "Controlar la dirección rotacional mediante una caja de cambios", + "create.ponder.gearshift.text_1": "La caja de cambios transmitirá la rotación en línea recta", + "create.ponder.gearshift.text_2": "Cuando es alimentada con redstone, invierte la transmisión", + + "create.ponder.hand_crank.header": "Generar fuerza rotacional mediante manivelas", + "create.ponder.hand_crank.text_1": "Las manivelas pueden ser utilizadas para aplicar fuerza rotacional manualmente", + "create.ponder.hand_crank.text_2": "Mantén pulsado clic derecho para girar en sentido antihorario", + "create.ponder.hand_crank.text_3": "Su velocidad de transmisión es relativamente alta", + "create.ponder.hand_crank.text_4": "Mayús izdo + clic derecho pulsado para girar en sentido horario", + + "create.ponder.hose_pulley.header": "Llenado y vaciado de fuentes mediante poleas de manguera", + "create.ponder.hose_pulley.text_1": "Las poleas para mangueras pueden utilizarse para llenar o drenar grandes masas de fluido", + "create.ponder.hose_pulley.text_2": "Con entrada cinética, se puede controlar la altura de la manguera de las poleas", + "create.ponder.hose_pulley.text_3": "La polea se retrae mientras la rotación de entrada se invierte", + "create.ponder.hose_pulley.text_4": "En el lado opuesto, se pueden conectar las tuberías", + "create.ponder.hose_pulley.text_5": "Las redes de tuberías conectadas pueden proporcionar fluido a la manguera...", + "create.ponder.hose_pulley.text_6": "...o tirar de él, vaciando la piscina en su lugar", + "create.ponder.hose_pulley.text_7": "La velocidad de llenado y vaciado de la polea depende totalmente del caudal de las redes de fluidos", + + "create.ponder.hose_pulley_infinite.header": "Llenado y drenaje pasivo de grandes masas de fluido", + "create.ponder.hose_pulley_infinite.text_1": "Al desplegar la polea de manguera en un océano lo suficientemente grande...", + "create.ponder.hose_pulley_infinite.text_2": "Proporcionará/eliminará fluidos sin afectar a la fuente", + "create.ponder.hose_pulley_infinite.text_3": "Las redes de tuberías pueden llevar fluidos de forma ilimitada desde/hacia dichas poleas", + + "create.ponder.hose_pulley_level.header": "Nivel de llenado y vaciado de las poleas de las mangueras", + "create.ponder.hose_pulley_level.text_1": "Mientras esté totalmente retraída, la polea de la manguera no puede funcionar", + "create.ponder.hose_pulley_level.text_2": "El drenaje va de arriba a abajo", + "create.ponder.hose_pulley_level.text_3": "El nivel de la superficie terminará justo debajo de donde termina la manguera", + "create.ponder.hose_pulley_level.text_4": "El llenado va de abajo a arriba", + "create.ponder.hose_pulley_level.text_5": "La piscina llena no crecerá más allá de la capa por encima del extremo de la manguera", + + "create.ponder.item_drain.header": "Vaciar contenedores de fluidos mediante drenajes de objetos", + "create.ponder.item_drain.text_1": "Los drenajes de objetos pueden extraer los fluidos de los objetos", + "create.ponder.item_drain.text_2": "Haz clic derecho para verter los fluidos de tu objeto retenido en él", + "create.ponder.item_drain.text_3": "Cuando los artículos se insertan desde el lado...", + "create.ponder.item_drain.text_4": "...ruedan a través, vaciando su líquido contenido", + "create.ponder.item_drain.text_5": "Las redes de tuberías pueden ahora extraer el fluido del buffer interno de los desagües", + + "create.ponder.large_cogwheel.header": "Transmitir fuerza rotacional mediante engranajes grandes", + "create.ponder.large_cogwheel.text_1": "Los engranajes grandes pueden conectarse entre sí en ángulo recto", + "create.ponder.large_cogwheel.text_2": "Ayudarán a transmitir la velocidad transportada a otros ejes de rotación.", + + "create.ponder.linear_chassis_attachment.header": "Fijar bloques mediante el chasis lineal", + "create.ponder.linear_chassis_attachment.text_1": "Las caras abiertas de un chasis lineal pueden hacerse pegajosas", + "create.ponder.linear_chassis_attachment.text_2": "Haz clic de nuevo para que se pegue el lado opuesto", + "create.ponder.linear_chassis_attachment.text_3": "Mayús izdo + clic derecho con la mano vacía para eliminar el pegamento", + "create.ponder.linear_chassis_attachment.text_4": "Las caras pegadas del chasis lineal fijarán una línea de bloques delante de él", + "create.ponder.linear_chassis_attachment.text_5": "Utilizando una llave inglesa, se puede especificar un rango preciso", + "create.ponder.linear_chassis_attachment.text_6": "Manteniendo pulsada la tecla [Ctrl] y usando la rueda central del ratón, se ajusta el rango de todos los bloques de chasis adjuntos", + "create.ponder.linear_chassis_attachment.text_7": "Para fijar los bloques a cualquier otro lado es necesario utilizar pegamento", + "create.ponder.linear_chassis_attachment.text_8": "Utilizando esta mecánica, las estructuras de cualquier forma pueden moverse como un artilugio", + + "create.ponder.linear_chassis_group.header": "Mover chasis lineales en grupos", + "create.ponder.linear_chassis_group.text_1": "Los chasis lineales se conectan a los bloques de chasis idénticos que se encuentren a su lado", + "create.ponder.linear_chassis_group.text_2": "Cuando uno es movido por un artilugio, los otros son arrastrados con él", + "create.ponder.linear_chassis_group.text_3": "Los chasis de otro tipo u orientados en otra dirección no se fijan", + + "create.ponder.mechanical_arm.header": "Configurar los brazos mecánicos", + "create.ponder.mechanical_arm.text_1": "A los brazos mecánicos hay que asignarles sus entradas y salidas antes de colocarlos", + "create.ponder.mechanical_arm.text_2": "Clic derecho en los inventarios mientras mantiene el brazo mecánico para asignarlos como objetivos", + "create.ponder.mechanical_arm.text_3": "Clic derecho denuevo para alternar entre la entrada (azul) y la salida (naranja)", + "create.ponder.mechanical_arm.text_4": "Clic izquierdo en los componentes para eliminar su selección", + "create.ponder.mechanical_arm.text_5": "Una vez colocado, el brazo mecánico apuntará a los bloques seleccionados previamente", + "create.ponder.mechanical_arm.text_6": "Pueden tener cualquier cantidad de entradas y salidas dentro de su rango", + "create.ponder.mechanical_arm.text_7": "Sin embargo, no se puede interactuar directamente con todos los tipos de inventario", + "create.ponder.mechanical_arm.text_8": "Los embudos y depósitos pueden ayudar a salvar esa distancia", + + "create.ponder.mechanical_arm_filtering.header": "Filtrar salidas del brazo mecánico", + "create.ponder.mechanical_arm_filtering.text_1": "Entradas", + "create.ponder.mechanical_arm_filtering.text_2": "Salidas", + "create.ponder.mechanical_arm_filtering.text_3": "A veces es conveniente restringir los objetivos del brazo mecánico haciendo coincidir un filtro", + "create.ponder.mechanical_arm_filtering.text_4": "Por sí mismos no ofrecen ninguna opción de filtrado", + "create.ponder.mechanical_arm_filtering.text_5": "Sin embargo, los embudos de latón como objetivos comunican su propio filtro al brazo", + "create.ponder.mechanical_arm_filtering.text_6": "El brazo mecánico es lo suficientemente inteligente como para no recoger objetos que no podría distribuir", + + "create.ponder.mechanical_arm_modes.header": "Modos de distribución del brazo mecánico", + "create.ponder.mechanical_arm_modes.text_1": "Entradas", + "create.ponder.mechanical_arm_modes.text_2": "Salidas", + "create.ponder.mechanical_arm_modes.text_3": "Siempre que un brazo tenga que elegir entre varias salidas válidas...", + "create.ponder.mechanical_arm_modes.text_4": "...funcionará según su configuración", + "create.ponder.mechanical_arm_modes.text_5": "Usando la rueda del ratón con una llave inglesa te permitirá configurarlo", + "create.ponder.mechanical_arm_modes.text_6": "El modo Round Robin simplemente hace un ciclo a través de todas las salidas que están disponibles", + "create.ponder.mechanical_arm_modes.text_7": "Si una salida no puede admitir más objetos, se omitirá", + "create.ponder.mechanical_arm_modes.text_8": "El modo Round Robin forzado nunca omitirá las salidas, sino que esperará a que estén libres", + "create.ponder.mechanical_arm_modes.text_9": "Preferir el primero da prioridad a las salidas seleccionadas anteriormente al configurar este brazo", + + "create.ponder.mechanical_arm_redstone.header": "Controlar brazos mecánicos con redstone", + "create.ponder.mechanical_arm_redstone.text_1": "Cuando se alimentan con redstone, los brazos mecánicos no se activan", + "create.ponder.mechanical_arm_redstone.text_2": "Antes de detenerse, terminará los ciclos iniciados", + "create.ponder.mechanical_arm_redstone.text_3": "Así, un pulso negativo puede utilizarse para activar exactamente un ciclo de activación", + + "create.ponder.mechanical_bearing.header": "Mover estructuras mediante el rodamiento mecánico", + "create.ponder.mechanical_bearing.text_1": "Los rodamientos mecánicos se fijan al bloque que tienen delante", + "create.ponder.mechanical_bearing.text_2": "Al recibir fuerza rotacional, la ensamblará en un artilugio giratorio", + + "create.ponder.mechanical_crafter.header": "Configurar ensambladores mecánicos", + "create.ponder.mechanical_crafter.text_1": "Se puede utilizar una serie de ensambladores mecánicos para automatizar cualquier receta de elaboración.", + "create.ponder.mechanical_crafter.text_2": "Usando una llave inglesa, puedes establecer los caminos de los ensambladores ", + "create.ponder.mechanical_crafter.text_3": "Para que la configuración sea válida, todos los caminos tienen que converger en una salida, en cualquiera de los lados", + "create.ponder.mechanical_crafter.text_4": "Los puertos de salida de objetos se colocarán en un inventario a la salida", + "create.ponder.mechanical_crafter.text_5": "Los ensambladores mecánicos requieren fuerza rotacional para funcionar", + "create.ponder.mechanical_crafter.text_6": "Haga clic derecho en la parte delantera para insertar objetos manualmente", + "create.ponder.mechanical_crafter.text_7": "Una vez que cada ranura de una ruta contenga un objeto, comenzará el proceso de elaboración", + "create.ponder.mechanical_crafter.text_8": "Para las recetas que no ocupen totalmente la instalación del ensamblador, se puede forzar el arranque utilizando un pulso de redstone", + + "create.ponder.mechanical_crafter_connect.header": "Conectar inventarios a los ensambladores mecánicos", + "create.ponder.mechanical_crafter_connect.text_1": "Los objetos pueden ser insertados a los ensambladores mecánicos automáticamente", + "create.ponder.mechanical_crafter_connect.text_2": "Utilizando la llave inglesa a sus espaldas, las entradas pueden combinarse", + "create.ponder.mechanical_crafter_connect.text_3": "Ahora se puede acceder a todos los ensambladores mecánicos conectados por la misma ubicación de entrada", + + "create.ponder.mechanical_crafter_covers.header": "Cubrir las ranuras de los ensambladores mecánicos", + "create.ponder.mechanical_crafter_covers.text_1": "Algunas recetas requerirán ensambladores mecánicos adicionales para salvar las brechas en el camino", + "create.ponder.mechanical_crafter_covers.text_2": "Utilizando las tapas de ranuras del ensamblador mecánico, pueden actuar como una ranura vacía a su disposición", + "create.ponder.mechanical_crafter_covers.text_3": "Las entradas compartidas creadas con la llave inglesa en la parte posterior también pueden llegar a través de los ensambladores revestidos", + + "create.ponder.mechanical_drill.header": "Romper bloques con el taladro mecánico", + "create.ponder.mechanical_drill.text_1": "Cuando se le aplica fuerza rotacional, el taladro mecánico rompe los bloques que tiene delante.", + "create.ponder.mechanical_drill.text_2": "Su velocidad de trabajo depende de la fuerza rotacional suministrada", + + "create.ponder.mechanical_drill_contraption.header": "Usar taladros mecánicos en artilugios", + "create.ponder.mechanical_drill_contraption.text_1": "Siempre que los taladros mecánicos se muevan como parte de un artilugio animado...", + "create.ponder.mechanical_drill_contraption.text_2": "...romperán los bloques por los que artilugio los hace pasar", + + "create.ponder.mechanical_harvester.header": "Utilizar cosechadoras mecánicas en artilugios", + "create.ponder.mechanical_harvester.text_1": "Siempre que las cosechadoras mecánicas se muevan como parte de un artilugio animado...", + "create.ponder.mechanical_harvester.text_2": "...recogerán y repondrán los cultivos maduros en su camino", + + "create.ponder.mechanical_mixer.header": "Procesar objetos con la mezcladora mecánica", + "create.ponder.mechanical_mixer.text_1": "Con una mezcladora mecánica y una cuenca, se pueden automatizar algunas recetas", + "create.ponder.mechanical_mixer.text_2": "Las recetas disponibles incluyen cualquier receta de elaboración amorfa, además de un par de recetas adicionales", + "create.ponder.mechanical_mixer.text_3": "Algunas de esas recetas pueden requerir el calor de un quemador de blaze", + "create.ponder.mechanical_mixer.text_4": "La ranura para filtros se puede utilizar en caso de que dos recetas sean conflictivas.", + + "create.ponder.mechanical_piston.header": "Mover estructuras mediante pistones mecánicos", + "create.ponder.mechanical_piston.text_1": "Los pistones mecánicos pueden mover los bloques que tienen delante", + "create.ponder.mechanical_piston.text_2": "La velocidad y la dirección del movimiento dependen de la fuerza rotacional suministrada", + "create.ponder.mechanical_piston.text_3": "Los pistones mecánicos pegajosos pueden tirar de los bloques unidos hacia atrás", + + "create.ponder.mechanical_piston_modes.header": "Modos de movimiento del pistón mecánico", + "create.ponder.mechanical_piston_modes.text_1": "Cuando los pistones mecánicos dejan de moverse, la estructura movida vuelve a los bloques", + "create.ponder.mechanical_piston_modes.text_2": "Puede configurarse para que no vuelva nunca a los bloques sólidos, o sólo en la ubicación en la que comenzó", + + "create.ponder.mechanical_plough.header": "Utilizar arados mecánicos en los artilugios", + "create.ponder.mechanical_plough.text_1": "Cuando los arados mecánicos se mueven como parte de un artilugio animado...", + "create.ponder.mechanical_plough.text_2": "...romperán los bloques sin un hitbox de colisión sólido", + "create.ponder.mechanical_plough.text_3": "Además, pueden crear tierras de cultivo", + "create.ponder.mechanical_plough.text_4": "...también pueden lanzar entidades sin dañarlas", + + "create.ponder.mechanical_press.header": "Procesar objetos con la prensa mecánica", + "create.ponder.mechanical_press.text_1": "La prensa mecánica puede procesar los objetos proporcionados por debajo de ella", + "create.ponder.mechanical_press.text_2": "Los objetos de entrada pueden soltarse o colocarse en un depósito bajo la prensa", + "create.ponder.mechanical_press.text_3": "Cuando los objetos se proporcionan en una 'cinta'...", + "create.ponder.mechanical_press.text_4": "...la prensa mecánica los retendrá y procesará automáticamente", + + "create.ponder.mechanical_press_compacting.header": "Compactar objetos con la prensa mecánica", + "create.ponder.mechanical_press_compacting.text_1": "Al presionar los objetos que se encuentran en una cuenca, éstos se compactan.", + "create.ponder.mechanical_press_compacting.text_2": "La compactación incluye cualquier receta de elaboración de 2x2 o 3x3 rellena, además de un par extra", + "create.ponder.mechanical_press_compacting.text_3": "Algunas de esas recetas pueden requerir el calor de un quemador de blaze", + "create.ponder.mechanical_press_compacting.text_4": "La ranura para filtros se puede utilizar en caso de que dos recetas sean conflictivas.", + + "create.ponder.mechanical_pump_flow.header": "Transportar fluidos mediante bombas mecánicas", + "create.ponder.mechanical_pump_flow.text_1": "Las bombas mecánicas gobiernan el flujo de sus redes de tuberías anexas", + "create.ponder.mechanical_pump_flow.text_2": "Cuando están alimentadas, su flecha indica la dirección del flujo", + "create.ponder.mechanical_pump_flow.text_3": "La red de atrás está ahora tirando de fluidos...", + "create.ponder.mechanical_pump_flow.text_4": "...mientras la red de enfrente la transfiere hacia el exterior", + "create.ponder.mechanical_pump_flow.text_5": "Al invertir la rotación de la entrada se invierte el sentido del flujo", + "create.ponder.mechanical_pump_flow.text_6": "Utilice una llave inglesa para invertir la orientación de las bombas manualmente", + + "create.ponder.mechanical_pump_speed.header": "Rendimiento de las bombas mecánicas", + "create.ponder.mechanical_pump_speed.text_1": "Independientemente de la velocidad, las bombas mecánicas afectan a las tuberías conectadas hasta 16 bloques de distancia", + "create.ponder.mechanical_pump_speed.text_2": "Acelerar la rotación de entrada cambia la velocidad de propagación del flujo...", + "create.ponder.mechanical_pump_speed.text_3": "...así como la rapidez con la que se transfieren los fluidos", + "create.ponder.mechanical_pump_speed.text_4": "Las bombas pueden combinar sus rendimientos en redes de tuberías compartidas", + "create.ponder.mechanical_pump_speed.text_5": "Alternar su orientación puede ayudar a alinear sus direcciones de flujo", + + "create.ponder.mechanical_saw_breaker.header": "Cortar árboles con la sierra mecánica", + "create.ponder.mechanical_saw_breaker.text_1": "Cuando se le da una fuerza rotacional, la sierra mecánica cortará los árboles que estén directamente frente a ella", + "create.ponder.mechanical_saw_breaker.text_2": "Para poder cortar el árbol por completo, la sierra tiene que romper el último bloque que lo une al suelo", + + "create.ponder.mechanical_saw_contraption.header": "Utilizar sierras mecánicas en artilugios", + "create.ponder.mechanical_saw_contraption.text_1": "Cuando las sierras mecánicas se mueven como parte de un artilugio animado...", + "create.ponder.mechanical_saw_contraption.text_2": "...cortarán cualquier árbol con el que el artilugio se tope", + + "create.ponder.mechanical_saw_processing.header": "Procesar objetos en la sierra mecánica", + "create.ponder.mechanical_saw_processing.text_1": "Las sierras mecánicas orientadas hacia arriba pueden procesar una variedad de objetos", + "create.ponder.mechanical_saw_processing.text_2": "El objeto procesado siempre se mueve en contra de la fuerza rotacional de la sierra", + "create.ponder.mechanical_saw_processing.text_3": "Las sierras mecánicas pueden trabajar en línea con las correas mecánicas", + "create.ponder.mechanical_saw_processing.text_4": "Cuando un ingrediente tiene varios resultados posibles, la ranura para filtros puede especificarlo", + "create.ponder.mechanical_saw_processing.text_5": "Sin filtro, al contrario, la sierra mecánica pasaría por todos los resultados", + + "create.ponder.millstone.header": "Procesar objetos en la piedra de molino", + "create.ponder.millstone.text_1": "Las piedras de molino procesan los objetos mediante la molienda", + "create.ponder.millstone.text_2": "Se pueden accionar lateralmente mediante engranajes...", + "create.ponder.millstone.text_3": "... y tirar o insertar objetos en la parte superior", + "create.ponder.millstone.text_4": "Después de un tiempo, el resultado se puede obtener usando el clic derecho del ratón", + "create.ponder.millstone.text_5": "Las salidas también pueden extraerse mediante la automatización", + + "create.ponder.nixie_tube.header": "Usar los tubos Nixie", + "create.ponder.nixie_tube.text_1": "Cuando son alimentados con redstone, los tubos nixie mostrarán la fuerza de las señales de redstone", + "create.ponder.nixie_tube.text_2": "Con las etiquetas editadas en un yunque, pueden mostar un texto personalizado", + "create.ponder.nixie_tube.text_3": "Haga clic derecho con un tinte para cambiar su color de visualización", + + "create.ponder.piston_pole.header": "Pértigas de extensión de pistones", + "create.ponder.piston_pole.text_1": "Sin las pértigas de extensión unidas, un pistón mecánico no puede moverse", + "create.ponder.piston_pole.text_2": "La longitud de la pértiga añadida en su parte posterior determina el rango de alcance", + + "create.ponder.portable_fluid_interface.header": "Interfaz de fluidos portátil", + "create.ponder.portable_fluid_interface.text_1": "No se puede acceder a los depósitos de fluidos de los artilugios en movimiento por ninguna tubería", + "create.ponder.portable_fluid_interface.text_2": "Este componente puede interactuar con los depósitos de fluidos sin necesidad de detener el artilugio", + "create.ponder.portable_fluid_interface.text_3": "Coloca una segunda con un espacio de 1 o 2 bloques entre ellas", + "create.ponder.portable_fluid_interface.text_4": "Cada vez que pasen por delante de la otra, entablarán una conexión", + "create.ponder.portable_fluid_interface.text_5": "Mientras esté activada, la interfaz estacionaria representará TODOS los tanques del artilugio", + "create.ponder.portable_fluid_interface.text_6": "Ahora se puede introducir el fluido...", + "create.ponder.portable_fluid_interface.text_7": "...o extraerlo del artilugio", + "create.ponder.portable_fluid_interface.text_8": "Cuando no se intercambien contenidos durante un tiempo, el artilugio seguirá su camino", + + "create.ponder.portable_storage_interface.header": "Interfaz de almacenamiento portátil", + "create.ponder.portable_storage_interface.text_1": "Los jugadores no pueden acceder a los inventarios de los artilugios en movimiento.", + "create.ponder.portable_storage_interface.text_2": "Este componente puede interactuar con el almacenamiento sin necesidad de detener el artilugio.", + "create.ponder.portable_storage_interface.text_3": "Coloca una segunda unidad con un espacio de 1 o 2 bloques entre ellas", + "create.ponder.portable_storage_interface.text_4": "Cada vez que pasen por delante del otro, entablarán una conexión", + "create.ponder.portable_storage_interface.text_5": "Mientras esté conectada, la interfaz fija representará TODOS los inventarios del artilugio", + "create.ponder.portable_storage_interface.text_6": "Ahora pueden insertarse objetos...", + "create.ponder.portable_storage_interface.text_7": "...o extraerse", + "create.ponder.portable_storage_interface.text_8": "Cuando no se hayan intercambiado objetos durante un tiempo, el artilugio seguirá su camino", + + "create.ponder.portable_storage_interface_redstone.header": "Interfaz de almacenamiento portátil controlada por redstone", + "create.ponder.portable_storage_interface_redstone.text_1": "La energía de redstone impedirá que las interfaces de almacenamiento portátil se conecten", + + "create.ponder.powered_latch.header": "Controlar señales mediante la palanca motorizada", + "create.ponder.powered_latch.text_1": "Las palancas motorizadas son palancas controlables por redstone", + "create.ponder.powered_latch.text_2": "Las señales en la parte trasera la encienden", + "create.ponder.powered_latch.text_3": "Las señales sobre un lateral la vuelven a apagar", + "create.ponder.powered_latch.text_4": "Las palancas motorizadas también se pueden accionar manualmente", + + "create.ponder.powered_toggle_latch.header": "Controlar señales mediante la palanca de cierre motorizada", + "create.ponder.powered_toggle_latch.text_1": "Las palancas de cierre motorizadas son palancas controlables por redstone", + "create.ponder.powered_toggle_latch.text_2": "Las señales en la parte trasera cambiarán su estado...", + "create.ponder.powered_toggle_latch.text_3": "...encender y apagar", + "create.ponder.powered_toggle_latch.text_4": "Las palancas de cierre motorizadas también se pueden accionar manualmente", + + "create.ponder.pulse_repeater.header": "Controlar señales mediante repetidores de pulsos", + "create.ponder.pulse_repeater.text_1": "Los repetidores de pulsos acortan cualquier señal de redstone a un solo pulso", + + "create.ponder.radial_chassis.header": "Fijar bloques mediante chasis radiales", + "create.ponder.radial_chassis.text_1": "Los chasis radiales se conectan a bloques de chasis idénticos en una fila", + "create.ponder.radial_chassis.text_2": "Cuando uno es movido por un artilugio, los otros son arrastrados con él", + "create.ponder.radial_chassis.text_3": "Las caras laterales de un chasis radial pueden hacerse adhesivas", + "create.ponder.radial_chassis.text_4": "Haga clic de nuevo para que todos los demás lados sean pegajosos", + "create.ponder.radial_chassis.text_5": "Mayús izdo + clic derecho con la mano vacía para eliminar el pegamento", + "create.ponder.radial_chassis.text_6": "Cada vez que un bloque está junto a una cara pegajosa...", + "create.ponder.radial_chassis.text_7": "...adjuntará todos los bloques alcanzables dentro de un radio en esa capa", + "create.ponder.radial_chassis.text_8": "Con una llave inglesa y usando la rueda de desplazamiento del ratón se puede especificar un radio preciso", + "create.ponder.radial_chassis.text_9": "Los bloques no alcanzables por ninguna cara adhesiva no se fijarán", + + "create.ponder.redstone_contact.header": "Contactos de redstone", + "create.ponder.redstone_contact.text_1": "Los contactos de redstone enfrentados emitirán una señal de redstone", + "create.ponder.redstone_contact.text_2": "Esto sigue siendo válido cuando uno de ellos forma parte de un artilugio en movimiento", + + "create.ponder.redstone_link.header": "Usar los enlaces de redstone", + "create.ponder.redstone_link.text_1": "Los enlaces de redstone pueden transmitir señales redstone de forma inalámbrica", + "create.ponder.redstone_link.text_2": "Mayús izdo + clic derecho para cambiar el modo de recepción", + "create.ponder.redstone_link.text_3": "Un simple clic derecho con una llave inglesa puede hacer lo mismo", + "create.ponder.redstone_link.text_4": "Los receptores emiten la potencia de redstone de los transmisores en 128 bloques", + "create.ponder.redstone_link.text_5": "Colocando objetos en las dos ranuras puede especificar una frecuencia", + "create.ponder.redstone_link.text_6": "Sólo se comunicarán los enlaces con frecuencias coincidentes", + + "create.ponder.rope_pulley.header": "Mover estructuras con poleas de cuerda", + "create.ponder.rope_pulley.text_1": "Las poleas de cuerda pueden mover los bloques verticalmente cuando se les aplica una fuerza rotacional", + "create.ponder.rope_pulley.text_2": "La dirección y la velocidad del movimiento dependen de la fuerza rotacional suministrada", + + "create.ponder.rope_pulley_attachment.header": "Mover poleas como parte de un artilugio", + "create.ponder.rope_pulley_attachment.text_1": "Siempre que las poleas de cuerda sean movidas por un artilugio...", + "create.ponder.rope_pulley_attachment.text_2": "...su estructura adjunta será arrastrada con ella", + "create.ponder.rope_pulley_attachment.text_3": "Tenga en cuenta que las poleas de cuerda sólo se mueven cuando están paradas", + + "create.ponder.rope_pulley_modes.header": "Modos de movimiento de la polea de cuerda", + "create.ponder.rope_pulley_modes.text_1": "Cuando las poleas de cuerda dejan de moverse, la estructura movida vuelve a los bloques", + "create.ponder.rope_pulley_modes.text_2": "Puede configurarse para que no vuelva nunca a los bloques sólidos, o sólo en la ubicación en la que comenzó", + + "create.ponder.rotation_speed_controller.header": "Usar el controlador de velocidad rotacional", + "create.ponder.rotation_speed_controller.text_1": "Los controladores de velocidad rotacional transmiten la rotación de su eje a un engranaje grande situado encima.", + "create.ponder.rotation_speed_controller.text_2": "Utilizando la rueda de desplazamiento del ratón, puede configurarse la velocidad rotacional", + + "create.ponder.sail.header": "Montar molinos de viento usando velas", + "create.ponder.sail.text_1": "Las velas son bloques muy útiles para crear molinos de viento", + "create.ponder.sail.text_2": "Se fijarán a los bloques y entre sí sin necesidad de pegamento o bloques de chasis", + "create.ponder.sail.text_3": "Clic derecho con un tinte para pintarlas", + "create.ponder.sail.text_4": "Clic derecho con una tijera para volver a convertirlas en marcos", + + "create.ponder.sail_frame.header": "Montar molinos de viento con marcos de vela", + "create.ponder.sail_frame.text_1": "Los marcos de vela son prácticos bloques para crear molinos de viento", + "create.ponder.sail_frame.text_2": "Se fijarán a los bloques y entre sí sin necesidad de pegamento o bloques de chasis", + + "create.ponder.sequenced_gearshift.header": "Controlar la velocidad de rotación mediante la caja de cambios secuenciales", + "create.ponder.sequenced_gearshift.text_1": "La caja de cambios secuencial retransmite la rotación siguiendo una lista cronometrada de instrucciones", + "create.ponder.sequenced_gearshift.text_2": "Haga clic con el botón derecho para abrir la interfaz de configuración", + "create.ponder.sequenced_gearshift.text_3": "Al recibir una señal de redstone, comenzará a ejecutar su secuencia configurada", + "create.ponder.sequenced_gearshift.text_4": "Una vez terminado, espera la siguiente señal de redstone y vuelve a empezar", + "create.ponder.sequenced_gearshift.text_5": "Se puede utilizar un comparador de redstone para leer el progreso actual", + + "create.ponder.shaft.header": "Transmitir fuerza rotacional mediante ejes", + "create.ponder.shaft.text_1": "Los ejes transmiten la rotación en línea recta.", + + "create.ponder.shaft_casing.header": "Ejes revestidos", + "create.ponder.shaft_casing.text_1": "Puedes utilizar el revestidor de latón o de andesita para decorar tus ejes", + + "create.ponder.smart_chute.header": "Filtrar objetos mediante ductos inteligentes", + "create.ponder.smart_chute.text_1": "Los ductos inteligentes son ductos verticales con control adicional", + "create.ponder.smart_chute.text_2": "Los objetos en la ranura para filtros especifican lo que pueden extraer y transferir exactamente", + "create.ponder.smart_chute.text_3": "Usa la rueda del ratón para especificar el tamaño de la pila extraída", + "create.ponder.smart_chute.text_4": "La energía de redstone impedirá que funcionen.", + + "create.ponder.smart_pipe.header": "Controlar el flujo de fluidos mediante tuberías inteligentes", + "create.ponder.smart_pipe.text_1": "Las tuberías inteligentes pueden ayudar a controlar los flujos por tipo de fluido", + "create.ponder.smart_pipe.text_2": "Cuando se colocan directamente en la fuente, pueden especificar el tipo de fluido a extraer", + "create.ponder.smart_pipe.text_3": "Simplemente haga clic derecho en su ranura de filtro con cualquier elemento que contenga el fluido deseado", + "create.ponder.smart_pipe.text_4": "Cuando se colocan detrás de una red de tuberías, las tuberías inteligentes sólo dejan que los fluidos coincidentes continúen", + + "create.ponder.speedometer.header": "Controlar la información cinética mediante el velocímetro", + "create.ponder.speedometer.text_1": "El velocímetro muestra la velocidad actual de los componentes conectados", + "create.ponder.speedometer.text_2": "Cuando se usan las gafas del constructor, el jugador puede obtener información más detallada del medidor", + "create.ponder.speedometer.text_3": "Los comparadores pueden emitir señales analógicas de redstone en relación con las mediciones del velocímetro", + + "create.ponder.spout_filling.header": "Llenar objetos con un surtidor", + "create.ponder.spout_filling.text_1": "El surtidor puede llenar los elementos de retención de fluidos que se encuentran debajo de él", + "create.ponder.spout_filling.text_2": "No se puede acceder manualmente al contenido de un surtidor", + "create.ponder.spout_filling.text_3": "En su lugar, se pueden utilizar tuberías para suministrarle fluidos", + "create.ponder.spout_filling.text_4": "Los objetos de entrada pueden colocarse en un depósito bajo el surtidor", + "create.ponder.spout_filling.text_5": "Cuando los artículos se proporcionan en una cinta...", + "create.ponder.spout_filling.text_6": "El surtidor los retendrá y procesará automáticamente", + + "create.ponder.stabilized_bearings.header": "Estabilizar artilugios", + "create.ponder.stabilized_bearings.text_1": "Siempre que los rodamientos mecánicos formen parte de una estructura móvil...", + "create.ponder.stabilized_bearings.text_2": "...intentarán mantenerse derechos", + "create.ponder.stabilized_bearings.text_3": "Una vez más, el rodamiento se unirá al bloque de enfrente", + "create.ponder.stabilized_bearings.text_4": "Como resultado, todo el sub-artilugio se mantendrá en posición vertical", + + "create.ponder.sticker.header": "Fijar bloques con stickers", + "create.ponder.sticker.text_1": "Los stickers son ideales para la fijación de bloques controlados por redstone", + "create.ponder.sticker.text_2": "Al recibir una señal, cambiarán su estado", + "create.ponder.sticker.text_3": "Si ahora se mueve en un artilugio, el bloque se moverá con él", + "create.ponder.sticker.text_4": "Si se vuelve a activar, el bloque dejará de estar fijado", + + "create.ponder.stressometer.header": "Supervisar la información cinética con el estresómetro", + "create.ponder.stressometer.text_1": "El estresómetro muestra la capacidad de estrés actual de la red cinética conectada", + "create.ponder.stressometer.text_2": "Cuando se usan las gafas del constructor, el jugador puede obtener información más detallada del medidor", + "create.ponder.stressometer.text_3": "Los comparadores pueden emitir señales analógicas de redstone en relación con las mediciones del estresómetro", + + "create.ponder.super_glue.header": "Fijar bloques con pegamento", + "create.ponder.super_glue.text_1": "Se puede utilizar pegamento entre dos bloques cualquiera", + "create.ponder.super_glue.text_2": "Los bloques fijados se moverán juntos cuando se ensamblen en un artilugio", + "create.ponder.super_glue.text_3": "Cada vez que el pegamento es sostenido en la mano...", + "create.ponder.super_glue.text_4": "...los bloques añadidos se pegarán a la cara en la que fueron colocados automáticamente", + "create.ponder.super_glue.text_5": "El pegamento se puede quitar con un clic izquierdo", + + "create.ponder.valve_handle.header": "Generar fuerza rotacional mediante asas de válvula", + "create.ponder.valve_handle.text_1": "Los jugadores pueden utilizar las asas de válvulas para aplicar fuerza rotacional manualmente", + "create.ponder.valve_handle.text_2": "Mantén pulsado el clic derecho para rotar en sentido contrario a las agujas del reloj", + "create.ponder.valve_handle.text_3": "Su velocidad de transmisión es lenta y precisa", + "create.ponder.valve_handle.text_4": "Mayús izdo + clic derecho para rotar en el sentido de las agujas del reloj", + "create.ponder.valve_handle.text_5": "Las asas de las válvulas pueden teñirse con fines estéticos", + + "create.ponder.valve_pipe.header": "Controlar el flujo de fluidos mediante válvulas", + "create.ponder.valve_pipe.text_1": "Las tuberías con válvulas ayudan a controlar los fluidos que se propagan por las redes de tuberías", + "create.ponder.valve_pipe.text_2": "Su entrada en el eje controla si el fluido puede pasar por", + "create.ponder.valve_pipe.text_3": "Dada la fuerza de rotación en la dirección de apertura, la válvula se abrirá", + "create.ponder.valve_pipe.text_4": "Se puede volver a cerrar invirtiendo el giro de entrada", + + "create.ponder.water_wheel.header": "Generar fuerza rotacional mediante ruedas hidráulicas", + "create.ponder.water_wheel.text_1": "Las ruedas hidráulicas extraen la fuerza de las corrientes de agua adyacentes", + "create.ponder.water_wheel.text_2": "Cuantas más caras se alimenten, más rápido girará", + "create.ponder.water_wheel.text_3": "Las paletas de las ruedas deben estar orientadas en contra del flujo", + "create.ponder.water_wheel.text_4": "Orientadas hacia el lado contrario, no serán tan eficaces", + + "create.ponder.weighted_ejector.header": "Usar eyectores de peso", + "create.ponder.weighted_ejector.text_1": "Mayús izdo + clic derecho sosteniendo un eyector de peso para seleccionar la ubicación de destino", + "create.ponder.weighted_ejector.text_10": "Ahora estára limitado a este tamaño de pila, y sólo se activara cuando su pila retenida alcance esta cantidad", + "create.ponder.weighted_ejector.text_11": "Otras entidades activarán el eyector al pisarlos", + "create.ponder.weighted_ejector.text_2": "El eyector colocado lanzará ahora los objetos al lugar marcado", + "create.ponder.weighted_ejector.text_3": "Un objetivo válido puede estar a cualquier altura o distancia dentro del alcance", + "create.ponder.weighted_ejector.text_4": "Sin embargo, no pueden estar a un costado", + "create.ponder.weighted_ejector.text_5": "Si no se ha seleccionado ningún objetivo válido, simplemente se dirigirá al bloque que se encuentra justo delante", + "create.ponder.weighted_ejector.text_6": "Suministrale fuerza rotacional para cargarlo", + "create.ponder.weighted_ejector.text_7": "Los objetos colocados en el eyector hacen que se dispare", + "create.ponder.weighted_ejector.text_8": "Si se dirigen a un inventario, el eyector esperará hasta que haya espacio", + "create.ponder.weighted_ejector.text_9": "Con la llave inglesa se puede configurar el tamaño de pila requerido", + + "create.ponder.weighted_ejector_redstone.header": "Controlar los eyectores de peso con redstone", + "create.ponder.weighted_ejector_redstone.text_1": "Cuando se alimentan con redstone, los eyectores no se activan", + "create.ponder.weighted_ejector_redstone.text_2": "Además, los observadores de contenido pueden detectar cuando los eyectores se activan", + + "create.ponder.weighted_ejector_tunnel.header": "Dividir pilas de objetos mediante eyectores de peso", + "create.ponder.weighted_ejector_tunnel.text_1": "En combinación con los túneles de latón, los eyectores de peso pueden dividir las pilas de objetos en cantidades específicas", + "create.ponder.weighted_ejector_tunnel.text_2": "En primer lugar, configure el túnel de latón en 'Preferir lo más cercano', para dar prioridad a su salida lateral", + "create.ponder.weighted_ejector_tunnel.text_3": "El tamaño de la pila fijado en el eyector determina ahora la cantidad que se va a dividir", + "create.ponder.weighted_ejector_tunnel.text_4": "Mientras una nueva pila del tamaño configurado se expulse por la salida lateral...", + "create.ponder.weighted_ejector_tunnel.text_5": "...el resto seguirá su camino", + + "create.ponder.windmill_source.header": "Generar fuerza rotacional mediante rodamientos del molino de viento", + "create.ponder.windmill_source.text_1": "Los rodamientos del molino de viento se fijan al bloque que tienen delante", + "create.ponder.windmill_source.text_2": "Si se unen suficientes bloques tipo vela al bloque, éste puede actuar como un molino de viento", + "create.ponder.windmill_source.text_3": "Activado con un clic derecho, el rodamiento del molino de viento comenzará a proporcionar fuerza rotacional", + "create.ponder.windmill_source.text_4": "La cantidad de bloques de vela determina su velocidad de rotación", + "create.ponder.windmill_source.text_5": "Utiliza una llave inglesa para configurar su sentido de rotación", + "create.ponder.windmill_source.text_6": "Haga clic derecho sobre el rodamiento del molino en cualquier momento para detener y editar la estructura de nuevo", + + "create.ponder.windmill_structure.header": "Artilugios para molinos de viento", + "create.ponder.windmill_structure.text_1": "Cualquier estructura puede contar como un molino de viento válido, siempre que contenga al menos 8 bloques tipo vela.", "_": "Thank you for translating Create!" diff --git a/src/main/resources/assets/create/lang/es_mx.json b/src/main/resources/assets/create/lang/es_mx.json deleted file mode 100644 index 5264b5a87..000000000 --- a/src/main/resources/assets/create/lang/es_mx.json +++ /dev/null @@ -1,804 +0,0 @@ -{ - - "_": "->------------------------] Game Elements [------------------------<-", - - "block.create.acacia_window": "Ventana de Acacia", - "block.create.acacia_window_pane": "Panel de Ventana de Acacia", - "block.create.adjustable_chain_gearshift": "Cambio Ajustable de Velocidad de Cadena", - "block.create.adjustable_crate": "Caja Ajustable", - "block.create.adjustable_pulse_repeater": "Repetidor de Pulso Ajustable", - "block.create.adjustable_repeater": "Repetidor Ajustable", - "block.create.analog_lever": "Palanca Analogica", - "block.create.andesite_belt_funnel": "UNLOCALIZED: Andesite Belt Funnel", - "block.create.andesite_bricks": "Ladrillos de Andesita", - "block.create.andesite_bricks_slab": "Losa de Ladrillos de Andesita", - "block.create.andesite_bricks_stairs": "Escaleras de Ladrillos de Andesita", - "block.create.andesite_bricks_wall": "Pared de Ladrillos de Andesita", - "block.create.andesite_casing": "Carcasa de Andesita", - "block.create.andesite_cobblestone": "Piedra Labrada de Andesita", - "block.create.andesite_cobblestone_slab": "Losa de Piedra Labrada de Andesita", - "block.create.andesite_cobblestone_stairs": "Escaleras de Piedra Labrada de Andesita", - "block.create.andesite_cobblestone_wall": "Pared de Piedra Labrada de Andesita", - "block.create.andesite_encased_shaft": "Eje empotrado de Andesita", - "block.create.andesite_funnel": "Embudo de Andesita", - "block.create.andesite_pillar": "Pilar de Andesita", - "block.create.andesite_tunnel": "Túnel de Andesita", - "block.create.basin": "Cuenco", - "block.create.belt": "Correa", - "block.create.birch_window": "Ventana de Abedul", - "block.create.birch_window_pane": "Panel de Ventana de Abedul", - "block.create.black_sail": "Vela Negra", - "block.create.black_seat": "Asiento Negro", - "block.create.black_valve_handle": "Manija de Válvula Negra", - "block.create.blaze_burner": "Quemador de Blaze", - "block.create.blue_sail": "Vela Azul", - "block.create.blue_seat": "Asiento Azul", - "block.create.blue_valve_handle": "Manija de Válvula Azul", - "block.create.brass_belt_funnel": "UNLOCALIZED:Brass Belt Funnel", - "block.create.brass_block": "Bloque de Latón", - "block.create.brass_casing": "Carcasa de Latón", - "block.create.brass_encased_shaft": "Eje empotrado de Latón", - "block.create.brass_funnel": "Embudo de Latón", - "block.create.brass_tunnel": "Túnel de Latón", - "block.create.brown_sail": "Vela Café", - "block.create.brown_seat": "Asiento Café ", - "block.create.brown_valve_handle": "Manija de Válvula Café", - "block.create.cart_assembler": "Ensamblador de Vagonetas", - "block.create.chiseled_dark_scoria": "Escoria Oscura Grabada", - "block.create.chiseled_dolomite": "Dolomita Grabada", - "block.create.chiseled_gabbro": "Gabro Grabado", - "block.create.chiseled_limestone": "Caliza Grabada", - "block.create.chiseled_scoria": "Escoria Grabada", - "block.create.chiseled_weathered_limestone": "Caliza Meteorizada Grabada", - "block.create.chocolate": "Chocolate", - "block.create.chute": "Vertedor", - "block.create.clockwork_bearing": "Rodamiento de Reloj", - "block.create.clutch": "Embrague", - "block.create.cogwheel": "Rueda Dentada", - "block.create.content_observer": "Observador de Contenido", - "block.create.controller_rail": "Vía de Control", - "block.create.copper_block": "Bloque de Cobre", - "block.create.copper_casing": "Carcasa de Cobre", - "block.create.copper_ore": "Mineral de Cobre", - "block.create.copper_shingles": "Techado de Cobre", - "block.create.copper_tiles": "Baldosas de Cobre", - "block.create.copper_valve_handle": "Manija de Válvula de Cobre", - "block.create.creative_crate": "Caja del Creativo", - "block.create.creative_fluid_tank": "Tanque de Fluido del Creativo", - "block.create.creative_motor": "Motor del Creativo", - "block.create.crimson_window": "Ventana Carmesí", - "block.create.crimson_window_pane": "Panel de Ventana Carmesí", - "block.create.crushing_wheel": "Rueda Trituradora", - "block.create.crushing_wheel_controller": "UNLOCALIZED:Crushing Wheel Controller", - "block.create.cuckoo_clock": "Reloj Cuco", - "block.create.cyan_sail": "Vela Cian", - "block.create.cyan_seat": "Asiento Cian", - "block.create.cyan_valve_handle": "Manija de Válvula Cian", - "block.create.dark_oak_window": "Ventana de Roble Oscuro", - "block.create.dark_oak_window_pane": "Panel de Ventana de Roble Oscuro", - "block.create.dark_scoria": "Escoria Oscura", - "block.create.dark_scoria_bricks": "Ladrillos de Escoria Oscura", - "block.create.dark_scoria_bricks_slab": "Losa de Ladrillos de Escoria Oscura", - "block.create.dark_scoria_bricks_stairs": "Escaleras de Ladrillos de Escoria Oscura", - "block.create.dark_scoria_bricks_wall": "Pared de Ladrillos de Escoria Oscura", - "block.create.dark_scoria_cobblestone": "Piedra Labrada de Escoria Oscura", - "block.create.dark_scoria_cobblestone_slab": "Losa de Piedra Labrada de Escoria Oscura", - "block.create.dark_scoria_cobblestone_stairs": "Escaleras de Piedra Labrada de Escoria Oscura", - "block.create.dark_scoria_cobblestone_wall": "Pared de Piedra Labrada de Escoria Oscura", - "block.create.dark_scoria_pillar": "Pilar de Escoria Oscura", - "block.create.deployer": "Desplegador", - "block.create.depot": "Depósito", - "block.create.diorite_bricks": "Ladrillos de Diorita", - "block.create.diorite_bricks_slab": "Losa de Ladrillos de Diorita", - "block.create.diorite_bricks_stairs": "Escaleras de Ladrillos de Diorita", - "block.create.diorite_bricks_wall": "Pared de Ladrillos de Diorita", - "block.create.diorite_cobblestone": "Piedra Labrada de Diorita", - "block.create.diorite_cobblestone_slab": "Losa de Piedra Labrada de Diorita", - "block.create.diorite_cobblestone_stairs": "Escaleras de Piedra Labrada de Diorita", - "block.create.diorite_cobblestone_wall": "Pared de Piedra Labrada de Diorita", - "block.create.diorite_pillar": "Pared de Diorita", - "block.create.dolomite": "Dolomita", - "block.create.dolomite_bricks": "Ladrillos de Dolomita", - "block.create.dolomite_bricks_slab": "Losa de Ladrillos de Dolomita", - "block.create.dolomite_bricks_stairs": "Escaleras de Ladrillos de Dolomita", - "block.create.dolomite_bricks_wall": "Pared de Ladrillos de Dolomita", - "block.create.dolomite_cobblestone": "Piedra Labrada de Dolomita", - "block.create.dolomite_cobblestone_slab": "Losa de Piedra Labrada de Dolomita", - "block.create.dolomite_cobblestone_stairs": "Escaleras de Piedra Labrada de Dolomita", - "block.create.dolomite_cobblestone_wall": "Pared de Piedra Labrada de Dolomita", - "block.create.dolomite_pillar": "Pilar de Dolomita", - "block.create.encased_chain_drive": "Transmisión de Cadena Empotrada", - "block.create.encased_fan": "Ventilador Acoplado", - "block.create.encased_fluid_pipe": "Tubería de Fluidos Recubierta", - "block.create.fancy_andesite_bricks": "Ladrillos de Andesita Elegantes", - "block.create.fancy_andesite_bricks_slab": "Losa de Ladrillos de Andesita Elegantes", - "block.create.fancy_andesite_bricks_stairs": "Escaleras de Ladrillos de Andesita Elegantes", - "block.create.fancy_andesite_bricks_wall": "Pared de Ladrillos de Andesita Elegantes", - "block.create.fancy_dark_scoria_bricks": "Ladrillos de Escoria Oscura Elegantes", - "block.create.fancy_dark_scoria_bricks_slab": "Losa de Ladrillos de Escoria Oscura Elegantes", - "block.create.fancy_dark_scoria_bricks_stairs": "Escaleras de Ladrillos de Escoria Oscura Elegantes", - "block.create.fancy_dark_scoria_bricks_wall": "Pared de Ladrillos de Escoria Oscura Elegantes", - "block.create.fancy_diorite_bricks": "Ladrillos de Diorita Elegantes", - "block.create.fancy_diorite_bricks_slab": "Losa de Ladrillos de Diorita Elegantes", - "block.create.fancy_diorite_bricks_stairs": "Escaleras de Ladrillos de Diorita Elegantes", - "block.create.fancy_diorite_bricks_wall": "Pared de Ladrillos de Diorita Elegantes", - "block.create.fancy_dolomite_bricks": "Ladrillos de Dolomita Elegantes", - "block.create.fancy_dolomite_bricks_slab": "Losa de Ladrillos de Dolomita Elegantes", - "block.create.fancy_dolomite_bricks_stairs": "Escaleras de Ladrillos de Dolomita Elegantes", - "block.create.fancy_dolomite_bricks_wall": "Pared de Ladrillos de Dolomita Elegantes", - "block.create.fancy_gabbro_bricks": "Ladrillos de Gabro Elegantes", - "block.create.fancy_gabbro_bricks_slab": "Losa Ladrillos de Gabro Elegantes", - "block.create.fancy_gabbro_bricks_stairs": "Escaleras Ladrillos de Gabro Elegantes", - "block.create.fancy_gabbro_bricks_wall": "Pared de Ladrillos de Gabro Elegantes", - "block.create.fancy_granite_bricks": "Ladrillos de Granito Elegantes", - "block.create.fancy_granite_bricks_slab": "Losa de Ladrillos de Granito Elegantes", - "block.create.fancy_granite_bricks_stairs": "Escaleras de Ladrillos de Granito Elegantes", - "block.create.fancy_granite_bricks_wall": "Pared de Ladrillos de Granito Elegantes", - "block.create.fancy_limestone_bricks": "Ladrillos de Caliza Elegantes", - "block.create.fancy_limestone_bricks_slab": "Losa de Ladrillos de Caliza Elegantes", - "block.create.fancy_limestone_bricks_stairs": "Escaleras de Ladrillos de Caliza Elegantes", - "block.create.fancy_limestone_bricks_wall": "Pared de Ladrillos de Caliza Elegantes", - "block.create.fancy_scoria_bricks": "Ladrillos de Escoria Elegantes", - "block.create.fancy_scoria_bricks_slab": "Losa de Ladrillos de Escoria Elegantes", - "block.create.fancy_scoria_bricks_stairs": "Escaleras de Ladrillos de Escoria Elegantes", - "block.create.fancy_scoria_bricks_wall": "Pared de Ladrillos de Escoria Elegantes", - "block.create.fancy_weathered_limestone_bricks": "Ladrillos de Caliza Meteorizada Elegantes", - "block.create.fancy_weathered_limestone_bricks_slab": "Losa de Ladrillos de Caliza Meteorizada Elegantes", - "block.create.fancy_weathered_limestone_bricks_stairs": "Escaleras de Ladrillos de Caliza Meteorizada Elegantes", - "block.create.fancy_weathered_limestone_bricks_wall": "Pared de Ladrillos de Caliza Meteorizada Elegantes", - "block.create.fluid_pipe": "Tubería de Fluidos", - "block.create.fluid_tank": "Tanque de Fluidos", - "block.create.fluid_valve": "Válvula de Fluidos", - "block.create.flywheel": "Rueda de Inercia", - "block.create.framed_glass": "Vidrio Enmarcado", - "block.create.framed_glass_pane": "Panel de Vidrio Enmarcado", - "block.create.furnace_engine": "Motor de Horno", - "block.create.gabbro": "Gabro", - "block.create.gabbro_bricks": "Ladrillos de Gabro", - "block.create.gabbro_bricks_slab": "Losa de Ladrillos de Gabro", - "block.create.gabbro_bricks_stairs": "Escaleras de Ladrillos de Gabro", - "block.create.gabbro_bricks_wall": "Pared de Ladrillos de Gabro", - "block.create.gabbro_cobblestone": "Piedra Labrada de Gabro", - "block.create.gabbro_cobblestone_slab": "Losa de Piedra Labrada de Gabro", - "block.create.gabbro_cobblestone_stairs": "Escaleras de Piedra Labrada de Gabro", - "block.create.gabbro_cobblestone_wall": "Pared de Piedra Labrada de Gabro", - "block.create.gabbro_pillar": "Pilar de Gabro", - "block.create.gearbox": "Transmisión", - "block.create.gearshift": "Cambio de Marcha", - "block.create.glass_fluid_pipe": "Tubería de Fluidos de Vidrio", - "block.create.granite_bricks": "Ladrillos de Granito", - "block.create.granite_bricks_slab": "Losa de Ladrillos de Granito", - "block.create.granite_bricks_stairs": "Escaleras de Ladrillos de Granito", - "block.create.granite_bricks_wall": "Pared de Ladrillos de Granito", - "block.create.granite_cobblestone": "Piedra Labrada de Granito", - "block.create.granite_cobblestone_slab": "Losa de Piedra Labrada de Granito", - "block.create.granite_cobblestone_stairs": "Escaleras de Piedra Labrada de Granito", - "block.create.granite_cobblestone_wall": "Pared de Piedra Labrada de Granito", - "block.create.granite_pillar": "Pilar de Granito", - "block.create.gray_sail": "Vela Gris", - "block.create.gray_seat": "Asiento Gris", - "block.create.gray_valve_handle": "Manija de Válvula Gris", - "block.create.green_sail": "Vela Verde", - "block.create.green_seat": "Asiento Verde", - "block.create.green_valve_handle": "Manija de Válvula Verde", - "block.create.hand_crank": "Manivela", - "block.create.honey": "Miel", - "block.create.horizontal_framed_glass": "Vidrio Enmarcado Horizontal", - "block.create.horizontal_framed_glass_pane": "Panel de Vidrio Enmarcado Horizontal", - "block.create.hose_pulley": "Polea con Manguera", - "block.create.item_drain": "Extractor de Fluidos", - "block.create.jungle_window": "Ventana de Jungla", - "block.create.jungle_window_pane": "Panel de Ventana de Jungla", - "block.create.large_cogwheel": "Rueda Dentada Grande", - "block.create.layered_andesite": "Andesita en Capas", - "block.create.layered_dark_scoria": "Escoria Oscura en Capas", - "block.create.layered_diorite": "Diorita en Capas", - "block.create.layered_dolomite": "Dolomita en Capas", - "block.create.layered_gabbro": "Gabro en Capas", - "block.create.layered_granite": "Granito en Capas", - "block.create.layered_limestone": "Caliza en Capas", - "block.create.layered_scoria": "Escoria en Capas", - "block.create.layered_weathered_limestone": "Caliza Meteorizada en Capas", - "block.create.light_blue_sail": "Vela Azul Claro", - "block.create.light_blue_seat": "Asiento Azul Claro", - "block.create.light_blue_valve_handle": "Manija de Válvula Azul Claro", - "block.create.light_gray_sail": "Vela Gris Claro", - "block.create.light_gray_seat": "Asiento Gris Claro", - "block.create.light_gray_valve_handle": "Manija de Válvula Gris Claro", - "block.create.lime_sail": "Vela Verde Lima", - "block.create.lime_seat": "Asiento Verde Lima", - "block.create.lime_valve_handle": "Manija de Válvula Verde Lima", - "block.create.limesand": "Arena de Caliza", - "block.create.limestone": "Caliza", - "block.create.limestone_bricks": "Ladrillos de Caliza", - "block.create.limestone_bricks_slab": "Losa de Ladrillos de Caliza", - "block.create.limestone_bricks_stairs": "Escaleras de Ladrillos de Caliza", - "block.create.limestone_bricks_wall": "Pared de Ladrillos de Caliza", - "block.create.limestone_cobblestone": "Piedra Labrada de Caliza", - "block.create.limestone_cobblestone_slab": "Losa de Piedra Labrada de Caliza", - "block.create.limestone_cobblestone_stairs": "Escaleras de Piedra Labrada de Caliza", - "block.create.limestone_cobblestone_wall": "Pared de Piedra Labrada de Caliza", - "block.create.limestone_pillar": "Pilar de Caliza", - "block.create.linear_chassis": "Chasis Lineal", - "block.create.lit_blaze_burner": "Quemador de Blaze Iluminado", - "block.create.magenta_sail": "Vela Magenta", - "block.create.magenta_seat": "Asiento Magenta", - "block.create.magenta_valve_handle": "Manija de Válvula Magenta", - "block.create.mechanical_arm": "Brazo Mecánico", - "block.create.mechanical_bearing": "Rodamiento Mecánico", - "block.create.mechanical_crafter": "Crafter Mecánico", - "block.create.mechanical_drill": "Taladro Mecánico", - "block.create.mechanical_harvester": "Cosechador Mecánico", - "block.create.mechanical_mixer": "Mezcladora Mecánica", - "block.create.mechanical_piston": "Pistón Mecánico", - "block.create.mechanical_piston_head": "Cabeza de Pistón Mecánico", - "block.create.mechanical_plough": "Arado Mecánico", - "block.create.mechanical_press": "Prensa Mecánica", - "block.create.mechanical_pump": "Bomba Mecánica", - "block.create.mechanical_saw": "Sierra Mecánica", - "block.create.metal_bracket": "Soporte de Metal", - "block.create.millstone": "Molino", - "block.create.minecart_anchor": "Ancla de Vagonetas", - "block.create.mossy_andesite": "Andesita Musgosa", - "block.create.mossy_dark_scoria": "Escoria Oscura Musgosa", - "block.create.mossy_diorite": "Diorita Musgosa", - "block.create.mossy_dolomite": "Dolomita Musgosa", - "block.create.mossy_gabbro": "Gabro Musgoso", - "block.create.mossy_granite": "Granito Musgoso", - "block.create.mossy_limestone": "Caliza Musgosa", - "block.create.mossy_scoria": "Escoria Musgosa", - "block.create.mossy_weathered_limestone": "Caliza Meteorizada Musgosa", - "block.create.mysterious_cuckoo_clock": "Reloj Cuco", - "block.create.natural_scoria": "Escoria Natural", - "block.create.nixie_tube": "Tubo Nixie", - "block.create.nozzle": "Boquilla", - "block.create.oak_window": "Ventana de Roble", - "block.create.oak_window_pane": "Panel de Ventana de Roble", - "block.create.orange_sail": "Vela Naranja", - "block.create.orange_seat": "Asiento Naranja", - "block.create.orange_valve_handle": "Manija de Válvula Naranja", - "block.create.ornate_iron_window": "Ventana Ornamentada", - "block.create.ornate_iron_window_pane": "Panel de Ventana Ornamentada", - "block.create.overgrown_andesite": "Andesita Descuidada", - "block.create.overgrown_dark_scoria": "Escoria Oscura Descuidada", - "block.create.overgrown_diorite": "Diorita Descuidada", - "block.create.overgrown_dolomite": "Dolomita Descuidada", - "block.create.overgrown_gabbro": "Gabro Descuidado", - "block.create.overgrown_granite": "Granito Descuidado", - "block.create.overgrown_limestone": "Caliza Descuidada", - "block.create.overgrown_scoria": "Escoria Descuidada", - "block.create.overgrown_weathered_limestone": "Caliza Meteorizada Descuidada", - "block.create.paved_andesite": "Andesita Pavimentada", - "block.create.paved_andesite_slab": "Losa de Andesita Pavimentada", - "block.create.paved_andesite_stairs": "Escaleras de Andesita Pavimentada", - "block.create.paved_andesite_wall": "Pared de Andesita Pavimentada", - "block.create.paved_dark_scoria": "Escoria Oscura Pavimentada", - "block.create.paved_dark_scoria_slab": "Losa de Escoria Oscura Pavimentada", - "block.create.paved_dark_scoria_stairs": "Escaleras de Escoria Oscura Pavimentada", - "block.create.paved_dark_scoria_wall": "Pared de Escoria Oscura Pavimentada", - "block.create.paved_diorite": "Diorita Pavimentada", - "block.create.paved_diorite_slab": "Losa de Diorita Pavimentada", - "block.create.paved_diorite_stairs": "Escaleras de Diorita Pavimentada", - "block.create.paved_diorite_wall": "Pared de Diorita Pavimentada", - "block.create.paved_dolomite": "Dolomita Pavimentada", - "block.create.paved_dolomite_slab": "Losa de Dolomita Pavimentada", - "block.create.paved_dolomite_stairs": "Escaleras de Dolomita Pavimentada", - "block.create.paved_dolomite_wall": "Pared de Dolomita Pavimentada", - "block.create.paved_gabbro": "Gabro Pavimentado", - "block.create.paved_gabbro_slab": "Losa de Gabro Pavimentado", - "block.create.paved_gabbro_stairs": "Escaleras de Gabro Pavimentado", - "block.create.paved_gabbro_wall": "Pared de Gabro Pavimentado", - "block.create.paved_granite": "Granito Pavimentado", - "block.create.paved_granite_slab": "Losa de Granito Pavimentado", - "block.create.paved_granite_stairs": "Escaleras de Granito Pavimentado", - "block.create.paved_granite_wall": "Pared de Granito Pavimentado", - "block.create.paved_limestone": "Caliza Pavimentada", - "block.create.paved_limestone_slab": "Losa de Caliza Pavimentada", - "block.create.paved_limestone_stairs": "Escaleras de Caliza Pavimentada", - "block.create.paved_limestone_wall": "Pared de Caliza Pavimentada", - "block.create.paved_scoria": "Escoria Pavimentada", - "block.create.paved_scoria_slab": "Losa de Escoria Pavimentada", - "block.create.paved_scoria_stairs": "Escaleras de Escoria Pavimentada", - "block.create.paved_scoria_wall": "Pared de Escoria Pavimentada", - "block.create.paved_weathered_limestone": "Caliza Meteorizada Pavimentada", - "block.create.paved_weathered_limestone_slab": "Losa de Caliza Meteorizada Pavimentada", - "block.create.paved_weathered_limestone_stairs": "Escaleras de Caliza Meteorizada Pavimentada", - "block.create.paved_weathered_limestone_wall": "Pared de Caliza Meteorizada Pavimentada", - "block.create.pink_sail": "Vela Rosa", - "block.create.pink_seat": "Asiento Rosa", - "block.create.pink_valve_handle": "Manija de Válvula Rosa", - "block.create.piston_extension_pole": "Poste de Extensión de Pistón", - "block.create.polished_dark_scoria": "Escoria Oscura Pulida", - "block.create.polished_dark_scoria_slab": "Losa de Escoria Oscura Pulida", - "block.create.polished_dark_scoria_stairs": "Escaleras de Escoria Oscura Pulida", - "block.create.polished_dark_scoria_wall": "Pared de Escoria Oscura Pulida", - "block.create.polished_dolomite": "Dolomita Pulida", - "block.create.polished_dolomite_slab": "Losa de Dolomita Pulida", - "block.create.polished_dolomite_stairs": "Escaleras de Dolomita Pulida", - "block.create.polished_dolomite_wall": "Pared de Dolomita Pulida", - "block.create.polished_gabbro": "Gabro Pulido", - "block.create.polished_gabbro_slab": "Losa de Gabro Pulido", - "block.create.polished_gabbro_stairs": "Escaleras de Gabro Pulido", - "block.create.polished_gabbro_wall": "Pared de Gabro Pulido", - "block.create.polished_limestone": "Caliza Pulida", - "block.create.polished_limestone_slab": "Losa de Caliza Pulida", - "block.create.polished_limestone_stairs": "Escaleras de Caliza Pulida", - "block.create.polished_limestone_wall": "Pared de Caliza Pulida", - "block.create.polished_scoria": "Escoria Pulida", - "block.create.polished_scoria_slab": "Losa de Escoria Pulida", - "block.create.polished_scoria_stairs": "Escaleras de Escoria Pulida", - "block.create.polished_scoria_wall": "Pared de Escoria Pulida", - "block.create.polished_weathered_limestone": "Caliza Meteorizada Pulida", - "block.create.polished_weathered_limestone_slab": "Losa de Escoria Pulida", - "block.create.polished_weathered_limestone_stairs": "Escaleras de Escoria Pulida", - "block.create.polished_weathered_limestone_wall": "Pared de Escoria Pulida", - "block.create.portable_fluid_interface": "Interfaz de Fluidos Portable", - "block.create.portable_storage_interface": "Interfaz de Almacenamiento Portable", - "block.create.powered_latch": "Cerradura Electrica", - "block.create.powered_toggle_latch": "Cerradura Electrica de Palanca", - "block.create.pulley_magnet": "Polea con Imán", - "block.create.pulse_repeater": "Repetidor de Pulso", - "block.create.purple_sail": "Vela Morada", - "block.create.purple_seat": "Asiento Morado", - "block.create.purple_valve_handle": "Manija de Válvula Morada", - "block.create.radial_chassis": "Chasis Radial", - "block.create.red_sail": "Vela Roja", - "block.create.red_seat": "Asiento Rojo", - "block.create.red_valve_handle": "Manija de Válvula Roja", - "block.create.redstone_contact": "Contacto de Redstone", - "block.create.redstone_link": "Enlace de Redstone", - "block.create.refined_radiance_casing": "Carcasa Radiante", - "block.create.reinforced_rail": "Vía Reforzada", - "block.create.rope": "Cuerda", - "block.create.rope_pulley": "Polea con Cuerda", - "block.create.rotation_speed_controller": "Controlador de Velocidad de Rotación", - "block.create.sail_frame": "Marco de Vela", - "block.create.schematic_table": "Mesa de Esquemas", - "block.create.schematicannon": "Esquemacañon", - "block.create.scoria": "Escoria", - "block.create.scoria_bricks": "Ladrillos de Escoria", - "block.create.scoria_bricks_slab": "Losa de Ladrillos de Escoria", - "block.create.scoria_bricks_stairs": "Escaleras de Ladrillos de Escoria", - "block.create.scoria_bricks_wall": "Pared de Ladrillos de Escoria", - "block.create.scoria_cobblestone": "Piedra Labrada de Escoria", - "block.create.scoria_cobblestone_slab": "Losa de Piedra Labrada de Escoria", - "block.create.scoria_cobblestone_stairs": "Escaleras de Piedra Labrada de Escoria", - "block.create.scoria_cobblestone_wall": "Pared de Piedra Labrada de Escoria", - "block.create.scoria_pillar": "Pilar de Escoria", - "block.create.secondary_linear_chassis": "Chasis Lineal Secundario", - "block.create.sequenced_gearshift": "Cambio de Marcha Secuenciado", - "block.create.shadow_steel_casing": "Carcasa Sombría", - "block.create.shaft": "Eje", - "block.create.smart_fluid_pipe": "Tubería de Fluidos Inteligente", - "block.create.speedometer": "Velocímetro", - "block.create.spout": "Canaleta", - "block.create.spruce_window": "Ventana de Abeto", - "block.create.spruce_window_pane": "Panel de Ventana de Abeto", - "block.create.sticky_mechanical_piston": "Pistón Mecánico Pegajoso", - "block.create.stockpile_switch": "Interruptor de Pila", - "block.create.stressometer": "Estresómetro", - "block.create.tiled_glass": "Vidrio de Azulejos", - "block.create.tiled_glass_pane": "Panel de Vidrio de Azulejos", - "block.create.turntable": "Mesa Giratoria", - "block.create.vertical_framed_glass": "Vidrio Enmarcado Vertical", - "block.create.vertical_framed_glass_pane": "Panel de Vidrio Enmarcado Vertical", - "block.create.warped_window": "Ventana Distorsionada", - "block.create.warped_window_pane": "Panel de ventana Distorsionada", - "block.create.water_wheel": "Rueda Hidráulica", - "block.create.weathered_limestone": "Caliza Meteorizada", - "block.create.weathered_limestone_bricks": "Ladrillos de Caliza Meteorizada", - "block.create.weathered_limestone_bricks_slab": "Losa de Caliza Meteorizada", - "block.create.weathered_limestone_bricks_stairs": "Escaleras de Caliza Meteorizada", - "block.create.weathered_limestone_bricks_wall": "Pared de Caliza Meteorizada", - "block.create.weathered_limestone_cobblestone": "Piedra Labrada de Caliza Meteorizada", - "block.create.weathered_limestone_cobblestone_slab": "Losa de Piedra Labrada de Caliza Meteorizada", - "block.create.weathered_limestone_cobblestone_stairs": "Escaleras de Piedra Labrada de Caliza Meteorizada", - "block.create.weathered_limestone_cobblestone_wall": "Pared de Piedra Labrada de Caliza Meteorizada", - "block.create.weathered_limestone_pillar": "Pilar de Caliza Meteorizada", - "block.create.white_sail": "Vela Blanca", - "block.create.white_seat": "Asiento Blanco", - "block.create.white_valve_handle": "Manija de Válvula Blanca", - "block.create.windmill_bearing": "Rodamiento de Molino de Viento", - "block.create.wooden_bracket": "Soporte de Madera", - "block.create.yellow_sail": "Vela Amarilla", - "block.create.yellow_seat": "Asiento Amarillo", - "block.create.yellow_valve_handle": "Manija de Válvula Amarilla", - "block.create.zinc_block": "Bloque de Zinc", - "block.create.zinc_ore": "Mineral de Zinc", - - "entity.create.contraption": "Artefacto", - "entity.create.seat": "Asiento", - "entity.create.stationary_contraption": "Artefacto Estacionario", - "entity.create.super_glue": "Super Pegamento", - - "fluid.create.chocolate": "Chocolate", - "fluid.create.honey": "Miel", - "fluid.create.milk": "Leche", - "fluid.create.potion": "Poción", - "fluid.create.tea": "Té del Constructor", - - "item.create.andesite_alloy": "Aleación de Andesita", - "item.create.attribute_filter": "Filtro por Atributos", - "item.create.bar_of_chocolate": "Barra de Chocolate", - "item.create.belt_connector": "Conector de Correa", - "item.create.blaze_cake": "Pastel de Blaze", - "item.create.blaze_cake_base": "Base de Pastel de Blaze", - "item.create.brass_hand": "Mano de Latón", - "item.create.brass_ingot": "Lingote de Latón", - "item.create.brass_nugget": "Pepita de Latón", - "item.create.brass_sheet": "Lámina de Latón", - "item.create.builders_tea": "Té del Constructor", - "item.create.chest_minecart_contraption": "Artefacto de Vagón con Cofre", - "item.create.chocolate_bucket": "Cubeta de Chocolate", - "item.create.chromatic_compound": "Compuesto Cromático", - "item.create.cinder_flour": "Ceniza Molida", - "item.create.copper_ingot": "Lingote de Cobre", - "item.create.copper_nugget": "Pepita de Cobre", - "item.create.copper_sheet": "Lámina de Cobre", - "item.create.crafter_slot_cover": "Cubierta de Ranura del Crafter", - "item.create.crushed_aluminum_ore": "Mineral de Aluminio Molido", - "item.create.crushed_brass": "Latón Molido", - "item.create.crushed_copper_ore": "Mineral de Cobre Molido", - "item.create.crushed_gold_ore": "Mineral de Oro Molido", - "item.create.crushed_iron_ore": "Mineral de Hierro Molido", - "item.create.crushed_lead_ore": "Mineral de Plomo Molido", - "item.create.crushed_nickel_ore": "Mineral de Nickel Molido", - "item.create.crushed_osmium_ore": "Mineral de Osmio Molido", - "item.create.crushed_platinum_ore": "Mineral de Platino Molido", - "item.create.crushed_quicksilver_ore": "Mineral de Mercurio Molido", - "item.create.crushed_silver_ore": "Mineral de Plata Molido", - "item.create.crushed_tin_ore": "Mineral de Estaño Molido", - "item.create.crushed_uranium_ore": "Mineral de Uranio Molido", - "item.create.crushed_zinc_ore": "Mineral de Zinc Molido", - "item.create.deforester": "Deforestador", - "item.create.dough": "Masa", - "item.create.electron_tube": "Válvula Electrónica", - "item.create.empty_blaze_burner": "Quemador de Blaze Vacío", - "item.create.empty_schematic": "Esquema Vacío", - "item.create.extendo_grip": "Brazo Extensor", - "item.create.extendo_grip": "Brazo Extensor", - "item.create.filter": "Filtro", - "item.create.furnace_minecart_contraption": "Artefacto de Vagón con Horno", - "item.create.goggles": "Gafas de Protección para Ingenieros", - "item.create.golden_sheet": "Lámina de Oro", - "item.create.handheld_blockzapper": "Pistola de Manipulación de Bloques", - "item.create.handheld_worldshaper": "Pistola de Manipulación de Mundo", - "item.create.honey_bucket": "Cubeta de Miel", - "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.minecart_contraption": "Artefacto de Vagón", - "item.create.minecart_coupling": "Acoplamiento de Vagonetas", - "item.create.polished_rose_quartz": "Cuarzo Rosa Pulido", - "item.create.powdered_obsidian": "Polvo de Obsidiana", - "item.create.propeller": "Hélice", - "item.create.red_sand_paper": "Papel de Arena Roja", - "item.create.refined_radiance": "Radiancia Refinada", - "item.create.rose_quartz": "Cuarzo Rosa", - "item.create.sand_paper": "Papel de Arena", - "item.create.schematic": "Esquema", - "item.create.schematic_and_quill": "Esquema y Pluma", - "item.create.shadow_steel": "Acero Sombrío", - "item.create.super_glue": "Super Pegamento", - "item.create.tree_fertilizer": "Fertilizador de Árboles", - "item.create.vertical_gearbox": "Transmisión Vertical", - "item.create.wand_of_symmetry": "Vara de la Simetria", - "item.create.wheat_flour": "Harina de Trigo", - "item.create.whisk": "Batidor", - "item.create.wrench": "Llave Inglesa", - "item.create.zinc_ingot": "Lingote de Zinc", - "item.create.zinc_nugget": "Pepita de Zinc", - - - "_": "->------------------------] 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": "EJE EMPOTRADO DE ANDESITA", - "block.create.andesite_encased_shaft.tooltip.summary": "Objeto _exclusivo_ _del_ _Creativo_ .Cubre los ejes _en_ _el_ _mundo_ usando Carcasa de _Andesita_ . Los bloques de carcasa no se consumirán.", - - "block.create.brass_encased_shaft.tooltip": "EJE EMPOTRADO DE LATÓN", - "block.create.brass_encased_shaft.tooltip.summary": "Objeto _exclusivo_ _del_ _Creativo_ .Cubre los ejes _en_ _el_ _mundo_ usando Carcasa de _Latón_ . Los bloques de carcasa no se consumirán.", - - "block.create.wooden_bracket.tooltip": "SOPORTE DE MADERA", - "block.create.wooden_bracket.tooltip.summary": "_Decora_ tus _ejes,_ _ruedas_ _dentadas_ y _tuberías_ con un pequeño y acogedor refuerzo de madera", - - "block.create.metal_bracket.tooltip": "SOPORTE DE METAL", - "block.create.metal_bracket.tooltip.summary": "_Decora_ tus _ejes,_ _ruedas_ _dentadas_ y _tuberías_ con un robusto refuerzo industrial de metal", - - "block.create.andesite_casing.tooltip": "CARCASA DE ANDESITA", - "block.create.andesite_casing.tooltip.summary": "Una simple carcasa para máquinas con una variedad de usos. Segura para la decoración. Se puede usar para cubrir _ejes_ y _correas_ _mecánicas_ .", - - "block.create.andesite_funnel.tooltip": "EMBUDO DE ANDESITA", - "block.create.andesite_funnel.tooltip.summary": "Un componente de transferencia de objetos generales, que hace la transición entre los medios de transporte. Puede ser controlado con una _señal_ _de_ _redstone_ .", - "block.create.andesite_funnel.tooltip.condition1": "Comportamiento General", - "block.create.andesite_funnel.tooltip.behaviour1": "La _cara_ _abierta_ recogerá los _objetos_ en el bloque que tiene delante y los _introducirá_ en cualquier contenedor en el lado opuesto del embudo.", - "block.create.andesite_funnel.tooltip.condition2": "Cuando se monta en correas, depósitos y similares", - "block.create.andesite_funnel.tooltip.behaviour2": "_Recoge_ o _Coloca_ artículos en el componente montado, desde o hacia el _inventario_ _detrás_ de sí mismo. Siempre que el embudo tenga una direccionalidad específica, esta puede ser invertida usando una llave inglesa.", - "block.create.andesite_funnel.tooltip.condition3": "Cuando esta vertical entre dos inventarios", - "block.create.andesite_funnel.tooltip.behaviour3": "_Transferirá_ los objetos _hacia abajo_ , como si fuera una tolva sin buffer.", - - "block.create.andesite_tunnel.tooltip": "TÚNEL DE ANDESITA", - "block.create.andesite_tunnel.tooltip.summary": "Una cubierta protectora para sus _Correas_ y una gran manera de cubrir los agujeros dejados en su pared por ellas.", - "block.create.andesite_tunnel.tooltip.control1": "Click derecho a un lado con la llave inglesa", - "block.create.andesite_tunnel.tooltip.action1": "Ajusta las percianas de la ventana si el túnel tiene una en esa cara.", - - "block.create.brass_funnel.tooltip": "EMBUDO DE LATÓN", - "block.create.brass_funnel.tooltip.summary": "Un componente de transferencia de objetos generales, que hace la transición entre los medios de transporte. Puede ser controlado con una _señal_ _de_ _redstone_ . Viene con un practico _filtro_ .", - "block.create.brass_funnel.tooltip.condition1": "Comportamiento General", - "block.create.brass_funnel.tooltip.behaviour1": "La _cara_ _abierta_ recogerá los _objetos_ en el bloque que tiene delante y los _introducirá_ en cualquier contenedor en el lado opuesto del embudo.", - "block.create.brass_funnel.tooltip.condition2": "Cuando se monta en correas, depósitos y similares", - "block.create.brass_funnel.tooltip.behaviour2": "_Recoge_ o _Coloca_ artículos en el componente montado, desde o hacia el _inventario_ _detrás_ de sí mismo. Siempre que el embudo tenga una direccionalidad específica, esta puede ser invertida usando una llave inglesa.", - "block.create.brass_funnel.tooltip.condition3": "Cuando esta vertical entre dos inventarios", - "block.create.brass_funnel.tooltip.behaviour3": "_Transferirá_ los objetos _hacia abajo_ , como si fuera una tolva sin buffer.", - - "block.create.brass_tunnel.tooltip": "TÚNEL DE LATÓN", - "block.create.brass_tunnel.tooltip.summary": "El _Túnel_ _de_ _Latón_ vienen con un número de opciones de _filtrado_ y _separación_ de objetos para sus _correas_ .", - "block.create.brass_tunnel.tooltip.condition1": "Cuando se colocan uno al lado del otro", - "block.create.brass_tunnel.tooltip.behaviour1": "Los _Túneles_ _de_ _Latón_ se conectan entre sí permitiendo que el contenido de una _correa_ sea redirigido a otra.", - "block.create.brass_tunnel.tooltip.condition2": "Filtraje", - "block.create.brass_tunnel.tooltip.behaviour2": "Los _Túneles_ _de_ _ Latón_ vienen con filtros tanto para la entrada como para la salida. Si un _objeto_ no está permitido desde el filtro de salida de un _Túnel_ será transferido a la salida de otro _Túnel_ conectado.", - "block.create.brass_tunnel.tooltip.condition3": "Dividiendo", - "block.create.brass_tunnel.tooltip.behaviour3": "Los _Túneles_ _de_ _Latón_ de pueden ser configurados para cambiar el método en el que se ordenan los _objetos_ en las _correas_ conectadas.", - "block.create.brass_tunnel.tooltip.control1": "Click derecho a un lado con la llave inglesa", - "block.create.brass_tunnel.tooltip.action1": "Ajusta las percianas de la ventana si el túnel tiene una en esa cara.", - "block.create.brass_tunnel.tooltip.control2": "Girar la rueda del ratón con la llave inglesa en la parte superior", - "block.create.brass_tunnel.tooltip.action2": "Cambia el método de división de los _túneles_ conectados.", - - "block.create.copper_casing.tooltip": "CARCASA DE COBRE", - "block.create.copper_casing.tooltip.summary": "Una simple carcasa para máquinas con una variedad de usos. Segura para la decoración.", - "block.create.copper_casing.tooltip.condition1": "Cuando se usa en una Tubería de Fluidos", - "block.create.copper_casing.tooltip.behaviour1": "Recubre la _Tubería_ _de_ _Fluidos_ con la _Carcasa_ _de_ _Cobre._ Las tuberías recubiertas _bloquearán_ _sus_ _conexiones_ en su lugar, ya no reaccionarán a los cambios de las tuberías vecinas.", - - "block.create.encased_fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS RECUBIERTA", - "block.create.encased_fluid_pipe.tooltip.summary": "Una _Tubería_ _de_ _Fluidos_ recubierta con una _Carcasa_ _de_ _Cobre_", - - "block.create.copper_valve_handle.tooltip": "MANIJA DE VÁLVULA DE COBRE", - "block.create.copper_valve_handle.tooltip.summary": "Una precisa _fuente_ de _Fuerza_ _Rotacional_ que requiere la interacción de los jugadores. ¡Ten cuidado de no desgastarte!", - "block.create.copper_valve_handle.tooltip.condition1": "Cuando se usa", - "block.create.copper_valve_handle.tooltip.behaviour1": "Proporciona _fuerza_ _rotacional_ a un artefacto adjunto. _agáchate_ _para_ _revertir_ la rotación.", - - "block.create.seat.tooltip": "ASIENTO", - "block.create.seat.tooltip.summary": "¡Siéntese y disfrute del paseo! Anclará a un jugador en una _artefacto_ en movimiento. ¡También es Grandioso para las construcciones estáticas! Viene en una variedad de colores.", - "block.create.seat.tooltip.condition1": "Click Derecho en el asiento", - "block.create.seat.tooltip.behaviour1": "Sienta al jugador en el _asiento_ . Presiona el shift izquierdo para salir del _asiento._", - - "block.create.chute.tooltip": "VERTEDOR", - "block.create.chute.tooltip.summary": "_Recoge_ y transporta objetos en vertical o en diagonal. Puede llevar y colocar los objetos en _contenedores._ También puede interactuar con los vertedores desde el lado usando _tolvas_ o _embudos_ _montados._", - "block.create.chute.tooltip.condition1": "Cuando es usado con un ventilador", - "block.create.chute.tooltip.behaviour1": "Los vertedores usados con _ventiladores_ pueden transportar _objetos_ hacia arriba y succionar _objetos_ de _depósitos_ y _correas._", - - "block.create.depot.tooltip": "DEPÓSITO", - "block.create.depot.tooltip.summary": "Un lugar práctico para colocar sus _Objetos._ Proporciona un punto de interacción para varias máquinas", - "block.create.depot.tooltip.condition1": "Click Derecho en un Depósito", - "block.create.depot.tooltip.behaviour1": "Coloca o toma un _objeto_ del _depósito._ Los _bloques_ y _artefactos_ que interactúan con una _correa_ también funcionan en un _depósito._", - - "item.create.blaze_cake.tooltip": "PASTEL DE BLAZE", - "item.create.blaze_cake.tooltip.summary": "Un delicioso regalo para tus grandiosos _quemadores_ _de_ _blaze._ ¡Los enciende a todos!", - - "item.create.empty_blaze_burner.tooltip": "QUEMADOR DE BLAZE VACIO", - "item.create.empty_blaze_burner.tooltip.summary": "Un pequeño hogar de hierro para tus ardientes amigos. Estoy seguro de que podrías darles un buen uso.", - "item.create.empty_blaze_burner.tooltip.condition1": "Cuando es usado en un generador de blaze", - "item.create.empty_blaze_burner.tooltip.behaviour1": "_Captura_ un blaze en el objeto", - - "block.create.fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS", - "block.create.fluid_pipe.tooltip.summary": "Se usa para mover _fluidos._ Necesita una _bomba_ _mecánica_ para mover el fluido.", - "block.create.fluid_pipe.tooltip.condition1": "Transferencia de fluidos", - "block.create.fluid_pipe.tooltip.behaviour1": "Puede conectarse a _contenedores_ _de_ _fluidos_ como _tanques_ o _cuencas._ Los extremos expuestos de las _tuberías_ también pueden drenar o colocar bloques de fluido. ¡Ten cuidado con las fugas!", - "block.create.fluid_pipe.tooltip.control1": "Click Derecho con una Llave Inglesa", - "block.create.fluid_pipe.tooltip.action1": "Coloca una ventana en la tubería si está disponible", - - "block.create.hose_pulley.tooltip": "POLEA CON MANGUERA", - "block.create.hose_pulley.tooltip.summary": "Se utiliza para _colocar_ o _drenar_ grandes _cuerpos_ _de_ _fluido_ en el mundo.", - "block.create.hose_pulley.tooltip.condition1": "Cuando es impulsado por la cinética", - "block.create.hose_pulley.tooltip.behaviour1": "_Sube_ o _baja_ la manguera, La ubicación de la manguera determina hasta qué _altura_ actuará la _extracción_ o el _llenado_ .", - "block.create.hose_pulley.tooltip.condition2": "Cuando los fluidos son extraídos de la polea", - "block.create.hose_pulley.tooltip.behaviour2": "Empieza a _extraer_ bloques de _líquido_ del cuerpo en el que se bajó la punta de la manguera. Los cuerpos de fluido _muy_ _grandes_ serán _considerados_ _infinitos_ .", - "block.create.hose_pulley.tooltip.condition3": "Cuando los fluidos son empujados a la polea", - "block.create.hose_pulley.tooltip.behaviour3": "Comienza a _llenar_ con _fluido_ en el mundo _hasta_ _arriba_ a la _altura_ de la _punta_ _de_ _la_ _manguera_ .", - - "block.create.fluid_tank.tooltip": "TANQUE DE FLUIDOS", - "block.create.fluid_tank.tooltip.summary": "Almacena todos tus _fluidos_ favoritos. Escala en anchura y altura.", - "block.create.fluid_tank.tooltip.condition1": "Click Derecho con una Llave Inglesa", - "block.create.fluid_tank.tooltip.behaviour1": "Cambia la ventana opcional", - - "block.create.creative_fluid_tank.tooltip": "TANQUE DE FLUIDOS DEL CREATIVO", - "block.create.creative_fluid_tank.tooltip.summary": "Este _Tanque_ _de_ _Fluidos_ permite la replicación infinita de cualquier Fluido. Escala en anchura y altura.", - "block.create.creative_fluid_tank.tooltip.condition1": "Cuando hay fluido en el tanque", - "block.create.creative_fluid_tank.tooltip.behaviour1": "Cualquier cosa que _extraiga_ de este tanque proporcionará un _suministro_ _ilimitado_ del fluido especificado. Los fluidos _insertados_ en este tanque serán _eliminados._", - "block.create.creative_fluid_tank.tooltip.condition2": "Click Derecho con una Llave Inglesa", - "block.create.creative_fluid_tank.tooltip.behaviour2": "Cambia la ventana opcional", - - "block.create.fluid_valve.tooltip": "VÁLVULAL DE FLUIDOS", - "block.create.fluid_valve.tooltip.summary": "Detiene el flujo de fluido por una tubería.", - "block.create.fluid_valve.tooltip.condition1": "Flujo controlable", - "block.create.fluid_valve.tooltip.behaviour1": "Aplicando una _fuerza_ _de_ _rotación_ forzará a la _válvula_ a cerrarse, cesando el flujo de _fluidos._ Invierte la dirección de la _fuerza_ _de_ _rotación_ para reabrir la válvula.", - - "block.create.mechanical_pump.tooltip": "BOMBA MECÁNICA", - "block.create.mechanical_pump.tooltip.summary": "Toma la _fuerza_ _de_ _rotación_ y la usa para mover el _fluido_ a lo largo de un _tubo._ Tiene un rango de efecto máximo en ambas direcciones. (16 bloques por defecto)", - "block.create.mechanical_pump.tooltip.condition1": "Flujo de fluidos", - "block.create.mechanical_pump.tooltip.behaviour1": "La _fuerza_ _de_ _rotación_ aplicada crea una presión que fuerza el _fluido_ a través de la red de _tuberías._ Invierte la dirección de la fuerza de rotación para cambiar la dirección en la que fluye el _fluido._", - "block.create.mechanical_pump.tooltip.control1": "Click Derecho con una Llave Inglesa", - "block.create.mechanical_pump.tooltip.action1": "Invierte la dirección de la _bomba,_ cambiando la dirección por defecto del flujo", - - "block.create.smart_fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS INTELIGENTE", - "block.create.smart_fluid_pipe.tooltip.summary": "Una _tubería_ _de_ _fluidos_ con un filtro. Puede especificar que _fluidos_ pasan por ella.", - "block.create.smart_fluid_pipe.tooltip.condition1": "Cuando los fluidos son empujados hacia ella", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "Las tuberías inteligentes que reciben un fluido que no coincide con su filtro bloquearán el flujo.", - "block.create.smart_fluid_pipe.tooltip.condition2": "Cuando está adyacente a un recipiente de fluido", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "Las tuberías inteligentes que _inicien_ un _flujo_ desde cualquier contenedor sólo extraerán los fluidos que _coincidan_ con su _filtro._", - - "block.create.spout.tooltip": "CANALETA", - "block.create.spout.tooltip.summary": "Un inyector para rellenar sus _objetos_ con _fluidos._", - "block.create.spout.tooltip.condition1": "Transferencia de fluidos", - "block.create.spout.tooltip.behaviour1": "Cuando se coloca un _objeto_ que puede _contener_ _fluidos_ como una _cubeta_ o _botella_ debajo, la canaleta intentará rellenarlo con su propio _fluido_ almacenado.", - "block.create.spout.tooltip.condition2": "Automatización de fluidos", - "block.create.spout.tooltip.behaviour2": "La canaleta colocada sobre una _correa_ o _depósito_ reaccionará automáticamente con un _contenedor_ _de_ _líquido_ que pase por debajo de él.", - - "block.create.item_drain.tooltip": "ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "Un depósito con rejilla para vaciar sus _objetos_ _con_ _fluidos._", - "block.create.item_drain.tooltip.condition1": "Transferencia de fluidos", - "block.create.item_drain.tooltip.behaviour1": "Cuando se inserta un _contenedor_ _de_ _fluidos_ como una _cubeta_ o _botella_ desde el lado, el extractor intentará vaciarlo en su propio _contenedor_ de _fluidos._ El objeto será entonces expulsado por el lado opuesto.", - - "block.create.mechanical_arm.tooltip": "MECHANICAL ARM", - "block.create.mechanical_arm.tooltip.summary": "Un artefacto avanzado para reubicar _objetos._", - "block.create.mechanical_arm.tooltip.condition1": "Transferencia de objetos", - "block.create.mechanical_arm.tooltip.behaviour1": "Puede tomar o colocar artículos en cualquier _inventario_ _accesible,_ como _Correas,_ _Depósitos,_ _Embudos_ y _Crafters_ _Mecánicos._", - "block.create.mechanical_arm.tooltip.control1": "Mientras que este en la mano", - "block.create.mechanical_arm.tooltip.action1": "Click Derecho en un _inventario_ _de_ _objetos_ _accesible_ para establecerlo como _fuente_ del _Brazo_ _Mecánico._ Haga clic derecho dos veces para establecerlo como el _destino._", - "block.create.mechanical_arm.tooltip.control2": "Girar la rueda del ratón con la llave inglesa", - "block.create.mechanical_arm.tooltip.action2": "Establece el criterio de comportamiento para la salida de los _objetos_ por el _Brazo_ _Mecánico._", - - "item.create.wand_of_symmetry.tooltip": "SYMMETRY WAND", - "item.create.wand_of_symmetry.tooltip.summary": "Crea un 'espejo' que refleja perfectamente la colocación de bloques a través de los planos configurados.", - "item.create.wand_of_symmetry.tooltip.condition1": "Cuando esta en la barra de ítems", - "item.create.wand_of_symmetry.tooltip.behaviour1": "Se mantiene activo", - "item.create.wand_of_symmetry.tooltip.control1": "Click Derecho en el suelo", - "item.create.wand_of_symmetry.tooltip.action1": "_Crea_ o _mueve_ el 'espejo'.", - "item.create.wand_of_symmetry.tooltip.control2": "Click Derecho en el aire", - "item.create.wand_of_symmetry.tooltip.action2": "_Remueve_ el 'espejo' activo", - "item.create.wand_of_symmetry.tooltip.control3": "Click Derecho cuando se esta agachado", - "item.create.wand_of_symmetry.tooltip.action3": "Abre la _Interfaz_ _de_ _Configuración_", - - "item.create.handheld_blockzapper.tooltip": "BLOCKZAPPER", - "item.create.handheld_blockzapper.tooltip.summary": "Novedoso artilugio para colocar o intercambiar bloques a distancia.", - "item.create.handheld_blockzapper.tooltip.control1": "Click Izquierdo a un bloque", - "item.create.handheld_blockzapper.tooltip.action1": "Establece los bloques que serán colocados por la herramienta en el bloque objetivo.", - "item.create.handheld_blockzapper.tooltip.control2": "Click Derecho en un bloque", - "item.create.handheld_blockzapper.tooltip.action2": "_Coloca_ o _reemplaza_ el bloque objetivo.", - "item.create.handheld_blockzapper.tooltip.control3": "Click Derecho mientras se está agachado", - "item.create.handheld_blockzapper.tooltip.action3": "Abre la _Interfaz_ _de_ _Configuración._", - - "item.create.handheld_worldshaper.tooltip": "HANDHELD WORLDSHAPER", - "item.create.handheld_worldshaper.tooltip.summary": "Una herramienta útil para crear _paisajes_ y _características_ en el _terreno._", - "item.create.handheld_worldshaper.tooltip.control1": "Click Izquierdo a un bloque", - "item.create.handheld_worldshaper.tooltip.action1": "Establece los bloques que serán colocados por la herramienta en el bloque objetivo.", - "item.create.handheld_worldshaper.tooltip.control2": "Click Derecho en un bloque", - "item.create.handheld_worldshaper.tooltip.action2": "Aplica el _Pincel_ y la _Herramienta_ actualmente seleccionados en el lugar objetivo.", - "item.create.handheld_worldshaper.tooltip.control3": "Click Derecho mientras se está agachado", - "item.create.handheld_worldshaper.tooltip.action3": "Abre la _Interfaz_ _de_ _Configuración._", - - "item.create.tree_fertilizer.tooltip": "TREE FERTILIZER", - "item.create.tree_fertilizer.tooltip.summary": "Una poderosa combinación de minerales adecuados para acelerar el crecimiento de los tipos de árboles comunes.", - "item.create.tree_fertilizer.tooltip.condition1": "Cuando se usa en un retoño de árbol", - "item.create.tree_fertilizer.tooltip.behaviour1": "Hace crecer los árboles, sin importar el espacio entre ellos.", - - "item.create.deforester.tooltip": "DEFORESTER", - "item.create.deforester.tooltip.summary": "Un _hacha_ _radiante_ capaz de cortar árboles en una fracción de segundo.", - - "item.create.extendo_grip.tooltip": "EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "Boioioing! En gran medida, _aumenta_ _la_ _distancia_ _de_ _alcance_ del portador.", - "item.create.extendo_grip.tooltip.condition1": "Cuando está en la mano secundaria", - "item.create.extendo_grip.tooltip.behaviour1": "Aumenta el rango de alcance de los objetos usados en la _mano_ _principal._", - - "item.create.filter.tooltip": "FILTER", - "item.create.filter.tooltip.summary": "_Controla_ las _salidas_ y _entradas_ de los dispositivos logísticos con más _precisión,_ comparándolas con un _conjunto_ _de_ _objetos_ o varios _filtros_ _anidados._", - "item.create.filter.tooltip.condition1": "Cuando está en la ranura del filtro", - "item.create.filter.tooltip.behaviour1": "_Controla_ el flujo de objetos según su _configuración._", - "item.create.filter.tooltip.condition2": "Con Click Derecho", - "item.create.filter.tooltip.behaviour2": "Abre la _Interfaz_ _de_ _Configuración._", - - "item.create.attribute_filter.tooltip": "ATTRIBUTE FILTER", - "item.create.attribute_filter.tooltip.summary": "_Controla_ las _salidas_ y _entradas_ de los dispositivos logísticos con más _precisión,_ comparándolas con un _conjunto_ _de_ _atributos_ _de_ _objetos_ y _categorias._", - "item.create.attribute_filter.tooltip.condition1": "Cuando está en la ranura del filtro", - "item.create.attribute_filter.tooltip.behaviour1": "_Controla_ el flujo de objetos según su _configuración._", - "item.create.attribute_filter.tooltip.condition2": "Con Click Derecho", - "item.create.attribute_filter.tooltip.behaviour2": "Abre la _Interfaz_ _de_ _Configuración._", - - "item.create.empty_schematic.tooltip": "EMPTY SCHEMATIC", - "item.create.empty_schematic.tooltip.summary": "Se usa como ingrediente en una receta y para escribir en la _Mesa_ _de_ _Esquemas._", - - "item.create.schematic.tooltip": "SCHEMATIC", - "item.create.schematic.tooltip.summary": "Sostiene una estructura para ser posicionada y colocada en el mundo. Posiciona el Holograma como se desee y usa un _Esquemacañon_ para construirlo.", - "item.create.schematic.tooltip.condition1": "Cuando es sostenido", - "item.create.schematic.tooltip.behaviour1": "Se puede posicionar usando las Herramientas en Pantalla.", - "item.create.schematic.tooltip.control1": "Click Derecho mientras se está agachado", - "item.create.schematic.tooltip.action1": "Abre una _interfaz_ para introducir las _coordenadas_ exactas.", - - "item.create.schematic_and_quill.tooltip": "SCHEMATIC AND QUILL", - "item.create.schematic_and_quill.tooltip.summary": "Se usa para guardar una estructura de tu mundo en un archivo .nbt", - "item.create.schematic_and_quill.tooltip.condition1": "Paso 1", - "item.create.schematic_and_quill.tooltip.behaviour1": "Selecciona dos esquinas con Click Derecho.", - "item.create.schematic_and_quill.tooltip.condition2": "Paso 2", - "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrl_ _+_ _girar_ _rueda_ _del_ _ratón_ en las caras para ajustar el tamaño. Click Derecho de nuevo para Guardar.", - "item.create.schematic_and_quill.tooltip.control1": "Click Derecho", - "item.create.schematic_and_quill.tooltip.action1": "Selecciona una esquina / confirma el guardado.", - "item.create.schematic_and_quill.tooltip.control2": "Manteniendo la tecla Ctrl", - "item.create.schematic_and_quill.tooltip.action2": "Selecciona los puntos en _medio_ _del_ _aire._ _Girar_ _rueda_ _del_ _ratón_ para ajustar la distancia.", - "item.create.schematic_and_quill.tooltip.control3": "Click Derecho mientras se está agachado", - "item.create.schematic_and_quill.tooltip.action3": "_Reinicia_ y quita la selección.", - - "block.create.schematicannon.tooltip": "SCHEMATICANNON", - "block.create.schematicannon.tooltip.summary": "Dispara bloques para recrear un _esquema_ ya desplegado en el mundo. Utiliza objetos de los inventarios adyacentes y _Pólvora_ como combustible.", - "block.create.schematicannon.tooltip.control1": "Click Derecho sobre él", - "block.create.schematicannon.tooltip.action1": "Abre la interfaz", - - "block.create.schematic_table.tooltip": "SCHEMATIC TABLE", - "block.create.schematic_table.tooltip.summary": "Escribe los esquemas guardados en un _Esquema_ _Vacío._", - "block.create.schematic_table.tooltip.condition1": "Cuando se le da un esquema vacío", - "block.create.schematic_table.tooltip.behaviour1": "Carga un archivo elegido de su carpeta de esquemas.", - - "block.create.shaft.tooltip": "SHAFT", - "block.create.shaft.tooltip.summary": "_Transmite_ la _rotación_ en una línea recta.", - - "block.create.cogwheel.tooltip": "COGWHEEL", - "block.create.cogwheel.tooltip.summary": "_Transmite_ la _rotación_ en una línea recta, y a las _Ruedas_ _Dentadas_ adyacentes.", - - "block.create.large_cogwheel.tooltip": "LARGE COGWHEEL", - "block.create.large_cogwheel.tooltip.summary": "Una versión más grande de la _Rueda_ _Dentada,_ que permite _cambiar_ _la_ _Velocidad_ _de_ _Rotación_ cuando se conecta a su Contraparte más pequeña.", - - "block.create.encased_shaft.tooltip": "ENCASED SHAFT", - "block.create.encased_shaft.tooltip.summary": "_Transmite_ la _rotación_ en una línea recta. Adecuado para transmitir la rotación a través de las paredes.", - - "block.create.gearbox.tooltip": "GEARBOX", - "block.create.gearbox.tooltip.summary": "_Transmite_ la _rotación_ en _cuatro_ _direcciones._ Invierte las conexiones rectas.", - - "block.create.gearshift.tooltip": "GEARSHIFT", - "block.create.gearshift.tooltip.summary": "Un control para cambiar la dirección de rotación de los ejes conectados.", - "block.create.gearshift.tooltip.condition1": "Cuando tiene una señal de Redstone", - "block.create.gearshift.tooltip.behaviour1": "_Invierte_ la rotación de salida.", - - "block.create.clutch.tooltip": "CLUTCH", - "block.create.clutch.tooltip.summary": "Un control para activar/desactivar la rotación de los ejes conectados.", - "block.create.clutch.tooltip.condition1": "Cuando tiene una señal de Redstone", - "block.create.clutch.tooltip.behaviour1": "_Deja_ de transmitir la rotación hacia el otro lado.", - - "block.create.encased_chain_drive.tooltip": "ENCASED_CHAIN_DRIVE", - "block.create.encased_chain_drive.tooltip.summary": "_Transmite_ la _rotación_ en una línea recta y a las _Transmisiones_ _de_ _Cadena_ _Empotrada_ adyacentes. Las transmisiones de cadena se conectan en un grupo cuando se colocan juntas por cualquier cara sin un eje. Su orientación no tiene por qué coincidir.", - "block.create.encased_chain_drive.tooltip.condition1": "Cuando se conectan", - "block.create.encased_chain_drive.tooltip.behaviour1": "Los bloques adjuntos transmitirán la _velocidad_ _de_ _rotación_ y el sentido de este componente.", - - "block.create.adjustable_chain_gearshift.tooltip": "ADJUSTABLE CHAIN GEARSHIFT", - "block.create.adjustable_chain_gearshift.tooltip.summary": "_Transmite_ la _rotación_ en una línea recta y a las _Transmisiones_ _de_ _Cadena_ _Empotrada_ adyacentes. Una _señal_ _de_ _redstone_ proporcionada a este bloque controlará el tamaño de la rueda motriz que se acopla a las cadenas de transmisión.", - "block.create.adjustable_chain_gearshift.tooltip.condition1": "Control por Redstone", - "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "_Sin_ una señal, las cadenas adyacentes transmitirán la _misma_ _velocidad._ Con una señal a _máxima_ _potencia,_ las cadenas adyacentes transmitirán exactamente el _doble_ _de_ _su_ _velocidad._ Cualquier cosa intermedia dará resultados entre 1-2x su velocidad.", - - "item.create.belt_connector.tooltip": "BELT CONNECTOR", - "item.create.belt_connector.tooltip.summary": "Conecta dos o más _ejes_ con una _Correa_ _Mecánica._ Los ejes conectados tendrán exactamente la misma velocidad y dirección de rotación. La cinta puede actuar como un _transportador_ para _Objetos_ y _Entidades._", - "item.create.belt_connector.tooltip.control1": "Click Derecho en un eje", - "item.create.belt_connector.tooltip.action1": "Selecciona el eje como una polea del cinturón. Ambos ejes seleccionados tienen que _alinearse_ ya sea _Verticalmente,_ _Horizontalmente,_ o _Diagonalmente_ hacia la dirección de la Correa.", - "item.create.belt_connector.tooltip.control2": "Click Derecho mientras se está agachado", - "item.create.belt_connector.tooltip.action2": "_Reinicia_ la primera posición seleccionada para la correa.", - - "item.create.goggles.tooltip": "GOGGLES", - "item.create.goggles.tooltip.summary": "Un par de gafas para aumentar la visión con _información_ _cinética_ útil.", - "item.create.goggles.tooltip.condition1": "Cuando se usan", - "item.create.goggles.tooltip.behaviour1": "Muestra _indicadores_ _con_ _colores_ correspondientes al _Nivel_ _de_ _Velocidad_ de un componente cinético colocado, así como _Impacto_ _de_ _Estrés_ y _Capacidad_ de los componentes individuales.", - "item.create.goggles.tooltip.condition2": "Al mirar el medidor", - "item.create.goggles.tooltip.behaviour2": "Muestra información detallada sobre la _velocidad_ o el _estrés_ de la red a la que está conectado el medidor.", - - "item.create.wrench.tooltip": "WRENCH", - "item.create.wrench.tooltip.summary": "Una herramienta útil para trabajar en artefactos cinéticos. Se puede utilizar para _Rotar,_ _Desmantelar_ y _Configurar_ componentes.", - "item.create.wrench.tooltip.control1": "Click Derecho en un bloqueo cinético", - "item.create.wrench.tooltip.action1": "_Gira_ los componentes hacia o en contra de la cara con la que interactuó.", - "item.create.wrench.tooltip.control2": "Click Derecho mientras se está agachado", - "item.create.wrench.tooltip.action2": "_Desmonta_ los _componentes_ _cinéticos_ y los coloca de nuevo en _tú_ _inventario._" - -} \ No newline at end of file diff --git a/src/main/resources/assets/create/lang/ja_jp.json b/src/main/resources/assets/create/lang/ja_jp.json index 6e05619b5..967b1a5d5 100644 --- a/src/main/resources/assets/create/lang/ja_jp.json +++ b/src/main/resources/assets/create/lang/ja_jp.json @@ -3,7 +3,7 @@ "_": "->------------------------] Game Elements [------------------------<-", "block.create.acacia_window": "アカシアの窓", - "block.create.acacia_window_pane": "アカシアの窓パネル", + "block.create.acacia_window_pane": "アカシアの窓板", "block.create.adjustable_chain_gearshift": "可変チェーンギアシフト", "block.create.adjustable_crate": "可変クレート", "block.create.adjustable_pulse_repeater": "可変パルスリピーター", @@ -13,12 +13,12 @@ "block.create.andesite_bricks": "安山岩レンガ", "block.create.andesite_bricks_slab": "安山岩レンガのハーフブロック", "block.create.andesite_bricks_stairs": "安山岩レンガの階段", - "block.create.andesite_bricks_wall": "安山岩レンガの壁", + "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_cobblestone_wall": "安山岩の丸石の塀", "block.create.andesite_encased_shaft": "安山岩のケース入りシャフト", "block.create.andesite_funnel": "安山岩ファンネル", "block.create.andesite_pillar": "安山岩の柱", @@ -26,11 +26,13 @@ "block.create.basin": "鉢", "block.create.belt": "メカニカルベルト", "block.create.birch_window": "シラカバの窓", - "block.create.birch_window_pane": "シラカバの窓パネル", + "block.create.birch_window_pane": "シラカバの窓板", + "block.create.black_nixie_tube": "黒色のニキシー管", "block.create.black_sail": "黒色の帆", "block.create.black_seat": "黒色のシート", "block.create.black_valve_handle": "黒色のバルブハンドル", "block.create.blaze_burner": "ブレイズバーナー", + "block.create.blue_nixie_tube": "青色のニキシー管", "block.create.blue_sail": "青色の帆", "block.create.blue_seat": "青色のシート", "block.create.blue_valve_handle": "青色のバルブハンドル", @@ -40,6 +42,7 @@ "block.create.brass_encased_shaft": "真鍮のケース入りシャフト", "block.create.brass_funnel": "真鍮ファンネル", "block.create.brass_tunnel": "真鍮トンネル", + "block.create.brown_nixie_tube": "茶色のニキシー管", "block.create.brown_sail": "茶色の帆", "block.create.brown_seat": "茶色のシート", "block.create.brown_valve_handle": "茶色のバルブハンドル", @@ -57,6 +60,7 @@ "block.create.cogwheel": "歯車", "block.create.content_observer": "コンテンツオブザーバー", "block.create.controller_rail": "コントローラーレール", + "block.create.copper_backtank": "銅のバックタンク", "block.create.copper_block": "銅ブロック", "block.create.copper_casing": "銅ケーシング", "block.create.copper_ore": "銅鉱石", @@ -67,45 +71,46 @@ "block.create.creative_fluid_tank": "クリエイティブ液体タンク", "block.create.creative_motor": "クリエイティブモーター", "block.create.crimson_window": "真紅の窓", - "block.create.crimson_window_pane": "真紅の窓パネル", + "block.create.crimson_window_pane": "真紅の窓板", "block.create.crushing_wheel": "破砕ホイール", "block.create.crushing_wheel_controller": "破砕ホイールコントローラー", "block.create.cuckoo_clock": "鳩時計", + "block.create.cyan_nixie_tube": "水色のニキシー管", "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_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_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_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_bricks_wall": "閃緑岩レンガの塀", "block.create.diorite_cobblestone": "閃緑岩の丸石", "block.create.diorite_cobblestone_slab": "閃緑岩の丸石のハーフブロック", "block.create.diorite_cobblestone_stairs": "閃緑岩の丸石の階段", - "block.create.diorite_cobblestone_wall": "閃緑岩の丸石の壁", + "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_bricks_wall": "苦灰岩レンガの塀", "block.create.dolomite_cobblestone": "苦灰岩の丸石", "block.create.dolomite_cobblestone_slab": "苦灰岩の丸石のハーフブロック", "block.create.dolomite_cobblestone_stairs": "苦灰岩の丸石の階段", - "block.create.dolomite_cobblestone_wall": "苦灰岩の丸石の壁", + "block.create.dolomite_cobblestone_wall": "苦灰岩の丸石の塀", "block.create.dolomite_pillar": "苦灰岩の柱", "block.create.encased_chain_drive": "ケース入りチェーンドライブ", "block.create.encased_fan": "ケース入りファン", @@ -113,39 +118,39 @@ "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_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_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_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_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_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_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_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_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.fancy_weathered_limestone_bricks_wall": "装飾された風化した石灰岩レンガの塀", "block.create.fluid_pipe": "液体パイプ", "block.create.fluid_tank": "液体タンク", "block.create.fluid_valve": "液体バルブ", @@ -157,11 +162,11 @@ "block.create.gabbro_bricks": "斑れい岩レンガ", "block.create.gabbro_bricks_slab": "斑れい岩レンガのハーフブロック", "block.create.gabbro_bricks_stairs": "斑れい岩レンガの階段", - "block.create.gabbro_bricks_wall": "斑れい岩レンガの壁", + "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_cobblestone_wall": "斑れい岩の丸石の塀", "block.create.gabbro_pillar": "斑れい岩の柱", "block.create.gantry_carriage": "ガントリーキャリッジ", "block.create.gantry_shaft": "ガントリーシャフト", @@ -171,26 +176,29 @@ "block.create.granite_bricks": "花崗岩レンガ", "block.create.granite_bricks_slab": "花崗岩レンガのハーフブロック", "block.create.granite_bricks_stairs": "花崗岩レンガの階段", - "block.create.granite_bricks_wall": "花崗岩レンガの壁", + "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_cobblestone_wall": "花崗岩の丸石の塀", "block.create.granite_pillar": "花崗岩の柱", + "block.create.gray_nixie_tube": "灰色のニキシー管", "block.create.gray_sail": "灰色の帆", "block.create.gray_seat": "灰色のシート", "block.create.gray_valve_handle": "灰色のバルブハンドル", + "block.create.green_nixie_tube": "緑色のニキシー管", "block.create.green_sail": "緑色の帆", "block.create.green_seat": "緑色のシート", "block.create.green_valve_handle": "緑色のバルブハンドル", "block.create.hand_crank": "ハンドクランク", + "block.create.haunted_bell": "憑りつかれた鐘", "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.jungle_window_pane": "ジャングルの窓板", "block.create.large_cogwheel": "大きな歯車", "block.create.layered_andesite": "安山岩の組石", "block.create.layered_dark_scoria": "ダークスコリアの組石", @@ -201,12 +209,16 @@ "block.create.layered_limestone": "石灰岩の組石", "block.create.layered_scoria": "スコリアの組石", "block.create.layered_weathered_limestone": "風化した石灰岩の組石", + "block.create.lectern_controller": "書見台コントローラー", + "block.create.light_blue_nixie_tube": "空色のニキシー菅", "block.create.light_blue_sail": "空色の帆", "block.create.light_blue_seat": "空色のシート", "block.create.light_blue_valve_handle": "空色のバルブハンドル", + "block.create.light_gray_nixie_tube": "薄灰色のニキシー管", "block.create.light_gray_sail": "薄灰色の帆", "block.create.light_gray_seat": "薄灰色のシート", "block.create.light_gray_valve_handle": "薄灰色のバルブハンドル", + "block.create.lime_nixie_tube": "黄緑色のニキシー管", "block.create.lime_sail": "黄緑色の帆", "block.create.lime_seat": "黄緑色のシート", "block.create.lime_valve_handle": "黄緑色のバルブハンドル", @@ -215,14 +227,15 @@ "block.create.limestone_bricks": "石灰岩レンガ", "block.create.limestone_bricks_slab": "石灰岩レンガのハーフブロック", "block.create.limestone_bricks_stairs": "石灰岩レンガの階段", - "block.create.limestone_bricks_wall": "石灰岩レンガの壁", + "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_cobblestone_wall": "石灰岩の丸石の塀", "block.create.limestone_pillar": "石灰岩の柱", "block.create.linear_chassis": "リニアシャーシ", "block.create.lit_blaze_burner": "燃焼中のブレイズバーナー", + "block.create.magenta_nixie_tube": "赤紫色のニキシー管", "block.create.magenta_sail": "赤紫色の帆", "block.create.magenta_seat": "赤紫色のシート", "block.create.magenta_valve_handle": "赤紫色のバルブハンドル", @@ -255,12 +268,12 @@ "block.create.nixie_tube": "ニキシー管", "block.create.nozzle": "ノズル", "block.create.oak_window": "オークの窓", - "block.create.oak_window_pane": "オークの窓パネル", + "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.ornate_iron_window_pane": "鉄の装飾ガラス板", "block.create.overgrown_andesite": "生い茂った安山岩", "block.create.overgrown_dark_scoria": "生い茂ったダークスコリア", "block.create.overgrown_diorite": "生い茂った閃緑岩", @@ -273,39 +286,41 @@ "block.create.paved_andesite": "舗装された安山岩", "block.create.paved_andesite_slab": "舗装された安山岩のハーフブロック", "block.create.paved_andesite_stairs": "舗装された安山岩の階段", - "block.create.paved_andesite_wall": "舗装された安山岩の壁", + "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_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_diorite_wall": "舗装された閃緑岩の塀", "block.create.paved_dolomite": "舗装された苦灰岩", "block.create.paved_dolomite_slab": "舗装された苦灰岩のハーフブロック", "block.create.paved_dolomite_stairs": "舗装された苦灰岩の階段", - "block.create.paved_dolomite_wall": "舗装された苦灰岩の壁", + "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_gabbro_wall": "舗装された斑れい岩の塀", "block.create.paved_granite": "舗装された花崗岩", "block.create.paved_granite_slab": "舗装された花崗岩のハーフブロック", "block.create.paved_granite_stairs": "舗装された花崗岩の階段", - "block.create.paved_granite_wall": "舗装された花崗岩の壁", + "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_limestone_wall": "舗装された石灰岩の塀", "block.create.paved_scoria": "舗装されたスコリア", "block.create.paved_scoria_slab": "舗装されたスコリアのハーフブロック", "block.create.paved_scoria_stairs": "舗装されたスコリアの階段", - "block.create.paved_scoria_wall": "舗装されたスコリアの壁", + "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.paved_weathered_limestone_wall": "舗装された風化した石灰岩の塀", + "block.create.peculiar_bell": "風変わりな鐘", + "block.create.pink_nixie_tube": "桃色のニキシー管", "block.create.pink_sail": "桃色の帆", "block.create.pink_seat": "桃色のシート", "block.create.pink_valve_handle": "桃色のバルブハンドル", @@ -313,37 +328,39 @@ "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_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_dolomite_wall": "磨かれた苦灰岩の塀", "block.create.polished_gabbro": "磨かれた斑れい岩", "block.create.polished_gabbro_slab": "磨かれた斑れい岩のハーフブロック", "block.create.polished_gabbro_stairs": "磨かれた斑れい岩の階段", - "block.create.polished_gabbro_wall": "磨かれた斑れい岩の壁", + "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_limestone_wall": "磨かれた石灰岩の塀", "block.create.polished_scoria": "磨かれたスコリア", "block.create.polished_scoria_slab": "磨かれたスコリアのハーフブロック", "block.create.polished_scoria_stairs": "磨かれたスコリアの階段", - "block.create.polished_scoria_wall": "磨かれたスコリアの壁", + "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.polished_weathered_limestone_wall": "磨かれた風化した石灰岩の塀", "block.create.portable_fluid_interface": "ポータブル液体インターフェース", "block.create.portable_storage_interface": "ポータブルストレージインターフェース", "block.create.powered_latch": "パワードラッチ", "block.create.powered_toggle_latch": "パワードトグルラッチ", "block.create.pulley_magnet": "プーリーマグネット", "block.create.pulse_repeater": "パルスリピーター", + "block.create.purple_nixie_tube": "紫色のニキシー管", "block.create.purple_sail": "紫色の帆", "block.create.purple_seat": "紫色のシート", "block.create.purple_valve_handle": "紫色のバルブハンドル", "block.create.radial_chassis": "ラジアルシャーシ", + "block.create.red_nixie_tube": "赤色のニキシー管", "block.create.red_sail": "赤色の帆", "block.create.red_seat": "赤色のシート", "block.create.red_valve_handle": "赤色のバルブハンドル", @@ -354,18 +371,18 @@ "block.create.rope": "ロープ", "block.create.rope_pulley": "ローププーリー", "block.create.rotation_speed_controller": "回転速度コントローラー", - "block.create.sail_frame": "帆のフレーム", + "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_bricks_wall": "スコリアレンガの塀", "block.create.scoria_cobblestone": "スコリアの丸石", "block.create.scoria_cobblestone_slab": "スコリアの丸石のハーフブロック", "block.create.scoria_cobblestone_stairs": "スコリアの丸石の階段", - "block.create.scoria_cobblestone_wall": "スコリアの丸石の壁", + "block.create.scoria_cobblestone_wall": "スコリアの丸石の塀", "block.create.scoria_pillar": "スコリアの柱", "block.create.secondary_linear_chassis": "セカンダリリニアシャーシ", "block.create.sequenced_gearshift": "シーケンスギアシフト", @@ -376,9 +393,9 @@ "block.create.speedometer": "速度メーター", "block.create.spout": "アイテム注液口", "block.create.spruce_window": "マツの窓", - "block.create.spruce_window_pane": "マツの窓パネル", + "block.create.spruce_window_pane": "マツの窓板", "block.create.sticker": "スティッカー", - "block.create.sticky_mechanical_piston": "粘着メカニカルピストン", + "block.create.sticky_mechanical_piston": "メカニカル粘着ピストン", "block.create.stockpile_switch": "在庫スイッチ", "block.create.stressometer": "応力メーター", "block.create.tiled_glass": "タイルガラス", @@ -387,32 +404,39 @@ "block.create.vertical_framed_glass": "縦型ガラス窓", "block.create.vertical_framed_glass_pane": "縦型ガラス窓板", "block.create.warped_window": "歪んだ窓", - "block.create.warped_window_pane": "歪んだ窓パネル", + "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_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_cobblestone_wall": "風化した石灰岩の丸石の塀", "block.create.weathered_limestone_pillar": "風化した石灰岩の柱", "block.create.weighted_ejector": "重量射出機", + "block.create.white_nixie_tube": "白色のニキシー管", "block.create.white_sail": "白色の帆", "block.create.white_seat": "白色のシート", "block.create.white_valve_handle": "白色のバルブハンドル", "block.create.windmill_bearing": "風車ベアリング", "block.create.wooden_bracket": "木製ブラケット", + "block.create.yellow_nixie_tube": "黄色のニキシー管", "block.create.yellow_sail": "黄色の帆", "block.create.yellow_seat": "黄色のシート", "block.create.yellow_valve_handle": "黄色のバルブハンドル", "block.create.zinc_block": "亜鉛ブロック", "block.create.zinc_ore": "亜鉛鉱石", + "enchantment.create.capacity": "容量増加", + "enchantment.create.potato_recovery": "ポテト回収", + "entity.create.contraption": "からくり", + "entity.create.crafting_blueprint": "クラフトブループリント", "entity.create.gantry_contraption": "ガントリーからくり", + "entity.create.potato_projectile": "ポテト弾", "entity.create.seat": "シート", "entity.create.stationary_contraption": "付設からくり", "entity.create.super_glue": "超粘着剤", @@ -437,10 +461,12 @@ "item.create.chocolate_glazed_berries": "チョコレートグレーズドベリー", "item.create.chromatic_compound": "色彩の化合物", "item.create.cinder_flour": "ネザーラックの粉", + "item.create.copper_backtank": "銅のバックタンク", "item.create.copper_ingot": "銅インゴット", "item.create.copper_nugget": "銅塊", "item.create.copper_sheet": "銅板", "item.create.crafter_slot_cover": "クラフタースロットカバー", + "item.create.crafting_blueprint": "クラフトブループリント", "item.create.crushed_aluminum_ore": "砕いたアルミニウム鉱石", "item.create.crushed_brass": "砕いた真鍮", "item.create.crushed_copper_ore": "砕いた銅鉱石", @@ -455,7 +481,8 @@ "item.create.crushed_tin_ore": "砕いた錫鉱石", "item.create.crushed_uranium_ore": "砕いたウラン鉱石", "item.create.crushed_zinc_ore": "砕いた亜鉛鉱石", - "item.create.deforester": "デフォレスター", + "item.create.diving_boots": "潜水ブーツ", + "item.create.diving_helmet": "潜水ヘルメット", "item.create.dough": "生地", "item.create.electron_tube": "電子管", "item.create.empty_blaze_burner": "空のブレイズバーナー", @@ -465,17 +492,20 @@ "item.create.furnace_minecart_contraption": "からくりかまど付きトロッコ", "item.create.goggles": "エンジニアのゴーグル", "item.create.golden_sheet": "金板", - "item.create.handheld_blockzapper": "携帯型ブロックザッパー", "item.create.handheld_worldshaper": "携帯型ワールドシェーパー", "item.create.honey_bucket": "ハチミツ入りバケツ", "item.create.honeyed_apple": "リンゴのハチミツかけ", - "item.create.integrated_circuit": "集積回路", + "item.create.incomplete_cogwheel": "組み立て中の歯車", + "item.create.incomplete_large_cogwheel": "組み立て中の大きな歯車", + "item.create.incomplete_precision_mechanism": "組み立て中の精密機構", "item.create.iron_sheet": "鉄板", - "item.create.lapis_sheet": "ラピスラズリ板", + "item.create.linked_controller": "リンクコントローラー", "item.create.minecart_contraption": "からくり付きトロッコ", "item.create.minecart_coupling": "トロッコ連結器", "item.create.polished_rose_quartz": "磨かれたローズクォーツ", + "item.create.potato_cannon": "ポテトキャノン", "item.create.powdered_obsidian": "黒曜石の粉", + "item.create.precision_mechanism": "精密機構", "item.create.propeller": "プロペラ", "item.create.red_sand_paper": "赤い紙やすり", "item.create.refined_radiance": "高貴な光輝", @@ -499,7 +529,7 @@ "_": "->------------------------] Advancements [------------------------<-", "advancement.create.root": "Createへようこそ", - "advancement.create.root.desc": "素晴らしいからくり機構を作る時間だ!", + "advancement.create.root.desc": "素晴らしいからくり仕掛けを作る時間だ!", "advancement.create.andesite_alloy": "大いに押韻", "advancement.create.andesite_alloy.desc": "Createの素材には変な名前がついています、安山岩合金もその一つです", "advancement.create.its_alive": "こいつ…動くぞ!", @@ -508,51 +538,51 @@ "advancement.create.shifting_gears.desc": "大きい歯車と小さい歯車を噛み合わせて回転速度を変更する", "advancement.create.overstressed": "超過応力", "advancement.create.overstressed.desc": "応力の限界を肌で感じる", - "advancement.create.belt": "コンブ駆動", + "advancement.create.belt": "ベルトコンブア", "advancement.create.belt.desc": "2つのシャフトをメカニカルベルトで繋ぐ", - "advancement.create.tunnel": "隠せ!", - "advancement.create.tunnel.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": "机上の空論", "advancement.create.upward_chute.desc": "落ちているアイテムがファンで駆動するシュートに飛んでいく様子を見る", - "advancement.create.belt_funnel": "ファンネルのぶらさがってる、ひらひらしたやつ", - "advancement.create.belt_funnel.desc": "ベルトやデポ等の上に横向きのファンネルを置き、特殊形態にする", - "advancement.create.belt_funnel_kiss": "オウムと羽ばたき", + "advancement.create.belt_funnel": "ファンネルのひらひら", + "advancement.create.belt_funnel.desc": "ベルトやデポなどの上に横向きのファンネルを置き、特殊形態にする", + "advancement.create.belt_funnel_kiss": "コウノトリの羽ばたき", "advancement.create.belt_funnel_kiss.desc": "2つのベルトに載せたファンネルにキスをさせる", "advancement.create.fan": "メカニカルエアベンダー", "advancement.create.fan.desc": "ケース入りファンから出る風に乗る", - "advancement.create.fan_lava": "地熱暖房器具", + "advancement.create.fan_lava": "地熱ファンヒーター", "advancement.create.fan_lava.desc": "アイテムを精錬する熱風に巻き込まれる", - "advancement.create.fan_water": "奇妙な洗濯機", + "advancement.create.fan_water": "風変りな洗濯機", "advancement.create.fan_water.desc": "アイテムを洗浄する涼風に巻き込まれる", "advancement.create.fan_smoke": "メカニカルふいご", "advancement.create.fan_smoke.desc": "アイテムを燻製する暖風に巻き込まれる", - "advancement.create.wrench": "便利に設定", + "advancement.create.wrench": "便利な設定", "advancement.create.wrench.desc": "からくり作りに役立つレンチを作る", "advancement.create.goggles": "応力をこの目で", "advancement.create.goggles.desc": "機械からより多くの情報を手に入れるために、エンジニアのゴーグルを作る", "advancement.create.speedometer": "正確な速度は?", - "advancement.create.speedometer.desc": "動作中の速度メーターをゴーグルで見て、正確な値を読み取る", + "advancement.create.speedometer.desc": "動作中の回転速度メーターをゴーグルで見て、正確な値を読み取る", "advancement.create.stressometer": "正確な応力は?", "advancement.create.stressometer.desc": "動作中の応力メーターをゴーグルを通して見て、正確な値を読み取る", "advancement.create.aesthetics": "装飾ブーム!", "advancement.create.aesthetics.desc": "シャフト、パイプ、歯車に木製ブラケットや金属ブラケットを取り付ける", "advancement.create.reinforced": "補強ブーム!", - "advancement.create.reinforced.desc": "シャフト、パイプ、メカニカルベルトなどにケーシングブロックを取り付ける", + "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.lava_wheel.desc": "こんなはずじゃなかった", "advancement.create.cuckoo": "今がその時だ", "advancement.create.cuckoo.desc": "鳩時計が就寝時間を告げるのを目撃する", - "advancement.create.millstone": "ポケット粉砕機", + "advancement.create.millstone": "ポケットクラッシャー", "advancement.create.millstone.desc": "石臼を置いて、回転させる", - "advancement.create.windmill": "凱風快晴", + "advancement.create.windmill": "微風", "advancement.create.windmill.desc": "風車を組み立てる", "advancement.create.maxed_windmill": "雄風", "advancement.create.maxed_windmill.desc": "最強の風車を組み立てる", @@ -584,13 +614,13 @@ "advancement.create.copper_casing.desc": "銅と木材を使って銅ケーシングを作る", "advancement.create.spout": "ぱしゃぱしゃ", "advancement.create.spout.desc": "アイテム注液口が液体を充填している様子を見る", - "advancement.create.spout_potion": "大きな醸造台", + "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": "アイテムころりん", "advancement.create.chained_item_drain.desc": "自動化したアイテム排液口の上を転がるアイテムを見る", "advancement.create.glass_pipe": "フロウ・スパイ", "advancement.create.glass_pipe.desc": "まっすぐな液体パイプにレンチを使って、窓から通る液体を見る", @@ -606,7 +636,7 @@ "advancement.create.infinite_lava.desc": "無限と言えるほどの大量の溶岩を吸引する", "advancement.create.infinite_chocolate": "空想に溺れて", "advancement.create.infinite_chocolate.desc": "無限と言えるほどの大量の溶けたチョコレートを吸引する", - "advancement.create.crafter": "自動作業台", + "advancement.create.crafter": "部品集結!", "advancement.create.crafter.desc": "メカニカルクラフターを設置して、回転力を供給する", "advancement.create.clockwork_bearing": "時計仕掛け", "advancement.create.clockwork_bearing.desc": "時計仕掛けのベアリングの上に構造物を組み立てる", @@ -620,10 +650,10 @@ "advancement.create.flywheel.desc": "かまどエンジンを勢車に繋ぐ", "advancement.create.overstress_flywheel": "ハイレベル応力", "advancement.create.overstress_flywheel.desc": "かまどエンジンに超過応力をかける", - "advancement.create.integrated_circuit": "複素数の計算", - "advancement.create.integrated_circuit.desc": "集積回路を組み立てる", + "advancement.create.precision_mechanism": "手間暇かけた骨董品", + "advancement.create.precision_mechanism.desc": "精密機構を組み立てる", "advancement.create.mechanical_arm": "手が離せない!", - "advancement.create.mechanical_arm.desc": "搬入元と搬出先を設定したメカニカルアームを設置して、稼働させ、あなたのために一生懸命労働している様子を見る", + "advancement.create.mechanical_arm.desc": "搬入元と搬出先を設定したメカニカルアームを設置して稼働させ、あなたのために一生懸命働いている様子を見る", "advancement.create.musical_arm": "お気に入りの曲を流して!", "advancement.create.musical_arm.desc": "メカニカルアームがジュークボックスを使う様子を見る", "advancement.create.arm_many_targets": "整理整頓", @@ -644,16 +674,12 @@ "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": "ビヨヨーン!", "advancement.create.extendo_grip.desc": "マジックハンドを手に入れる", + "advancement.create.potato_cannon": "バキューン!", + "advancement.create.potato_cannon.desc": "ポテトキャノンで敵を倒す", "advancement.create.dual_extendo_grip": "究極のビヨンビヨン時代", "advancement.create.dual_extendo_grip.desc": "二刀流のマジックハンドで超人的なリーチを手に入れる", "advancement.create.eob": "ベータ版はここまで", @@ -665,16 +691,32 @@ "itemGroup.create.base": "Create", "itemGroup.create.palettes": "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 は改ざんされた鳩時計に爆破された", + "death.attack.create.crush": "%1$sは破砕ホイールによって処理された", + "death.attack.create.crush.player": "%1$sは%2$sに破砕ホイールに投入された", + "death.attack.create.fan_fire": "%1$sはケース入りファンによって燻製にされた", + "death.attack.create.fan_fire.player": "%1$sは%2$sによって燻製にされた", + "death.attack.create.fan_lava": "%1$sはケース入りファンで精錬された", + "death.attack.create.fan_lava.player": "%1$sは%2$sによって熱風に投げ込まれた", + "death.attack.create.mechanical_drill": "%1$sはメカニカルドリルに突き抜かれた", + "death.attack.create.mechanical_drill.player": "%1$sは%2$sにドリルの目の前に投げ込まれた", + "death.attack.create.mechanical_saw": "%1$sはメカニカルソーで半分にカットされた", + "death.attack.create.mechanical_saw.player": "%1$sは%2$sによってメカニカルソーの回転する刃に投げ込まれた", + "death.attack.create.potato_cannon": "%1$sは%2$sのポテトキャノンに撃ち抜かれた", + "death.attack.create.potato_cannon.item": "%1$sは%3$sで%2$sに撃た抜かれた", + "death.attack.create.cuckoo_clock_explosion": "%1$sは改造された鳩時計に爆破された", + "death.attack.create.cuckoo_clock_explosion.player": "%1$sは何者かによって改造された鳩時計に爆破された", "create.block.deployer.damage_source_name": "悪いデプロイヤー", "create.block.cart_assembler.invalid": "トロッコアセンブラはレールの上にのみ設置できます", + "create.menu.return": "メニューに戻る", + "create.menu.configure": "設定...", + "create.menu.ponder_index": "思案索引", + "create.menu.only_ingame": "一時停止メニューで利用可能", + "create.menu.project_page": "プロジェクトページ", + "create.menu.report_bugs": "バグ報告", + "create.menu.support": "私たちを応援する", + "create.recipe.crushing": "粉砕", "create.recipe.milling": "製粉", "create.recipe.fan_washing": "一括洗浄", @@ -685,6 +727,7 @@ "create.recipe.fan_blasting.fan": "溶岩の奥のケース入りファン", "create.recipe.pressing": "プレス", "create.recipe.mixing": "混合", + "create.recipe.deploying": "使用", "create.recipe.automatic_shapeless": "自動不定形クラフト", "create.recipe.automatic_brewing": "自動醸造", "create.recipe.packing": "圧縮", @@ -694,11 +737,20 @@ "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.sequenced_assembly": "組立ライン", + "create.recipe.assembly.next": "次の工程: %1$s", + "create.recipe.assembly.step": "手順: %1$s:", + "create.recipe.assembly.progress": "進捗: %1$s/%2$s", + "create.recipe.assembly.pressing": "プレスする", + "create.recipe.assembly.spout_filling_fluid": "%1$sを注液", + "create.recipe.assembly.deploying_item": "%1$sを組み込む", + "create.recipe.assembly.cutting": "ソーでの切断", + "create.recipe.assembly.repeat": "%1$s回繰り返す", + "create.recipe.assembly.junk": "ランダムな仕損品", "create.recipe.processing.chance": "%1$s%%チャンス", "create.recipe.heat_requirement.none": "加熱不要", "create.recipe.heat_requirement.heated": "加熱が必要", @@ -751,20 +803,16 @@ "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.title": "携帯型ブロックザッパー", + "create.gui.terrainzapper.searchDiagonal": "対角線にフォロー", + "create.gui.terrainzapper.searchFuzzy": "素材の境界を無視", + "create.gui.terrainzapper.patternSection": "模様", + "create.gui.terrainzapper.pattern.solid": "敷き詰め", + "create.gui.terrainzapper.pattern.checkered": "市松模様", + "create.gui.terrainzapper.pattern.inversecheckered": "逆市松模様", + "create.gui.terrainzapper.pattern.chance25": "25%", + "create.gui.terrainzapper.pattern.chance50": "50%", + "create.gui.terrainzapper.pattern.chance75": "75%", "create.gui.terrainzapper.placement": "配置", "create.gui.terrainzapper.placement.merged": "合併", "create.gui.terrainzapper.placement.attached": "添える", @@ -773,6 +821,8 @@ "create.gui.terrainzapper.brush.cuboid": "直方体", "create.gui.terrainzapper.brush.sphere": "球体", "create.gui.terrainzapper.brush.cylinder": "円筒", + "create.gui.terrainzapper.brush.surface": "表面", + "create.gui.terrainzapper.brush.cluster": "鉱石", "create.gui.terrainzapper.tool": "ツール", "create.gui.terrainzapper.tool.fill": "埋立", "create.gui.terrainzapper.tool.place": "設置", @@ -782,19 +832,8 @@ "create.gui.terrainzapper.tool.flatten": "なだらかに", "create.terrainzapper.shiftRightClickToSet": "シフト-右クリックで形状を選択", - - "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.terrainzapper.usingBlock": "使用中: %1$s", + "create.terrainzapper.leftClickToSet": "ブロックをスニークせず左クリックでブロックを選択", "create.minecart_coupling.two_couplings_max": "トロッコを2つ以上連結させることはできません", "create.minecart_coupling.unloaded": "列車の一部のあるチャンクがロードされていません", @@ -1025,6 +1064,11 @@ "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.shulker_level": "%1$sシュルカーか", + "create.item_attributes.shulker_level.inverted": "%1$sシュルカーでないか", + "create.item_attributes.shulker_level.full": "満杯の", + "create.item_attributes.shulker_level.empty": "空の", + "create.item_attributes.shulker_level.partial": "一部埋まっている", "create.item_attributes.has_enchant": "エンチャントされているか%1$s", "create.item_attributes.has_enchant.inverted": "エンチャントがされていないか", "create.item_attributes.color": "%1$sで染められているか", @@ -1120,6 +1164,27 @@ "create.tooltip.chute.fans_pull_up": "ファンが上から吸い込んでいます", "create.tooltip.chute.fans_pull_down": "ファンが下から吸い込んでいます", "create.tooltip.chute.contains": "内容物: %1$s x%2$s", + "create.tooltip.brass_tunnel.contains": "配布中", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "右クリックで取り出し", + + "create.linked_controller.bind_mode": "割り当てモード", + "create.linked_controller.press_keybind": "%1$s、%2$s、%3$s、%4$s、%5$sまたは%6$sを押すとこの周波数がそのキーに割り当てられます", + "create.linked_controller.key_bound": "周波数を割り当てました %1$s", + "create.linked_controller.frequency_slot_1": "キーバインド: %1$s、周波数 #1", + "create.linked_controller.frequency_slot_2": "キーバインド: %1$s、周波数 #2", + + "create.crafting_blueprint.crafting_slot": "材料スロット", + "create.crafting_blueprint.filter_items_viable": "フィルターが使えます", + "create.crafting_blueprint.display_slot": "表示スロット", + "create.crafting_blueprint.inferred": "レシピから推測", + "create.crafting_blueprint.manually_assigned": "手動割り当て", + "create.crafting_blueprint.secondary_display_slot": "第2表示スロット", + "create.crafting_blueprint.optional": "オプション", + + "create.potato_cannon.ammo.attack_damage": "攻撃力: %1$s", + "create.potato_cannon.ammo.reload_ticks": "リロード時間(tick): %1$s", + "create.potato_cannon.ammo.knockback": "ノックバック: %1$s", "create.hint.hose_pulley.title": "底なし搬出", "create.hint.hose_pulley": "対象となる液体は無限とみなされています。", @@ -1148,32 +1213,46 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "このからくりトロッコは大きすぎて拾えません。", + "create.contraption.minecart_contraption_illegal_pickup": "神秘的な力がからくりカートを世界に縛り付けています。", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "歯車がゴロゴロと鳴る", - "create.subtitle.slime_added": "スライムがぐしゃっとつぶれる", "create.subtitle.contraption_disassemble": "からくりが止まる", - "create.subtitle.wrench_rotate": "レンチを使う", + "create.subtitle.peculiar_bell_use": "風変わりな鐘が鳴る", "create.subtitle.mixing": "混ぜる音", "create.subtitle.mechanical_press_activation_belt": "メカニカルプレスがボンと鳴る", - "create.subtitle.blockzapper_confirm": "成功音", + "create.subtitle.fwoomp": "ポテトランチャーがバキューンと鳴る", + "create.subtitle.worldshaper_place": "ワールドシェーパーが設置する", + "create.subtitle.crushing_1": "粉砕音", "create.subtitle.depot_slide": "アイテムが滑る", - "create.subtitle.blockzapper_place": "ブロックを発射して設置する", + "create.subtitle.saw_activate_stone": "メカニカルソーが動作する", "create.subtitle.blaze_munch": "ブレイズの咀嚼音", - "create.subtitle.schematicannon_launch_block": "概略図砲が発射する", "create.subtitle.funnel_flap": "ファンネルがはためく", "create.subtitle.schematicannon_finish": "概略図砲が作業を終える", + "create.subtitle.haunted_bell_use": "憑りつかれた鐘が鳴る", "create.subtitle.scroll_value": "スクロールのカチカチ音", + "create.subtitle.crafter_craft": "メカニカルクラフターがクラフトする", + "create.subtitle.controller_put": "コントローラのトントン音", + "create.subtitle.cranking": "ハンドクランクが回る", + "create.subtitle.wrench_remove": "機械を壊す", + "create.subtitle.cogs": "歯車がゴロゴロと鳴る", + "create.subtitle.slime_added": "スライムがぐしゃっとつぶれる", + "create.subtitle.wrench_rotate": "レンチが使用される", + "create.subtitle.potato_hit": "野菜が衝突する", + "create.subtitle.saw_activate_wood": "メカニカルソーが動作する", + "create.subtitle.haunted_bell_convert": "憑りつかれた鐘が目覚める", + "create.subtitle.deployer_polish": "デプロイヤーが磨く", + "create.subtitle.deny": "失敗音", + "create.subtitle.controller_click": "コントローラーのカチカチ音", + "create.subtitle.schematicannon_launch_block": "概略図砲が発射する", + "create.subtitle.copper_armor_equip": "潜水服がチャリンと鳴る", + "create.subtitle.controller_take": "書見台が空になる", "create.subtitle.mechanical_press_activation": "メカニカルプレスがガーンと鳴る", "create.subtitle.contraption_assemble": "からくりが動く", - "create.subtitle.crafter_craft": "メカニカルクラフターがクラフトする", - "create.subtitle.blockzapper_deny": "失敗音", - "create.subtitle.cranking": "ハンドクランクが回る", "create.subtitle.crafter_click": "メカニカルクラフターのカチカチ音", - "create.subtitle.wrench_remove": "機械を壊す", "create.subtitle.depot_plop": "デプロイヤーにアイテムが入れられる", + "create.subtitle.confirm": "成功音", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1193,14 +1272,6 @@ "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": "右クリックしたとき", @@ -1209,65 +1280,6 @@ "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": "ホットバーにあるとき", @@ -1277,16 +1289,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": "_設定インターフェース_を開きます。", - - "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": "_設定インターフェース_を開きます。", + "item.create.wand_of_symmetry.tooltip.action3": "_設定画面_を開きます。", "item.create.handheld_worldshaper.tooltip": "携帯型ワールドシェーパー", "item.create.handheld_worldshaper.tooltip.summary": "特色ある_風景_や_地形_を作成する便利なツール。", @@ -1295,44 +1298,50 @@ "item.create.handheld_worldshaper.tooltip.control2": "ブロックを右クリックしたとき", "item.create.handheld_worldshaper.tooltip.action2": "現在選択されている_ブラシ_と_ツール_を目標の場所に適用します。", "item.create.handheld_worldshaper.tooltip.control3": "スニークしながら右クリックしたとき", - "item.create.handheld_worldshaper.tooltip.action3": "_設定インターフェース_を開きます。", + "item.create.handheld_worldshaper.tooltip.action3": "_設定画面_を開きます。", "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": "ビヨヨーン!着用者の_射程_を大幅に_伸ばし_ます。", "item.create.extendo_grip.tooltip.condition1": "オフハンドに装備したとき", "item.create.extendo_grip.tooltip.behaviour1": "_メインハンド_で使うアイテムの_射程_を_伸ばし_ます。", + "item.create.extendo_grip.tooltip.condition2": "銅のバックタンクを装備したとき", + "item.create.extendo_grip.tooltip.behaviour2": "_耐久値_を消費しなくなります。代わりに_圧縮空気_をタンクから消費します。", + + "item.create.potato_cannon.tooltip": "ポテトキャノン", + "item.create.potato_cannon.tooltip.summary": "バキューン!自分が育てた野菜を敵に発射します。_銅のバックタンク_の圧縮空気でも動かせます。", + "item.create.potato_cannon.tooltip.condition1": "左クリックしたとき", + "item.create.potato_cannon.tooltip.behaviour1": "_インベントリ_の中から_適切_なアイテムを発射します。", + "item.create.potato_cannon.tooltip.condition2": "銅のバックタンクを装備した時", + "item.create.potato_cannon.tooltip.behaviour2": "_耐久性_を消費しなくなります。代わりに_圧縮空気_をタンクから消費します", "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.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.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.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ファイルに保存できます。", @@ -1348,9 +1357,9 @@ "item.create.schematic_and_quill.tooltip.action3": "選択を_リセット_して削除します。", "block.create.schematicannon.tooltip": "概略図砲", - "block.create.schematicannon.tooltip.summary": "ブロックを撃って、展開された_概略図_をもとにワールドに設置します。隣接する収納ブロックからのアイテムを自動搬入し、_火薬_を燃料とします。", + "block.create.schematicannon.tooltip.summary": "ブロックを撃って、_概略図_をもとにワールドに設置します。隣接する収納ブロックからのアイテムを自動搬入し、_火薬_を燃料とします。", "block.create.schematicannon.tooltip.condition1": "右クリックしたとき", - "block.create.schematicannon.tooltip.behaviour1": "_インターフェース_を開きます。", + "block.create.schematicannon.tooltip.behaviour1": "_UI_を開きます。", "block.create.schematic_table.tooltip": "概略図テーブル", "block.create.schematic_table.tooltip.summary": "保存された構造物を_空の概略図_に書き込みます。", @@ -1362,7 +1371,7 @@ "item.create.goggles.tooltip.condition1": "着用したとき", "item.create.goggles.tooltip.behaviour1": "設置された機械の_回転速度_および、_機械_の_応力への影響_と_許容量_を_色付きのインジケーター_で表示します。", "item.create.goggles.tooltip.condition2": "計器を見たとき", - "item.create.goggles.tooltip.behaviour2": "計器が接続されているネットワークの_回転速度_または_応力_に関する詳細情報を表示します。", + "item.create.goggles.tooltip.behaviour2": "計器が接続されている動力ネットワークの_回転速度_または_応力_に関する詳細情報を表示します。", "item.create.goggles.tooltip.condition3": "液体コンテナを見たとき", "item.create.goggles.tooltip.behaviour3": "ブロックの_容量_と、その中に貯蔵されている_液体_の詳細情報を表示します。", @@ -1384,28 +1393,21 @@ "block.create.turntable.tooltip": "ターンテーブル", "block.create.turntable.tooltip.summary": "_回転力_を洗練された乗り物酔いに変えます。", - "block.create.portable_fluid_interface.tooltip": "ポータブル液体インターフェース", - "block.create.portable_fluid_interface.tooltip.summary": "ピストン、ベアリング、トロッコ、またはプーリーで移動する_構造物_との間で_液体_を_移動_させる可搬式の交換ポイント。2つのインターフェースは、互いに_向かい合って_、_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.summary": "接続されたコンテナの_空き容量_によってレッドストーン信号を切り替えます。便利なフィルターが付属しています。_コンパレータ―_とは違って、_在庫スイッチ_は、信号が反転される_しきい値_を設定できます。", "block.create.stockpile_switch.tooltip.condition1": "右クリックしたとき", - "block.create.stockpile_switch.tooltip.behaviour1": "_設定インターフェース_を開きます。", + "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.condition": "右クリックしたとき", - "block.create.adjustable_crate.tooltip.behaviour1": "_インターフェース_を開きます。", + "block.create.adjustable_crate.tooltip.condition1": "右クリックしたとき", + "block.create.adjustable_crate.tooltip.behaviour1": "_UI_を開きます。", "block.create.creative_crate.tooltip": "クリエイティブクレート", - "block.create.creative_crate.tooltip.summary": "この_収納ブロック_は、あらゆるアイテムを無限に複製します。隣接する_概略図砲_へブロックを無限に供給します。", + "block.create.creative_crate.tooltip.summary": "あらゆるアイテムを無限に複製する_収納ブロック_。隣接する_概略図砲_へブロックを無限に供給します。", "block.create.creative_crate.tooltip.condition1": "フィルタースロットにアイテムが入っているとき", "block.create.creative_crate.tooltip.behaviour1": "このクレートから何かを_搬出_すると、指定されたアイテムが_無限_に_搬出_されます。このクレートに_搬入_されたアイテムは_消滅_します。", @@ -1424,27 +1426,61 @@ "item.create.refined_radiance.tooltip": "高貴な光輝", "item.create.refined_radiance.tooltip.summary": "_吸収した光輝_から鍛造した色彩素材。", + "item.create.refined_radiance.tooltip.condition1": "作業中", + "item.create.refined_radiance.tooltip.behaviour1": "この素材の使用方法は将来のリリースで実装予定です。", "item.create.shadow_steel.tooltip": "シャドウスチール", "item.create.shadow_steel.tooltip.summary": "_奈落の虚無_から鍛造した色彩素材。", + "item.create.shadow_steel.tooltip.condition1": "作業中", + "item.create.shadow_steel.tooltip.behaviour1": "この素材の使用方法は将来のリリースで実装予定です。", + + "item.create.linked_controller.tooltip": "リンクコントローラー", + "item.create.linked_controller.tooltip.summary": "_6つのボタン_に割り当てられた_レッドストーンリンク_周波数を_片手_で_制御_できます。", + "item.create.linked_controller.tooltip.condition1": "左クリック", + "item.create.linked_controller.tooltip.behaviour1": "コントローラーを_オンオフ_します。_制御_がオンのときは_移動_できません。", + "item.create.linked_controller.tooltip.condition2": "スニークしながら左クリック", + "item.create.linked_controller.tooltip.behaviour2": "手動_設定画面_を開きます", + "item.create.linked_controller.tooltip.condition3": "レッドストーンリンク受信機を左クリックしたとき", + "item.create.linked_controller.tooltip.behaviour3": "_割り当てモード_をオンにします。_6つのコントロール_のうち1つを押してリンクの周波数に_割り当て_ます。", + "item.create.linked_controller.tooltip.condition4": "書見台を左クリックしたとき", + "item.create.linked_controller.tooltip.behaviour4": "コントローラーを書見台に設置し、簡単に使えるようにします。(スニーク中に左クリックで取り出せます)", + + "item.create.diving_helmet.tooltip": "潜水ヘルメット", + "item.create.diving_helmet.tooltip.summary": "_銅のバックタンク_と一緒に使うと、長時間_水中_で_呼吸_できるようになるヘルメット。", + "item.create.diving_helmet.tooltip.condition1": "装備したとき", + "item.create.diving_helmet.tooltip.behaviour1": "バックタンクからゆっくりと_圧縮空気_を排出しながら、_水中呼吸_の効果を供給します。", + + "item.create.copper_backtank.tooltip": "銅のバックタンク", + "item.create.copper_backtank.tooltip.summary": "圧縮空気を運ぶため_携帯タンク_", + "item.create.copper_backtank.tooltip.condition1": "装備したとき", + "item.create.copper_backtank.tooltip.behaviour1": "必要な装備に_圧縮空気_を供給します。", + "item.create.copper_backtank.tooltip.condition2": "設置して動力を供給したとき", + "item.create.copper_backtank.tooltip.behaviour2": "_圧縮空気_を_集めます_。速度は回転速度によって決まります。", + + "item.create.diving_boots.tooltip": "潜水ブーツ", + "item.create.diving_boots.tooltip.summary": "海底を歩けるようになる_重いブーツ_。", + "item.create.diving_boots.tooltip.condition1": "装備したとき", + "item.create.diving_boots.tooltip.behaviour1": "_沈むのが早くなり_、_泳げなく_なります。その代わり、水中で_歩行_と_ジャンプ_が可能になります。また、メカニカルベルトの影響を受けなくなります。", + + "item.create.crafting_blueprint.tooltip": "クラフトブループリント", + "item.create.crafting_blueprint.tooltip.summary": "壁に_貼り_、_材料_の_配置_を_指定_することで手作業でのクラフトを簡単にできます。各スロットが1つのレシピを表しています。", + "item.create.crafting_blueprint.tooltip.condition1": "空きスロットを左クリックしたとき", + "item.create.crafting_blueprint.tooltip.behaviour1": "_レシピ_や表示するアイテムを_設定_できる_クラフトメニュー_を開きます。", + "item.create.crafting_blueprint.tooltip.condition2": "設定済みスロットを左クリックしたとき", + "item.create.crafting_blueprint.tooltip.behaviour2": "_インベントリ_にある一致する材料で_設定されたレシピ_を_クラフト_します。_スニーク_すれば最大_スタック_分を一気にクラフトできます", "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": "それを使ったことをすぐ後悔するだろう。", + "block.create.peculiar_bell.tooltip": "風変わりな鐘", + "block.create.peculiar_bell.tooltip.summary": "装飾用の_真鍮の鐘。_魂の炎_の真上に置くと、別の使い方が見つかるかもしれません...", + "block.create.haunted_bell.tooltip": "憑りつかれた鐘", + "block.create.haunted_bell.tooltip.summary": "ネザーに彷徨う魂が宿る、呪われた鐘", + "block.create.haunted_bell.tooltip.condition1": "持ったとき、鳴らしたとき", + "block.create.haunted_bell.tooltip.behaviour1": "_敵モブ_がスポーンする近くの_光のない場所_を示します", "_": "->------------------------] Ponder Content [------------------------<-", @@ -1461,6 +1497,11 @@ "create.ponder.replay": "最初から", "create.ponder.think_back": "戻る", "create.ponder.slow_text": "熟考(スロー再生)", + "create.ponder.exit": "終了", + "create.ponder.welcome": "思案画面へようこそ", + "create.ponder.categories": "Createで利用可能なカゴテリ", + "create.ponder.index_description": "アイテムをクリックすると、関連するアイテムやブロックの情報が表示されます。", + "create.ponder.index_title": "思案索引", "create.ponder.shared.movement_anchors": "シャーシや超粘着剤を使えば大きな構造物も動かせます", "create.ponder.shared.rpm32": "32 RPM", "create.ponder.shared.sneak_and": "スニーク +", @@ -1521,10 +1562,10 @@ "create.ponder.andesite_tunnel.text_4": "残ったものは、そのルートを進み続けます", "create.ponder.basin.header": "鉢によるアイテム加工", - "create.ponder.basin.text_1": "鉢には材料となるアイテムや液体を入れられます", + "create.ponder.basin.text_1": "鉢には素材となるアイテムや液体を入れられます", "create.ponder.basin.text_2": "鉢は完成品アイテムを斜め下へ搬出しようとします", - "create.ponder.basin.text_3": "搬出できる機械が存在する場合、鉢には搬出用の蛇口が表示されます", - "create.ponder.basin.text_4": "ここではいくつかの選択肢があります", + "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": "これは、完成品アイテムを材料として再利用する必要がある場合に役立ちます", @@ -1533,7 +1574,7 @@ "create.ponder.bearing_modes.header": ":メカニカルベアリングの動作モード", "create.ponder.bearing_modes.text_1": "止まったとき、ベアリングは格子に沿った近い角度に構造物を配置します", - "create.ponder.bearing_modes.text_2": "通常のブロックに戻らないように設定したり、開始時の角度のみブロックに戻るように設定することもできます", + "create.ponder.bearing_modes.text_2": "通常のブロックに戻らないように設定したり、開始時の角度のみブロックに戻るように設定したりできます", "create.ponder.belt_casing.header": "ケース入りベルト", "create.ponder.belt_casing.text_1": "真鍮か安山岩のケーシングを使ってメカニカルベルトを飾れます", @@ -1542,16 +1583,16 @@ "create.ponder.belt_connector.header": "メカニカルベルトの使い方", "create.ponder.belt_connector.text_1": "メカニカルベルトを持って2つのシャフトを右クリックすると、シャフトにベルトコンベアを繋げて設置されます", "create.ponder.belt_connector.text_2": "誤ったシャフトをクリックしてしまった場合、スニークしながら右クリックでキャンセルできます", - "create.ponder.belt_connector.text_3": "ベルトの何処にでもシャフトを追加できます", + "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_2": "1.水平", "create.ponder.belt_directions.text_3": "2.斜め", - "create.ponder.belt_directions.text_4": "3.垂直方向", + "create.ponder.belt_directions.text_4": "3.垂直", "create.ponder.belt_directions.text_5": "4.垂直方向のシャフトを水平に", "create.ponder.belt_directions.text_6": "これらはすべて接続可能な方向です。ベルトの長さは2~20ブロックの間で自由に接続できます", @@ -1562,7 +1603,7 @@ "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_3": "ブレイズケーキを与えると、バーナーはさらに火力を出せます", "create.ponder.blaze_burner.text_4": "供給作業は、デプロイヤーやメカニカルアームで自動化できます", "create.ponder.brass_funnel.header": "真鍮ファンネル", @@ -1581,7 +1622,7 @@ "create.ponder.brass_tunnel.text_7": "搬入したアイテムは、接続されているすべての搬出口に分配されます", "create.ponder.brass_tunnel.text_8": "アイテムをトンネルへ直接搬入することもできます", - "create.ponder.brass_tunnel_modes.header": "真鍮トンネルのモード", + "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": "アイテムはグループ内の全てのトンネルがアイテムを搬入できる場合のみ通過を許可します", @@ -1596,34 +1637,35 @@ "create.ponder.brass_tunnel_modes.text_9": "「ランダム」は、スタック全体をランダムに選択された搬出口に分配します ", "create.ponder.cart_assembler.header": "トロッコアセンブラによる構造物の移動", - "create.ponder.cart_assembler.text_1": "レッドストーン信号を受けたアセンブラは、通過するトロッコに接続された構造物を取り付けます", + "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": "2つのトロッコアセンブラが構造物を共有している場合...", - "create.ponder.cart_assembler_dual.text_2": "...どちらかにレッドストーン信号を受けると、列車が組み立てられます", + "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_modes.text_2": "この矢印は、構造物のどちら側が前面かを示します", + "create.ponder.cart_assembler_modes.text_3": "アセンブラが「常に向きを固定する」に設定されている場合、からくりの向きは変わりません", "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_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_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": "信号を受けている時は、列内の他のチェーンドライブに伝達される速度が2倍になります", - "create.ponder.chain_gearshift.text_3": "信号を受けているチェーンギアシフトが動力源に無い場合、速度が半分になります", + "create.ponder.chain_gearshift.text_3": "信号を受けているチェーンギアシフトが動力源でない場合、速度が半分になります", "create.ponder.chain_gearshift.text_4": "いずれの場合も、列内のチェーンドライブは常に「信号入りチェーンギアシフト」の2倍の速度で動作します", "create.ponder.chain_gearshift.text_5": "レッドストーン信号の強度で、比率を1と2の間でより正確に調整できます", "create.ponder.chain_gearshift.text_6": "12 RPM", @@ -1635,7 +1677,7 @@ "create.ponder.chute_upward.header": "シュートでの上方向へ運搬", "create.ponder.chute_upward.text_1": "シュートの上部または下部にファンを配置すると、アイテムを上方向へ運搬できます", - "create.ponder.chute_upward.text_2": "エンジニアのゴーグルを付けてシュートを見ると、移動方向の情報が表示されます", + "create.ponder.chute_upward.text_2": "エンジニアのゴーグルを付けてシュートを見ると、移動方向が表示されます", "create.ponder.chute_upward.text_3": "ブロックで詰まっている端では、アイテムを側面から搬出入する必要があります", "create.ponder.clockwork_bearing.header": "時計仕掛けのベアリングを使った構造物のアニメーション", @@ -1649,21 +1691,27 @@ "create.ponder.clockwork_bearing.text_8": "2つ目の構造物は分針として回転します", "create.ponder.clutch.header": "クラッチによる回転力の制御", - "create.ponder.clutch.text_1": "クラッチは直線に回転を伝達します", - "create.ponder.clutch.text_2": "レッドストーン信号を受けると、回転の伝達を停止します", + "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": "大きな歯車から歯車に接続すると、伝達される回転速度が2倍になります", - "create.ponder.cog_speedup.text_3": "逆に接続すると、伝達される回転速度が半分になります", + "create.ponder.cog_speedup.text_2": "大きな歯車から歯車に接続すると、伝達先の回転速度が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": "クリエイティブ液体タンク", + "create.ponder.creative_fluid_tank.text_1": "クリエイティブ液体タンクは、液体を無限に供給できます", + "create.ponder.creative_fluid_tank.text_2": "液体容器アイテムで右クリックで液体を指定できます", + "create.ponder.creative_fluid_tank.text_3": "液体ネットワークはタンクから指定された液体を無限に引き出すことができます", + "create.ponder.creative_fluid_tank.text_4": "クリエイティブ液体タンクに押し入れた液体は消滅します", + "create.ponder.creative_motor.header": "クリエイティブモーターによる回転力の生成", - "create.ponder.creative_motor.text_1": "クリエイティブモーターは、コンパクトで調整できる原動機です", - "create.ponder.creative_motor.text_2": "背面パネルを見てスクロールすると、モーターの回転速度を変更できます", + "create.ponder.creative_motor.text_1": "クリエイティブモーターは、コンパクトで調整可能な原動機です", + "create.ponder.creative_motor.text_2": "背面パネルを見ながらスクロールすると、モーターの回転速度を変更できます", "create.ponder.crushing_wheels.header": "破砕ホイールによるアイテム加工", "create.ponder.crushing_wheels.text_1": "一対の破砕ホイールは、非常に効果的にアイテムを粉砕できます", @@ -1679,7 +1727,7 @@ "create.ponder.deployer.text_13": "フィルターを設定すると、一致するアイテムを持っている時だけ稼働します", "create.ponder.deployer.text_14": "また、フィルターに一致するアイテムのみが搬入されるようになり...", "create.ponder.deployer.text_15": "...一致しないアイテムのみが搬出されます", - "create.ponder.deployer.text_2": "動作は、常に前方2ブロックの位置へ行われます", + "create.ponder.deployer.text_2": "動作は、常に手前2ブロックの位置へ行われます", "create.ponder.deployer.text_3": "真正面のブロックが邪魔になることはありません", "create.ponder.deployer.text_4": "デプロイヤーは以下の動作に使えます", "create.ponder.deployer.text_5": "ブロックの設置", @@ -1693,31 +1741,43 @@ "create.ponder.deployer_contraption.text_2": "...稼働した場所ごとに稼働し、からくり内の収納ブロックのアイテムを使用します", "create.ponder.deployer_contraption.text_3": "フィルタースロットを使って、どのアイテムを使用するか指定できます", - "create.ponder.deployer_modes.header": "デプロイヤーのモード", + "create.ponder.deployer_modes.header": "デプロイヤーの動作モード", "create.ponder.deployer_modes.text_1": "デフォルトでは、デプロイヤーは右クリックの動作を模倣します", "create.ponder.deployer_modes.text_2": "レンチを使えば、左クリックの動作を模倣するように設定できます", + "create.ponder.deployer_processing.header": "デプロイヤーによるアイテムの処理", + "create.ponder.deployer_processing.text_1": "装着されたアイテムで、デプロイヤーの先にあるアイテムを処理することができます", + "create.ponder.deployer_processing.text_2": "加工したいアイテムはドロップしたり、デプロイヤーの下のデポに置いてください", + "create.ponder.deployer_processing.text_3": "ベルトでアイテムを供給すると", + "create.ponder.deployer_processing.text_4": "デプロイヤーが自動でアイテムを止め、加工します。", + "create.ponder.deployer_redstone.header": "レッドストーン信号によるデプロイヤーの制御", "create.ponder.deployer_redstone.text_1": "レッドストーン信号を受けている間、デプロイヤーは稼働しません", "create.ponder.deployer_redstone.text_2": "デプロイヤーは停止する前に、開始したサイクルは終了させます", - "create.ponder.deployer_redstone.text_3": "その為、オフのパルス信号を使って丁度1サイクルだけ稼働させられます", + "create.ponder.deployer_redstone.text_3": "その為、反転したパルス信号を使って丁度1サイクルだけ稼働させられます", "create.ponder.depot.header": "デポの使い方", "create.ponder.depot.text_1": "デポは動かないメカニカルベルトのようなブロックです", - "create.ponder.depot.text_2": "右クリックして、手動でのアイテム搬出入できます", + "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_1": "空のバーナーでブレイズを右クリックすると捕獲できます", "create.ponder.empty_blaze_burner.text_2": "また、ブレイズはスポーンブロックから直接捕獲することもできます", - "create.ponder.empty_blaze_burner.text_3": "これで、様々な機械で利用する理想的な熱源が得られます", + "create.ponder.empty_blaze_burner.text_3": "これで、様々な機械で利用できる理想的な熱源が得られます", "create.ponder.empty_blaze_burner.text_4": "空のブレイズバーナーは火打石と打ち金を使って火を付ければ装飾にも使えます", - "create.ponder.empty_blaze_burner.text_5": "しかし、これは加工用の熱源には適していません", + "create.ponder.empty_blaze_burner.text_5": "さらに、魂の宿ったアイテムを使うことで炎を変化させられます", + "create.ponder.empty_blaze_burner.text_6": "しかし、これは加工用の熱源には適していません", + + "create.ponder.encased_fluid_pipe.header": "ケース入り液体パイプ", + "create.ponder.encased_fluid_pipe.text_1": "銅ケーシングで液体パイプを飾ることができます", + "create.ponder.encased_fluid_pipe.text_2": "ただの飾りではなく、ケース入りパイプは接続がロックされます", + "create.ponder.encased_fluid_pipe.text_3": "隣接するブロックの設置や破壊などの更新に反応しなくなります", "create.ponder.fan_direction.header": "ケース入りファンの気流", "create.ponder.fan_direction.text_1": "ケース入りファンは、回転力を利用して気流を生み出します", - "create.ponder.fan_direction.text_2": "気流の強さと方向は、供給される回転力に依存します", + "create.ponder.fan_direction.text_2": "気流の強さと方向は、供給される回転力によって決まります", "create.ponder.fan_processing.header": "ケース付きファンによるアイテム加工", "create.ponder.fan_processing.text_1": "溶岩を通過した気流は、加熱されます", @@ -1733,6 +1793,35 @@ "create.ponder.fan_source.text_1": "ファンを熱源に向けて設置すると、回転力を生成できます", "create.ponder.fan_source.text_2": "レッドストーン信号を受けると、回転力が生成されます", + "create.ponder.fluid_pipe_flow.header": "銅パイプを使った液体の移動", + "create.ponder.fluid_pipe_flow.text_1": "液体パイプは2つ以上の液体源と輸送先を繋ぐことができます", + "create.ponder.fluid_pipe_flow.text_2": "レンチを使うと、まっすぐなパイプに窓を付けられます", + "create.ponder.fluid_pipe_flow.text_3": "窓付きパイプは側面と隣接するパイプとつながりません", + "create.ponder.fluid_pipe_flow.text_4": "メカニカルポンプを使えば液体を輸送できます", + "create.ponder.fluid_pipe_flow.text_5": "はじめは液体が輸送されません", + "create.ponder.fluid_pipe_flow.text_6": "液れが終点まで届くと徐々に輸送されていきます", + "create.ponder.fluid_pipe_flow.text_7": "つまり、パイプブロック自体には液体は物理的に入っていないということです", + + "create.ponder.fluid_pipe_interaction.header": "液体容器の排出と充填", + "create.ponder.fluid_pipe_interaction.text_1": "液体ネットワークは終点でさまざまなブロックとやりとりできます", + "create.ponder.fluid_pipe_interaction.text_2": "液体を溜めることができれば、どのようなブロックでも液体の搬入・搬出ができます", + "create.ponder.fluid_pipe_interaction.text_3": "開いているパイプの端の目の前の液体ブロックは吸い込めます", + "create.ponder.fluid_pipe_interaction.text_4": "また、開いたスペースに液体ブロックを設置できます", + "create.ponder.fluid_pipe_interaction.text_5": "パイプは、いくつかのブロックから直接液体を吸い込めます", + + "create.ponder.fluid_tank_sizes.header": "液体タンクのサイズ", + "create.ponder.fluid_tank_sizes.text_1": "液体タンクは複数組み合わせて容量を増やせます。", + "create.ponder.fluid_tank_sizes.text_2": "横幅は最大3ブロック", + "create.ponder.fluid_tank_sizes.text_3": "高さは30ブロック以上重ねられます", + "create.ponder.fluid_tank_sizes.text_4": "レンチを使って、タンクの窓を付け外しできます", + + "create.ponder.fluid_tank_storage.header": "液体タンクへの液体の貯蔵", + "create.ponder.fluid_tank_storage.text_1": "液体タンクは大量の液体を貯蔵することができます", + "create.ponder.fluid_tank_storage.text_2": "どの方向からでも液体を搬出入できます", + "create.ponder.fluid_tank_storage.text_3": "コンパレーターで液体量を測れます", + "create.ponder.fluid_tank_storage.text_4": "しかし、サバイバルモードでは手動で液体を出し入れできません。", + "create.ponder.fluid_tank_storage.text_5": "鉢、アイテム排液口、アイテム注液口などを使えばアイテムから液体を出し入れできます。", + "create.ponder.flywheel.header": "勢車による回転力の生成", "create.ponder.flywheel.text_1": "かまどエンジンで回転力を生成するには、勢車が必要です", "create.ponder.flywheel.text_2": "これによって生成される回転力は、非常に大きな応力許容量を持っています", @@ -1745,9 +1834,9 @@ "create.ponder.funnel_compat.text_4": "アイテム排液口など", "create.ponder.funnel_direction.header": "運搬の方向", - "create.ponder.funnel_direction.text_1": "通常の配置では、収納ブロックからアイテムを搬出ます", + "create.ponder.funnel_direction.text_1": "通常の配置では、収納ブロックからアイテムを搬出します", "create.ponder.funnel_direction.text_2": "スニークしながら設置すると、収納ブロックにアイテムを搬入します", - "create.ponder.funnel_direction.text_3": "レンチを使って、設置後にファンネルのモードを変えられます", + "create.ponder.funnel_direction.text_3": "レンチを使って、設置後にファンネルの動作モードを変えられます", "create.ponder.funnel_direction.text_4": "ほとんどの方向で同じことができます", "create.ponder.funnel_direction.text_5": "ベルト上のファンネルは、ベルトの移動方向に応じて搬入/搬出が決まります", @@ -1768,18 +1857,18 @@ "create.ponder.furnace_engine.text_3": "溶鉱炉を使うと、エンジンの効率が2倍になります", "create.ponder.gantry_carriage.header": "ガントリーキャリッジの使い方", - "create.ponder.gantry_carriage.text_1": "ガントリーキャリッジは、ガントリーシャフトに取り付けてスライドさせられます", - "create.ponder.gantry_carriage.text_2": "ガントリーの仕掛けは、取り付けたブロックを動かせます", + "create.ponder.gantry_carriage.text_1": "ガントリーキャリッジは、ガントリーシャフトに取り付けてスライドできます", + "create.ponder.gantry_carriage.text_2": "ガントリーは、取り付けられたブロックを動かします", - "create.ponder.gantry_cascaded.header": "立体ガンドリー", + "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_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_3": "また、シャフトの回転方向によっても決まります", "create.ponder.gantry_direction.text_4": "キャリッジへ伝達する回転力も同じルールが適用されます", "create.ponder.gantry_redstone.header": "ガントリーでの回転力の伝播", @@ -1793,11 +1882,11 @@ "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.gearbox.text_3": "直角に曲げて伝達すると、鏡映しの方向に回転します", + "create.ponder.gearbox.text_4": "まっすぐ伝達すると、回転方向が逆になります", "create.ponder.gearshift.header": "ギアシフトによる回転力の制御", - "create.ponder.gearshift.text_1": "ギアシフトは、直線に回転を伝達します", + "create.ponder.gearshift.text_1": "ギアシフトは、まっすぐ回転を伝達します", "create.ponder.gearshift.text_2": "レッドストーン信号を受けると、回転方向を逆に伝達します", "create.ponder.hand_crank.header": "ハンドクランクによる回転力の生成", @@ -1806,6 +1895,34 @@ "create.ponder.hand_crank.text_3": "回転速度は比較的速めです", "create.ponder.hand_crank.text_4": "スニークしながら右クリックし続けると、時計回りに回転します", + "create.ponder.hose_pulley.header": "ホースプーリーを使った液体の吸入・放出", + "create.ponder.hose_pulley.text_1": "ホースプーリーは、大規模な液体の吸入や放出に使います", + "create.ponder.hose_pulley.text_2": "回転力の入出口はプーリーのホースの高さを変えるのに使います", + "create.ponder.hose_pulley.text_3": "回転方向を逆にするとプーリーが収納されます", + "create.ponder.hose_pulley.text_4": "反対側にはパイプを接続できます", + "create.ponder.hose_pulley.text_5": "接続された液体ネットワークはプーリーに液体を供給し、放出できます", + "create.ponder.hose_pulley.text_6": "また、プーリーから吸い出し、代わりに吸入することもできます", + "create.ponder.hose_pulley.text_7": "プーリーの吸入・放出速度は液体ネットワークの性能で決まります", + + "create.ponder.hose_pulley_infinite.header": "大規模な液体の無限の吸入・放出", + "create.ponder.hose_pulley_infinite.text_1": "ホースプーリーを十分に大きな海に設置すると", + "create.ponder.hose_pulley_infinite.text_2": "海に影響を与えずに液体を吸入・放出できます", + "create.ponder.hose_pulley_infinite.text_3": "つまり、液体ネットワークはこのプーリーから液体を無限に出し入れできます", + + "create.ponder.hose_pulley_level.header": "ホースプーリーの吸入・放出レベル", + "create.ponder.hose_pulley_level.text_1": "完全に収納された状態では、ホースプーリーは稼働しません", + "create.ponder.hose_pulley_level.text_2": "上から下に水を吸入します", + "create.ponder.hose_pulley_level.text_3": "表面の高さはホースのすぐ下になります", + "create.ponder.hose_pulley_level.text_4": "下から上に向かって放出します", + "create.ponder.hose_pulley_level.text_5": "ホースの端より上に放出されることはありません", + + "create.ponder.item_drain.header": "アイテム排液口で液体容器を空にする", + "create.ponder.item_drain.text_1": "アイテム排液口はアイテムから液体を取り出せます", + "create.ponder.item_drain.text_2": "右クリックすると、持っているアイテムの中の液体を注ぐことができます", + "create.ponder.item_drain.text_3": "横からアイテムを入れると...", + "create.ponder.item_drain.text_4": "...中に詰まった液体を出しながら横に転がっていきます", + "create.ponder.item_drain.text_5": "液体ネットワークで、排液口から液体を取り出せます", + "create.ponder.large_cogwheel.header": "大きな歯車による回転力の伝達", "create.ponder.large_cogwheel.text_1": "大きな歯車は、直角に接続できます", "create.ponder.large_cogwheel.text_2": "回転力の回転軸を変えてに伝達するのに役立ちます", @@ -1816,12 +1933,12 @@ "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_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_1": "リニアシャーシは、隣の同じ種類のシャーシと繋がります", "create.ponder.linear_chassis_group.text_2": "からくり機械で1つを動かすと、他のリニアシャーシも一緒に動きます", "create.ponder.linear_chassis_group.text_3": "異なる種類のシャーシや、別の方向を向いているシャーシは接続されません", @@ -1846,7 +1963,7 @@ "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_3": "アームは複数の有効な搬出先が設定されていると...", "create.ponder.mechanical_arm_modes.text_4": "...設定に従ってアイテムを分配します", "create.ponder.mechanical_arm_modes.text_5": "レンチを持ってスクロールすると設定を変えられます", "create.ponder.mechanical_arm_modes.text_6": "「順繰り分配」は、有効な全ての搬出先へ順番に搬出します", @@ -1860,8 +1977,8 @@ "create.ponder.mechanical_arm_redstone.text_3": "それを利用し、反転したパルス信号を使って1回だけ稼働させられます", "create.ponder.mechanical_bearing.header": "メカニカルベアリングによる構造物の移動", - "create.ponder.mechanical_bearing.text_1": "メカニカルベアリングは、前方にブロックを取り付けられます", - "create.ponder.mechanical_bearing.text_2": "回転力を供給すると、組み立てた構造物を回転できます", + "create.ponder.mechanical_bearing.text_1": "メカニカルベアリングは、手前にブロックを取り付けられます", + "create.ponder.mechanical_bearing.text_2": "回転力を供給すると、組み立てた構造物を回せます", "create.ponder.mechanical_crafter.header": "メカニカルクラフターの配置", "create.ponder.mechanical_crafter.text_1": "メカニカルクラフターは、あらゆるクラフトレシピを自動化できます", @@ -1885,7 +2002,7 @@ "create.ponder.mechanical_drill.header": "メカニカルドリルでブロックを破壊する", "create.ponder.mechanical_drill.text_1": "メカニカルドリルは回転力を供給すると、目の前のブロックを破壊します", - "create.ponder.mechanical_drill.text_2": "採掘速度は回転速度に依存します", + "create.ponder.mechanical_drill.text_2": "採掘速度は回転速度で決まります", "create.ponder.mechanical_drill_contraption.header": "からくりに組み込んでのメカニカルドリルの使い方", "create.ponder.mechanical_drill_contraption.text_1": "からくりの一部として、メカニカルドリルを動かすと...", @@ -1899,34 +2016,49 @@ "create.ponder.mechanical_mixer.text_1": "ミキサーと鉢があれば、いくつかのクラフトレシピを自動化できます", "create.ponder.mechanical_mixer.text_2": "自動化できるのは不定形レシピといくつかの追加レシピです", "create.ponder.mechanical_mixer.text_3": "レシピの中には、ブレイズバーナーの熱を必要とするものもあります", - "create.ponder.mechanical_mixer.text_4": "フィルタースロットは、2つのレシピが競合する場合に使えます", + "create.ponder.mechanical_mixer.text_4": "フィルタースロットは、2つのレシピが競合するときに使えます", "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.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_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_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.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": "フィルタースロットは、2つのレシピが競合する場合に使えます", + "create.ponder.mechanical_press_compacting.text_4": "フィルタースロットは、2つのレシピが競合するときに使えます", + + "create.ponder.mechanical_pump_flow.header": "メカニカルポンプによる液体輸送", + "create.ponder.mechanical_pump_flow.text_1": "メカニカルポンプは、接続されたネットワークの液体の流れを制御します", + "create.ponder.mechanical_pump_flow.text_2": "稼働させると、矢印が液体の流れる方向を示します", + "create.ponder.mechanical_pump_flow.text_3": "後ろのネットワークが液体を吸い取っているのに対し...", + "create.ponder.mechanical_pump_flow.text_4": "...前のネットワークが液体を外側に送っています", + "create.ponder.mechanical_pump_flow.text_5": "回転方向を逆にすると、流れの方向が逆になります", + "create.ponder.mechanical_pump_flow.text_6": "レンチを使って手動でポンプの向きを変えることもできます", + + "create.ponder.mechanical_pump_speed.header": "メカニカルポンプの輸送速度", + "create.ponder.mechanical_pump_speed.text_1": "速度に関わらず、メカニカルポンプは16ブロック先までのパイプに影響を与えます", + "create.ponder.mechanical_pump_speed.text_2": "回転速度を速くすることで、流れの送られる速度と...", + "create.ponder.mechanical_pump_speed.text_3": "...液体の輸送速度が変わります", + "create.ponder.mechanical_pump_speed.text_4": "液体ネットワーク内のポンプはそれぞれ別の速度で動かすことができます", + "create.ponder.mechanical_pump_speed.text_5": "向きを交互にすることで、流れの方向を揃えることができます", "create.ponder.mechanical_saw_breaker.header": "メカニカルソーによる伐採", "create.ponder.mechanical_saw_breaker.text_1": "メカニカルソーは回転力を供給すると、目の前の木を伐採できます", @@ -1941,7 +2073,7 @@ "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.mechanical_saw_processing.text_5": "フィルターがない場合、ソーは全ての加工を順番に繰り返します", "create.ponder.millstone.header": "石臼でのアイテム加工", "create.ponder.millstone.text_1": "石臼はアイテムを粉砕加工する機械です", @@ -1953,17 +2085,28 @@ "create.ponder.nixie_tube.header": "ニキシー管の使い方", "create.ponder.nixie_tube.text_1": "ニキシー管は受けたレッドストーン信号の強度を表示します", "create.ponder.nixie_tube.text_2": "金床で名付けた名札を使って、好きな文字を表示することもできます", + "create.ponder.nixie_tube.text_3": "染料で右クリックすることで表示の色を変えられます", "create.ponder.piston_pole.header": "ピストン延長ポール", "create.ponder.piston_pole.text_1": "ポールが無いとメカニカルピストンは動きません", "create.ponder.piston_pole.text_2": "後ろに付けたポールの長さによって、伸び縮みする長さが決まります", + "create.ponder.portable_fluid_interface.header": "からくり液体交換", + "create.ponder.portable_fluid_interface.text_1": "移動しているからくりの液体タンクは、どんなパイプでも出し入れできません", + "create.ponder.portable_fluid_interface.text_2": "この機械は、からくりをブロックに戻すことなく液体を出し入れできます", + "create.ponder.portable_fluid_interface.text_3": "1~2ブロックの隙間を開けて2つ目のインターフェースを設置しましょう", + "create.ponder.portable_fluid_interface.text_4": "すれ違ったときに必ず接続されます", + "create.ponder.portable_fluid_interface.text_5": "接続中は、設置されている方のインターフェースはからくり内全てのタンクのように振る舞います", + "create.ponder.portable_fluid_interface.text_6": "液体の搬入と...", + "create.ponder.portable_fluid_interface.text_7": "...搬出ができるます", + "create.ponder.portable_fluid_interface.text_8": "しばらく中身が出し入れされないと、このからくりはまた動き出します", + "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_3": "1~2ブロックの間隔をあけて、2つ目のインターフェースを設置しましょう", "create.ponder.portable_storage_interface.text_4": "両者がすれ違うたびに接続されます", - "create.ponder.portable_storage_interface.text_5": "接続されている間、設置されている方のインターフェースはからくり内全ての収納ブロックのように振る舞います", + "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": "しばらくの間アイテムのやり取りがないと、からくりは稼働を再開します", @@ -1975,19 +2118,19 @@ "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_latch.text_4": "パワードラッチは、手動でもオンオフできます", "create.ponder.powered_toggle_latch.header": "パワードトグルラッチによる信号制御", "create.ponder.powered_toggle_latch.text_1": "パワードトグルラッチはレッドストーン信号で切り替えできるレバーです", "create.ponder.powered_toggle_latch.text_2": "後ろからの信号で切り替えできます", "create.ponder.powered_toggle_latch.text_3": "何度も信号を送るとオンとオフと繰り返します", - "create.ponder.powered_toggle_latch.text_4": "パワードトグルラッチは、手動で切り替えることもできます", + "create.ponder.powered_toggle_latch.text_4": "パワードトグルラッチは、手動でもオンオフもできます", "create.ponder.pulse_repeater.header": "パルスリピーターによる信号制御", "create.ponder.pulse_repeater.text_1": "パルスリピーターは、レッドストーン信号を短縮して1tickのパルス信号にします", "create.ponder.radial_chassis.header": "ラジアルシャーシによるブロックの取り付け", - "create.ponder.radial_chassis.text_1": "ラジアルシャーシは、同種のシャーシブロックと繋がります", + "create.ponder.radial_chassis.text_1": "ラジアルシャーシは、同じ種類のシャーシと繋がります", "create.ponder.radial_chassis.text_2": "からくり機械によって1つが動かされると、他も一緒に動きます", "create.ponder.radial_chassis.text_3": "ラジアルシャーシの側面を粘着面にできます", "create.ponder.radial_chassis.text_4": "もう一度クリックすると、他の全ての面も粘着面になります", @@ -2011,7 +2154,7 @@ "create.ponder.rope_pulley.header": "ローププーリーによる構造物の移動", "create.ponder.rope_pulley.text_1": "ローププーリーは、回転力を供給するとブロックを垂直に動かせます", - "create.ponder.rope_pulley.text_2": "移動の方向と速度は、供給される回転力に依存します", + "create.ponder.rope_pulley.text_2": "移動の方向と速度は、供給される回転力で決まります", "create.ponder.rope_pulley_attachment.header": "プーリーをからくりの一部として動かす", "create.ponder.rope_pulley_attachment.text_1": "プーリーがからくりによって動かされると...", @@ -2020,11 +2163,11 @@ "create.ponder.rope_pulley_modes.header": "ローププーリーの動作モード", "create.ponder.rope_pulley_modes.text_1": "プーリーの動きが止まると、移動した構造物はブロックに戻ります", - "create.ponder.rope_pulley_modes.text_2": "ブロックに戻らないように設定することも、動かし始めた場所でのみブロックに戻るように設定することもできます", + "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.rotation_speed_controller.text_2": "側面のパネルを見ながらスクロールすると、伝達する回転速度を調整できます", "create.ponder.sail.header": "帆による風車の組み立て", "create.ponder.sail.text_1": "帆は、風車を作るのに便利なブロックです", @@ -2038,7 +2181,7 @@ "create.ponder.sequenced_gearshift.header": "シーケンスギアシフトによる回転の制御", "create.ponder.sequenced_gearshift.text_1": "シーケンスギアシフトは、設定されたプログラムに従って回転を伝達します", - "create.ponder.sequenced_gearshift.text_2": "右クリックで設定インターフェースを開けます", + "create.ponder.sequenced_gearshift.text_2": "右クリックで設定画面を開けます", "create.ponder.sequenced_gearshift.text_3": "レッドストーン信号を受けると、設定されたプログラムを実行します", "create.ponder.sequenced_gearshift.text_4": "終了すると止まり、また次のレッドストーン信号を受けると同じように実行します", "create.ponder.sequenced_gearshift.text_5": "レッドストーンコンパレータで、現在の進捗を読み取れます", @@ -2055,22 +2198,36 @@ "create.ponder.smart_chute.text_3": "マウスホイールで搬出するスタック量を指定できます", "create.ponder.smart_chute.text_4": "レッドストーン信号で、スマートシュートを停止させることもできます", + "create.ponder.smart_pipe.header": "スマートパイプによる液体制御", + "create.ponder.smart_pipe.text_1": "スマートパイプは液体の種類によって流れを制御できます", + "create.ponder.smart_pipe.text_2": "搬入元に直接つなげることで、搬出する液体の種類を指定できます", + "create.ponder.smart_pipe.text_3": "フィルタースロットを右クリックして、液体の入ったアイテムを装着して指定することもできます", + "create.ponder.smart_pipe.text_4": "スマートパイプは、パイプネットワークの搬出先に設置すると指定された液体のみを流します", + "create.ponder.speedometer.header": "速度メーターによる動力情報の監視", "create.ponder.speedometer.text_1": "速度メーターは、接続された機械の現在の回転速度を表示します", "create.ponder.speedometer.text_2": "エンジニアのゴーグルを装着していると、より詳細な情報を得られます", "create.ponder.speedometer.text_3": "コンパレータは、速度メーターの測定値に応じたレッドストーン信号を出力します", + "create.ponder.spout_filling.header": "アイテム注液口によるアイテム充填", + "create.ponder.spout_filling.text_1": "注液口は、その下に用意されたアイテムを液体で満たすことができます", + "create.ponder.spout_filling.text_2": "注液口の中身は手動で出し入れすることはできません", + "create.ponder.spout_filling.text_3": "代わりに、パイプを使って液体を供給しましょう", + "create.ponder.spout_filling.text_4": "容器アイテムは、注液口の下のデポに置きましょう", + "create.ponder.spout_filling.text_5": "ベルトでアイテムを供給すると...", + "create.ponder.spout_filling.text_6": "...注液口が自動でアイテムを止め、加工します", + "create.ponder.stabilized_bearings.header": "からくりの角度の固定", - "create.ponder.stabilized_bearings.text_1": "メカニカルベアリングが動いている構造物に組み込まれているとき ...", + "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.sticker.text_2": "レッドストーン信号を受けると、状態が切り替わります", + "create.ponder.sticker.text_3": "付いているときは、からくりが動かされるとブロックも一緒に動きます", + "create.ponder.sticker.text_4": "もう一度信号を受けると、ブロックは外れます", "create.ponder.stressometer.header": "応力メーターによる動力情報の監視", "create.ponder.stressometer.text_1": "応力メーターは、接続された動力ネットワークの現在の応力許容量を表示します", @@ -2091,6 +2248,12 @@ "create.ponder.valve_handle.text_4": "スニーク状態で右クリックし続けると、時計回りに回転します", "create.ponder.valve_handle.text_5": "バルブハンドルは、染色できます", + "create.ponder.valve_pipe.header": "バルブによる液体制御", + "create.ponder.valve_pipe.text_1": "バルブは、液体ネットワークに流れる液体を制御するのに役立ちます", + "create.ponder.valve_pipe.text_2": "回転力で、液体が現在通過できるか制御します", + "create.ponder.valve_pipe.text_3": "開放方向に回転力を与えるとバルブが開きます", + "create.ponder.valve_pipe.text_4": "回転方向を逆にすることでバルブを閉められます", + "create.ponder.water_wheel.header": "水車による回転力の生成", "create.ponder.water_wheel.text_1": "水車は隣接する水流から回転力を生み出します", "create.ponder.water_wheel.text_2": "水流を受ける面が多ければ多いほど、水車の回転速度は速くなります", @@ -2130,5 +2293,8 @@ "create.ponder.windmill_source.text_6": "いつでもベアリングを右クリックすれば、回転を停止させて構造物を組み立てなおせます", "create.ponder.windmill_structure.header": "からくり風車", - "create.ponder.windmill_structure.text_1": "帆とみなされるブロックが8個以上あれば、どのような構造物でも風車として動きます" -} \ No newline at end of file + "create.ponder.windmill_structure.text_1": "帆とみなされるブロックが8個以上あれば、どのような構造物でも風車として動きます", + + "_": "Thank you for translating Create!" + +} diff --git a/src/main/resources/assets/create/lang/ko_kr.json b/src/main/resources/assets/create/lang/ko_kr.json index 3e8843be4..0f02f0855 100644 --- a/src/main/resources/assets/create/lang/ko_kr.json +++ b/src/main/resources/assets/create/lang/ko_kr.json @@ -1,8 +1,8 @@ { "_": "->------------------------] Game Elements [------------------------<-", - "block.create.andesite_bricks": "안산안 벽돌", - "block.create.layered_andesite": "층이 있는 안산암", + "block.create.andesite_bricks": "안산암 벽돌", + "block.create.layered_andesite": "이어지는 안산암", "block.create.andesite_bricks": "안산암 벽돌", "block.create.andesite_bricks_slab": "안산암 벽돌 반 블록", "block.create.andesite_bricks_stairs": "안산암 벽돌 계단", @@ -41,7 +41,7 @@ "block.create.fancy_dark_scoria_bricks_slab": "장식된 짙은 스코리아 벽돌 반 블록", "block.create.fancy_dark_scoria_bricks_stairs": "장식된 짙은 스코리아 벽돌 계단", "block.create.fancy_dark_scoria_bricks_wall": "장식된 짙은 스코리아 벽돌 담장", - "block.create.layered_dark_scoria": "층이 있는 짙은 스코리아", + "block.create.layered_dark_scoria": "이어지는 짙은 스코리아", "block.create.mossy_dark_scoria": "이끼 낀 짙은 스코리아", "block.create.overgrown_dark_scoria": "이끼가 뒤덮힌 짙은 스코리아", "block.create.paved_dark_scoria": "포장된 짙은 스코리아", @@ -67,7 +67,7 @@ "block.create.fancy_diorite_bricks_slab": "장식된 섬록암 벽돌 반 블록", "block.create.fancy_diorite_bricks_stairs": "장식된 섬록암 벽돌 계단", "block.create.fancy_diorite_bricks_wall": "장식된 섬록암 벽돌 담장", - "block.create.layered_diorite": "층이 있는 섬록암", + "block.create.layered_diorite": "이어지는 섬록암", "block.create.mossy_diorite": "이끼 낀 섬록암", "block.create.overgrown_diorite": "이끼로 뒤덮힌 섬록암", "block.create.paved_diorite": "포장된 섬록암", @@ -85,7 +85,7 @@ "block.create.dolomite_bricks_stairs": "백운암 벽돌 계단", "block.create.dolomite_bricks_slab": "백운암 벽돌 반 블록", "block.create.polished_dolomite": "윤나는 백운암", - "block.create.layered_dolomite": "층이 있는 백운암", + "block.create.layered_dolomite": "이어지는 백운암", "block.create.dolomite_cobblestone": "백운암 조약돌", "block.create.dolomite_cobblestone_slab": "백운암 조약돌 반 블록", "block.create.dolomite_cobblestone_stairs": "백운암 조약돌 계단", @@ -94,7 +94,7 @@ "block.create.fancy_dolomite_bricks_slab": "장식된 백운암 벽돌 반 블록", "block.create.fancy_dolomite_bricks_stairs": "장식된 백운암 벽돌 계단", "block.create.fancy_dolomite_bricks_wall": "장식된 백운암 벽돌 담장", - "block.create.paved_dolomite": "포장된 백운암", + "block.create.paved_dolomite": "포장된 백운암", "block.create.paved_dolomite_slab": "포장된 백운암 반 블록", "block.create.paved_dolomite_stairs": "포장된 백운암 계단", "block.create.paved_dolomite_wall": "포장된 백운암 담장", @@ -102,7 +102,7 @@ "block.create.polished_dolomite_stairs": "윤나는 백운암 계단", "block.create.polished_dolomite_wall": "윤나는 백운암 담장", "block.create.chiseled_dolomite": "조각된 백운암", - "block.create.mossy_dolomite": "이끼낀 백운암", + "block.create.mossy_dolomite": "이끼 낀 백운암", "block.create.overgrown_dolomite": "이끼로 뒤덮힌 백운암", "block.create.dolomite_pillar": "백운암 기둥", @@ -129,8 +129,8 @@ "block.create.gabbro_cobblestone_slab": "반려암 조약돌 반 블록", "block.create.gabbro_cobblestone_stairs": "반려암 조약돌 계단", "block.create.gabbro_cobblestone_wall": "반려암 조약돌 담장", - "block.create.layered_gabbro": "층이 있는 반려암", - "block.create.mossy_gabbro": "이끼낀 반려암", + "block.create.layered_gabbro": "이어지는 반려암", + "block.create.mossy_gabbro": "이끼 낀 반려암", "block.create.overgrown_gabbro": "이끼로 뒤덮힌 반려암", "block.create.paved_gabbro": "포장된 반려암", "block.create.paved_gabbro_slab": "포장된 반려암 반 블록", @@ -144,14 +144,14 @@ "block.create.gabbro_pillar": "반려암 기둥", "block.create.granite_bricks": "화강암 벽돌", - "block.create.layered_granite": "층이 있는 화강암", + "block.create.layered_granite": "이어지는 화강암", "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.granite_bricks_slab": "화강함 벽돌 반 블록", - "block.create.granite_bricks_stairs": "화강함 벽돌 계단", - "block.create.granite_bricks_wall": "화강함 벽돌 담장", + "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": "화강암 조약돌 계단", @@ -176,7 +176,7 @@ "block.create.polished_limestone": "윤나는 석회암", "block.create.polished_limestone_slab": "윤나는 석회암 반 블록", "block.create.limestone_pillar": "석회암 기둥", - "block.create.layered_limestone": "층이 있는 석회암", + "block.create.layered_limestone": "이어지는 석회암", "block.create.chiseled_limestone": "조각된 석회암", "block.create.fancy_limestone_bricks": "장식된 석회암 벽돌", "block.create.fancy_limestone_bricks_slab": "장식된 석회암 벽돌 반 블록", @@ -204,7 +204,7 @@ "block.create.polished_scoria": "윤나는 스코리아", "block.create.polished_scoria_slab": "윤나는 스코리아 반 블록", "block.create.scoria_pillar": "스코리아 기둥", - "block.create.layered_scoria": "층이 있는 스코리아", + "block.create.layered_scoria": "이어지는 스코리아", "block.create.chiseled_scoria": "조각된 스코리아", "block.create.fancy_scoria_bricks": "장식된 스코리아 벽돌", "block.create.fancy_scoria_bricks_slab": "장식된 스코리아 벽돌 반 블록", @@ -237,7 +237,7 @@ "block.create.weathered_limestone_bricks_wall": "풍화된 석회암 벽돌 담장", "block.create.weathered_limestone_bricks_slab": "풍화된 석회암 벽돌 반 블록", "block.create.weathered_limestone_pillar": "풍화된 석회암 기둥", - "block.create.layered_weathered_limestone": "층이 있는 풍화된 석회암", + "block.create.layered_weathered_limestone": "이어지는 풍화된 석회암", "block.create.chiseled_weathered_limestone": "조각된 풍화된 석회암", "block.create.fancy_weathered_limestone_bricks": "장식된 풍화된 석회암 벽돌", "block.create.fancy_weathered_limestone_bricks_slab": "장식된 풍화된 석회암 벽돌 반 블록", @@ -267,7 +267,8 @@ "block.create.dark_oak_window": "짙은 참나무 유리창", "block.create.acacia_window": "아카시아 유리창", "block.create.ornate_iron_window": "장식된 철 유리창", - + "block.create.crimson_window": "진홍빛 유리창", + "block.create.warped_window": "뒤틀린 유리창", "block.create.tiled_glass_pane": "타일 유리판", "block.create.framed_glass_pane": "큰 유리판", @@ -280,6 +281,8 @@ "block.create.dark_oak_window_pane": "짙은 참나무 유리판", "block.create.acacia_window_pane": "아카시아나무 유리판 ", "block.create.ornate_iron_window_pane": "장식된 철 유리판", + "block.create.crimson_window_pane": "진홍빛 유리판", + "block.create.warped_window_pane": "뒤틀린 유리판", "block.create.black_seat": "검은색 좌석", "block.create.blue_seat": "파란색 좌석", @@ -316,16 +319,7 @@ "block.create.yellow_valve_handle": "노란색 밸브 손잡이", "block.create.purple_valve_handle": "보라색 밸브 손잡이", - "block.create.encased_fluid_pipe": "구리 케이스를 씌운 파이프", - "block.create.fluid_pipe": "액체 파이프", - "block.create.fluid_tank": "액체 탱크", - "block.create.fluid_valve": "액체 밸브", - "block.create.glass_fluid_pipe": "액체 파이프", - "block.create.mechanical_pump": "펌프", - "block.create.smart_fluid_pipe": "스마트 액체 파이프", - "block.create.creative_fluid_tank": "크리에이티브 탱크", - - "block.create.sail_frame": "풍차 날개 프레임", + "block.create.sail_frame": "풍차 날개 틀", "block.create.black_sail": "검은색 날개", "block.create.blue_sail": "파란색 날개", "block.create.brown_sail": "갈색 날개", @@ -342,113 +336,151 @@ "block.create.red_sail": "빨간색 날개", "block.create.white_sail": "하얀색 날개", "block.create.yellow_sail": "노란색 날개", + + "block.create.nixie_tube": "닉시관", + "block.create.black_nixie_tube": "검은색 닉시관", + "block.create.blue_nixie_tube": "파란색 닉시관", + "block.create.brown_nixie_tube": "갈색 닉시관", + "block.create.cyan_nixie_tube": "청록색 닉시관", + "block.create.gray_nixie_tube": "회색 닉시관", + "block.create.green_nixie_tube": "초록색 닉시관", + "block.create.light_blue_nixie_tube": "하늘핵 닉시관", + "block.create.light_gray_nixie_tube": "회백색 닉시관", + "block.create.lime_nixie_tube": "연두색 닉시관", + "block.create.magenta_nixie_tube": "자홍색 닉시관", + "block.create.pink_nixie_tube": "분홍색 닉시관", + "block.create.purple_nixie_tube": "보라샥 닉시관", + "block.create.red_nixie_tube": "빨간색 닉시관", + "block.create.white_nixie_tube": "하얀색 닉시관", + "block.create.yellow_nixie_tube": "노란색 닉시관", + "block.create.encased_fluid_pipe": "구리 케이스를 씌운 파이프", + "block.create.fluid_pipe": "액체 파이프", + "block.create.fluid_tank": "액체 탱크", + "block.create.fluid_valve": "액체 밸브", + "block.create.glass_fluid_pipe": "액체 파이프", + "block.create.mechanical_pump": "펌프", + "block.create.smart_fluid_pipe": "스마트 액체 파이프", + "block.create.creative_fluid_tank": "크리에이티브 탱크", + "block.create.portable_fluid_interface": "액체 인터페이스", + "block.create.hose_pulley": "호스 도르래", + "block.create.item_drain": "아이템 배수구", + "block.create.spout": "주입기", + "block.create.creative_motor": "크리에이티브 모터", "block.create.encased_fan": "선풍기", "block.create.flywheel": "플라이휠", "block.create.furnace_engine": "화로 엔진", - "block.create.cogwheel": "톱니바퀴", - "block.create.encased_chain_drive": "케이스를 씌운 축", - "block.create.encased_shaft": "케이스를 씌운 축", - "block.create.belt": "컨베이어 벨트", - "block.create.adjustable_chain_gearshift": "벨트 변속기", - "block.create.gearbox": "기어박스", - "block.create.gearshift": "기어쉬프트", + "block.create.water_wheel": "물레바퀴", + "block.create.windmill_bearing": "풍차 베어링", "block.create.hand_crank": "핸드 크랭크", + + "item.create.belt_connector": "벨트", + "block.create.shaft": "축", + "block.create.belt": "벨트", + "block.create.cogwheel": "톱니바퀴", "block.create.large_cogwheel": "큰 톱니바퀴", "block.create.rotation_speed_controller": "회전 속도 컨트롤러", - "block.create.shaft": "축", + "block.create.andesite_encased_shaft": "안산암 케이스를 씌운 축", + "block.create.brass_encased_shaft": "황동 케이스를 씌운 축", + + "item.create.vertical_gearbox": "수직 기어박스", + "block.create.gearbox": "기어박스", + "block.create.gearshift": "기어쉬프트", + "block.create.clutch": "클러치", + "block.create.encased_chain_drive": "체인 드라이브", + "block.create.adjustable_chain_gearshift": "벨트 변속기", "block.create.speedometer": "속도 계측기", "block.create.stressometer": "피로도 계측기", - "block.create.water_wheel": "물레방아", - "item.create.belt_connector": "기계식 벨트", - "item.create.vertical_gearbox": "수직 기어박스", - "block.create.clutch": "클러치", - "block.create.windmill_bearing": "풍차 베어링", - "block.create.cart_assembler": "카트 조립기", "block.create.linear_chassis": "어두운 직선 섀시", - "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.clockwork_bearing": "시계 베어링", + "block.create.cart_assembler": "카트 조립기", "block.create.mechanical_piston": "기계식 피스톤", "block.create.mechanical_piston_head": "기계식 피스톤 머리", + "block.create.sticky_mechanical_piston": "기계식 끈끈이 피스톤", + "block.create.sticker": "부착기", + "block.create.pulley_magnet": "도르래 자석", + "block.create.radial_chassis": "원형 섀시", + "block.create.secondary_linear_chassis": "밝은 직선 섀시", + "block.create.piston_extension_pole": "피스톤 연장 축", + "block.create.sequenced_gearshift": "순서 기어쉬프트", + "block.create.rope": "밧줄", + "block.create.rope_pulley": "밧줄 도르래", + "block.create.gantry_carriage": "갠트리 운반대", + "block.create.gantry_shaft": "갠트리 축", + + "block.create.millstone": "맷돌", + "block.create.mechanical_mixer": "믹서", + "block.create.mechanical_arm": "기계 팔", + "block.create.mechanical_crafter": "조합기", + "block.create.mechanical_drill": "드릴", + "block.create.mechanical_harvester": "수확기", "block.create.mechanical_plough": "쟁기", "block.create.mechanical_press": "압착기", "block.create.mechanical_saw": "톱", - "block.create.millstone": "맷돌", + "block.create.deployer": "배포기", "block.create.minecart_anchor": "광산 수레 정박기", "block.create.mysterious_cuckoo_clock": "뻐꾸기 시계?", "block.create.crushing_wheel": "분쇄 휠", "block.create.crushing_wheel_controller": "분쇄 휠 컨트롤러", "block.create.cuckoo_clock": "뻐꾸기 시계", - "block.create.clockwork_bearing": "시계 베어링", - "block.create.deployer": "배포기", - "block.create.nozzle": "노즐", - "block.create.blaze_burner": "블레이즈 버너", - "block.create.brass_belt_funnel": "황동 깔때기", - "block.create.brass_block": "황동 블록", - "block.create.brass_casing": "황동 케이스", - "block.create.brass_funnel": "황동 깔때기", - "block.create.brass_tunnel": "황동 터널", - "block.create.pulley_magnet": "도르래 자석", - "block.create.radial_chassis": "원형 섀시", - "block.create.secondary_linear_chassis": "밝은 직선 섀시", - "block.create.sequenced_gearshift": "순서 기어쉬프트", - "block.create.piston_extension_pole": "피스톤 연장 축", - "block.create.portable_fluid_interface": "이동식 액체 인터페이스", - "block.create.portable_storage_interface": "이동식 아이템 인터페이스", + "block.create.nozzle": "노즐", + "block.create.portable_storage_interface": "아이템 인터페이스", + "block.create.turntable": "돌림판", + "block.create.weighted_ejector": "투척기", "block.create.content_observer": "정보 감지기", "block.create.chute": "슈트", + "block.create.smart_chute": "스마트 슈트", "block.create.basin": "대야", "block.create.depot": "아이템 거치대", "block.create.adjustable_crate": "가변 창고", - "block.create.nixie_tube": "디지털 표시증", - "block.create.rope": "밧줄", - "block.create.rope_pulley": "밧줄 도르래", - "block.create.hose_pulley": "호스 도르래", - "block.create.item_drain": "아이템 배수구", - "block.create.schematic_table": "청사진 테이블", - "block.create.schematicannon": "청사진 대포", - "block.create.spout": "수도꼭지", - "block.create.sticky_mechanical_piston": "끈끈이 기계식 피스톤", - "block.create.turntable": "돌림판", - "entity.create.contraption": "장치", - "entity.create.seat": "좌석", - "entity.create.stationary_contraption": "고정된 장치", - "entity.create.super_glue": "강력 접착제", "block.create.andesite_casing": "안산암 케이스", - "block.create.andesite_funnel": "안산암 깔때기", - "block.create.andesite_belt_funnel": "안산암 깔때기", + "block.create.andesite_funnel": "안산암 퍼널", + "block.create.andesite_belt_funnel": "안산암 퍼널", "block.create.andesite_tunnel": "안산암 터널", "block.create.reinforced_rail": "강화된 레일", + "block.create.blaze_burner": "블레이즈 버너", + "block.create.brass_belt_funnel": "황동 퍼널", + "block.create.brass_block": "황동 블록", + "block.create.brass_casing": "황동 케이스", + "block.create.brass_funnel": "황동 퍼널", + "block.create.brass_tunnel": "황동 터널", + + "entity.create.contraption": "구조물", + "entity.create.seat": "좌석", + "entity.create.stationary_contraption": "고정된 구조물", + "entity.create.super_glue": "강력 접착제", + "entity.create.crafting_blueprint": "조합 청사진", + "entity.create.gantry_contraption": "갠트리 구조물", + "entity.create.potato_projectile": "감자포 투사체", + "item.create.attribute_filter": "속성 필터 틀", - "item.create.furnace_minecart_contraption": "화로가 실린 광산 수레 장치", - "item.create.chest_minecart_contraption": "상자가 실린 광산 수레 장치", - "item.create.minecart_contraption": "광산 수레 장치", + "item.create.furnace_minecart_contraption": "화로가 실린 광산 수레 구조물", + "item.create.chest_minecart_contraption": "상자가 실린 광산 수레 구조물", + "item.create.minecart_contraption": "광산 수레 구조물", "item.create.minecart_coupling": "광산 수레 커플링", - "block.create.andesite_encased_shaft": "안산암 케이스를 씌운 축", - "block.create.brass_encased_shaft": "황동 케이스를 씌운 축", + "block.create.powered_latch": "레드스톤 걸쇠", "block.create.powered_toggle_latch": "레드스톤 토글 걸쇠", - "block.create.pulse_repeater": "펄스 리피터", + "block.create.pulse_repeater": "펄스 중계기", "block.create.redstone_contact": "동형 감지기", "block.create.redstone_link": "레드스톤 링크", - "block.create.adjustable_pulse_repeater": "가변 펄스 리피터", - "block.create.adjustable_repeater": "가변 리피터", + "block.create.adjustable_pulse_repeater": "가변 펄스 중계기", + "block.create.adjustable_repeater": "가변 중계기", "block.create.analog_lever": "아날로그 레버", "block.create.stockpile_switch": "수량 스위치", "block.create.controller_rail": "방향 레일", "block.create.creative_crate": "크리에이티브 창고", + "block.create.schematic_table": "청사진 탁자", + "block.create.schematicannon": "청사진 대포", "item.create.deforester": "산림파괴자", "item.create.extendo_grip": "외장형 연장 팔", "item.create.handheld_blockzapper": "휴대용 블록발사기", - "item.create.handheld_worldshaper": "휴대용 세계편집기", + "item.create.handheld_worldshaper": "크리에이티브 세계편집기", "item.create.goggles": "엔지니어의 고글", "item.create.red_sand_paper": "붉은 사포", "item.create.sand_paper": "사포", @@ -463,7 +495,7 @@ "block.create.copper_tiles": "구리 타일", "block.create.refined_radiance_casing": "빛나는 케이스", "block.create.shadow_steel_casing": "그림자 케이스", - "block.create.zinc_block": "아연 블", + "block.create.zinc_block": "아연 블록", "block.create.zinc_ore": "아연 광석", "item.create.andesite_alloy": "안산암 합금", "item.create.blaze_cake": "블레이즈 케이크", @@ -508,6 +540,20 @@ "block.create.metal_bracket": "금속 지지대", "block.create.wooden_bracket": "나무 지지대", "block.create.lit_blaze_burner": "불타는 빈 블레이즈 버너", + "item.create.precision_mechanism": "정밀 기계장치", + "item.create.potato_cannon": "감자포", + "item.create.linked_controller": "레드스톤 링크 조작기", + "item.create.incomplete_cogwheel": "미완성된 톱니바퀴", + "item.create.incomplete_large_cogwheel": "미완성된 큰 톱니바퀴", + "item.create.incomplete_precision_mechanism": "미완성된 정밀 기계장치", + "item.create.diving_boots": "다이빙 부츠", + "item.create.diving_helmet": "다이빙 헬멧", + "block.create.copper_backtank": "구리 산소통", + "item.create.crafting_blueprint": "조합 청사진", + "item.create.copper_backtank": "구리 산소통", + "block.create.peculiar_bell": "황동 종", + "block.create.lectern_controller": "독서대 조작기", + "block.create.haunted_bell": "귀신들린 종", "block.create.chocolate": "초콜릿", "block.create.honey": "꿀", @@ -520,34 +566,40 @@ "item.create.bar_of_chocolate": "초콜릿 바", "item.create.chocolate_bucket": "초콜릿 양동이", "item.create.honey_bucket": "꿀 양동이", + "item.create.sweet_roll": "롤빵", + "item.create.chocolate_glazed_berries": "초콜릿 바른 열매", + "item.create.honeyed_apple": "꿀 바른 사과", + + "enchantment.create.capacity": "저장량", + "enchantment.create.potato_recovery": "대포알 회수", "_": "->------------------------] Advancements [------------------------<-", - "advancement.create.root": "Create모드에 어서오세요", - "advancement.create.root.desc": "멋진 장치들을 만들 시간입니다!", - "advancement.create.andesite_alloy": "합금..?", + "advancement.create.root": "Create!", + "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.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.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.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.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": "지열 난방기", @@ -561,43 +613,43 @@ "advancement.create.goggles": "피로돋보기", "advancement.create.goggles.desc": "장치에 대한 운동 정보를 가져다 줄 고글을 만드세요.", "advancement.create.speedometer": "근데 얼마나 빨라?", - "advancement.create.speedometer.desc": "속도 계측기를 가동하세요. 고글을 통해 수치가 얼마나 되는지 보세요.", + "advancement.create.speedometer.desc": "속도 계측기를 작동하세요. 고글을 통해 수치가 얼마나 되는지 보세요.", "advancement.create.stressometer": "근데 얼마나 피로해?", - "advancement.create.stressometer.desc": "피로도 계측기를 가동하세요. 고글을 통해 수치가 얼마나 되는지 보세요.", - "advancement.create.aesthetics": "짠! 예술!", + "advancement.create.stressometer.desc": "피로도 계측기를 작동하세요. 고글을 통해 수치가 얼마나 되는지 보세요.", + "advancement.create.aesthetics": "미적 감각!", "advancement.create.aesthetics.desc": "축, 파이프, 톱니바퀴에 지지대를 설치하세요.", - "advancement.create.reinforced": "짠! 강화!", + "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.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.millstone.desc": "멧돌을 설치하고 작동시키세요.", + "advancement.create.windmill": "산들 바람", "advancement.create.windmill.desc": "풍차 베어링을 작동시키세요.", - "advancement.create.maxed_windmill": "강한 바람", + "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.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": "삐-빅", "advancement.create.electron_tube.desc": "전지 튜브를 만드세요. 발전된 장치들에 쓰입니다.", - "advancement.create.mechanical_saw": "벌목기 가동", - "advancement.create.mechanical_saw.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.mixer.desc": "대야 위에 믹서를 설치하고, 작동시켜 재료를 만드세요.", "advancement.create.blaze_burner": "살아있는 불", "advancement.create.blaze_burner.desc": "블레이즈 버너를 얻으세요.", "advancement.create.compact": "자동 압축", @@ -610,38 +662,38 @@ "advancement.create.copper_casing": "구리 시대", "advancement.create.copper_casing.desc": "구리 판을 이용해 구리 케이스를 만드세요.", "advancement.create.spout": "쪼르록", - "advancement.create.spout.desc": "수도꼭지가 아이템에 액체를 채우는 것을 보세요.", + "advancement.create.spout.desc": "주입기를 사용하여 아이템에 액체를 채우세요.", "advancement.create.spout_potion": "대규모 양조", - "advancement.create.spout_potion.desc": "수도꼭지가 병에 포션을 채우는 것을 보세요.", + "advancement.create.spout_potion.desc": "주입기를 사용하여 유리병에 물약을 채우세요.", "advancement.create.chocolate": "상상의 세계", - "advancement.create.chocolate.desc": "양동이에 녹은 초콜릿을 채우세요.", + "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.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": "지옥을 흡수하다", "advancement.create.infinite_lava.desc": "무한으로 인식되는 용암 웅덩이에서 용암을 끌어올리세요.", "advancement.create.infinite_chocolate": "상상 속에 잠기다", - "advancement.create.infinite_chocolate.desc": "무한으로 인식되는 초콜릿 웅덩이에서 초콜릿을 끌어올리세요..", + "advancement.create.infinite_chocolate.desc": "무한으로 인식되는 초콜릿 웅덩이에서 초콜릿을 끌어올리세요.", "advancement.create.crafter": "자동 조합", - "advancement.create.crafter.desc": "기계식 조합기를 설치하고 가동시키세요.", + "advancement.create.crafter.desc": "기계식 조합기를 설치하고 작동시키세요.", "advancement.create.clockwork_bearing": "시계 제작", "advancement.create.clockwork_bearing.desc": "시계 베어링에 구조물을 달고 작동시키세요.", - "advancement.create.nixie_tube": "스타일있게 표시하기", - "advancement.create.nixie_tube.desc": "디지털 표시등을 얻고 설치하세요.", + "advancement.create.nixie_tube": "나는 스타일있게 표시해", + "advancement.create.nixie_tube.desc": "닉시관을 만들고 설치하세요.", "advancement.create.deployer": "찌르고, 설치하고, 공격!", - "advancement.create.deployer.desc": "당신의 분신, 배포기를 설치하고 가동시키세요.", + "advancement.create.deployer.desc": "당신의 분신, 배포기를 설치하고 작동시키세요.", "advancement.create.fist_bump": "하이파이브!", "advancement.create.fist_bump.desc": "두 배포기를 서로 부딫치게 하세요.", "advancement.create.crushing_wheel": "한 쌍의 거인들", @@ -650,11 +702,11 @@ "advancement.create.speed_controller.desc": "궁극의 회전속도 변경장치, 회전 속도 컨트롤러를 설치하세요.", "advancement.create.flywheel": "공장의 심장", "advancement.create.flywheel.desc": "화로엔진에 플라이휠을 연결하세요.", - "advancement.create.overstress_flywheel": "정말 높은 피로", + "advancement.create.overstress_flywheel": "정말정말 높은 피로", "advancement.create.overstress_flywheel.desc": "화로 엔진을 과부하하세요.", "advancement.create.integrated_circuit": "복잡한 계산", "advancement.create.integrated_circuit.desc": "집적 회로를 제작하세요.", - "advancement.create.mechanical_arm": "할일이 많아!", + "advancement.create.mechanical_arm": "바쁘다 바빠!", "advancement.create.mechanical_arm.desc": "기계 팔을 조합하고, 입력부와 출력부를 정하고, 설치한 다음 돌리세요. 그리고 그것이 작동하는 것을 보세요.", "advancement.create.musical_arm": "볼륨 최대로!", "advancement.create.musical_arm.desc": "기계 팔이 주크박스를 작동시키는 것을 보세요.", @@ -664,18 +716,22 @@ "advancement.create.arm_blaze_burner.desc": "기계 팔이 블레이즈 버너에 연료를 넣도록 하세요.", "advancement.create.chromatic_compound": "양극성 재료", "advancement.create.chromatic_compound.desc": "색채 혼합물를 만드세요.", - "advancement.create.shadow_steel": "공허를 받아들이다", + "advancement.create.shadow_steel": "공허에서의 복귀", "advancement.create.shadow_steel.desc": "무의 금속, 그림자 강철을 생성하세요.", - "advancement.create.refined_radiance": "빛으로 제련되다", + "advancement.create.refined_radiance": "빛으로부터의 자극", "advancement.create.refined_radiance.desc": "강력한 색채 물질, 정제된 빛을 생성하세요.", "advancement.create.chromatic_age": "양극 시대", "advancement.create.chromatic_age.desc": "빛과 어둠의 케이스를 제작하세요.", - "advancement.create.blaze_cake": "설탕 러시", + "advancement.create.blaze_cake": "폭주", "advancement.create.blaze_cake.desc": "블레이즈 버너에게 줄 특별한 케이크를 만드세요.", "advancement.create.extendo_grip": "띠요오옹!", - "advancement.create.extendo_grip.desc": "외장형 연장 팔을 드세요.", + "advancement.create.extendo_grip.desc": "외장형 연장 팔을 손에 쥐세요.", "advancement.create.dual_extendo_grip": "궁극의 띠용!", "advancement.create.dual_extendo_grip.desc": "쌍으로 외장형 연장 팔을 들어 인간을 뛰어넘은 사거리를 가지세요.", + "advancement.create.potato_cannon": "퐁!", + "advancement.create.potato_cannon.desc": "감자포로 적을 처치하세요.", + "advancement.create.precision_mechanism": "복잡한 호기심", + "advancement.create.precision_mechanism.desc": "정밀 기계장치를 조립하세요.", "advancement.create.zapper": "나는 스타일있게 건축해", "advancement.create.zapper.desc": "당신의 건축을 도와줄 멋진 레이저 건, 휴대용 블록발사기를 만드세요.", @@ -694,18 +750,34 @@ "itemGroup.create.base": "Create", "itemGroup.create.palettes": "Create 팔레트", - "death.attack.create.crush": "%1$s이(가) 분쇄 휠에 의해 가공되었습니다", - "death.attack.create.fan_fire": "%1$s이(가) 뜨거운 바람에 의해 익어버렸습니다", - "death.attack.create.fan_lava": "%1$s이(가) 용암 바람으로 구워졌습니다", + "death.attack.create.crush": "%1$s이(가) 분쇄 휠로 가공되었습니다", + "death.attack.create.crush.player": "%1$s이(가) %2$s 때문에 분쇄 휠에서 가공되었습니다", + "death.attack.create.fan_fire": "%1$s이(가) 뜨거운 바람에 익어버렸습니다", + "death.attack.create.fan_fire.player": "%1$s이(가) %2$s 때문에 뜨거운 바람으로 익어버렸습니다", + "death.attack.create.fan_lava": "%1$s이(가) 용암 바람으로 제가 되었습니다", + "death.attack.create.fan_lava.player": "%1$s이(가) %2$s 때문에 용암 바람으로 재가 되었습니다", "death.attack.create.mechanical_drill": "%1$s이(가) 드릴에 관통당했습니다", + "death.attack.create.mechanical_drill.player": "%1$s이(가) %2$s 때문에 드릴에 관통당했습니다", "death.attack.create.mechanical_saw": "%1$s이(가) 톱날에 반으로 갈라져 죽었습니다", + "death.attack.create.mechanical_saw.player": "%1$s이(가) %2$s 때문에 톱날에 반으로 갈라져 죽었습니다", + "death.attack.create.potato_cannon": "%1$s이(가) %2$s의 감자포에 맞고 죽었습니다.", + "death.attack.create.potato_cannon.item": "%1$s이(가) %3$s을(를) 사용한 %2$s에게 맞아 죽었습니다.", "death.attack.create.cuckoo_clock_explosion": "%1$s이(가) 조작된 뻐꾸기 시계에 의해 폭파당했습니다", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s이(가) 조작된 뻐꾸기 시계에 의해 폭파당했습니다", "create.block.deployer.damage_source_name": "배포기", - "create.block.cart_assembler.invalid": "카트조립기를 레일 위에 설치하세요", + "create.block.cart_assembler.invalid": "카트 조립기를 레일 위에 설치하세요", + + "create.menu.return": "메뉴로 돌아가기", + "create.menu.configure": "설정...", + "create.menu.ponder_index": "분석 메뉴", + "create.menu.only_ingame": "일시 정지 메뉴에서 가능합니다", + "create.menu.project_page": "Curseforge 페이지", + "create.menu.report_bugs": "버그 제보하기", + "create.menu.support": "후원하기", "create.recipe.crushing": "분쇄", - "create.recipe.milling": "맷돌질", + "create.recipe.milling": "제분", "create.recipe.fan_washing": "세척", "create.recipe.fan_washing.fan": "물과 선풍기", "create.recipe.fan_smoking": "훈연", @@ -721,16 +793,27 @@ "create.recipe.sawing": "제재", "create.recipe.mechanical_crafting": "기계 조합", "create.recipe.automatic_shaped": "유형 자동 조합", - "create.recipe.block_cutting": "블 절단", + "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.sequenced_assembly": "순서 조립", + "create.recipe.assembly.next": "다음 단계: %1$s", + "create.recipe.assembly.step": "단계 %1$s:", + "create.recipe.assembly.progress": "진행도: %1$s/%2$s", + "create.recipe.assembly.pressing": "압착하기", + "create.recipe.assembly.spout_filling_fluid": "%1$s 주입하기", + "create.recipe.assembly.deploying_item": "%1$s 사용하기", + "create.recipe.assembly.cutting": "톱으로 자르기", + "create.recipe.assembly.repeat": "%1$s번 반복하기", + "create.recipe.assembly.junk": "조립 실패한 조각들", "create.recipe.processing.chance": "%1$s%% 확률", "create.recipe.heat_requirement.none": "열이 필요하지 않음", - "create.recipe.heat_requirement.heated": "고온으로 가열됨", - "create.recipe.heat_requirement.superheated": "초고온으로 가열됨", + "create.recipe.heat_requirement.heated": "가열됨", + "create.recipe.heat_requirement.superheated": "초고온 가열됨", "create.generic.range": "범위", "create.generic.radius": "반지름", @@ -756,8 +839,8 @@ "create.action.discard": "삭제", "create.keyinfo.toolmenu": "메뉴 세부정보 보기", - "create.keyinfo.scrollup": "Simulate Mousewheel Up (inworld)", - "create.keyinfo.scrolldown": "Simulate Mousewheel Down (inworld)", + "create.keyinfo.scrollup": "마우스 휠을 위로 이동 (인게임에서)", + "create.keyinfo.scrolldown": "마우스 휠을 아래로 이동 (인게임에서)", "create.gui.scrollInput.defaultTitle": "옵션을 선택하세요:", "create.gui.scrollInput.scrollToModify": "스크롤로 수정하기", @@ -766,12 +849,12 @@ "create.gui.scrollInput.shiftScrollsFaster": "쉬프트-스크롤로 빨리 수정하기", "create.gui.toolmenu.focusKey": "[%1$s]를 눌러 세부정보 보기", "create.gui.toolmenu.cycle": "스크롤로 순환", - "create.gui.symmetryWand.mirrorType": "반사", - "create.gui.symmetryWand.orientation": "방위", + "create.gui.symmetryWand.mirrorType": "거울의 형태", + "create.gui.symmetryWand.orientation": "거울의 방향", - "create.symmetry.mirror.plane": "거울 모드", - "create.symmetry.mirror.doublePlane": "사각형 모드", - "create.symmetry.mirror.triplePlane": "팔각형 모드", + "create.symmetry.mirror.plane": "거울", + "create.symmetry.mirror.doublePlane": "사각형", + "create.symmetry.mirror.triplePlane": "팔각형", "create.orientation.orthogonal": "수직으로", "create.orientation.diagonal": "대각선으로", @@ -779,50 +862,37 @@ "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.title": "크리에이티브 세계편집기", + "create.gui.terrainzapper.searchDiagonal": "대각선 블록 포함", + "create.gui.terrainzapper.searchFuzzy": "물질 경계 무시", + "create.gui.terrainzapper.patternSection": "패턴", + "create.gui.terrainzapper.pattern.solid": "기본", + "create.gui.terrainzapper.pattern.checkered": "체스판", + "create.gui.terrainzapper.pattern.inversecheckered": "반전된 체스판", + "create.gui.terrainzapper.pattern.chance25": "랜덤하게 25% 채우기", + "create.gui.terrainzapper.pattern.chance50": "랜덤하게 50% 채우기", + "create.gui.terrainzapper.pattern.chance75": "랜덤하게 75% 채우기", + "create.gui.terrainzapper.placement": "설치 기준", "create.gui.terrainzapper.placement.merged": "선택한 블록에", - "create.gui.terrainzapper.placement.attached": "선택한 블록 옆에", + "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.brush.cylinder": "원기둥", + "create.gui.terrainzapper.brush.surface": "면", + "create.gui.terrainzapper.brush.cluster": "원", + "create.gui.terrainzapper.tool": "설치 방식", "create.gui.terrainzapper.tool.fill": "채우기", - "create.gui.terrainzapper.tool.place": "설치", + "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.gui.terrainzapper.tool.flatten": "다듬기", "create.terrainzapper.shiftRightClickToSet": "쉬프트-우클릭으로 모양 설정하기", - - "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.terrainzapper.usingBlock": "사용 중: %1$s", + "create.terrainzapper.leftClickToSet": "좌클릭으로 재료로 쓸 블록을 선택하세요", "create.minecart_coupling.two_couplings_max": "광산 수레는 최대 2개의 커플링만 가질 수 있습니다", "create.minecart_coupling.unloaded": "열차 일부분이 로딩되지 않은 청크에 있는 것 같습니다", @@ -831,18 +901,18 @@ "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.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.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.clock_hands": "시계침", "create.contraptions.clockwork.hour_first": "시침 먼저", "create.contraptions.clockwork.minute_first": "분침 먼저", "create.contraptions.clockwork.hour_first_24": "24시간 바늘 먼저", @@ -850,55 +920,70 @@ "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.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.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.goggles.pole_length": "축 길이:", + "create.gui.goggles.fluid_container": "액체 저장 정보:", + "create.gui.goggles.fluid_container.capacity": "용량: ", + "create.gui.assembly.exception": "이 구조물은 움직일 수 없습니다:", + "create.gui.assembly.exception.unmovableBlock": "[%1$s,%2$s,%3$s]에 움직일 수 없는 [%4$s]이(가) 있습니다.", + "create.gui.assembly.exception.chunkNotLoaded": "[%1$s,%2$s,%3$s]에 있는 블록이 로드되지 않은 청크에 있습니다.", + "create.gui.assembly.exception.structureTooLarge": "이 구조물에 너무 많은 블록이 포함되어 있습니다.\n설정된 최댓값: %1$s개", + "create.gui.assembly.exception.tooManyPistonPoles": "이 피스톤에 너무 많은 연장 축이 부착되어 있습니다.\n설정된 최댓값: %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.stressometer.no_rotation": "동력없음", "create.gui.contraptions.not_fast_enough": "이 %1$s은(는) 작동하기에 _회전 속도_가 _부족합니다_", "create.gui.contraptions.network_overstressed": "_과부하!_ _높은 피로도_ _용량_을 가진 발전기를 추가로 설치하거나 _장치 속도_를 _늦추세요_.", "create.gui.goggles.contraptions.unmovable_block": "움직일 수 없는 블록: (%d, %d, %d)의 \"%s\"", - "create.gui.adjustable_crate.title": "가변 창고 ", + "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": "지시", + "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": "피스톤", + "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.wait": "정지", - "create.gui.sequenced_gearshift.instruction.wait.duration": "지속시간", - "create.gui.sequenced_gearshift.instruction.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": "새 레드스톤 신호 대기", + "create.gui.sequenced_gearshift.instruction.await": "대기", "create.gui.sequenced_gearshift.speed": "속도, 방향", - "create.gui.sequenced_gearshift.speed.forward": "입력된 속도, 그대로 회전", - "create.gui.sequenced_gearshift.speed.forward_fast": "입력된 속도의 2배, 그대로 회전", - "create.gui.sequenced_gearshift.speed.back": "입력된 속도, 반대로 회전", - "create.gui.sequenced_gearshift.speed.back_fast": "입력된 속도의 2배, 반대로 회전", + "create.gui.sequenced_gearshift.speed.forward": "입력 속도, 그대로 회전", + "create.gui.sequenced_gearshift.speed.forward_fast": "입력 속도의 2배, 그대로 회전", + "create.gui.sequenced_gearshift.speed.back": "입력 속도, 반대로 회전", + "create.gui.sequenced_gearshift.speed.back_fast": "입력 속도의 2배, 반대로 회전", - "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.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": "My Schematic", + "create.schematicAndQuill.saved": "%1$s으(로) 저장했습니다", "create.schematic.invalid": "[!] 없는 아이템 - 청사진 테이블을 이용하세요", "create.schematic.position": "위치", @@ -917,12 +1002,12 @@ "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.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": "청사진을 수직 이동시킵니다.", @@ -934,7 +1019,7 @@ "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.1": "[우클릭]으로 현재 지점에 설치합니다.", "create.schematic.tool.print.description.2": "이 도구는 크리에이티브 모드 전용입니다.", "create.schematic.tool.print.description.3": "", "create.schematic.tool.flip.description.0": "당신이 보는 면으로 청사진을 뒤집습니다.", @@ -944,7 +1029,7 @@ "create.schematics.synchronizing": "동기화 중...", "create.schematics.uploadTooLarge": "청사진이 너무 큽니다!.", - "create.schematics.maxAllowedSize": "최대 청사진 파일 크기는:", + "create.schematics.maxAllowedSize": "최대 청사진 파일 크기:", "create.gui.schematicTable.title": "청사진 테이블", "create.gui.schematicTable.refresh": "파일 새로고침", @@ -954,7 +1039,7 @@ "create.gui.schematicTable.uploading": "업로딩 중...", "create.gui.schematicTable.finished": "업로드 완료!", "create.gui.schematicannon.title": "청사진 대포", - "create.gui.schematicannon.listPrinter": "재료 목록 프린터", + "create.gui.schematicannon.listPrinter": "재료 목록 인쇄", "create.gui.schematicannon.gunpowderLevel": "화약 용량 %1$s%%", "create.gui.schematicannon.shotsRemaining": "남은 발포 수 : %1$s", "create.gui.schematicannon.shotsRemainingWithBackup": "화약 여분: %1$s", @@ -975,16 +1060,16 @@ "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.gui.schematicannon.option.replaceWithEmpty.description": "대포가 작업구역의 블록들을 제거합니다.", "create.schematicannon.status.idle": "휴식", "create.schematicannon.status.ready": "준비됨", - "create.schematicannon.status.running": "가동 중", + "create.schematicannon.status.running": "작동 중", "create.schematicannon.status.finished": "완료", - "create.schematicannon.status.paused": "멈춤", + "create.schematicannon.status.paused": "일시 중지", "create.schematicannon.status.stopped": "중단됨", "create.schematicannon.status.noGunpowder": "화약이 부족함", - "create.schematicannon.status.targetNotLoaded": "블록이 준비되지 않음", + "create.schematicannon.status.targetNotLoaded": "목표가 없음", "create.schematicannon.status.targetOutsideRange": "목표가 너무 멀리 떨어져 있습니다.", "create.schematicannon.status.searching": "검색 중", "create.schematicannon.status.skipping": "건너뛰는 중", @@ -995,6 +1080,9 @@ "create.schematicannon.status.schematicNotPlaced": "청사진이 전개되지 않음", "create.schematicannon.status.schematicExpired": "청사진 파일이 제거됨", + "create.materialChecklist": "재료 목록", + "create.materialChecklist.blocksNotLoaded": "* 경고 *\n\n관련된 청크가 불러와지지 않아 재료 목록이 부정확할 수 있습니다.", + "create.gui.filter.blacklist": "블랙리스트", "create.gui.filter.blacklist.description": "위 목록에 맞지않는 아이템이면 통과합니다. 빈 블랙리스트는 모두 통과시킵니다.", "create.gui.filter.whitelist": "화이트리스트", @@ -1036,24 +1124,57 @@ "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.shulker_level": "셜커가 %1$s있음", + "create.item_attributes.shulker_level.inverted": "셜커가 %1$s있지 않음", + "create.item_attributes.shulker_level.full": "가득 차", + "create.item_attributes.shulker_level.empty": "비어", + "create.item_attributes.shulker_level.partial": "조금 차", + "create.item_attributes.has_enchant": "%1$s 마법부여를 가지고 있음", + "create.item_attributes.has_enchant.inverted": "%1$s 마법부여를 가지고 있지 않음", + "create.item_attributes.color": "염색됨", + "create.item_attributes.color.inverted": "염색되지 않음", + "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.whitelist_disjunctive": "화이트리스트 (최소)", - "create.gui.attribute_filter.whitelist_disjunctive.description": "아이템이 선택된 속성 중 하나라도 가지고 있다면 통과시킵니다.", - "create.gui.attribute_filter.whitelist_conjunctive": "화이트리스트 (모두)", - "create.gui.attribute_filter.whitelist_conjunctive.description": "아이템이 선택된 속성 모두를 가지고 있어야 통과시킵니다.", - "create.gui.attribute_filter.blacklist": "블랙리스트", - "create.gui.attribute_filter.blacklist.description": "아이템이 선택된 속성이 없다면 통과시킵니다.", + "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.holdForDescription": "[%1$s]을 눌러 설명 보기", + "create.tooltip.holdForControls": "[%1$s]을 눌러 조작법 보기", "create.tooltip.keyShift": "Shift", "create.tooltip.keyCtrl": "Ctrl", - "create.tooltip.speedRequirement": "회전속도 요구: %1$s", + "create.tooltip.speedRequirement": "요구 회전속도: %1$s", "create.tooltip.speedRequirement.none": "없음", "create.tooltip.speedRequirement.medium": "보통", "create.tooltip.speedRequirement.high": "빠름", @@ -1061,50 +1182,79 @@ "create.tooltip.stressImpact.low": "낮음", "create.tooltip.stressImpact.medium": "보통", "create.tooltip.stressImpact.high": "높음", - "create.tooltip.stressImpact.overstressed": "과부하됨", + "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.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.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.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.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.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.tooltip.brass_tunnel.contains": "분배 중인 아이템:", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "우클릭하여 회수", + "create.linked_controller.bind_mode": "연결 모드 활성화", + "create.linked_controller.press_keybind": "%1$s, %2$s, %3$s, %4$s, %5$s, %6$s 중 하나를 눌러 이 주파수를 해당 조작키에 연결하세요", + "create.linked_controller.key_bound": "%1$s에 주파수가 연결되었습니다", + "create.linked_controller.frequency_slot_1": "조작키: %1$s, 주파수 #1", + "create.linked_controller.frequency_slot_2": "조작키: %1$s, 주파수 #2", + + "create.crafting_blueprint.crafting_slot": "재료 슬롯", + "create.crafting_blueprint.filter_items_viable": "필터도 가능합니다", + "create.crafting_blueprint.display_slot": "전시 슬롯", + "create.crafting_blueprint.inferred": "실제 조합법과 같음", + "create.crafting_blueprint.manually_assigned": "직접 지정함", + "create.crafting_blueprint.secondary_display_slot": "두번째 전시 슬롯", + "create.crafting_blueprint.optional": "추가적", + + "create.potato_cannon.ammo.attack_damage": "%1$s 공격 피해", + "create.potato_cannon.ammo.reload_ticks": "%1$s 재장전 틱", + "create.potato_cannon.ammo.knockback": "%1$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.horizontal_funnel.title": "깔때기가 수평임", - "create.hint.horizontal_funnel": "깔때기는 더이상 아이템을 _직접_ 이동시킬 수 없습니다. _벨트나 아이템 거치대_위에 깔때기를 설치하여 아이템을 이동시키세요.", - "create.hint.upward_funnel.title": "깔때기가 위를 바라보고 있음", - "create.hint.upward_funnel": "_기계 팔_, 선풍기가 부착된 _슈트_를 이용하거나, 혹은 아이템이 _던져져야만_ 이동시킬 수 있습니다. 아이템을 _수직으로_ 옮기고 싶다면 _슈트_를 사용해보세요.", - "create.hint.empty_bearing.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": "UNLOCALIZED: Hi :)", "create.gui.config.overlay2": "UNLOCALIZED: This is a sample overlay", @@ -1123,16 +1273,46 @@ "create.command.killTPSCommand.status.usage.1": "[Create]: use /killtps start to artificially slow down the server tick", "create.command.killTPSCommand.argument.tickTime": "tickTime", - "create.subtitle.schematicannon_launch_block": "청사진 대포가 발포함", + "create.contraption.minecart_contraption_too_big": "이 수레 구조물은 들기에 너무 큽니다", + "create.contraption.minecart_contraption_illegal_pickup": "신비로운 힘이 이 수레 구조물을 세계에 묶어두고 있습니다", + + "_": "->------------------------] Subtitles [------------------------<-", + + "create.subtitle.contraption_disassemble": "구조물이 멈춤", + "create.subtitle.peculiar_bell_use": "황동 종이 울림", + "create.subtitle.mixing": "섞는 소리", + "create.subtitle.mechanical_press_activation_belt": "압착기가 작동함", + "create.subtitle.fwoomp": "감자포를 쏨", + "create.subtitle.worldshaper_place": "세계편집기가 쏨", + "create.subtitle.crushing_1": "분쇄되는 소리", + "create.subtitle.depot_slide": "아이템이 미끄러짐", + "create.subtitle.saw_activate_stone": "톱이 작동함", + "create.subtitle.blaze_munch": "블레이즈 버너가 섭취함", + "create.subtitle.funnel_flap": "퍼널이 펄럭거림", "create.subtitle.schematicannon_finish": "청사진 대포가 끝남", + "create.subtitle.haunted_bell_use": "귀신들린 종이 울림", + "create.subtitle.scroll_value": "스크롤 소리", + "create.subtitle.crafter_craft": "조합기가 조합함", + "create.subtitle.controller_put": "조작기를 놓음", + "create.subtitle.cranking": "크랭크가 돌아감", + "create.subtitle.wrench_remove": "장치가 부숴짐", + "create.subtitle.cogs": "톱니바퀴가 돌아감", "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": "블레이즈가 행복하게 섭취함", + "create.subtitle.wrench_rotate": "렌치를 사용함", + "create.subtitle.potato_hit": "채소가 부딫힘", + "create.subtitle.saw_activate_wood": "톱이 작동함", + "create.subtitle.haunted_bell_convert": "종에 귀신이 들림", + "create.subtitle.deployer_polish": "배포기가 윤나게 함", + "create.subtitle.deny": "취소음", + "create.subtitle.controller_click": "조작기를 누름", + "create.subtitle.schematicannon_launch_block": "청사진 대포가 발사함", + "create.subtitle.copper_armor_equip": "잠수용 장비가 철커덕거림", + "create.subtitle.controller_take": "독서대가 비워짐", + "create.subtitle.mechanical_press_activation": "압착기가 작동함", + "create.subtitle.contraption_assemble": "구조물이 움직임", + "create.subtitle.crafter_click": "조합기가 작동함", + "create.subtitle.depot_plop": "아이템이 놓임", + "create.subtitle.confirm": "확인음", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1146,170 +1326,22 @@ "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": "ENCASED FLUID PIPE", - "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.fluid_pipe.tooltip": "FLUID PIPE", - "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": "HOSE PULLEY", - "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": "FLUID TANK", - "block.create.fluid_tank.tooltip.summary": "당신이 좋아하는 _액체_를 모두 _저장_하세요. 넓이와 높이를 조정할 수 있습니다.", - "block.create.fluid_tank.tooltip.condition1": "렌치로 우클릭", - "block.create.fluid_tank.tooltip.behaviour1": "창문 설정을 변경합니다.", - - "block.create.creative_fluid_tank.tooltip": "CREATIVE FLUID TANK", - "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": "FLUID VALVE", - "block.create.fluid_valve.tooltip.summary": "파이프 속 액체의 흐름을 멈춥니다.", - "block.create.fluid_valve.tooltip.condition1": "설정가능한 흐름", - "block.create.fluid_valve.tooltip.behaviour1": "_회전력_은 밸브를 닫게만들어, 액체의 흐름을 _중지_시킵니다. _반대_ _방향의_ 회전력은 밸브를 다시 엽니다.", - - "block.create.mechanical_pump.tooltip": "MECHANICAL PUMP", - "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": "SMART FLUID PIPE", - "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": "SPOUT", - "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": "ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "액체 용기를 _비우기위해_ 철창을 붙인 아이템 거치대입니다.", - "block.create.item_drain.tooltip.condition1": "액체 수송", - "block.create.item_drain.tooltip.behaviour1": "_양동이나 병같은_ 액체 용기가 옆에서 들어오면, 배수구는 자신의 용기에 액체를 _쏟아낼_ 것입니다. 아이템은 반대편으로 배출됩니다.", - - "block.create.mechanical_arm.tooltip": "MECHANICAL ARM", - "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": "_기계_ _팔_이 아이템을 _놓을_ _패턴_을 설정합니다.", - - "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": "SEAT", - "block.create.seat.tooltip.summary": "앉아서 드라이브를 즐기세요! _움직이는 장치_에 _플레이어_를 _고정_시킵니다. 가구용으로도 좋습니다! 다양한 색깔이 존재합니다.", + "block.create.seat.tooltip.summary": "앉아서 드라이브를 즐기세요! _움직이는 구조물_에 _플레이어_를 _고정_시킵니다. 가구용으로도 좋습니다! 다양한 색깔이 존재합니다.", "block.create.seat.tooltip.condition1": "좌석에 우클릭", "block.create.seat.tooltip.behaviour1": "플레이어가 좌석에 _앉습니다_. _왼쪽 쉬프트_를 눌러 좌석에서 _일어섭니다_.", - "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": "EMPTY BLAZE BURNER", - "item.create.empty_blaze_burner.tooltip.summary": "불타는 친구를 위한 작은 집입니다. 그들을 _좋은 곳_에 쓸 수 있을 겁니다.", - "item.create.empty_blaze_burner.tooltip.condition1": "블레이즈나 블레이즈 스포너에 사용했을 때", - "item.create.empty_blaze_burner.tooltip.behaviour1": "블레이즈를 _포획_합니다.", + "item.create.blaze_cake.tooltip.summary": "열심히 일하는 _블레이즈_ _버너_의 식사입니다. 블레이즈를 더 뜨겁게 만드세요!", "item.create.wand_of_symmetry.tooltip": "SYMMETRY WAND", - "item.create.wand_of_symmetry.tooltip.summary": "설정된 반사 모드에 따라 블록 설치를 _똑같이_ _재현_합니다.", + "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": "땅에다 우클릭", @@ -1319,15 +1351,6 @@ "item.create.wand_of_symmetry.tooltip.control3": "웅크린 상태에서 우클릭", "item.create.wand_of_symmetry.tooltip.action3": "_설정_ _창_을 엽니다.", - "item.create.handheld_blockzapper.tooltip": "BLOCKZAPPER", - "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": "_설정_ _창_을 엽니다.", - "item.create.handheld_worldshaper.tooltip": "HANDHELD WORLDSHAPER", "item.create.handheld_worldshaper.tooltip.summary": "_지형경관_을 만들 때 좋은 간편한 도구입니다.", "item.create.handheld_worldshaper.tooltip.control1": "블록을 보고 좌클릭", @@ -1342,16 +1365,22 @@ "item.create.tree_fertilizer.tooltip.condition1": "묘목에 사용했을 때", "item.create.tree_fertilizer.tooltip.behaviour1": "묘목을 주위 공간과 _상관없이_ 성장시킵니다.", - "item.create.deforester.tooltip": "DEFORESTER", - "item.create.deforester.tooltip.summary": "수 초 만에 나무를 쓰러뜨리는 _놀라운_ _도끼_입니다.", - "item.create.extendo_grip.tooltip": "EXTENDO GRIP", "item.create.extendo_grip.tooltip.summary": "띠요오옹! 사용자의 _사거리_를 늘려줍니다.", "item.create.extendo_grip.tooltip.condition1": "다른 손에 있을 때", "item.create.extendo_grip.tooltip.behaviour1": "_기존_ _손_에있는 아이템의 사거리를 늘립니다.", + "item.create.extendo_grip.tooltip.condition2": "구리 산소통을 착용했을 때", + "item.create.extendo_grip.tooltip.behaviour2": "_내구도_가 _소모되지_ _않고_, 탱크에서 _공기_가 _소모됩니다_.", + + "item.create.potato_cannon.tooltip": "POTATO CANNON", + "item.create.potato_cannon.tooltip.summary": "퐁! 집에서 키운 작물로 적을 처치하세요! _구리_ _산소통_의 산소로 움직일 수 있습니다.", + "item.create.potato_cannon.tooltip.condition1": "우클릭", + "item.create.potato_cannon.tooltip.behaviour1": "_인벤토리_에서 적당한 아이템을 _쏩니다_.", + "item.create.potato_cannon.tooltip.condition2": "구리 산소통을 착용했을 때", + "item.create.potato_cannon.tooltip.behaviour2": "_내구도_가 _소모되지_ _않고_, 탱크에서 _공기_가 _소모됩니다_.", "item.create.filter.tooltip": "FILTER", - "item.create.filter.tooltip.summary": "장치의 _입력_과 _출력_을 필터 _아이템_ 목록에 따라 _조정_합니다.", + "item.create.filter.tooltip.summary": "장치의 _입력_과 _출력_을 _필터_ 목록에 따라 _조정_합니다.", "item.create.filter.tooltip.condition1": "필터 슬롯에 있을 때", "item.create.filter.tooltip.behaviour1": "필터 _설정_에 따라 아이템 흐름을 _조정_합니다.", "item.create.filter.tooltip.condition2": "우클릭", @@ -1369,7 +1398,7 @@ "item.create.schematic.tooltip": "SCHEMATIC", "item.create.schematic.tooltip.summary": "세계에 구조물을 _홀로그램으로_ 불러와 지정하고 설치합니다. 지정된 홀로그램은 _청사진_ _대포_의 _작업_ _영역_이 됩니다.", - "item.create.schematic.tooltip.condition1": "들고 있을 떄", + "item.create.schematic.tooltip.condition1": "들고 있을 때", "item.create.schematic.tooltip.behaviour1": "UI의 도구로 _변경/설치_ 할 수 있습니다.", "item.create.schematic.tooltip.control1": "웅크린 상태에서 우클릭", "item.create.schematic.tooltip.action1": "정확한 _좌표_ 입력을 위한 창을 엽니다.", @@ -1388,392 +1417,72 @@ "item.create.schematic_and_quill.tooltip.action3": "선택 영역을 리셋하고 _삭제_합니다.", "block.create.schematicannon.tooltip": "SCHEMATICANNON", - "block.create.schematicannon.tooltip.summary": "장착된 청사진을 바탕으로 블록들을 _발포_합니다. _화약_을 연료로 사용하고 주변 인벤토리 공간에서 아이템을 사용합니다.", - "block.create.schematicannon.tooltip.control1": "우클릭", - "block.create.schematicannon.tooltip.action1": "창을 엽니다.", + "block.create.schematicannon.tooltip.summary": "장착된 청사진을 바탕으로 블록들을 _발포_합니다. _화약_을 연료로 사용하고 주변 보관함에서 아이템을 사용합니다.", + "block.create.schematicannon.tooltip.condition1": "우클릭", + "block.create.schematicannon.tooltip.behaviour1": "설정 창을 엽니다.", "block.create.schematic_table.tooltip": "SCHEMATIC TABLE", "block.create.schematic_table.tooltip.summary": "_빈_ _청사진_에 저장된 청사진을 불러옵니다.", "block.create.schematic_table.tooltip.condition1": "빈 청사진을 넣을 때", "block.create.schematic_table.tooltip.behaviour1": "Schematics 폴더에서 선택한 파일을 업로드합니다.", - "block.create.shaft.tooltip": "SHAFT", - "block.create.shaft.tooltip.summary": "_일직선_으로 _회전_을 전달합니다.", - - "block.create.cogwheel.tooltip": "COGWHEEL", - "block.create.cogwheel.tooltip.summary": " _일직선_이나 _옆_ _톱니바퀴_로 _회전_을 _전달_합니다.", - - "block.create.large_cogwheel.tooltip": "LARGE COGWHEEL", - "block.create.large_cogwheel.tooltip.summary": "큰 톱니바퀴입니다. 작은 톱니바퀴와 맞물렸을때, _회전 속도_가 _변합니다_.", - - "block.create.encased_shaft.tooltip": "ENCASED SHAFT", - "block.create.encased_shaft.tooltip.summary": "_일직선_으로 _회전_을 전달합니다. _벽을_ _넘어_ 회전을 보낼 때 유용합니다.", - - "block.create.gearbox.tooltip": "GEARBOX", - "block.create.gearbox.tooltip.summary": "_전후좌우_로 회전을 보냅니다. 한번 더 조합해서 설정을 바꿀 수 있습니다.", - - "block.create.gearshift.tooltip": "GEARSHIFT", - "block.create.gearshift.tooltip.summary": "연결된 축의 회전 방향을 _변경_합니다.", - "block.create.gearshift.tooltip.condition1": "레드스톤 신호를 받았을 때", - "block.create.gearshift.tooltip.behaviour1": "_출력_ 회전 방향을 _반전_시킵니다.", - - "block.create.clutch.tooltip": "CLUTCH", - "block.create.clutch.tooltip.summary": "연결된 축의 회전을 _끄고_ _킬_ 수 있습니다.", - "block.create.clutch.tooltip.condition1": "레드스톤 신호를 받았을 때", - "block.create.clutch.tooltip.behaviour1": "출력 방향 회전을 _멈춥니다_.", - - "block.create.encased_chain_drive.tooltip": "ENCASED_CHAIN_DRIVE", - "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": "ADJUSTABLE CHAIN GEARSHIFT", - "block.create.adjustable_chain_gearshift.tooltip.summary": "케이스를 씌운 벨트와 같은 역할을 가집니다. 또한 레드스톤 신호 세기에 따라 _회전_ _속도_를 _조정_할 수 있습니다.", - "block.create.adjustable_chain_gearshift.tooltip.condition1": "레드스톤 신호 설정", - "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "신호가 없다면, 인접한 벨트의 회전속도는 그대로 유지 됩니다. 최대 신호라면, 회전 속도가 정확히 2배가 됩니다. 중간 신호는 회전 속도를 1~2배 증가시킬 것입니다.", - - "item.create.belt_connector.tooltip": "BELT CONNECTOR", - "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": "GOGGLES", "item.create.goggles.tooltip.summary": "_장치 정보_를 착용자의 시야에 띄어주는 안경입니다.", "item.create.goggles.tooltip.condition1": "장착했을 때", "item.create.goggles.tooltip.behaviour1": "해당 장치의 _속도_, _피로도_, _용량_을 레벨에 따라 에 따라 색상 UI를 보여줍니다.", "item.create.goggles.tooltip.condition2": "계측기를 바라볼 때", "item.create.goggles.tooltip.behaviour2": "계측기가 연결된 네트워크의 _속도_나 _스트레스_의 자세한 정보를 보여줍니다.", + "item.create.goggles.tooltip.condition3": "액체 용기를 바라볼 때", + "item.create.goggles.tooltip.behaviour3": "_용량_이 얼마나 되는지, _어떤 액체_가 들어있는 지 알려줍니다.", - "item.create.wrench.tooltip": "WRENCH", + "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": "CREATIVE MOTOR", - "block.create.creative_motor.tooltip.summary": "회전 속도를 _조정_할 수 있는 장치입니다.", - - "block.create.water_wheel.tooltip": "WATER WHEEL", - "block.create.water_wheel.tooltip.summary": "인접한 _물의_ _흐름_에서 얻은 회전을 제공합니다.", - - "block.create.encased_fan.tooltip": "ENCASED FAN", - "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": "공기 흐름에 _액체_ 혹은 _불꽃_ 효과가 _추가_됩니다. 이는 아이템을 _공정_하는데 쓰일 수 있습니다.", + "item.create.wrench.tooltip.action2": "_장치_를 _해체_하고 _즉시_ _보관함_으로 넣습니다.", "block.create.nozzle.tooltip": "NOZZLE", - "block.create.nozzle.tooltip.summary": "덮힌 환풍기 _앞_에 붙여 환풍기의 효과를 _전방_으로 _확대_합니다.", - - "block.create.hand_crank.tooltip": "HAND CRANK", - "block.create.hand_crank.tooltip.summary": "간단한 회전력을 제공합니다. 플레이어의 _상호작용_이 필요합니다.", - "block.create.hand_crank.tooltip.condition1": "사용될 때", - "block.create.hand_crank.tooltip.behaviour1": "연결된 장치에 _회전력_을 _제공_합니다. 웅크리면 _반대로_ 회전시킵니다.", - + "block.create.nozzle.tooltip.summary": "선풍기 _앞_에 붙여 선풍기의 효과를 _전방향_으로 _확대_합니다.", + "block.create.cuckoo_clock.tooltip": "CUCKOO CLOCK", "block.create.cuckoo_clock.tooltip.summary": "_시간의_ _흐름_을 알고 공간을 _꾸미는_ 데 좋은 공예품입니다.", "block.create.cuckoo_clock.tooltip.condition1": "회전할 때", "block.create.cuckoo_clock.tooltip.behaviour1": "현재 시각을 보여주고 하루에 두 번 울립니다. 점심과 플레이어가 바로 잘 수 있는 저녁에 울립니다.", "block.create.turntable.tooltip": "TURNTABLE", - "block.create.turntable.tooltip.summary": "_회전력_으로 _멀미_를 일으킵니다.", - - "block.create.millstone.tooltip": "MILLSTONE", - "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": "CRUSHING WHEEL", - "block.create.crushing_wheel.tooltip.summary": "모든 것을 _부숴버리는_ 큰 바퀴입니다.", - "block.create.crushing_wheel.tooltip.condition1": "다른 분쇄 휠과 붙어있을 때", - "block.create.crushing_wheel.tooltip.behaviour1": "다양한 것을 _분쇄_하는 분쇄 기계를 형성합니다. 휠의 이빨이 _같은_ _속력_으로, _반대_ _방향_으로 맞물려야합니다.", - - "block.create.mechanical_press.tooltip": "MECHANICAL PRESS", - "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": "BASIN", - "block.create.basin.tooltip.summary": "믹서나 압착기와 같이 쓰이는 간편한 _아이템_ _저장소_입니다. 레드스톤 비교기와 호환됩니다.", - "block.create.basin.tooltip.condition1": "자동 배출", - "block.create.basin.tooltip.behaviour1": "벨트, 다른 대야, 아이템 거치대, 아이템 배수구와 같은 열린 인벤토리가 대야 아래 있다면, 아이템/액체 조합 결과가 자동으로 옮겨집니다. 자동화에 유용합니다.", - - "block.create.blaze_burner.tooltip": "BLAZE HEATER", - "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": "REINFORCED RAIL", - "block.create.reinforced_rail.tooltip.summary": "목재로 안정된 레일입니다. _지지대_가 _필요하지_ _않습니다_.", - - "block.create.mechanical_mixer.tooltip": "MECHANICAL MIXER", - "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": "MECHANICAL CRAFTER", - "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": "FURNACE ENGINE", - "block.create.furnace_engine.tooltip.summary": "_화로의_ _작동_을 필요로 하는 강력한 회전 동력원입니다.", - "block.create.furnace_engine.tooltip.condition1": "작동하는 화로에 붙였을 때", - "block.create.furnace_engine.tooltip.behaviour1": "붙어있는(한칸 띄어져있는) _플라이휠_에 동력을 공급합니다. _용광로_는 _두_ _배_의 화력을 냅니다.", - - "block.create.flywheel.tooltip": "FLYWHEEL", - "block.create.flywheel.tooltip.summary": "붙어있는 _화로_ _엔진_에서 생산된 힘을 안정시키고 _동력화_하는 거대한 금속 바퀴입니다. 화로 엔진으로부터 _한_ _칸_ _떨어져_ 설치해야 합니다.", - "block.create.flywheel.tooltip.condition1": "작동하는 엔진에 붙었을 때", - "block.create.flywheel.tooltip.behaviour1": "엔진의 힘에 따라 연결된 장치에 _회전력_을 제공합니다.", - - "block.create.portable_storage_interface.tooltip": "PORTABLE STORAGE INTERFACE", - "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": "PORTABLE FLUID INTERFACE", - "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": "ROTATION SPEED CONTROLLER", - "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": "MECHANICAL PISTON", - "block.create.mechanical_piston.tooltip.summary": "_피스톤_의 업그레이드 버전입니다. 회전력을 사용해 연결된 구조물을 옮깁니다. _피스톤_ _연장_ _축_을 후면에 붙여 이 장치의 사거리를 늘이거나 줄일 수 있습니다. 축이 없다면 움직이지 않습니다. _섀시_나 _슬라임_ _블록_을 붙여 일직선의 블록들을 움직일 수 있습니다.", - "block.create.mechanical_piston.tooltip.condition1": "회전될 때", - "block.create.mechanical_piston.tooltip.behaviour1": "붙어있는 구조물을 움직이기 시작합니다. 속도와 방향은 들어오는 회전 속도와 방향에 따라 달라집니다.", - - "block.create.piston_extension_pole.tooltip": "PISTON POLE", - "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": "MECHANICAL BEARING", - "block.create.mechanical_bearing.tooltip.summary": "큰 구조물을 _회전_시키거나 _바람으로부터_ 회전력을 얻습니다.", - "block.create.mechanical_bearing.tooltip.condition1": "회전될 때", - "block.create.mechanical_bearing.tooltip.behaviour1": "연결된 블록들을 돌리기 시작합니다. _섀시_나 _슬라임_ _블록_을 이용해 더 많은 블록을 움직이세요.", - - "block.create.windmill_bearing.tooltip": "WINDMILL BEARING", - "block.create.windmill_bearing.tooltip.summary": "_바람_을 _회전력으로 바꾸는 데_ 사용됩니다. 당신의 디자인을 붙이고 도는 걸 감사하세요!", - "block.create.windmill_bearing.tooltip.condition1": "우클릭했을 때", - "block.create.windmill_bearing.tooltip.behaviour1": "_붙여진 구조물_의 _회전_으로 얻어진 회전력을 제공합니다. 구조물은 _날개_나 _양털_을 포함해야합니다. _섀시, 슬라임볼, 강력 접착제_를 이용하여 여러 블록을 움직여보세요.", - - "block.create.sail_frame.tooltip": "SAIL FRAME", - "block.create.sail_frame.tooltip.summary": "유용한 건축 블록이며, _풍차 베어링_에 달아 동력을 만들 수도 있습니다.", - - "block.create.white_sail.tooltip": "SAIL", - "block.create.white_sail.tooltip.summary": "유용한 건축 블록이며, _풍차 베어링_에 달아 동력을 만들 수도 있습니다. 다양한 색깔이 있습니다.", - "block.create.white_sail.tooltip.condition1": "염료를 들고 우클릭", - "block.create.white_sail.tooltip.behaviour1": "날개의 색깔을 바꿉니다.", - - "block.create.clockwork_bearing.tooltip": "CLOCKWORK BEARING", - "block.create.clockwork_bearing.tooltip.summary": "현재 _인게임_ _시간_을 알려주는 _시침_, _분침_을 돌리는 업그레이드된 베어링입니다.", - "block.create.clockwork_bearing.tooltip.condition1": "회전될 때", - "block.create.clockwork_bearing.tooltip.behaviour1": "현재 시간에 맞춰 연결된 구조물을 _시침_으로써 돌리기 시작합니다. _다른_ _종류의_ _섀시_가 있다면, _분침_처럼 돌립니다.", - - "block.create.sequenced_gearshift.tooltip": "SEQUENCED GEARSHIFT", - "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": "CART ASSEMBLER", - "block.create.cart_assembler.tooltip.summary": "레일 위에 설치되었을 때, 지나가는 _광산_ _수레_에 연결된 구조물을 _설치/해체_합니다. [Ctrl]키를 눌러 레일 종류에 따른 작동 방법을 알아보세요.", - "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": "ROPE PULLEY", - "block.create.rope_pulley.tooltip.summary": "_수직으로_ 붙은 구조물을 움직입니다. _섀시_나 _슬라임_ _블록_을 붙여 일직선의 블록들을 움직일 수 있습니다.", - "block.create.rope_pulley.tooltip.condition1": "회전될 때", - "block.create.rope_pulley.tooltip.behaviour1": "연결된 구조물을 움직이기 시작합니다. 속도와 방향은 들어오는 회전 속도, 방향에 따라 다릅니다.", - - "block.create.linear_chassis.tooltip": "TRANSLATION CHASSIS", - "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": "SECONDARY LINEAR CHASSIS", - "block.create.secondary_linear_chassis.tooltip.summary": "다른 타입의 직선 섀시와 _이어지지_ _않는_ 두번째 종류의 직선 섀시입니다.", - - "block.create.radial_chassis.tooltip": "ROTATION CHASSIS", - "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": "MECHANICAL mechanical_drill", - "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": "MECHANICAL mechanical_harvester", - "block.create.mechanical_harvester.tooltip.summary": "중간 크기의 작물 자동화에 적합한 _작물_ _수확기_입니다. 베어링이나 기계식 피스톤으로 움직여집니다.", - "block.create.mechanical_harvester.tooltip.condition1": "움직일 때", - "block.create.mechanical_harvester.tooltip.behaviour1": "칼날에 닿는 모두 자란 작물을 수확하고 최초 성장 상태로 변경합니다.", - - "block.create.mechanical_plough.tooltip": "MECHANICAL PLOUGH", - "block.create.mechanical_plough.tooltip.summary": "다양한 용도로 쓸 수 있는 _쟁기_입니다. 기계식 피스톤, 베어링이나 기계식 피스톤으로 움직여집니다.", - "block.create.mechanical_plough.tooltip.condition1": "움직일 때", - "block.create.mechanical_plough.tooltip.behaviour1": "횃불, 눈, 레일 등 _통과되는_ 블록들을 부숩니다. 엔티티를 _해치지_ _않습니다_. _괭이_를 사용한 것처럼 땅도 갑니다.", - - "block.create.mechanical_saw.tooltip": "MECHANICAL mechanical_saw", - "block.create.mechanical_saw.tooltip.summary": "효율적인 _벌목_과 블록을 _제재_하는데 적합합니다. 베어링이나 기계식 피스톤으로 움직여집니다.", - "block.create.mechanical_saw.tooltip.condition1": "위를 바라볼 때", - "block.create.mechanical_saw.tooltip.behaviour1": "_제재_와 _석재_ _절단_ 조합법을 떨어진/투입된 아이템에 적용합니다. 결과물이 여러 종류고 필터가 적용이 되지 않았다면, 결과물은 _목록_ _순서_대로 배출됩니다.", - "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.turntable.tooltip.summary": "_동력_으로 _멀미_를 일으킵니다.", "block.create.stockpile_switch.tooltip": "stockpile_switch", - "block.create.stockpile_switch.tooltip.summary": "붙어있는 _저장소_에 들어있는 아이템을 기반으로 레드스톤 신호를 보냅니다. 필터도 제공됩니다. _비교기_와 반대로, 수량 스위치는 신호가 반전되는 _임계점_을 조절할 수 있습니다.", - "block.create.stockpile_switch.tooltip.condition1": "우클릭 할 때", - "block.create.stockpile_switch.tooltip.behaviour1": "UI를 엽니다.", + "block.create.stockpile_switch.tooltip.summary": "붙어있는 _보관함_에 들어있는 아이템을 기반으로 레드스톤 신호를 보냅니다. 필터도 제공됩니다. _비교기_와 반대로, 수량 스위치는 신호가 반전되는 _임계점_을 조절할 수 있습니다.", + "block.create.stockpile_switch.tooltip.condition1": "우클릭", + "block.create.stockpile_switch.tooltip.behaviour1": "설정 창을 엽니다.", "block.create.content_observer.tooltip": "CONTENT OBSERVER", - "block.create.content_observer.tooltip.summary": "저장소나 벨트의 아이템을 등록된 _필터_를 이용해 _탐지_합니다. _인벤토리, 벨트, 슈트_ 안에 해당 아이템을 탐지하는 동안, 레드스톤 신호를 보냅니다. _깔대기_가 해당 아이템을 수송하면, _1틱_의 레드스톤 신호를 보냅니다.", - - "block.create.redstone_link.tooltip": "REDSTONE LINK", - "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": "NIXIE TUBE", - "block.create.nixie_tube.tooltip.summary": "숫자와 문자를 나타내는 멋진 표시등입니다.", - "block.create.nixie_tube.tooltip.condition1": "레드스톤 신호를 받을 때", - "block.create.nixie_tube.tooltip.behaviour1": "_현재_ 레드스톤 _신호_ _세기_를 표시합니다.", - "block.create.nixie_tube.tooltip.condition2": "이름표를 사용할 때", - "block.create.nixie_tube.tooltip.behaviour2": "한 줄로 놓인 표시등에 _문자_를 표시합니다.", - - "block.create.redstone_contact.tooltip": "REDSTONE redstone_contact", - "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.content_observer.tooltip.summary": "보관함이나 벨트의 아이템을 등록된 _필터_를 이용해 _탐지_합니다. _보관함, 벨트, 슈트_ 안에 해당 아이템을 탐지하는 동안, 레드스톤 신호를 보냅니다. _퍼널_가 해당 아이템을 수송하면, _1틱_의 레드스톤 신호를 보냅니다.", "block.create.adjustable_crate.tooltip": "ADJUSTABLE CRATE", - "block.create.adjustable_crate.tooltip.summary": "이 저장소는 용량을 _직접_ _정할_ 수 있습니다. 아무아이템이나 최대 16스택씩 담을 수 있습니다. 레드스톤 비교기와 호환됩니다.", - "block.create.adjustable_crate.tooltip.control1": "우클릭 했을 때", - "block.create.adjustable_crate.tooltip.action1": "창을 엽니다.", + "block.create.adjustable_crate.tooltip.summary": "이 보관함는 용량을 _직접_ _정할_ 수 있습니다. 아무아이템이나 최대 16스택씩 담을 수 있습니다. 레드스톤 비교기와 호환됩니다.", + "block.create.adjustable_crate.tooltip.condition1": "우클릭", + "block.create.adjustable_crate.tooltip.behaviour1": "설정 창을 엽니다.", "block.create.creative_crate.tooltip": "THE ENDLESS CRATE", "block.create.creative_crate.tooltip.summary": "이 상자는 아무 아이템을 _무한히_ 저장합니다. 청사진 대포 옆에 놓을 시 준비물을 _전부_ 공급합니다.", "block.create.creative_crate.tooltip.condition1": "필터에 아이템을 설정할 시", "block.create.creative_crate.tooltip.behaviour1": "선택된 아이템을 _무한정_으로 _빼낼_ 수 있습니다. 대신 _들어간_ 아이템은 _삭제_됩니다.", - "block.create.deployer.tooltip": "DEPLOYER", - "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": "BRASS CASING", - "block.create.brass_casing.tooltip.summary": "다양한 용도로 쓰일 수 있는 단단한 기계 케이스입니다. 장식용으로 써도 무방합니다. _축_이나 _벨트_에 _씌울 수 있습니다_.", - - "block.create.pulse_repeater.tooltip": "PULSE REPEATER", - "block.create.pulse_repeater.tooltip.summary": "_1틱_의 레드스톤 신호를 보내는 간단한 리피터입니다.", - - "block.create.adjustable_repeater.tooltip": "FLEX REPEATER", - "block.create.adjustable_repeater.tooltip.summary": "최대 30분까지 _딜레이_를 설정할 수 있는 업그레이드된 _레드스톤_ _리피터_입니다.", - - "block.create.adjustable_pulse_repeater.tooltip": "FLEX PULSE REPEATER", - "block.create.adjustable_pulse_repeater.tooltip.summary": "최대 30분까지 _딜레이_를 설정할 수 있는 _펄스_ _리피터_입니다.", - - "block.create.analog_lever.tooltip": "ANALOG LEVER", - "block.create.analog_lever.tooltip.summary": "레드스톤 _신호_ _세기_를 자세히 _조정_할 수 있는 레버입니다.", - - "block.create.powered_toggle_latch.tooltip": "POWERED TOGGLE LATCH", - "block.create.powered_toggle_latch.tooltip.summary": "레드스톤 신호로 끄고 켤 수 있는 _레버_입니다.", - - "block.create.powered_latch.tooltip": "POWERED LATCH", - "block.create.powered_latch.tooltip.summary": "레드스톤 신호로 컨트롤 할 수 있는 _레버_입니다. 후면에서 들어오는 신호는 레버를 키고, 측면에서 들어오는 신호는 레버를 초기화합니다.", - "block.create.controller_rail.tooltip": "CONTROLLER RAIL", "block.create.controller_rail.tooltip.summary": "_광산 수레_의 _이동속도_를 _세밀하게_ _조정_할 수 있는 _양방향_ _전동 레일_입니다.", "block.create.controller_rail.tooltip.condition1": "레드스톤 신호를 받을 때", "block.create.controller_rail.tooltip.behaviour1": "_신호 세기에 따라_ 지나가는 수레를 _가속, 감속_합니다. 레드스톤 신호는 다른 방향 레일에도 전달됩니다. 두 방향레일에 다른 세기를 전달하면 중간 레일들은 두 세기 사이의 신호를 받습니다.", - "block.create.speedometer.tooltip": "SPEEDOMETER", - "block.create.speedometer.tooltip.summary": "연결된 장치의 _회전_ _속도_를 _계측_하고 _나타냅니다_. 레드스톤 비교기와 호환됩니다.", - "block.create.speedometer.tooltip.condition1": "회전될 때", - "block.create.speedometer.tooltip.behaviour1": "속도에 따라 색깔을 나타냅니다. _초록색_은 _느림_을, _파랑색_은 _보통_, _보라색_은 _빠른_ _속도_를 나타냅니다. 몇몇 장치들은 작동하기 위해 일정수준 이상의 속도가 필요합니다.", - - "block.create.stressometer.tooltip": "STRESSOMETER", - "block.create.stressometer.tooltip.summary": "연결된 네트워크의 _전체_ _피로도_ _수치_를 _계측_하고 _나타냅니다_. 레드스톤 비교기와 호환됩니다.", - "block.create.stressometer.tooltip.condition1": "회전될 때", - "block.create.stressometer.tooltip.behaviour1": "피로도에 따라 색깔을 나타냅니다. _과부화된_ _네트워크_는 움직이는 것을 멈춥니다. 과부하는 네트워크에 _추가_ _피로도_ _용량_을 가진 장치를 설치하면 해결됩니다. ", - "item.create.sand_paper.tooltip": "SAND PAPER", "item.create.sand_paper.tooltip.summary": "재료들을 _윤내는 데_ 쓰이는 거친 종이입니다. 배포기가 자동으로 쓸 수 있습니다.", "item.create.sand_paper.tooltip.condition1": "사용할 때", "item.create.sand_paper.tooltip.behaviour1": "_다른 손_에있는 아이템과 _바닥에 있는 아이템_을 윤냅니다.", - - "item.create.super_glue.tooltip": "SUPER GLUE", - "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": "BUILDERS TEA", - "item.create.builders_tea.tooltip.summary": "하루를 시작하기에 좋은 음료입니다. _ 새로운 영감_을 줍니다.", + "item.create.builders_tea.tooltip.summary": "하루를 시작하기에 좋은 음료입니다. _새로운 영감_을 줍니다.", "item.create.refined_radiance.tooltip": "REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "_흡수된_ _빛_으로 제련된 색채 혼합물입니다.", @@ -1781,13 +1490,53 @@ "item.create.shadow_steel.tooltip": "SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "_공허_에서 제련된 색채 혼합물입니다.", + "item.create.linked_controller.tooltip": "LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "_여섯_ _버튼_으로 _레드스톤_ _링크_와 연결되는 _휴대용_ _조작기_입니다.", + "item.create.linked_controller.tooltip.condition1": "우클릭", + "item.create.linked_controller.tooltip.behaviour1": "조작기를 킵니다. 조작하면서 _움직일_ _수_ _없습니다_.", + "item.create.linked_controller.tooltip.condition2": "웅크리면서 우클릭", + "item.create.linked_controller.tooltip.behaviour2": "_설정_ _창_을 엽니다.", + "item.create.linked_controller.tooltip.condition3": "레드스톤 링크 수신기에 우클릭", + "item.create.linked_controller.tooltip.behaviour3": "_연결_ _모드_를 활성화하고, _여섯_ _버튼_ 중 하나를 눌러 조작기를 주파수와 연결합니다.", + "item.create.linked_controller.tooltip.condition4": "독서대에 우클릭", + "item.create.linked_controller.tooltip.behaviour4": "조작기를 독서대에 올려놓아 쉽게 조작할 수 있습니다. (웅크리면서 우클릭으로 회수헙니다.)", + + "item.create.diving_helmet.tooltip": "DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "_구리_ _산소통_과 함께, 착용자가 물 속에서 _오랫동안_ _호흡_할 수 있게합니다.", + "item.create.diving_helmet.tooltip.condition1": "착용했을 때", + "item.create.diving_helmet.tooltip.behaviour1": "산소통에서 공기를 느리게 빨아들이며 _수중_ _호흡_ 효과를 제공합니다.", + + "item.create.copper_backtank.tooltip": "COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "공기를 옮길 수 있는 _착용가능한_ 탱크입니다.", + "item.create.copper_backtank.tooltip.condition1": "착용했을 때", + "item.create.copper_backtank.tooltip.behaviour1": "필요한 장비에 _공기_를 제공합니다.", + "item.create.copper_backtank.tooltip.condition2": "설치되고 동력으로 회전될 때", + "item.create.copper_backtank.tooltip.behaviour2": "동력 속도에 따라 _공기_를 _모읍니다_.", + + "item.create.diving_boots.tooltip": "DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "해저를 돌아다니기에 적합한 _무거운_ _부츠_ 한 켤레입니다.", + "item.create.diving_boots.tooltip.condition1": "착용했을 때", + "item.create.diving_boots.tooltip.behaviour1": "착용자는 빠르게 가라앉고 _수영_할 수 _없습니다_. 대신 물 속에서 _걷고_, _뛸_ 수 있습니다. 또한 _벨트_에 영향받지 않습니다.", + + "item.create.crafting_blueprint.tooltip": "CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "벽에 설치해 _특정_ _재료_로 더 _쉽게_ _조합_할 수 있습니다. 각 슬롯은 조합법을 나타냅니다.", + "item.create.crafting_blueprint.condition1": "빈 슬롯을 우클릭", + "item.create.crafting_blueprint.behaviour1": "_조합법_과 전시할 아이템을 설정하는 창을 엽니다.", + "item.create.crafting_blueprint.condition2": "설정된 슬롯에 우클릭", + "item.create.crafting_blueprint.behaviour2": "자신의 _인벤토리_에서 해당 슬롯의 _조합법_을 _실행_합니다. _웅크리면서_ 우클릭하면 한 번에 여러개를 조합합니다.", + "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": "_두 수레를 묶어_ 이동할 때 고정된 _거리를 유지하게_ 합니다.", - "item.create.crafter_slot_cover.tooltip": "SLOT COVER", - "item.create.crafter_slot_cover.tooltip.summary": "기계 조합기에서 _빈_ _슬롯_을 표시하기 위해 쓰입니다. 조합기들은 정사각형 모양을 형성할 필요는 없습니다. 재료가 서로 대각선인 조합법이있을 때 유용합니다.", + "block.create.peculiar_bell.tooltip": "PECULIAR BELL", + "block.create.peculiar_bell.tooltip.summary": "장식을 위한 황동 종입니다. 영혼 불꽃 위에 설치하면 _기이한_ 일이 일어난다고 합니다...", + + "block.create.haunted_bell.tooltip": "HAUNTED BELL", + "block.create.haunted_bell.tooltip.summary": "지옥의 길잃은 영혼들이 씌인 _저주받은_ 종입니다.", + "block.create.haunted_bell.tooltip.condition1": "들고 있거나 종을 울릴 때", + "block.create.haunted_bell.tooltip.behaviour1": "_적대적_ _몹_이 생성되는 _빛이_ _없는_ 자리를 표시합니다.", "create.tooltip.wip": "WIP", "create.tooltip.workInProgress": "Work in progress!", @@ -1801,5 +1550,816 @@ "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 [------------------------<-", + + "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.exit": "나가기", + "create.ponder.welcome": "분석 메뉴에 어서오세요", + "create.ponder.categories": "Create에서 둘러볼 수 있는 목록들", + "create.ponder.index_description": "아이콘을 클릭해 관련 아이템과 블록에 대해 알아볼 수 있습니다.", + "create.ponder.index_title": "분석 메뉴 제목", + "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": "구조물 장치", + "create.ponder.tag.contraption_actor.description": "움직이는 구조물에 부착되어 특정 기능을 수행하는 장치입니다.", + "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": "이동 고정장치", + "create.ponder.tag.movement_anchor.description": "부착된 구조물을 다양한 방법으로 움직이게하는 장치입니다.", + "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": "...터널은 통과하는 아이템 스택에서 1개의 아이템을 분리시킵니다.", + "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_modes.text_3": "조립기 설정에서 회전을 잠갔다면, 구조물은 회전하지 않습니다.", + + "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": "신호를 받으면, 다른 체인 드라이브에 전달되는 속도는 2배가 됩니다.", + "create.ponder.chain_gearshift.text_3": "반대로 벨트 변속기가 직접 회전을 받지 않고 있다면, 변속기의 속도는 절반이 됩니다.", + "create.ponder.chain_gearshift.text_4": "두 가지 경우에도, 같은 줄의 체인 드라이브의 속도는 변속기 속도의 2배가 됩니다.", + "create.ponder.chain_gearshift.text_5": "아날로그 레버를 사용하면, 속도 비율을 1 ~ 2배 사이로 맞출 수 있습니다.", + "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": "엔지니어의 고글로 슈트를 관찰하여 이동 방향을 확인하세요.", + "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": "큰 쪽에서 작은 쪽으로 가는 속도는 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": "크리에이티브 탱크", + "create.ponder.creative_fluid_tank.text_1": "크리에이티브 탱크는 무한히 액체를 공급합니다.", + "create.ponder.creative_fluid_tank.text_2": "액체가 든 용기로 우클릭하여 액체를 채울 수 있습니다.", + "create.ponder.creative_fluid_tank.text_3": "파이프로 탱크에서 액체를 무한히 뽑아낼 수 있습니다.", + "create.ponder.creative_fluid_tank.text_4": "크리에이티브 탱크로 들어가는 모든 액체는 사라집니다.", + + "create.ponder.creative_motor.header": "크리에이티브 모터를 이용해 동력 생산하기", + "create.ponder.creative_motor.text_1": "크리에이티브 모터는 동력을 쉽게 생산, 조절합니다.", + "create.ponder.creative_motor.text_2": "모터 후면을 스크롤해서 모터의 RPM을 조절합니다.", + + "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": "배포기로 아이템 가공하기", + "create.ponder.deployer_processing.text_1": "배포기가 적절한 아이템을 가지고 있으면, 아래 있는 아이템을 가공합니다.", + "create.ponder.deployer_processing.text_2": "가공할 아이템은 배포기 아래에 떨구거나 아이템 거치대에 올려두어야 합니다.", + "create.ponder.deployer_processing.text_3": "아이템이 벨트에 있으면...", + "create.ponder.deployer_processing.text_4": "...압착기가 알아서 아이템 이동을 멈추고 가공합니다.", + + "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.empty_blaze_burner.text_6": "그러나 장치에 쓰일 열원으로는 적합하지 않습니다.", + + "create.ponder.encased_fluid_pipe.header": "파이프에 케이스 씌우기", + "create.ponder.encased_fluid_pipe.text_1": "구리 케이스로 파이프를 꾸밀 수 있습니다.", + "create.ponder.encased_fluid_pipe.text_2": "파이프를 가려주는 것 외에도, 파이프의 방향을 고정시키는 역할도 합니다.", + "create.ponder.encased_fluid_pipe.text_3": "이 파이프는 이제 나중에 추가된 블록에 영향받지 않습니다.", + + "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": "파이프로 액체 옮기기", + "create.ponder.fluid_pipe_flow.text_1": "파이프는 한 종류의 액체만 옮깁니다.", + "create.ponder.fluid_pipe_flow.text_2": "렌치를 이용하여 직선 파이프에 창문을 달 수 있습니다.", + "create.ponder.fluid_pipe_flow.text_3": "창문이 있는 파이프는 옆에 있는 파이프와 연결되지 않습니다.", + "create.ponder.fluid_pipe_flow.text_4": "펌프를 이용하면 파이프로 액체를 옮길 수 있습니다.", + "create.ponder.fluid_pipe_flow.text_5": "처음엔 액체가 빠지지 않습니다.", + "create.ponder.fluid_pipe_flow.text_6": "액체 흐름이 이어지면, 시작 탱크에서 끝 탱크로 액체가 본격적으로 이동합니다.", + "create.ponder.fluid_pipe_flow.text_7": "이렇기 때문에, 파이프는 실질적으로 아무런 액체도 담지 않습니다.", + + "create.ponder.fluid_pipe_interaction.header": "액체 용기를 비우고 채우기", + "create.ponder.fluid_pipe_interaction.text_1": "파이프의 끝은 다양한 블록과 상호작용할 수 있습니다.", + "create.ponder.fluid_pipe_interaction.text_2": "액체를 담을 수 있는 모든 블록은 비우거나 채울 수 있습니다.", + "create.ponder.fluid_pipe_interaction.text_3": "끝 부분에 있는 액체의 원천도 흡수할 수 있으며...", + "create.ponder.fluid_pipe_interaction.text_4": "...비어있는 곳에 액체를 배출할 수도 있습니다.", + "create.ponder.fluid_pipe_interaction.text_5": "다양한 다른 블록에서도 액체를 뽑아낼 수도 있습니다.", + + "create.ponder.fluid_tank_sizes.header": "액체 탱크의 크기", + "create.ponder.fluid_tank_sizes.text_1": "액체 탱크는 여러개 연결하여 용량을 늘릴 수 있습니다.", + "create.ponder.fluid_tank_sizes.text_2": "밑면 너비는 3블록까지 늘릴 수 있습니다.", + "create.ponder.fluid_tank_sizes.text_3": "높이는 32블록까지 가능합니다.", + "create.ponder.fluid_tank_sizes.text_4": "렌치를 이용해 탱크의 창문을 닫을 수 있습니다.", + + "create.ponder.fluid_tank_storage.header": "탱크에 액체 저장하기", + "create.ponder.fluid_tank_storage.text_1": "탱크는 많은 양의 액체를 저장합니다.", + "create.ponder.fluid_tank_storage.text_2": "어느 쪽에서나 파이프로 액체를 넣고 빼낼 수 있습니다.", + "create.ponder.fluid_tank_storage.text_3": "담긴 액체의 양은 비교기로 측정할 수 있습니다.", + "create.ponder.fluid_tank_storage.text_4": "그러나 서바이벌 모드에서는 액체를 직접 빼내고 넣을 순 없습니다.", + "create.ponder.fluid_tank_storage.text_5": "대야, 아이템 배수구, 주입기를 통해 액체를 빼내거나 채울 수 있습니다.", + + "create.ponder.flywheel.header": "플라이휠로 동력 생산하기", + "create.ponder.flywheel.text_1": "플라이휠로 동력을 생산하기 위해선, 화로 엔진이 필요합니다.", + "create.ponder.flywheel.text_2": "플라이휠은 피로도 용량이 매우 높습니다.", + "create.ponder.flywheel.text_3": "용광로를 사용하면 동력 속도가 2배가 됩니다.", + + "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": "용광로를 사용하면 동력 속도가 2배가 됩니다.", + + "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": "호스 도르래로 액체 채우고 비우기", + "create.ponder.hose_pulley.text_1": "호스 도르래는 많은 양의 액체를 채우거나 비울 수 있습니다.", + "create.ponder.hose_pulley.text_2": "동력을 전달하여 호스의 높이를 정합니다.", + "create.ponder.hose_pulley.text_3": "동력 방향이 반전되면 호스는 올라갑니다.", + "create.ponder.hose_pulley.text_4": "반대쪽에는 파이프를 연결할 수 있습니다.", + "create.ponder.hose_pulley.text_5": "연결된 파이프에서 호스로 전달하여 액체를 채우거나...", + "create.ponder.hose_pulley.text_6": "...반대 방향으로 방향을 바꿔 액체를 비울 수 있습니다.", + "create.ponder.hose_pulley.text_7": "호스의 채우거나 비우는 속도는 펌프 속도에 기반합니다.", + + "create.ponder.hose_pulley_infinite.header": "매우 많은 양의 액체를 채우고 비우기", + "create.ponder.hose_pulley_infinite.text_1": "넓은 바다에서 호스 도르래를 작동시키면...", + "create.ponder.hose_pulley_infinite.text_2": "...물 블록을 없애거나 추가하지 않고 액체를 얻거나 버릴 수 있습니다.", + "create.ponder.hose_pulley_infinite.text_3": "파이프로 이런 도르래에서 무한한 액체를 얻을 수 있습니다.", + + "create.ponder.hose_pulley_level.header": "호스 도르래의 채우고 비우는 기준", + "create.ponder.hose_pulley_level.text_1": "호스가 완전히 올라가 있을 때, 도르래는 작동하지 않습니다.", + "create.ponder.hose_pulley_level.text_2": "맨 위부터 비웁니다.", + "create.ponder.hose_pulley_level.text_3": "호스 끝부분 아래의 액체는 그대로 남습니다.", + "create.ponder.hose_pulley_level.text_4": "맨 아래부터 채웁니다.", + "create.ponder.hose_pulley_level.text_5": "호스 끝부분 위는 채우지 않습니다.", + + "create.ponder.item_drain.header": "아이템 배수구로 액체 비우기", + "create.ponder.item_drain.text_1": "배수구는 아이템에서 액체를 비웁니다.", + "create.ponder.item_drain.text_2": "우클릭하여 손에 든 아이템에서 액체를 붓습니다.", + "create.ponder.item_drain.text_3": "아이템이 옆에서 들어온다면...", + "create.ponder.item_drain.text_4": "...아이템은 굴라가며 담긴 액체를 비웁니다.", + "create.ponder.item_drain.text_5": "배수구 탱크에 있는 액체는 파이프로 옮길 수 있습니다.", + + "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": "펌프를 이용해 액체 옮기기", + "create.ponder.mechanical_pump_flow.text_1": "펌프는 연결된 파이프속 흐름을 관리합니다.", + "create.ponder.mechanical_pump_flow.text_2": "동력을 전달받으면 화살표가 흐름의 방향을 알려줍니다.", + "create.ponder.mechanical_pump_flow.text_3": "화살표 뒤의 파이프는 액체를 뽑아내고...", + "create.ponder.mechanical_pump_flow.text_4": "...화살표 앞의 파이프는 액체를 밀어냅니다.", + "create.ponder.mechanical_pump_flow.text_5": "동력 방향을 반전시키면 흐름의 방향도 반전됩니다.", + "create.ponder.mechanical_pump_flow.text_6": "렌치로 펌프 방향 자체를 돌릴 수도 있습니다.", + + "create.ponder.mechanical_pump_speed.header": "펌프의 처리율", + "create.ponder.mechanical_pump_speed.text_1": "동력 속도와는 상관없이 펌프는 16블록 길이의 파이프까지 영향을 미칩니다.", + "create.ponder.mechanical_pump_speed.text_2": "동력 속도를 높이면 액체가 흐르는 속도가 높아지고...", + "create.ponder.mechanical_pump_speed.text_3": "...옮기는 액체의 양도 증가합니다.", + "create.ponder.mechanical_pump_speed.text_4": "펌프는 병렬로 설치할 수 있습니다.", + "create.ponder.mechanical_pump_speed.text_5": "펌프 방향을 바꾸어 흐름의 뱡향을 통일할 수 있습니다.", + + "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.nixie_tube.text_3": "염료를 들고 우클릭하여 색을 바꿀 수 있습니다.", + + "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_fluid_interface.header": "구조물 장치의 액체 교환", + "create.ponder.portable_fluid_interface.text_1": "액체 인터페이스는 장치를 멈추지 않아도 탱크와 상호작용할 수 있습니다.", + "create.ponder.portable_fluid_interface.text_3": "두 번째 인터페이스를 1~2 블록 띄우고 설치하세요.", + "create.ponder.portable_fluid_interface.text_4": "서로를 마주칠 때마다, 접속을 시도합니다.", + "create.ponder.portable_fluid_interface.text_5": "접속한 상태에서, 블록 상태의 인터페이스는 장치의 모든 탱크와 동일합니다.", + "create.ponder.portable_fluid_interface.text_6": "액체를 넣을 수도 있고...", + "create.ponder.portable_fluid_interface.text_7": "...장치에서 액체를 뺄 수도 있습니다.", + "create.ponder.portable_fluid_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": "레드스톤 토글 걸쇠 사용하기", + "create.ponder.powered_toggle_latch.text_1": "레드스톤 토글 걸쇠는 설정 가능한 레버입니다.", + "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": "펄스 중계기는 어느 레드스톤 신호라도 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": "스크롤하여 톱니바퀴에 전달되는 RPM을 조절합니다.", + + "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": "스마트 파이프를 통한 액체 필터", + "create.ponder.smart_pipe.text_1": "스마트 파이프는 필터 기능이 있는 파이프입니다.", + "create.ponder.smart_pipe.text_2": "비울 곳에다 설치하면, 어떤 액체를 뽑아낼지 설정할 수 있습니다.", + "create.ponder.smart_pipe.text_3": "필터 슬롯에 원하는 액체가 담긴 용기를 우클릭하면 됩니다.", + "create.ponder.smart_pipe.text_4": "다른 곳에 설치하면, 스마트 파이프는 맞는 액체만 통과시킵니다.", + + "create.ponder.speedometer.header": "속도 계측기를 통한 정보 확인", + "create.ponder.speedometer.text_1": "속도 계측기는 연결된 장치의 속도를 표시합니다.", + "create.ponder.speedometer.text_2": "고글을 장착하면, 세부 정보를 확인할 수 있습니다.", + "create.ponder.speedometer.text_3": "속도 계측기의 측정값에 따라 비교기가 레드스톤 신호를 내보냅니다.", + + "create.ponder.spout_filling.header": "주입기로 아이템에 액체 채우기", + "create.ponder.spout_filling.text_1": "주입기는 아래있는 아이템을 액체를 채웁니다.", + "create.ponder.spout_filling.text_2": "주입기 탱크는 직접 건드릴 수 없습니다.", + "create.ponder.spout_filling.text_3": "대신, 파이프로 액체를 공급할 수는 있습니다.", + "create.ponder.spout_filling.text_4": "주입기 아래 아이템 거치대에 아이템을 놓아, 액체를 채울 수 있습니다.", + "create.ponder.spout_filling.text_5": "아이템이 벨트에 있으면...", + "create.ponder.spout_filling.text_6": "...주입기가 알아서 아이템 이동을 멈추고 가공합니다.", + + "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": "고글을 장착하면, 세부 정보를 확인할 수 있습니다.", + "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": "밸브로 흐름 조절하기", + "create.ponder.valve_pipe.text_1": "밸브는 파이프 속 액체 흐름을 조절합니다.", + "create.ponder.valve_pipe.text_2": "밸브의 축으로 액체가 통과할 수 있는지 조절합니다.", + "create.ponder.valve_pipe.text_3": "동력을 제공하면 밸브가 열립니다.", + "create.ponder.valve_pipe.text_4": "반대 방향으로 동력을 제공하면 밸브가 닫힙니다.", + + "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/main/resources/assets/create/lang/pt_br.json b/src/main/resources/assets/create/lang/pt_br.json index aaee8b32c..db9f40431 100644 --- a/src/main/resources/assets/create/lang/pt_br.json +++ b/src/main/resources/assets/create/lang/pt_br.json @@ -1,190 +1,298 @@ { - - "_comment": "-------------------------] GAME ELEMENTS [------------------------------------------------", - - "item.create.wand_of_symmetry": "Varinha de Simetria", - "item.create.handheld_blockzapper": "Blockzapper Portátil", - "item.create.tree_fertilizer": "Fertilizante de Árvore", - "item.create.empty_schematic": "Esquema vazio", - "item.create.andesite_alloy_cube": "Liga de Andesite", - "item.create.blaze_brass_cube": "Latão de Blaze", - "item.create.chorus_chrome_cube": "Coro Cromada", - "item.create.chromatic_compound_cube": "Composto Cromático", - "item.create.shadow_steel_cube": "Aço Sombrio", - "item.create.schematic_and_quill": "Esquema e pena", - "item.create.schematic": "Esquema", - "item.create.belt_connector": "Esteira Mecânica", - "item.create.filter": "Filtro", - "item.create.rose_quartz": "Quartzo Rosa", - "item.create.refined_rose_quartz": "Quartzo Rosa Refinado", - "item.create.refined_radiance_cube": "Esplendor Refinado", - "item.create.iron_sheet": "Placas de Ferro", - "item.create.gold_sheet": "Placas de Outro", - "item.create.propeller": "Hélice", - "item.create.flour": "Farinha de Trigo", - "item.create.dough": "Massa", - - "item.create.blazing_pickaxe": "Picareta Ardente", - "item.create.blazing_shovel": "Pá Ardente", - "item.create.blazing_axe": "Machado Ardente", - "item.create.blazing_sword": "Espada Longa Ardente", - - "item.create.shadow_steel_pickaxe": "Picareta de Aço Sombrio", - "item.create.shadow_steel_mattock": "Enxada de Aço Sombrio", - "item.create.shadow_steel_sword": "Espada de Aço Sombrio", - - "item.create.rose_quartz_pickaxe": "Picareta de Quartzo Dourado", - "item.create.rose_quartz_shovel": "Pá de Quartzo Dourado", - "item.create.rose_quartz_axe": "Machado de Quartzo Dourado", - "item.create.rose_quartz_sword": "Lamina de Quartzo Dourado", - - "block.create.cogwheel": "Roda Dentada", - "block.create.large_cogwheel": "Roda Dentada Grande", - "block.create.turntable": "Mesa giratória", - "block.create.gearbox": "Caixa de Transmissão", - "block.create.gearshift": "Câmbio", - "block.create.clutch": "Embreagem", - "block.create.shaft": "Eixo", - "block.create.encased_belt": "Esteira Revestida", - "block.create.encased_shaft": "Eixo Revestido", - "block.create.encased_fan": "Ventilador Revestida", - "block.create.motor": "Motor", - "block.create.belt": "Esteira Mecânica", - "block.create.crushing_wheel": "Roda de Moer", - "block.create.mechanical_drill": "Furadeira Mecânica", - "block.create.mechanical_harvester": "Coletor Mecânico", - "block.create.water_wheel": "Roda de Água", - "block.create.belt_support": "Suporte da Esteira", - "block.create.mechanical_press": "Prensa Mecânico", - - "block.create.sticky_mechanical_piston": "Pistão Mecânico Grudento", - "block.create.mechanical_piston": "Pistão Mecânico", - "block.create.mechanical_piston_head": "Cabeça do Pistão Mecânico", - "block.create.piston_extension_pole": "Vara de Extensão do Pistão", - "block.create.mechanical_bearing": "Rolamento Mecânico", - "block.create.linear_chassis": "Chassis de Translado", - "block.create.radial_chassis": "Chassis de Rotação", - - "block.create.redstone_contact": "Contato de Redstone", - "block.create.redstone_link": "Conexão de Redstone", - "block.create.stockpile_switch": "Disjuntor de Armazenamento", - "block.create.adjustable_crate": "adjustable_crate", - "block.create.extractor": "Extrator", - "block.create.funnel": "Funil de Esteira", - "block.create.linked_extractor": "Extrator Conectado", - "block.create.pulse_repeater": "Repetidor de Pulso", - "block.create.adjustable_repeater": "Repetidor Flex", - "block.create.belt_observer": "Observador de Esteira", - - "block.create.tiled_glass": "Vidro Entalhado", - "block.create.tiled_glass_pane": "Vidraça Entalhada", - - "block.create.window_in_a_block": "Bloco com Vidraça", + "_": "->------------------------] Game Elements [------------------------<-", + "block.create.adjustable_chain_gearshift": "Correia Ajustável", + "block.create.adjustable_crate": "Caixa Ajustável", + "block.create.adjustable_pulse_repeater": "Repetidor de Pulso Ajustável", + "block.create.adjustable_repeater": "Repetidor Ajustável", + "block.create.analog_lever": "Alavanca Analógica", + "block.create.andesite_belt_funnel": "Funil de Esteira de Andesito", "block.create.andesite_bricks": "Tijolos de Andesite", + "block.create.andesite_casing": "Revestimento de Andesito", + "block.create.andesite_funnel": "Funil de Andesito", + "block.create.andesite_pillar": "UNLOCALIZED: Andesite Pillar", + "block.create.andesite_tunnel": "Tunel de Andesito", + "block.create.basin": "Bacia", + "block.create.belt": "Esteira Mecânica", + "block.create.brass_belt_funnel": "Funil de Esteira de Latão", + "block.create.brass_block": "Bloco de Latão", + "block.create.brass_casing": "Revestimento de Latão", + "block.create.brass_encased_shaft": "Eixo Revestido com Latão", + "block.create.brass_funnel": "Funil de Latão", + "block.create.brass_tunnel": "Tunel de Latão", + "block.create.cart_assembler": "Montador de Carrinho de Mina", + "block.create.chocolate": "Chocolate", + "block.create.chute": "Calha", + "block.create.clockwork_bearing": "Rolamento de relôgio", + "block.create.clutch": "Embreagem", + "block.create.cogwheel": "Roda Dentada", + "block.create.content_observer": "Observador de Conteúdo", + "block.create.controller_rail": "Trilho Controlador", + "block.create.copper_backtank": "Tanque Traseiro de Cobre", + "block.create.copper_block": "Bloco de Cobre", + "block.create.copper_casing": "Revestimento de Cobre", + "block.create.copper_ore": "Minério de Cobre", + "block.create.copper_valve_handle": "Válvula de Cobre", + "block.create.creative_crate": "Caixa Criativa", + "block.create.creative_fluid_tank": "Tanque de Fluidos Criativo", + "block.create.creative_motor": "Motor Criativo", + "block.create.crushing_wheel": "Roda de Moer", + "block.create.cuckoo_clock": "Relógio Cuckok", + "block.create.deployer": "Implantador", + "block.create.depot": "Depósito", "block.create.diorite_bricks": "Tijolos de Diorito", - "block.create.granite_bricks": "Tijolos de Granito", - + "block.create.dolomite": "Dolomite", + "block.create.dolomite_bricks": "Tijolos de Dolomite", + "block.create.dolomite_bricks_slab": "Lajotas de Tijolos de Dolomite", + "block.create.dolomite_bricks_stairs": "Escadas de Tijolos de Dolomite", + "block.create.dolomite_bricks_wall": "Muro de Tijolos de Dolomite", + "block.create.dolomite_cobblestone": "UNLOCALIZED: Dolomite Cobblestone", + "block.create.dolomite_pillar": "Pilar de Dolomite", + "block.create.encased_chain_drive": "Correia Revestida", + "block.create.encased_fan": "Ventilador Revestida", + "block.create.encased_fluid_pipe": "Cano de Fluidos Revestido", + "block.create.fluid_pipe": "Cano de Fluido", + "block.create.fluid_tank": "Tanque de fluido", + "block.create.fluid_valve": "Válvula", + "block.create.furnace_engine": "Motor de Fornalha", "block.create.gabbro": "Gabbro", - "block.create.gabbro_stairs": "Escadas de Gabbro", - "block.create.gabbro_slab": "Lajotas de Gabbro", - "block.create.gabbro_wall": "Muro de Gabbro", - "block.create.polished_gabbro": "Gabbro Polido", "block.create.gabbro_bricks": "Tijolos de Gabbro", "block.create.gabbro_bricks_stairs": "Escadas de Tijolos de Gabbro", "block.create.gabbro_bricks_wall": "Muros de Tijolos de Gabbro", - "block.create.paved_gabbro_bricks": "Tijolos de Gabbros Pavimentados", - "block.create.paved_gabbro_bricks_slab": "Lajotas de Tijolos de Gabbros Pavimentados", - "block.create.indented_gabbro": "Ladrilho Destacado de Gabbro", - "block.create.indented_gabbro_slab": "Lajota Destacada de Gabbro", - "block.create.slightly_mossy_gabbro_bricks": "Tijolos de Gabbros Musgosos", - "block.create.mossy_gabbro_bricks": "Tijolos de Gabbros Musgosos Infestados", - - "block.create.weathered_limestone": "Calcário Resistido", - "block.create.weathered_limestone_stairs": "Escadas de Calcário Resistido", - "block.create.weathered_limestone_wall": " Muro de Calcário Resistido", - "block.create.weathered_limestone_slab": "Lajota de Calcário Resistido", - "block.create.polished_weathered_limestone": "Calcário Polido Resistido", - "block.create.polished_weathered_limestone_slab": "Lajota de Calcário Polido Resistido", - "block.create.weathered_limestone_bricks": "Tijolos de Calcário Resistido", - "block.create.weathered_limestone_bricks_stairs": "Escadas de Tijolos de Calcário Resistido", - "block.create.weathered_limestone_bricks_wall": "Muro de Tijolos de Calcário Resistido", - "block.create.weathered_limestone_bricks_slab": "Lajota de Tijolos de Calcário Resistido", - "block.create.weathered_limestone_pillar": "Pilar de Calcário Resistido", - - "block.create.dolomite_pillar": "Pilar de Dolomite", - "block.create.dolomite": "Dolomite", - "block.create.dolomite_stairs": "Escadas de Dolomite", - "block.create.dolomite_wall": "Muro de Dolomite", - "block.create.dolomite_slab": "Lajota de Dolomite", - "block.create.dolomite_bricks": "Tijolos de Dolomite", - "block.create.dolomite_bricks_wall": "Muro de Tijolos de Dolomite", - "block.create.dolomite_bricks_stairs": "Escadas de Tijolos de Dolomite", - "block.create.dolomite_bricks_slab": "Lajotas de Tijolos de Dolomite", - "block.create.polished_dolomite": "Dolomite Polido", - + "block.create.gantry_carriage": "Carruagem de Pórtico", + "block.create.gantry_shaft": "Eixo de Pórtico", + "block.create.gearbox": "Caixa de Transmissão", + "block.create.gearshift": "Câmbio", + "block.create.glass_fluid_pipe": "Cano de Fluido de Vidro", + "block.create.granite_bricks": "Tijolos de Granito", + "block.create.hand_crank": "Manivela", + "block.create.haunted_bell": "Sino assombrado", + "block.create.honey": "Mel", + "block.create.hose_pulley": "Polia de Mangueira", + "block.create.item_drain": "Dreno de Item", + "block.create.large_cogwheel": "Roda Dentada Grande", + "block.create.lectern_controller": "Controle de Atril", "block.create.limesand": "Areia Calcária", "block.create.limestone": "Calcário", - "block.create.limestone_stairs": "Escadas de Calcário", - "block.create.limestone_slab": "Lajotas de Calcário", - "block.create.limestone_wall": "Muro de Calcário", "block.create.limestone_bricks": "Tijolos de Calcário", - "block.create.limestone_bricks_stairs": "Escadas de Tijolos de Calcário", "block.create.limestone_bricks_slab": "Lajotas de Tijolos de Calcário", + "block.create.limestone_bricks_stairs": "Escadas de Tijolos de Calcário", "block.create.limestone_bricks_wall": "Muro de Tijolos de Calcário", + "block.create.limestone_pillar": "Pilar de Calcário", + "block.create.linear_chassis": "Chassis Linear", + "block.create.lit_blaze_burner": "Queimador de Blaze Acesso", + "block.create.mechanical_arm": "Braço mecânico", + "block.create.mechanical_bearing": "Rolamento mecânico", + "block.create.mechanical_crafter": "Fabricador mecânico", + "block.create.mechanical_drill": "Broca Mecânica", + "block.create.mechanical_harvester": "Coletor Mecânico", + "block.create.mechanical_mixer": "Batedeira mecânica", + "block.create.mechanical_piston": "Pistão Mecânico", + "block.create.mechanical_piston_head": "Cabeça do Pistão Mecânico", + "block.create.mechanical_plough": "Arador Mecânico", + "block.create.mechanical_press": "Prensa Mecânica", + "block.create.mechanical_pump": "Bomba Mecânica", + "block.create.mechanical_saw": "Serra Mecânica", + "block.create.millstone": "Pedra de Moer", + "block.create.minecart_anchor": "Ancóra de carrinho de Mina", + "block.create.mysterious_cuckoo_clock": "Relógio cuckoo", + "block.create.nixie_tube": "Tubo de Nixie", + "block.create.peculiar_bell": "UNLOCALIZED: Peculiar Bell", + "block.create.pink_nixie_tube": "UNLOCALIZED: Pink Nixie Tube", + "block.create.piston_extension_pole": "Vara de Extensão do Pistão", + "block.create.polished_dolomite": "Dolomite Polido", + "block.create.polished_gabbro": "Gabbro Polido", "block.create.polished_limestone": "Calcário Polido", "block.create.polished_limestone_slab": "Lajotas de Calcário Polido", - "block.create.limestone_pillar": "Pilar de Calcário", - - "block.create.schematicannon": "Esquemaannon", - "block.create.schematic_table": "Mesa de Esquematizar", - "block.create.creative_crate": "Criativador Esquemaannon", - - "block.create.cocoa_log": "Madeira de Cacao da Selva", - - "block.create.shop_shelf": "Prateleira", - - "_comment": "-------------------------] UI & MESSAGES [------------------------------------------------", - + "block.create.polished_weathered_limestone": "Calcário Polido Resistido", + "block.create.polished_weathered_limestone_slab": "Lajota de Calcário Polido Resistido", + "block.create.polished_weathered_limestone_stairs": "UNLOCALIZED: Polished Weathered Limestone Stairs", + "block.create.polished_weathered_limestone_wall": "UNLOCALIZED: Polished Weathered Limestone Wall", + "block.create.pulley_magnet": "Imã da Polia", + "block.create.pulse_repeater": "Repetidor de Pulso", + "block.create.radial_chassis": "Chassi Radial", + "block.create.redstone_contact": "Contato de Redstone", + "block.create.redstone_link": "Conexão de Redstone", + "block.create.refined_radiance_casing": "Revestimento Brilhante", + "block.create.rope": "Corda", + "block.create.rope_pulley": "Polia", + "block.create.rotation_speed_controller": "Controlador de Velocidade Rotacionalr", + "block.create.schematic_table": "Mesa de Esquema", + "block.create.schematicannon": "Canhão de Esquema", + "block.create.shadow_steel_casing": "Revestiment das Sombras", + "block.create.shaft": "Eixo", + "block.create.smart_chute": "calha Inteligente", + "block.create.smart_fluid_pipe": "Cano de Fluidos Inteligente", + "block.create.speedometer": "Velocímetro", + "block.create.sticker": "Adesivo", + "block.create.sticky_mechanical_piston": "Pistão Mecânico Grudento", + "block.create.stockpile_switch": "Disjuntor de Armazenamento", + "block.create.stressometer": "Estressómetro", + "block.create.tiled_glass": "Vidro Entalhado", + "block.create.tiled_glass_pane": "Vidraça Entalhada", + "block.create.turntable": "Mesa giratória", + "block.create.water_wheel": "Roda de Água", + "block.create.weathered_limestone": "Calcário Resistido", + "block.create.weathered_limestone_bricks": "Tijolos de Calcário Resistido", + "block.create.weathered_limestone_bricks_slab": "Lajota de Tijolos de Calcário Resistido", + "block.create.weathered_limestone_bricks_stairs": "Escadas de Tijolos de Calcário Resistido", + "block.create.weathered_limestone_bricks_wall": "Muro de Tijolos de Calcário Resistido", + "block.create.weathered_limestone_pillar": "Pilar de Calcário Resistido", + "block.create.zinc_block": "Bloco de Zinco", + "block.create.zinc_ore": "Minério de Zinco", + "enchantment.create.capacity": "Capacidade", + "enchantment.create.potato_recovery": "Recuperação de Batata", + "entity.create.contraption": "Engenhoca", + "entity.create.crafting_blueprint": "Esquema de Fabricação", + "entity.create.gantry_contraption": "Engenhoca de Pórticolo", + "entity.create.potato_projectile": "Projétil deBatata", + "entity.create.seat": "Assento", + "entity.create.stationary_contraption": "Engenhoca estacionária", + "entity.create.super_glue": "Super Cola", + "fluid.create.potion": "Poção", + "fluid.create.tea": "Chá do Construtor", + "item.create.andesite_alloy": "Liga de Andesito", + "item.create.attribute_filter": "Filtro de Atributo", + "item.create.bar_of_chocolate": "Barra de Chocolate", + "item.create.belt_connector": "Esteira Mecânica", + "item.create.blaze_cake": "Bolo de Blaze", + "item.create.blaze_cake_base": "Base do Bolo de Blaze", + "item.create.brass_hand": "Mão de Latão", + "item.create.brass_ingot": "Barra de Latão", + "item.create.brass_nugget": "Pepita de Latão", + "item.create.brass_sheet": "Chapa de Latão", + "item.create.builders_tea": "Chá do Construtor", + "item.create.chest_minecart_contraption": "Engenhoca de carrinho de mina com baú", + "item.create.chocolate_bucket": "Balde de Chocolate", + "item.create.chocolate_glazed_berries": "Baga com Cobertura de Chocolate", + "item.create.chromatic_compound": "Composto Cromático", + "item.create.cinder_flour": "Farinha de Netherrack", + "item.create.copper_backtank": "Tanque Traseiro", + "item.create.copper_ingot": "Barra de Cobre", + "item.create.copper_nugget": "Pepita de Cobre", + "item.create.copper_sheet": "Chapa de Cobre", + "item.create.crafting_blueprint": "Esquema de Fabricação", + "item.create.creative_blaze_cake": "Bolo de Blaze Criativo", + "item.create.crushed_aluminum_ore": "Minério de Alumínio Esmagado", + "item.create.crushed_brass": "Latão Esmagado", + "item.create.crushed_copper_ore": "Minério de Cobre Esmagado", + "item.create.crushed_gold_ore": "Minério de Ouro Esmagado", + "item.create.crushed_iron_ore": "Minério de Ferro Esmagado", + "item.create.crushed_lead_ore": "Minério de Chumbo Esmagado", + "item.create.crushed_nickel_ore": "Minério de Niquel Esmagado", + "item.create.crushed_osmium_ore": "Minério de Osmio Esmagado", + "item.create.crushed_platinum_ore": "Minério de Pratina Esmagado", + "item.create.crushed_quicksilver_ore": "Minério de Mercúrio Esmagado", + "item.create.crushed_silver_ore": "Minério de Prata Esmagado", + "item.create.crushed_tin_ore": "Minério de Estanho Esmagado", + "item.create.crushed_uranium_ore": "Urânio Esmagado", + "item.create.crushed_zinc_ore": "Minério de Zinco Esmagado", + "item.create.diving_boots": "Botas de Mergulhador", + "item.create.diving_helmet": "Capacete de Mergulhador", + "item.create.dough": "Massa", + "item.create.electron_tube": "Tubo de Elétron", + "item.create.empty_blaze_burner": "Queimador de Blaze Vazio", + "item.create.empty_schematic": "Esquema vazio", + "item.create.extendo_grip": "Extensão de Pegador", + "item.create.filter": "Filtro", + "item.create.furnace_minecart_contraption": "Engenhoca de Carrinho de Mina com Fornalha", + "item.create.goggles": "Óculos de Engenheiro", + "item.create.golden_sheet": "Chapa de Ouro", + "item.create.handheld_worldshaper": "Modelador de Mundo Criativo", + "item.create.honey_bucket": "Balde de Mel", + "item.create.honeyed_apple": "Maçã com Cobertura de Mel", + "item.create.incomplete_cogwheel": "Roda Dentada Incompleta", + "item.create.incomplete_large_cogwheel": "Roda Dentada Grande Incompleta", + "item.create.incomplete_precision_mechanism": "Mecanismo de Precisão", + "item.create.iron_sheet": "Chapa de Ferro", + "item.create.linked_controller": "Controle conectado", + "item.create.minecart_contraption": "Engenhoca de Carrino de Mina", + "item.create.minecart_coupling": "Acoplamento de Carrinho de Mina", + "item.create.polished_rose_quartz": "Quartzo Rosa Polido", + "item.create.potato_cannon": "Canhão de Batata", + "item.create.powdered_obsidian": "Pó de Obsidiana", + "item.create.precision_mechanism": "Mecanismo de Precisão", + "item.create.propeller": "Hélice", + "item.create.red_sand_paper": "Lixa Vermelha", + "item.create.refined_radiance": "Luz Refinada", + "item.create.rose_quartz": "Quartzo Rosa", + "item.create.sand_paper": "Lixa", + "item.create.schematic": "Esquema", + "item.create.schematic_and_quill": "Esquema e pena", + "item.create.shadow_steel": "Aço sombrio", + "item.create.super_glue": "Super Cola", + "item.create.sweet_roll": "Rolinho Doce", + "item.create.tree_fertilizer": "Fertilizante de Árvore", + "item.create.vertical_gearbox": "Caixa de Transmissão Verticla", + "item.create.wand_of_symmetry": "Varinha de Simetria", + "item.create.wheat_flour": "Farinha de trigo", + "item.create.whisk": "Batedeira", + "item.create.wrench": "Chave Inglesa", + "item.create.zinc_ingot": "Barra de Zinco", + "item.create.zinc_nugget": "Pepita de Zinco", + "_": "->------------------------] Advancements [------------------------<-", + "advancement.create.root": "Bem vindo a Create", + "advancement.create.root.desc": "É hora de construir engenhocas maravilhosas", + "advancement.create.andesite_alloy.desc": "Materiais do Create tem nomes estranhos, a liga de andesito é um deles.", + "advancement.create.its_alive": "Esta vivo!", + "advancement.create.its_alive.desc": "Assista o seu primeiro componente cinético rodar.", + "advancement.create.shifting_gears": "Mudança de marcha", + "advancement.create.shifting_gears.desc": "Conecte uma roda dentada grande com uma roda dentada pequena, permitindo você a mudar a velocidade da engenhoca.", + "advancement.create.overstressed": "Excesso de tensão", + "advancement.create.overstressed.desc": "Experience os limites da tensão.", + "advancement.create.belt": "Correia de alga", + "advancement.create.belt.desc": "Conecte dois eixos com uma esteira mecanica.", + "advancement.create.splitter_tunnel": "Divida e Conquiste", + "advancement.create.splitter_tunnel.desc": "Crie um divisor com um grupo de túneis de latão.", + "advancement.create.chute.desc": "coloque uma calha a versão vertical da esteira mecanica.", + "advancement.create.upward_chute": "Abdução aéria", + "advancement.create.upward_chute.desc": "Assista um item voar para cima numa calha com ventilador.", + "_": "->------------------------] UI & Messages [------------------------<-", "death.attack.create.crush": "%1$s foi processado pelas Rodas de Moer", + "death.attack.create.crush.player": "%1$s foi jogando numa Roda de moer por %2$s", "death.attack.create.fan_fire": "%1$s foi queimado por ar quente", + "death.attack.create.fan_fire.player": "%1$s Foi jogado num defumador por %2$s", "death.attack.create.fan_lava": "%1$s foi queimado pelo ventilador de lava", - "death.attack.create.mechanical_drill": "%1$s foi empalado pela Furadeira Mecânica", - + "death.attack.create.fan_lava.player": "U%1$s foi jogado numa fundidora por %2$s", + "death.attack.create.mechanical_drill": "%1$s foi empalado pela Broca Mecânica", + "death.attack.create.mechanical_drill.player": "%1$s foi jogado na frente de uma broca por %2$s", "create.recipe.crushing": "Moendo", - "create.recipe.splashing": "Lavando em Massa", - "create.recipe.splashing.fan": "Ventilador atras de Água corrente", - "create.recipe.smoking_via_fan": "Fumaceando em Massa", - "create.recipe.smoking_via_fan.fan": "Ventilador atras de Fogo", - "create.recipe.blasting_via_fan": "Fundindo em Massa", - "create.recipe.blasting_via_fan.fan": "Ventilador atras de Lava", + "create.recipe.fan_washing": "Lavagem em massa", + "create.recipe.fan_washing.fan": "Ventilador atrás de água", + "create.recipe.fan_smoking": "Defumação em massa", + "create.recipe.fan_smoking.fan": "Ventilador atrás de fogo", + "create.recipe.fan_blasting": "Fundição em massa", + "create.recipe.fan_blasting.fan": "entilador atrás de lava", "create.recipe.pressing": "Prensa Mecânica", - "create.recipe.blockzapper_upgrade": "Blockzapper Portátil", - "create.recipe.processing.chance": "%1$s%% de chance", - + "create.recipe.mixing": "Misturando", + "create.recipe.deploying": "Implantando", + "create.recipe.packing": "Compactando", "create.generic.range": "Área", "create.generic.radius": "Raio", + "create.generic.width": "Largura", + "create.generic.height": "Altura", + "create.generic.length": "Comprimento", "create.generic.speed": "Velocidade", "create.generic.delay": "Demorada", "create.generic.unit.ticks": "Ticks", "create.generic.unit.seconds": "Segundos", "create.generic.unit.minutes": "Minutos", - + "create.generic.unit.rpm": "RPM", + "create.generic.unit.stress": "us", + "create.generic.unit.degrees": "°", + "create.generic.unit.millibuckets": "%1$smB", + "create.generic.clockwise": "Sentido horário", + "create.generic.counter_clockwise": "Sentido anti-horário", "create.action.scroll": "Rolar", "create.action.confirm": "Confirmar", "create.action.abort": "Abortar", "create.action.saveToFile": "Salvar", "create.action.discard": "Descartar", - "create.keyinfo.toolmenu": "Menu Focal da Ferramenta", - "create.gui.scrollInput.defaultTitle": "Escolha uma Opção:", "create.gui.scrollInput.scrollToModify": "Role o mouse para Modificar", "create.gui.scrollInput.scrollToSelect": "Role o mouse para Selecionar", - "create.gui.scrollInput.shiftRolarsFaster": "Shift para rolar mais rápido", - "create.gui.toolmenu.focusKey": "Segure [%1$s] para Focar", "create.gui.toolmenu.cycle": "[SCROLL] para Circular", - "create.gui.symmetryWand.mirrorType": "Espelhar", "create.gui.symmetryWand.orientation": "Orientação", "create.symmetry.mirror.plane": "Espelhar uma vez", @@ -195,57 +303,19 @@ "create.orientation.horizontal": "Horizontal", "create.orientation.alongZ": "Através de Z", "create.orientation.alongX": "Através de X", - - "create.gui.blockzapper.title": "Blockzapper Portátil", - "create.gui.blockzapper.replaceMode": "Modo de Substituição", - "create.gui.blockzapper.searchDiagonal": "Seguir as Diagonais", - "create.gui.blockzapper.searchFuzzy": "Ignorar Material nas Bordas", - "create.gui.blockzapper.range": "Raio de Expansão", - "create.gui.blockzapper.patternSection": "Padrões", - "create.gui.blockzapper.pattern.solid": "Sólido", - "create.gui.blockzapper.pattern.checkered": "Xadrez", - "create.gui.blockzapper.pattern.inversecheckered": "Xadrez invertido", - "create.gui.blockzapper.pattern.chance25": "25% de chance", - "create.gui.blockzapper.pattern.chance50": "50% de chance", - "create.gui.blockzapper.pattern.chance75": "75% de chance", - - "create.blockzapper.usingBlock": "Usando: %1$s", - "create.blockzapper.componentUpgrades": "Melhorias do Componente:", - "create.blockzapper.component.body": "Corpo", - "create.blockzapper.component.amplifier": "Amplificador", - "create.blockzapper.component.accelerator": "Acelerador", - "create.blockzapper.component.retriever": "Retornador", - "create.blockzapper.component.scope": "Mira", - "create.blockzapper.componentTier.none": "Nada", - "create.blockzapper.componentTier.blazebrass": "Latão de Blaze", - "create.blockzapper.componentTier.choruschrome": "Coro Cromado", - "create.blockzapper.leftClickToSet": "Botão-Esquerdo em um Bloco para selecionar Material", - "create.blockzapper.empty": "Sem Blocos!", - - "create.logistics.filter": "Filtros", - "create.logistics.firstFrequência": "Freq. #1", - "create.logistics.secondFrequência": "Freq. #2", - - "create.gui.adjustable_crate.title": "adjustable_crate", + "create.gui.goggles.generator_stats": "Estatísticas do gerador:", + "create.gui.goggles.kinetic_stats": "Estatísticas cinéticas:", + "create.gui.goggles.at_current_speed": "Na velocidade atual", + "create.gui.goggles.pole_length": "Comprimento da vara:", "create.gui.adjustable_crate.storageSpace": "Espaço de Armazenamento", - "create.gui.stockpile_switch.title": "Disjuntor de Armazenamento", - "create.gui.stockpile_switch.lowerLimit": "Limite Mínimo", - "create.gui.stockpile_switch.upperLimit": "Limite Máximo", - "create.gui.stockpile_switch.startAt": "Iniciar Sinal em", - "create.gui.stockpile_switch.startAbove": "Iniciar Sinal acima de", - "create.gui.stockpile_switch.stopAt": "Parar Sinal em", - "create.gui.stockpile_switch.stopBelow": "Parar Sinal abaixo de", - "create.schematicAndQuill.dimensions": "Tamanho Esquema: %1$sx%2$sx%3$s", "create.schematicAndQuill.firstPos": "Primeira posição feita.", "create.schematicAndQuill.secondPos": "Segunda posição feita.", "create.schematicAndQuill.noTarget": "Seguro [Ctrl] para selecionar Blocos de Ar.", "create.schematicAndQuill.abort": "Seleção removida.", - "create.schematicAndQuill.prompt": "Informe um nome para o Esquema:", "create.schematicAndQuill.fallbackName": "Meu Esquema", "create.schematicAndQuill.saved": "Salvo como %1$s", - "create.schematic.invalid": "[!] Item Inválido - Use a Mesa de Desenho no lugar", "create.schematic.position": "Posição", "create.schematic.rotation": "Rotação", @@ -257,14 +327,12 @@ "create.schematic.mirror.none": "Nada", "create.schematic.mirror.frontBack": "Frente para Trás", "create.schematic.mirror.leftRight": "Esquerda para Direita", - "create.schematic.tool.deploy": "Concluir", "create.schematic.tool.move": "Mover XZ", "create.schematic.tool.movey": "Mover Y", "create.schematic.tool.rotate": "Rodar", "create.schematic.tool.print": "Imprimir", "create.schematic.tool.flip": "Virar", - "create.schematic.tool.deploy.description.0": "Move o lugar da estrutura.", "create.schematic.tool.deploy.description.1": "Botão-direito no chão para colocar.", "create.schematic.tool.deploy.description.2": "Segure [Ctrl] para selecionar em uma distância fixa.", @@ -289,19 +357,13 @@ "create.schematic.tool.flip.description.1": "Aponte para o Esquema e [CTRL]-Rolar para virá-lo.", "create.schematic.tool.flip.description.2": "", "create.schematic.tool.flip.description.3": "", - "create.schematics.synchronizing": "Sincronizando...", "create.schematics.uploadTooLarge": "Seu esquema é muito grande", "create.schematics.maxAllowedSize": "O tamanho máximo permitido para o esquema é:", - "create.gui.schematicTable.title": "Mesa de Desenho", - "create.gui.schematicTable.availableEsquemas": "Esquemas Disponíveis", - "create.gui.schematicTable.noEsquemas": "Nenhum Esquemas salvo", "create.gui.schematicTable.uploading": "Importando...", "create.gui.schematicTable.finished": "Envio Concluído!", - - "create.gui.schematicannon.title": "Esquemaannon", - "create.gui.schematicannon.settingsTitle": "Parâmetros de Posicionamento", + "create.gui.schematicannon.title": "Canhão de esquema", "create.gui.schematicannon.listPrinter": "Impressora de Lista de Materiais", "create.gui.schematicannon.gunpowderLevel": "Pólvora em %1$s%%", "create.gui.schematicannon.shotsRemaining": "Disparos faltantes: %1$s", @@ -314,21 +376,19 @@ "create.gui.schematicannon.option.replaceWithEmpty": "Substituir Sólidos com Vazio", "create.gui.schematicannon.option.skipMissing": "Pulando Blocos faltantes", "create.gui.schematicannon.option.skipTileEntities": "Proteger Entidades Entalhadas", - - "create.gui.schematicannon.option.skipMissing.description": "Se o Esquemaannon não encontrar o Bloco para colocar, ele irá continuar para a próx. Posição.", - "create.gui.schematicannon.option.skipTileEntities.description": "O Esquemaannon vai evitar substituir blocos que contêm dados como Baus.", - "create.gui.schematicannon.option.dontReplaceSolid.description": "O canhão irá nunca substituir Blocos sólidos na área em trabalho, apenas não-Sólidos e Ar.", - "create.gui.schematicannon.option.replaceWithSolid.description": "O canhão irá apenas substituir Blocos sólidos na área de trabalho, se o Esquema conter um bloco Sólido naquela posição.", - "create.gui.schematicannon.option.replaceWithAny.description": "O canhão irá substituir Blocos sólidos na área de trabalho, se o Esquema conter qualquer Bloco naquela posição.", - "create.gui.schematicannon.option.replaceWithEmpty.description": "O canhão irá limpar todos os blocos na área de trabalho, incluindo os substituídos por Ar.", - + "create.gui.schematicannon.option.skipMissing.description": "Se o Canhão de esquema não encontrar o Bloco para colocar, ele irá continuar para a próx. Posição.", + "create.gui.schematicannon.option.skipTileEntities.description": "O Canhão de esquema vai evitar substituir blocos que contêm dados como Baus.", + "create.gui.schematicannon.option.dontReplaceSolid.description": "O Canhão de esquema nunca irá substituir Blocos sólidos na área em trabalho, apenas não-Sólidos e Ar.", + "create.gui.schematicannon.option.replaceWithSolid.description": "O Canhão de esquema irá apenas substituir Blocos sólidos na área de trabalho, se o Esquema conter um bloco Sólido naquela posição.", + "create.gui.schematicannon.option.replaceWithAny.description": "O Canhão de esquema irá substituir Blocos sólidos na área de trabalho, se o Esquema conter qualquer Bloco naquela posição.", + "create.gui.schematicannon.option.replaceWithEmpty.description": "O Canhão de esquema irá limpar todos os blocos na área de trabalho, incluindo os substituídos por Ar.", "create.schematicannon.status.idle": "Ocioso", "create.schematicannon.status.ready": "Pronto", "create.schematicannon.status.running": "Trabalhando", "create.schematicannon.status.finished": "Concluído", "create.schematicannon.status.paused": "Pausado", "create.schematicannon.status.stopped": "Parada", - "create.schematicannon.status.noPólvora": "Sem Pólvora", + "create.schematicannon.status.noGunpowder": "UNLOCALIZED: Sem pólvora", "create.schematicannon.status.targetNotLoaded": "Bloco não carregado", "create.schematicannon.status.targetOutsideRange": "Alvo está muito Longe", "create.schematicannon.status.searching": "Procurando", @@ -339,14 +399,10 @@ "create.schematicannon.status.schematicInvalid": "Esquema Inválido", "create.schematicannon.status.schematicNotPlaced": "Esquema não Colocado", "create.schematicannon.status.schematicExpired": "Arquivo de Esquema Expirado", - - "create.tooltip.holdKey": "Segure [%1$s]", - "create.tooltip.holdKeyOrKey": "Segure [%1$s] or [%2$s]", "create.tooltip.keyShift": "Shift", "create.tooltip.keyCtrl": "Ctrl", - - "_comment": "-------------------------] ITEM DESCRIPTIONS [------------------------------------------------", - + "_": "->------------------------] Subtitles [------------------------<-", + "_": "->------------------------] 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": "Quando this", @@ -355,7 +411,6 @@ "item.create.example_item.tooltip.behaviour2": "You can add as many behaviours as you like", "item.create.example_item.tooltip.control1": "Quando Ctrl pressed", "item.create.example_item.tooltip.action1": "These controls are displayed.", - "item.create.wand_of_symmetry.tooltip": "VARINHA DE SIMETRIA", "item.create.wand_of_symmetry.tooltip.summary": "Espelhar perfeitamente a colocação de blocos nos planos configurados.", "item.create.wand_of_symmetry.tooltip.condition1": "Quando na Hotbar", @@ -366,36 +421,18 @@ "item.create.wand_of_symmetry.tooltip.action2": "_Remove_ o Espelho ativo", "item.create.wand_of_symmetry.tooltip.control3": "B-Direito enquanto Abaixado", "item.create.wand_of_symmetry.tooltip.action3": "Abre _Interface_ de _Configuração_", - - "item.create.handheld_blockzapper.tooltip": "BLOCKZAPPER", - "item.create.handheld_blockzapper.tooltip.summary": "Gadget imaginário para colocar ou substituir blocos a distância.", - "item.create.handheld_blockzapper.tooltip.control1": "B-Esquerdo no Bloco", - "item.create.handheld_blockzapper.tooltip.action1": "Define os blocos colocados pela ferramenta no bloco de destino.", - "item.create.handheld_blockzapper.tooltip.control2": "B-Direito em Bloco", - "item.create.handheld_blockzapper.tooltip.action2": "_Coloca_ ou _Substitui_ o bloco alvo.", - "item.create.handheld_blockzapper.tooltip.control3": "B-Direito equando Abaixado", - "item.create.handheld_blockzapper.tooltip.action3": "Abre _Interface_ de _Configuração_", - "item.create.tree_fertilizer.tooltip": "FERTILIZANTE DE ARVORE", "item.create.tree_fertilizer.tooltip.summary": "Uma combinação poderosa de minerais para tipos comuns de arvores", "item.create.tree_fertilizer.tooltip.condition1": "Quando usada em Mudas", "item.create.tree_fertilizer.tooltip.behaviour1": "Cresce Arvores independentemente das suas Regras de espaço", - - "block.create.cocoa_log.tooltip": "MADEIRA DE COCOA", - "block.create.cocoa_log.tooltip.summary": "Um tronco de selva melhorado para facilitar automação de _Sementes_ _de_ _Cacau_", - "block.create.cocoa_log.tooltip.condition1": "Quando madura", - "block.create.cocoa_log.tooltip.behaviour1": "Cresce _Vagens_ _de_ _Cacau_ em todos os lados", - "item.create.empty_schematic.tooltip": "ESQUEMA VAZIO", "item.create.empty_schematic.tooltip.summary": "Usado como ingrediente em receitas e para escrever na _Mesa_ _de_ _Esquematizar_", - "item.create.schematic.tooltip": "ESQUEMA", "item.create.schematic.tooltip.summary": "Contem uma estrutura para ser posicionada e colocada no mundo. Posicione o Holograma como desejar e use um _Esquemaannon_ para construí-lo.", "item.create.schematic.tooltip.condition1": "Quando Em mãos", "item.create.schematic.tooltip.behaviour1": "Pode ser posicionado usando as Ferramentas em Tela", "item.create.schematic.tooltip.control1": "B-Direito enquanto Abaixado", "item.create.schematic.tooltip.action1": "Abre uma _Interface_ para informar as _Coordenadas_ exatas.", - "item.create.schematic_and_quill.tooltip": "ESQUEMA E PENA", "item.create.schematic_and_quill.tooltip.summary": "Usado para salvar uma Estrutura no mundo para um arquivo .nbt.", "item.create.schematic_and_quill.tooltip.condition1": "Passo 1", @@ -408,201 +445,20 @@ "item.create.schematic_and_quill.tooltip.action2": "Selecione pontos no _meio_ _do_ _ar_. _Rolar_ para ajustar a distância.", "item.create.schematic_and_quill.tooltip.control3": "B-Direito enquanto Abaixado", "item.create.schematic_and_quill.tooltip.action3": "_Cancela_ e remove a seleção.", - - "block.create.creative_crate.tooltip": "CRIATIVADOR ESQUEMAANNON", - "block.create.creative_crate.tooltip.summary": "Provê um suprimento infinito de blocos para _Esquemaannons_ próximos", - - "block.create.schematicannon.tooltip": "ESQUEMAANNON", + "block.create.schematicannon.tooltip": "Canhão de esquema", "block.create.schematicannon.tooltip.summary": "Dispara blocos para recriar um _Esquema_ no Mundo. Usa itens de Inventários adjacentes e _Pólvora_ como combustível.", - "block.create.schematicannon.tooltip.control1": "Quando Apertado com B-Direito", - "block.create.schematicannon.tooltip.action1": "Abre a _Interface_", - "block.create.schematic_table.tooltip": "MESA DE ESQUEMATIZAR", "block.create.schematic_table.tooltip.summary": "Escreve Esquemas salvos into um _Esquema_ _Vazio_", "block.create.schematic_table.tooltip.condition1": "Quando recebe um Esquema Vazio", "block.create.schematic_table.tooltip.behaviour1": "Importa um Arquivo escolhido da sua Pasta de Esquemas", - - "block.create.shaft.tooltip": "EIXO", - "block.create.shaft.tooltip.summary": "_Transmite_ _Rotação_ em uma linha reta.", - - "block.create.cogwheel.tooltip": "RODA DENTADA", - "block.create.cogwheel.tooltip.summary": "_Transmite_ _Rotação_ em uma linha reta, e para _Rodas_ _Dentadas_ adjacentes.", - - "block.create.large_cogwheel.tooltip": "RODA DENTADA GRADE", - "block.create.large_cogwheel.tooltip.summary": "Uma versão maior da _Roda_ _Dentada,_ permitindo mudança na _Velocidade_ de _Rotação_ quando conectada a sua Contraparte.", - - "block.create.encased_shaft.tooltip": "EIXO REVESTIDO", - "block.create.encased_shaft.tooltip.summary": " _Transmite_ _Rotação_ em uma linha reta. Apropriada para propagar Rotação através de Muros.", - - "block.create.gearbox.tooltip": "CAIXA DE TRANSMISSÃO", - "block.create.gearbox.tooltip.summary": "_Transmite_ _Rotação_ em _Quatro_ _direções._ Reverte conexões diretas.", - - "block.create.gearshift.tooltip": "CÂMBIO", - "block.create.gearshift.tooltip.summary": "Um _disjuntor_ de _rotação_ controlável para eixos conectados.", - "block.create.gearshift.tooltip.condition1": "Quando Ligado", - "block.create.gearshift.tooltip.behaviour1": "_Inverte_ a rotação de saída.", - - "block.create.clutch.tooltip": "EMBREAGEM", - "block.create.clutch.tooltip.summary": "Um _disjuntor_ de _rotação_ controlável para os eixos conectados.", - "block.create.clutch.tooltip.condition1": "Quando Ligado", - "block.create.clutch.tooltip.behaviour1": "_Para_ de prover rotação para o outro lado.", - - "block.create.encased_belt.tooltip": "ESTEIRA REVESTIDA", - "block.create.encased_belt.tooltip.summary": "_Transmite_ _Rotação_ através de si e para _Esteiras_ _Revestidas_ conectadas.", - "block.create.encased_belt.tooltip.condition1": "Quando Conectadas com outra Esteira Revestida", - "block.create.encased_belt.tooltip.behaviour1": "Bloco Conectado irá ter a mesma velocidade de rotação, na mesma direção. Esteiras Conectadas não precisam estar viradas para mesma direção.", - - "item.create.belt_connector.tooltip": "ESTEIRA MECÂNICA", - "item.create.belt_connector.tooltip.summary": "Conecta dois _Eixos_ com uma _Esteira_ _Mecânica._ Eixos conectados irá ter exatamente a mesma velocidade e direção de rotação. A Esteira pode atuar como um _Transporte_ para _Entidades._", - "item.create.belt_connector.tooltip.control1": "B-Direito em um Eixo", - "item.create.belt_connector.tooltip.action1": "Seleciona o eixo como uma polia da Esteira. Os dois Eixos selecionadas precisam estar _alinhados_ seja na _Vertical,_ _Horizontal_ ou _Diagonal_ na direção da Esteira.", - "item.create.belt_connector.tooltip.control2": "B-Direito enquanto Abaixado", - "item.create.belt_connector.tooltip.action2": "_Cancela_ a seleção da Posição para a Esteira", - - "block.create.belt_support.tooltip": "SUPORTE DA ESTEIRA", - "block.create.belt_support.tooltip.summary": "Apenas um bloco decorativo para montar _Esteiras_ _Mecânicas_ no Chão.", - "block.create.belt_support.tooltip.condition1": "Quando colocado abaixo de uma Esteira", - "block.create.belt_support.tooltip.behaviour1": "Suporta o topo da Esteira, escondendo a parte de baixo.", - - "block.create.motor.tooltip": "MOTOR", - "block.create.motor.tooltip.summary": "Uma fonte de _Força_ _Rotacional_ configurável", - - "block.create.water_wheel.tooltip": "RODA DE ÁGUA", - "block.create.water_wheel.tooltip.summary": "Prove _Força_ _Rotacional_ tirada de _Correntes_ de _Água_ próximas.", - - "block.create.encased_fan.tooltip": "VENTILADO REVESTIDO", - "block.create.encased_fan.tooltip.summary": "Converte _Força_ _Rotacional_ em _Correntes_ de _Ar_ e vice-versa. Muitos usos.", - "block.create.encased_fan.tooltip.condition1": "Quando sobre Fogo", - "block.create.encased_fan.tooltip.behaviour1": "Prove _Força_ _Rotacional_ (precisa ser na vertical)", - "block.create.encased_fan.tooltip.condition2": "Quando Invertido", - "block.create.encased_fan.tooltip.behaviour2": "_Empurra_ Entidades em um lado, _Puxa_ entidades no outro. Força e Velocidade dependem da Rotação de entrada.", - "block.create.encased_fan.tooltip.condition3": "Quando ar flui através de blocos especiais", - "block.create.encased_fan.tooltip.behaviour3": "Processa itens na frente do Bloco: _Água_ alva, _Fogo_ defuma, e _Lava_ derrete o ingrediente.", - "block.create.turntable.tooltip": "MESA GIRATÓRIA", "block.create.turntable.tooltip.summary": "Muda a _Força_ _Rotacional_ em uma forma refinada de Enjoo.", - - "block.create.crushing_wheel.tooltip": "RODA DE MOER", - "block.create.crushing_wheel.tooltip.summary": "Grandes rodas giratórias que _esmagam_ qualquer coisa que impeça seu movimento.", - "block.create.crushing_wheel.tooltip.condition1": "Quando conectado a outras Rodas de Moer", - "block.create.crushing_wheel.tooltip.behaviour1": "Forma uma estrutura de esmagamento para processar uma variedade de coisas. Os Dentes da rota precisam estar conectados e se movimentando com a _mesma_ _velocidade_ em _direções_ _opostas._", - - "block.create.mechanical_press.tooltip": "PRENSA MECÂNICA", - "block.create.mechanical_press.tooltip.summary": "Um forte pistão usado para comprimir itens abaixo dele. Precisa de _Força_ _Rotacional_ constante", - "block.create.mechanical_press.tooltip.condition1": "Quando Ligado com Redstone", - "block.create.mechanical_press.tooltip.behaviour1": "_Inicia_ compressão de itens jogados abaixo dele.", - "block.create.mechanical_press.tooltip.condition2": "Quando Sobre uma Esteira Mecânica", - "block.create.mechanical_press.tooltip.behaviour2": "_Automaticamente_ comprime itens que passando na Esteira.", - - "block.create.mechanical_piston.tooltip": "PISTÃO MECÂNICO", - "block.create.mechanical_piston.tooltip.summary": "Uma verão melhorada do _Pistão,_ usando _Força_ _Rotacional_ para mover estruturas de forma precisa. _Varas_ de _Extensão_ do _Pistão_ na traseira definem o _Alcance_ deste Dispositivo. Sem extensões o pistão não se move. Use __Chassis_ de _Translado_ para mover mais de uma linha de blocos.", - "block.create.mechanical_piston.tooltip.condition1": "Quando Rodado", - "block.create.mechanical_piston.tooltip.behaviour1": "Começa a mover blocos presos na estrutura. Velocidade e direção diretamente relacionados a Velocidade Rotação de entrada.", - - "block.create.sticky_mechanical_piston.tooltip": "PISTÃO MECÂNICO GRUDENTO", - "block.create.sticky_mechanical_piston.tooltip.summary": "Uma versão melhorada do _Pistão_ _Grudento,_ usando _Força_ _Rotacional_ para mover estruturas de forma precisa. Varas_ de _Extensão_ do _Pistão_ na traseira definem o _Alcance_ deste Dispositivo. Sem extensões o pistão não se move. Use __Chassis_ de _Translado_ para mover mais de uma linha de blocos.", - "block.create.sticky_mechanical_piston.tooltip.condition1": "Quando Rodado", - "block.create.sticky_mechanical_piston.tooltip.behaviour1": "Começa a mover blocos presos na estrutura. Velocidade e direção diretamente relacionados a Velocidade Rotação de entrada.", - - "block.create.piston_extension_pole.tooltip": "VARA DE EXTENSÃO DO PISTÃO", - "block.create.piston_extension_pole.tooltip.summary": "Aumenta o alcance de _Pistões_ _Mecânicos_", - "block.create.piston_extension_pole.tooltip.condition1": "Quando preso a um Pistão Mecânico", - "block.create.piston_extension_pole.tooltip.behaviour1": "Aumenta a extensão dos pistões em 1 bloco", - - "block.create.mechanical_bearing.tooltip": "ROLAMENTO MECÂNICO", - "block.create.mechanical_bearing.tooltip.summary": "Usado para rotacionar _estruturas_ _grandes_ ou geração de _Força_ _Rotacional_ do vento.", - "block.create.mechanical_bearing.tooltip.condition1": "Quando Rodado", - "block.create.mechanical_bearing.tooltip.behaviour1": "Começa a rotacionar _Chassis_ de _Rotação_ conectados e blocos conectados a eles.", - "block.create.mechanical_bearing.tooltip.condition2": "Quando Ligado por Redstone", - "block.create.mechanical_bearing.tooltip.behaviour2": "Começa a passar _Força_ _Rotacional_ das estruturas conectadas. A estrutura dele incluir _Blocos_ de _Vela_ válidos (atualmente qualquer Bloco de Lã).", - - "block.create.linear_chassis.tooltip": "CHASSIS DE TRANSLADO", - "block.create.linear_chassis.tooltip.summary": "Uma base configurável para Estruturas serem movidas por um _Pistão_ _Mecânico._ Esses Blocos precisam formas uma camada de blocos na frente do Pistão.", - "block.create.linear_chassis.tooltip.condition1": "Quando movido por Pistão Mecânico", - "block.create.linear_chassis.tooltip.behaviour1": "_Move_ todos os _Chassis_ _conectados_ na mesma orientação, e Blocos conectados a frente dele. Quando o Pistão volta, blocos apenas serão puxados se a face do chassis for _Grudenta_ (Ver [Ctrl]).", - "block.create.linear_chassis.tooltip.control1": "Quando clicado com B-Direito com Gosma de Slime", - "block.create.linear_chassis.tooltip.action1": "Torna a face clicada _Grudenta._ Quando o pistão volta, o chassis irá _puxar_ _junto_ todos os Blocos conectados na sua coluna e no Alcance configurado.", - - "block.create.radial_chassis.tooltip": "CHASSIS DE ROTAÇÃO", - "block.create.radial_chassis.tooltip.summary": "Nessário para rotacionar estruturas om um _Rolamento_ _Mecânico._ ", - "block.create.radial_chassis.tooltip.condition1": "Quando Rotacionado por Rolamento", - "block.create.radial_chassis.tooltip.behaviour1": "_Rotaciona_ todos os blocos conectados a lados _Grudentos_ (Veja [Ctrl]) dentro do alcance configurado no seu entorno. _Propaga_ a rotação para outros Chassis de Rotação conectados.", - "block.create.radial_chassis.tooltip.control1": "Quando clicado com B-Direito com Goma de Slime", - "block.create.radial_chassis.tooltip.action1": "Torna face clicada em _Grudenta._ Quando o Chassis girar, todos os blocos conectados nesse lado irão girar junto.", - - "block.create.mechanical_drill.tooltip": "FURADEIRA MECÂNICA", - "block.create.mechanical_drill.tooltip.summary": "Um dispositivo mecânido feito para _quebrar_ _blocos._", - "block.create.mechanical_drill.tooltip.condition1": "Quando Rodado", - "block.create.mechanical_drill.tooltip.behaviour1": "Atua como um Bloco Quebrador _estacionário._ Também _machuca_ _entidades_ na sua área de efeito.", - "block.create.mechanical_drill.tooltip.condition2": "Quando Empurrado por Pistão Mecânico", - "block.create.mechanical_drill.tooltip.behaviour2": "Quebra os Blocos na direção do avanço da broca.", - - "block.create.mechanical_harvester.tooltip": "COLETOR MECÂNICO", - "block.create.mechanical_harvester.tooltip.summary": "Um cortador de plantas mecânico indicado para automação de culturas de médio porte", - "block.create.mechanical_harvester.tooltip.condition1": "Quando Empurrado por Pistão Mecânico", - "block.create.mechanical_harvester.tooltip.behaviour1": "_Colhe_ todas as _safra_ _madura_ que a lâmina passar sobre, e os retorna a estado de crescimento inicial.", - "block.create.stockpile_switch.tooltip": "DISJUNTOR DE ARMAZENAMENTO", "block.create.stockpile_switch.tooltip.summary": "Alterna um sinal de Redstone com base no _Espaço_ de _Armazenamento_ do Reciente conectado.", "block.create.stockpile_switch.tooltip.condition1": "Quando abaixo do Limite Mínimo", "block.create.stockpile_switch.tooltip.behaviour1": "Para de enviar _Sinal_ de _Redstone_", - "block.create.stockpile_switch.tooltip.condition2": "Quando acima do Limite Máximo", - "block.create.stockpile_switch.tooltip.behaviour2": "Começa a enviar _Sinal_ de _Redstone_ até chegar no Limite Mínio novamente.", - "block.create.stockpile_switch.tooltip.control1": "Quando clicado com B-Direito", - "block.create.stockpile_switch.tooltip.action1": "Abre a _Interface_ de _Configuração_", - - "block.create.redstone_link.tooltip": "CONEXÃO DE REDSTONE", - "block.create.redstone_link.tooltip.summary": "Saida para conexões _Redstone_ _Sem-Fio._ Pode ter _Frequências_ usando qualquer item. Distancia do Sinal é limitada, mas resoavelmente justa.", - "block.create.redstone_link.tooltip.condition1": "Quando Ligado", - "block.create.redstone_link.tooltip.behaviour1": "Recebendo Conexões da mesma _Frequência_ irá gerar um sinal de Redstone.", - "block.create.redstone_link.tooltip.control1": "Quando clicado com B-Direito com um Item", - "block.create.redstone_link.tooltip.action1": "Altera a _Frequência_ para aquele item. Até _dois_ _itens_ _diferentes_ podem ser combinados para definir uma Frequência.", - "block.create.redstone_link.tooltip.control2": "Quando clicado com B-Direito enquanto Abaixado", - "block.create.redstone_link.tooltip.action2": "Muda entre Modo _Receptor_ e _Transmissor_ .", - - "block.create.redstone_contact.tooltip": "CONTATO DE REDSTONE", - "block.create.redstone_contact.tooltip.summary": "Um dispositivo simples para Mecanimos de Redstone avançados.", - "block.create.redstone_contact.tooltip.condition1": "Quando apontando para outro Contato", - "block.create.redstone_contact.tooltip.behaviour1": "Provê um _Sinal_ de _Redstone_", - "block.create.redstone_contact.tooltip.condition2": "Quando movido por Pistão Mecânico", - "block.create.redstone_contact.tooltip.behaviour2": "Ativa todos os Contatos imóveis na passagem", - "block.create.adjustable_crate.tooltip": "adjustable_crate", "block.create.adjustable_crate.tooltip.summary": "Este _Recipiente_ de _Armazenamento_ permite controle Manual da sua capacidade. Pode conter até _16_ _Pilhas_ de qualquer Item", - "block.create.adjustable_crate.tooltip.control1": "Quando clicado com B-Direito", - "block.create.adjustable_crate.tooltip.action1": "Abre a _Interface_", - - "block.create.extractor.tooltip": "EXTRATOR", - "block.create.extractor.tooltip.summary": "_Pega_ _itens_ de um _Inventário_ conectado e os joga no chão. Não irá jogar Itens até o espaço ser limpo. Pode ser configurado como para ser um _filtro._", - "block.create.extractor.tooltip.condition1": "Quando Ligado por Redstone", - "block.create.extractor.tooltip.behaviour1": "_Para_ o Extractor", - "block.create.extractor.tooltip.control1": "B-Direito no Espaço de Filtro", - "block.create.extractor.tooltip.action1": "Configura a _pilha_ atualmente _presente_ como um _Filtro._ Extrator irá apenas puxar apenas _tipo_ e _quantidade_ do item filtro.", - - "block.create.linked_extractor.tooltip": "EXTRATOR CONECTADO", - "block.create.linked_extractor.tooltip.summary": "_Pega_ _itens_ de um _Inventário_ e os joga no chão. Não vai jogar Itens até que o espaço ser limpo. Pode ser configurado como para ser um _filtro._ Pode ser controlado remotamente via _Conexão_ de _Redstone._", - "block.create.linked_extractor.tooltip.condition1": "Quando Conexão de Redstone Ativa", - "block.create.linked_extractor.tooltip.behaviour1": "_Para_ o Extrator", - "block.create.linked_extractor.tooltip.control1": "B-Direito no Espaço de Filtro", - "block.create.linked_extractor.tooltip.action1": "Configura a _pilha_ atualmente _presente_ como um _Filtro._ Extrator irá apenas puxar apenas _tipo_ e _quantidade_ do item filtro.", - "block.create.linked_extractor.tooltip.control2": "B-Direito no Espaço de Frequência", - "block.create.linked_extractor.tooltip.action2": "Configura a _pilha_ atualmente _presente_ como parte da Frequência a ouvir. Quando um _Conexão_ de _Redstone_ transmissor da mesma frequência é ligado, esse Extrator irá parar.", - - "block.create.funnel.tooltip": "FUNIL DE ESTEIRA", - "block.create.funnel.tooltip.summary": "Coleta itens passando numa _Esteira_ _Mecânica_ e os insere no _Inventário_ conetado, se possível. Precisa estar diretamente _sobre_ uma Esteira, com a abertura virada contra o movimento da Esteira. O inventário precisa estar na mesma altura que o funil.", - - "block.create.belt_observer.tooltip": "OBSERVADOR DE ESTEIRA", - "block.create.belt_observer.tooltip.summary": "Detecta os itens passando numa _Esteira_ _Mecânica_ a sua frente. Funciona bem com um _Pistão_ em cima, empurrando certos itens.", - "block.create.belt_observer.tooltip.condition1": "Quando item bate com Filtro", - "block.create.belt_observer.tooltip.behaviour1": "Provê um _Pulso_ curto de _Redstone_ para todos os lados. Um Filtro vazio considera todos os itens passando.", - "block.create.belt_observer.tooltip.control1": "B-Direito em um Espaço de Filtro", - "block.create.belt_observer.tooltip.action1": "Configura a _pilha_ atualmente _presente_ como um _Filtro._ Observador irá reagir apenas a esse tipo de item.", - - "block.create.pulse_repeater.tooltip": "REPETIDOR DE PULSO", - "block.create.pulse_repeater.tooltip.summary": "Um circuito simples para cortar pulsos de Redstone até um comprimento de _1_ _tick._", - - "block.create.adjustable_repeater.tooltip": "REPETIDOR FLEX", - "block.create.adjustable_repeater.tooltip.summary": "Um um _Repetidor_ de _Redstone_ avançado com um _Delay_ _configurável_ de até 30 Minutos.", - - "itemGroup.create": "Create" -} + "block.create.creative_crate.tooltip": "Caixa Criativa", + "block.create.creative_crate.tooltip.summary": "Provê um suprimento infinito de blocos para Canho~es de Esquema próximos" +} \ No newline at end of file diff --git a/src/main/resources/assets/create/lang/ru_ru.json b/src/main/resources/assets/create/lang/ru_ru.json index d88a93c3d..3031f418d 100644 --- a/src/main/resources/assets/create/lang/ru_ru.json +++ b/src/main/resources/assets/create/lang/ru_ru.json @@ -1,5 +1,6 @@ { - + "_": "Missing Localizations: -", + "_": "->------------------------] Game Elements [------------------------<-", "block.create.acacia_window": "Акациевое окно", @@ -26,11 +27,13 @@ "block.create.basin": "Чаша", "block.create.belt": "Конвейер", "block.create.birch_window": "Берёзовое окно", - "block.create.birch_window_pane": "Панель берёзового окна", + "block.create.birch_window_pane": "Панель из берёзового окна", + "block.create.black_nixie_tube": "Чёрный газоразрядный индикатор", "block.create.black_sail": "Чёрный парус", "block.create.black_seat": "Чёрное сиденье", "block.create.black_valve_handle": "Чёрный ручной вентиль", "block.create.blaze_burner": "Горелка Всполоха", + "block.create.blue_nixie_tube": "Синий газоразрядный индикатор", "block.create.blue_sail": "Синий парус", "block.create.blue_seat": "Синее сиденье", "block.create.blue_valve_handle": "Синий ручной вентиль", @@ -40,6 +43,7 @@ "block.create.brass_encased_shaft": "Вал в латунном корпусе", "block.create.brass_funnel": "Латунная воронка", "block.create.brass_tunnel": "Латунный туннель", + "block.create.brown_nixie_tube": "Коричневый газоразрядный индикатор", "block.create.brown_sail": "Коричневый парус", "block.create.brown_seat": "Коричневое сиденье", "block.create.brown_valve_handle": "Коричневый ручной вентиль", @@ -51,12 +55,13 @@ "block.create.chiseled_scoria": "Резной пепел", "block.create.chiseled_weathered_limestone": "Выветренный резной известняк", "block.create.chocolate": "Шоколад", - "block.create.chute": "Желоб", + "block.create.chute": "Жёлоб", "block.create.clockwork_bearing": "Часовой механизм", "block.create.clutch": "Сцепление", "block.create.cogwheel": "Шестерня", - "block.create.content_observer": "Наблюдетель за содержимым", + "block.create.content_observer": "Наблюдатель за содержимым", "block.create.controller_rail": "Контролирующая рельса", + "block.create.copper_backtank": "Медный баллон", "block.create.copper_block": "Медный блок", "block.create.copper_casing": "Медный корпус", "block.create.copper_ore": "Медная руда", @@ -71,8 +76,9 @@ "block.create.crushing_wheel": "Колесо дробления", "block.create.crushing_wheel_controller": "Контроллер колеса дробления", "block.create.cuckoo_clock": "Часы с кукушкой", + "block.create.cyan_nixie_tube": "Бирюзовый газоразрядный индикатор", "block.create.cyan_sail": "Бирюзовый парус", - "block.create.cyan_seat": "Бирюзовое сииденье", + "block.create.cyan_seat": "Бирюзовое сиденье", "block.create.cyan_valve_handle": "Бирюзовый ручной вентиль", "block.create.dark_oak_window": "Окно из тёмного дуба", "block.create.dark_oak_window_pane": "Панель из окна из тёмного дуб", @@ -81,11 +87,11 @@ "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.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": "Диоритовый кирпич", @@ -163,6 +169,8 @@ "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": "Стеклянная жидкостная труба", @@ -175,17 +183,20 @@ "block.create.granite_cobblestone_stairs": "Ступени из гранит-булыжника", "block.create.granite_cobblestone_wall": "Стена из гранит-булыжника", "block.create.granite_pillar": "Гранитная колонна", + "block.create.gray_nixie_tube": "Серый газоразрядный индикатор", "block.create.gray_sail": "Серый парус", "block.create.gray_seat": "Серое сиденье", "block.create.gray_valve_handle": "Серый ручной вентиль", + "block.create.green_nixie_tube": "Зелёный газоразрядный индикатор", "block.create.green_sail": "Зелёный парус", "block.create.green_seat": "Зелёное сиденье", "block.create.green_valve_handle": "Зелёный ручной вентиль", "block.create.hand_crank": "Рукоятка", + "block.create.haunted_bell": "Призрачный колокол", "block.create.honey": "Мёд", "block.create.horizontal_framed_glass": "Горизонтальное обрамлённое стекло", "block.create.horizontal_framed_glass_pane": "Горизонтальная обрамлённая стеклянная панель", - "block.create.hose_pulley": "Шкив с шлангом", + "block.create.hose_pulley": "Шкив со шлангом", "block.create.item_drain": "Предметный осушитель", "block.create.jungle_window": "Окно из тропического дерева", "block.create.jungle_window_pane": "Панель окна из тропического дерева", @@ -199,12 +210,16 @@ "block.create.layered_limestone": "Слоистый известняк", "block.create.layered_scoria": "Слоистый пепел", "block.create.layered_weathered_limestone": "Слоистый выветренный известняк", + "block.create.lectern_controller": "Контроллер кафедры", + "block.create.light_blue_nixie_tube": "Голубой газоразрядный индикатор", "block.create.light_blue_sail": "Голубой парус", "block.create.light_blue_seat": "Голубое сиденье", "block.create.light_blue_valve_handle": "Голубой ручной вентиль", + "block.create.light_gray_nixie_tube": "Светло-серый газоразрядный индикатор", "block.create.light_gray_sail": "Светло-серый парус", "block.create.light_gray_seat": "Светло-серое сиденье", "block.create.light_gray_valve_handle": "Светло-серый ручной вентиль", + "block.create.lime_nixie_tube": "Лаймовый газоразрядный индикатор", "block.create.lime_sail": "Лаймовый парус", "block.create.lime_seat": "Лаймовое сиденье", "block.create.lime_valve_handle": "Лаймовый ручной вентиль", @@ -220,7 +235,8 @@ "block.create.limestone_cobblestone_wall": "Стена из известняк-булыжника", "block.create.limestone_pillar": "Известковая колонна", "block.create.linear_chassis": "Линейное шасси", - "block.create.lit_blaze_burner": "Зажжёная горелка Всполоха", + "block.create.lit_blaze_burner": "Зажжённая горелка Всполоха", + "block.create.magenta_nixie_tube": "Пурпурный газоразрядный индикатор", "block.create.magenta_sail": "Пурпурный парус", "block.create.magenta_seat": "Пурпурное сиденье", "block.create.magenta_valve_handle": "Пурпурный ручной вентиль", @@ -304,6 +320,8 @@ "block.create.paved_weathered_limestone_slab": "Плита из мощёного выветренного известняка", "block.create.paved_weathered_limestone_stairs": "Ступени из мощёного выветренного известняка", "block.create.paved_weathered_limestone_wall": "Стена из мощёного выветренного известняка", + "block.create.peculiar_bell": "Особенный колокол", + "block.create.pink_nixie_tube": "Розовый газоразрядный индикатор", "block.create.pink_sail": "Розовый парус", "block.create.pink_seat": "Розовое сиденье", "block.create.pink_valve_handle": "Розовый ручной вентиль", @@ -316,10 +334,10 @@ "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_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": "Ступени из полированного известняка", @@ -334,19 +352,21 @@ "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": "Механизированная рычаг-защёлка", + "block.create.powered_latch": "Питаемый рычаг", + "block.create.powered_toggle_latch": "Питаемый рычаг-переключатель", "block.create.pulley_magnet": "Магнитный шкив", "block.create.pulse_repeater": "Импульсный повторитель", + "block.create.purple_nixie_tube": "Фиолетовый газоразрядный индикатор", "block.create.purple_sail": "Фиолетовый парус", "block.create.purple_seat": "Фиолетовое сиденье", "block.create.purple_valve_handle": "Фиолетовый ручной вентиль", "block.create.radial_chassis": "Радиальное шасси", + "block.create.red_nixie_tube": "Красный газоразрядный индикатор", "block.create.red_sail": "Красный парус", "block.create.red_seat": "Красное сиденье", "block.create.red_valve_handle": "Красный ручной вентиль", - "block.create.redstone_contact": "Контакт сигнала красного камня", - "block.create.redstone_link": "Беспроводной передатчик сигнала красного камня", + "block.create.redstone_contact": "Контакт редстоун сигнала", + "block.create.redstone_link": "Беспроводной передатчик редстоун сигнала", "block.create.refined_radiance_casing": "Сияющий корпус", "block.create.reinforced_rail": "Усиленные рельсы", "block.create.rope": "Канат", @@ -360,16 +380,16 @@ "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_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": "Вторичное линейное шасси", "block.create.sequenced_gearshift": "Последовательный переключатель передач", "block.create.shadow_steel_casing": "Теневой корпус", "block.create.shaft": "Вал", - "block.create.smart_chute": "Умный желоб", + "block.create.smart_chute": "Умный жёлоб", "block.create.smart_fluid_pipe": "Умная жидкостная труба", "block.create.speedometer": "Спидометр", "block.create.spout": "Дозатор", @@ -378,7 +398,7 @@ "block.create.sticker": "Блок-липучка", "block.create.sticky_mechanical_piston": "Липкий механический поршень", "block.create.stockpile_switch": "Настраиваемый компаратор", - "block.create.stressometer": "Динамометр", + "block.create.stressometer": "Стрессометр", "block.create.tiled_glass": "Плиточное стекло", "block.create.tiled_glass_pane": "Плиточная стеклянная панель", "block.create.turntable": "Поворотный стол", @@ -398,24 +418,30 @@ "block.create.weathered_limestone_cobblestone_wall": "Стена из известняк-булыжника", "block.create.weathered_limestone_pillar": "Колонна из выветренного известняка", "block.create.weighted_ejector": "Взвешенная катапульта", + "block.create.white_nixie_tube": "Белый газоразрядный индикатор", "block.create.white_sail": "Белый парус", "block.create.white_seat": "Белое сиденье", "block.create.white_valve_handle": "Белый ручной вентиль", "block.create.windmill_bearing": "Подшипник ветряной мельницы", "block.create.wooden_bracket": "Деревянная скоба", + "block.create.yellow_nixie_tube": "Жёлтый газоразрядный индикатор", "block.create.yellow_sail": "Жёлтый парус", "block.create.yellow_seat": "Жёлтое сиденье", "block.create.yellow_valve_handle": "Жёлтый ручной вентиль", "block.create.zinc_block": "Цинковый блок", "block.create.zinc_ore": "Цинковая руда", + "enchantment.create.capacity": "Вместимость", + "enchantment.create.potato_recovery": "Возобновление картофеля", + "entity.create.contraption": "Штуковина", + "entity.create.crafting_blueprint": "Создание чертежа", + "entity.create.gantry_contraption": "Крановая штуковина", + "entity.create.potato_projectile": "Картофельный снаряд", "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": "Чай Строителя", @@ -431,16 +457,18 @@ "item.create.brass_nugget": "Кусочек латуни", "item.create.brass_sheet": "Латунный лист", "item.create.builders_tea": "Чай Строителя", - "item.create.chest_minecart_contraption": "Сундуко-вагонеточная штуковина", + "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_backtank": "Медный баллон", "item.create.copper_ingot": "Медный слиток", "item.create.copper_nugget": "Кусочек меди", "item.create.copper_sheet": "Медный лист", "item.create.crafter_slot_cover": "Крышка на слот крафтера", - "item.create.crushed_aluminum_ore": "Измельчённая алюминиевая руда", + "item.create.crafting_blueprint": "Создание чертежа", + "item.create.crushed_aluminum_ore": "Дроблёная алюминиевая руда", "item.create.crushed_brass": "Дроблёная латунь", "item.create.crushed_copper_ore": "Дроблёная медная руда", "item.create.crushed_gold_ore": "Дроблёная золотая руда", @@ -450,31 +478,35 @@ "item.create.crushed_osmium_ore": "Дроблёная осмиевая руда", "item.create.crushed_platinum_ore": "Дроблёная платиновая руда", "item.create.crushed_quicksilver_ore": "Дроблёная ртутная руда", - "item.create.crushed_silver_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.diving_boots": "Ботинки для дайвинга", + "item.create.diving_helmet": "Шлем для дайвинга", "item.create.dough": "Тесто", "item.create.electron_tube": "Электронная лампа", - "item.create.empty_blaze_burner": "Пустая горелека Всполоха", + "item.create.empty_blaze_burner": "Пустая горелка Всполоха", "item.create.empty_schematic": "Пустая схематика", "item.create.extendo_grip": "Удлинённая рука", "item.create.filter": "Фильтр", - "item.create.furnace_minecart_contraption": "Печно-вагонеточная штуковина", + "item.create.furnace_minecart_contraption": "Штуковина самоходной вагонетки", "item.create.goggles": "Инженерные очки", "item.create.golden_sheet": "Золотой лист", - "item.create.handheld_blockzapper": "Ручная блоковая пушка", "item.create.handheld_worldshaper": "Ручной редактор мира", "item.create.honey_bucket": "Ведро мёда", "item.create.honeyed_apple": "Яблоко в меду", - "item.create.integrated_circuit": "Интегральная схема", + "item.create.incomplete_cogwheel": "Незаконченная шестерня", + "item.create.incomplete_large_cogwheel": "Незаконченная большая шестерня", + "item.create.incomplete_precision_mechanism": "Незаконченный механизм точности", "item.create.iron_sheet": "Железный лист", - "item.create.lapis_sheet": "Лазуритовый лист", + "item.create.linked_controller": "Контроллер связей", "item.create.minecart_contraption": "Вагонеточная штуковина", - "item.create.minecart_coupling": "Связыватель вагонеток", + "item.create.minecart_coupling": "Соединитель вагонеток", "item.create.polished_rose_quartz": "Полированный розовый кварц", + "item.create.potato_cannon": "Картофельная пушка", "item.create.powdered_obsidian": "Порошкообразный обсидиан", + "item.create.precision_mechanism": "Механизм точности", "item.create.propeller": "Пропеллер", "item.create.red_sand_paper": "Красная наждачная бумага", "item.create.refined_radiance": "Изысканное сияние", @@ -502,9 +534,9 @@ "advancement.create.andesite_alloy": "Повторение - мать учения", "advancement.create.andesite_alloy.desc": "Материалы Create имеют странные названия, одно из них - Андезитовый сплав", "advancement.create.its_alive": "Оно живое!", - "advancement.create.its_alive.desc": "Смастерите ваш первый кинетический компонент вращения.", + "advancement.create.its_alive.desc": "Смастерите ваш первый кинетический вращающийся компонент.", "advancement.create.shifting_gears": "Механизм переключения", - "advancement.create.shifting_gears.desc": "Подсоедините большую шестерню к шестерне, что позволит изменить скорость вращения.", + "advancement.create.shifting_gears.desc": "Подсоедините большую шестерню к обычной шестерне для изменения скорости вращения.", "advancement.create.overstressed": "Перегрузка", "advancement.create.overstressed.desc": "Столкнитесь с предельной перегрузкой лицом к лицу.", "advancement.create.belt": "Передайте за проезд!", @@ -520,9 +552,9 @@ "advancement.create.belt_funnel": "Болтающиеся воронки", "advancement.create.belt_funnel.desc": "Поместите воронку боком, сверху конвейера или депо, чтобы создать её специальный тип.", "advancement.create.belt_funnel_kiss": "Механический ужин", - "advancement.create.belt_funnel_kiss.desc": "Заставте две смонтированные на ремнях воронки поцеловаться.", + "advancement.create.belt_funnel_kiss.desc": "Заставьте две смонтированные на ремнях воронки поцеловаться.", "advancement.create.fan": "Механический маг воздуха", - "advancement.create.fan.desc": "Оседлайте поток воздуха от Венитлятора.", + "advancement.create.fan.desc": "Оседлайте поток воздуха от Вентилятора.", "advancement.create.fan_lava": "Геотермальный пространственный нагреватель", "advancement.create.fan_lava.desc": "Попадите в поток воздуха, плавящего вещи.", "advancement.create.fan_water": "Сумасшедшая мойка", @@ -532,19 +564,19 @@ "advancement.create.wrench": "Конфигурировать удобно", "advancement.create.wrench.desc": "Создайте гаечный ключ, чтобы помочь себе в создании изобретений.", "advancement.create.goggles": "Стресс-о-зрение", - "advancement.create.goggles.desc": "Создайте инженерные очки, чтобы получить больше кинетической информации о компонентах.", + "advancement.create.goggles.desc": "Создайте инженерные очки, чтобы получить больше информации о кинетике компонентов.", "advancement.create.speedometer": "Так быстро?", "advancement.create.speedometer.desc": "Поставьте и подключите спидометр. Посмотрите на спидометр через очки, чтобы прочитать точное значение.", "advancement.create.stressometer": "Так сильно?", - "advancement.create.stressometer.desc": "Поставьте и подключите динамометр. Посмотрите на динамометр через очки, чтобы прочитать точное значение.", + "advancement.create.stressometer.desc": "Поставьте и подключите стрессометр. Посмотрите на стрессометр через очки, чтобы прочитать точное значение.", "advancement.create.aesthetics": "Бах! Эстетично!", - "advancement.create.aesthetics.desc": "Разместите скобы на валу, трубе или шестерне.", + "advancement.create.aesthetics.desc": "Разместите скобы на вал, трубу или шестерню.", "advancement.create.reinforced": "Бах! Усилено!", "advancement.create.reinforced.desc": "Разместите подходящий блок корпуса на вал, трубу и конвейер.", - "advancement.create.water_wheel": "Гидравлика", + "advancement.create.water_wheel": "Обузданная гидравлика", "advancement.create.water_wheel.desc": "Поставьте водяное колесо и попытайтесь заставить его вращаться!", "advancement.create.chocolate_wheel": "Вкусная сила", - "advancement.create.chocolate_wheel.desc": "Зпустите водяное колесо с помощью раплавленного шоколада.", + "advancement.create.chocolate_wheel.desc": "Запустите водяное колесо с помощью расплавленного шоколада.", "advancement.create.lava_wheel": "Адское колесо", "advancement.create.lava_wheel.desc": "Это не должно было работать.", "advancement.create.cuckoo": "Уже?", @@ -557,12 +589,12 @@ "advancement.create.maxed_windmill.desc": "Соберите ветряную мельницу максимальной силы.", "advancement.create.andesite_casing": "Андезитовый век", "advancement.create.andesite_casing.desc": "Используйте немного андезитового сплава и дерева для создания корпуса.", - "advancement.create.mechanical_drill": "Стационарные выключатели", + "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.polished_rose_quartz.desc": "Используйте кусок наждачной бумаги, чтобы отполировать розовый кварц, пока он не станет глянцевым.", "advancement.create.electron_tube": "Бип бип", "advancement.create.electron_tube.desc": "Сделайте несколько электронных ламп, пригодных для изготовления менее примитивных машин.", "advancement.create.mechanical_saw": "Стационарная рубка", @@ -575,7 +607,7 @@ "advancement.create.blaze_burner.desc": "Получить Горелку Всполоха", "advancement.create.compact": "Автоматическое уплотнение", "advancement.create.compact.desc": "Используйте пресс и чашу для уплотнения некоторых предметов.", - "advancement.create.brass": "Действительный сплав", + "advancement.create.brass": "Реальный сплав", "advancement.create.brass.desc": "Используйте дроблёную медь и дроблёный цинк, чтобы создать немного латуни.", "advancement.create.brass_casing": "Бронзовый век", "advancement.create.brass_casing.desc": "Используйте только что полученную латунь и немного дерева, чтобы создать более продвинутый корпус.", @@ -591,7 +623,7 @@ "advancement.create.item_drain.desc": "Посмотрите как жидкость выкачивается из предмета, в Предметном осушителе.", "advancement.create.chained_item_drain": "Поехали!", "advancement.create.chained_item_drain.desc": "Наблюдайте за тем как предмет едет через несколько соединённых предметных осушителей.", - "advancement.create.glass_pipe": "Поточный шпион", + "advancement.create.glass_pipe": "Шпион за потоками", "advancement.create.glass_pipe.desc": "Наблюдайте через окно в трубе за тем как распространяется жидкость. Окно появится на трубе при использовании гаечного ключа.", "advancement.create.pipe_collision": "Никогда не скрещивайте потоки!", "advancement.create.pipe_collision.desc": "Наблюдайте за тем как две жидкости встречаются в вашей сети труб.", @@ -604,7 +636,7 @@ "advancement.create.infinite_lava": "Уничтожение ядра", "advancement.create.infinite_lava.desc": "Выкачивайте лаву из бассейна, считающегося бесконечным.", "advancement.create.infinite_chocolate": "Утопая в воображении", - "advancement.create.infinite_chocolate.desc": "Выкачивайте раславленный шоколад из резервуара, считающегося бесконечным.", + "advancement.create.infinite_chocolate.desc": "Выкачивайте расплавленный шоколад из резервуара, считающегося бесконечным.", "advancement.create.crafter": "Автоматизированная сборка", "advancement.create.crafter.desc": "Поставьте и подключите механический крафтер", "advancement.create.clockwork_bearing": "Хитрые часы", @@ -619,18 +651,18 @@ "advancement.create.flywheel.desc": "Успешно соедините двигатель с маховиком.", "advancement.create.overstress_flywheel": "Перенапряжение", "advancement.create.overstress_flywheel.desc": "Подайте слишком большую нагрузку на печной двигатель.", - "advancement.create.integrated_circuit": "Сложные вычисления", - "advancement.create.integrated_circuit.desc": "Создайте Интегральную схему.", + "advancement.create.precision_mechanism": "Сложные любопытства.", + "advancement.create.precision_mechanism.desc": "Создайте механизм точности.", "advancement.create.mechanical_arm": "Золотые руки!", - "advancement.create.mechanical_arm.desc": "Создайте Механическую руку, выбирете входы и выходы, установите в мире и запитайте. Затем смотрите как она делает за вас всю работу.", + "advancement.create.mechanical_arm.desc": "Создайте Механическую руку, выберите входы и выходы, установите в мире и запитайте. Затем смотрите как она делает за вас всю работу.", "advancement.create.musical_arm": "Сбацай что-нибудь!", "advancement.create.musical_arm.desc": "Посмотрите как механическая рука меняет пластинки.", - "advancement.create.arm_many_targets": "Организатор", + "advancement.create.arm_many_targets": "Организа-трон", "advancement.create.arm_many_targets.desc": "Запрограммируйте механическую руку на 10 и больше выходов.", - "advancement.create.arm_blaze_burner": "Поджигатель", + "advancement.create.arm_blaze_burner": "Поджигателе-трон", "advancement.create.arm_blaze_burner.desc": "Запрограммируйте механическую руку на кормление Горелки Всполоха.", "advancement.create.fist_bump": "Брось это, братан!", - "advancement.create.fist_bump.desc": "Сделайте два удара кулаком.", + "advancement.create.fist_bump.desc": "Сделайте два удара кулаками Автономных активаторов.", "advancement.create.crushing_wheel": "Пара гигантов", "advancement.create.crushing_wheel.desc": "Создайте несколько дробящих колес, чтобы более эффективно разрушать больше материалов.", "advancement.create.blaze_cake": "Сахарная лихорадка", @@ -643,17 +675,13 @@ "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": "Кипение!", + "advancement.create.extendo_grip": "Бойоиоинг!", "advancement.create.extendo_grip.desc": "Возьмите в руки удлинённую руку", - "advancement.create.dual_extendo_grip": "Окончательное выкипание", + "advancement.create.potato_cannon": "Свомп!", + "advancement.create.potato_cannon.desc": "Победите врага с помощью своей картофельной пушки!", + "advancement.create.dual_extendo_grip": "Время ультимативных пружин", "advancement.create.dual_extendo_grip.desc": "Две удлинённых руки для сверхчеловеческого охвата.", "advancement.create.eob": "Конец бета-версии", "advancement.create.eob.desc": "Ожидайте больше контента здесь в будущем. <3", @@ -665,15 +693,31 @@ "itemGroup.create.palettes": "Create: Декор", "death.attack.create.crush": "%1$s был передроблен", + "death.attack.create.crush.player": "%2$s столкнул %1$s в дробящие колёса", "death.attack.create.fan_fire": "%1$s был сожжен до смерти горячим воздухом", + "death.attack.create.fan_fire.player": "%2$s столкнул %1$s в коптильню", "death.attack.create.fan_lava": "%1$s был сожжен до смерти поклонником лавы", - "death.attack.create.mechanical_drill": "%1$s был пронзен с помощью механической дрели", + "death.attack.create.fan_lava.player": "%2$s столкнул %1$s в плавильню", + "death.attack.create.mechanical_drill": "%1$s был пронзён механической дрелью", + "death.attack.create.mechanical_drill.player": "%2$s толкнул %1$s под механическую дрель", "death.attack.create.mechanical_saw": "%1$s был разрезан пополам механической пилой", + "death.attack.create.mechanical_saw.player": "%2$s толкнул %1$s под механическую пилу", + "death.attack.create.potato_cannon": "%1$s был застрелен картофельной пушкой %2$s", + "death.attack.create.potato_cannon.item": "%1$s был застрелен %2$s при помощи «%3$s»", "death.attack.create.cuckoo_clock_explosion": "%1$s взорвали подделанные часы с кукушкой", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s был взорван подделанными часами с кукушкой", "create.block.deployer.damage_source_name": "автономным активатором", "create.block.cart_assembler.invalid": "Поместите сборщик вагонеток на блок рельс", + "create.menu.return": "Вернуться в меню", + "create.menu.configure": "Настроить...", + "create.menu.ponder_index": "Содержание размышлений", + "create.menu.only_ingame": "Доступно в меню Паузы", + "create.menu.project_page": "Страница проекта", + "create.menu.report_bugs": "Сообщите об ошибке", + "create.menu.support": "Поддержите нас", + "create.recipe.crushing": "Измельчение", "create.recipe.milling": "Помол", "create.recipe.fan_washing": "Массовая промывка", @@ -684,6 +728,7 @@ "create.recipe.fan_blasting.fan": "Вентилятор за текущей лавой", "create.recipe.pressing": "Прессование", "create.recipe.mixing": "Смешивание", + "create.recipe.deploying": "Автономная активация", "create.recipe.automatic_shapeless": "Автоматическая бесформенная сборка", "create.recipe.automatic_brewing": "Автоматическое смешивание", "create.recipe.packing": "Прессование", @@ -692,11 +737,21 @@ "create.recipe.mechanical_crafting": "Механическое создание", "create.recipe.automatic_shaped": "Автоматическая форменная сборка", "create.recipe.block_cutting": "Резка блока", - "create.recipe.blockzapper_upgrade": "Ручная блоковая пушка", + "create.recipe.wood_cutting": "Резка древесины", "create.recipe.sandpaper_polishing": "Полировка наждачной бумагой", "create.recipe.mystery_conversion": "Хроматический метаморфоз", "create.recipe.spout_filling": "Заполнение дозатором", "create.recipe.draining": "Осушение предметов", + "create.recipe.sequenced_assembly": "Последовательная сборка", + "create.recipe.assembly.next": "Следующее: %1$s", + "create.recipe.assembly.step": "Шаг %1$s:", + "create.recipe.assembly.progress": "Прогресс: %1$s/%2$s", + "create.recipe.assembly.pressing": "Обработайте в Прессе", + "create.recipe.assembly.spout_filling_fluid": "Долейте %1$s", + "create.recipe.assembly.deploying_item": "Добавьте %1$s", + "create.recipe.assembly.cutting": "Разрежьте пилой", + "create.recipe.assembly.repeat": "Повторите последовательность %1$s раз", + "create.recipe.assembly.junk": "Случайный мусор", "create.recipe.processing.chance": "%1$s%% шанса", "create.recipe.heat_requirement.none": "Не требует нагрева", "create.recipe.heat_requirement.heated": "Нагрето", @@ -713,7 +768,7 @@ "create.generic.unit.seconds": "секунд", "create.generic.unit.minutes": "минут", "create.generic.unit.rpm": "об./мин.", - "create.generic.unit.stress": "Н*м", + "create.generic.unit.stress": "ен", "create.generic.unit.degrees": "°", "create.generic.unit.millibuckets": "%1$smB", "create.generic.clockwise": "По часовой стрелке", @@ -749,20 +804,16 @@ "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.searchDiagonal": "Следование диагоналям", + "create.gui.terrainzapper.searchFuzzy": "Игнорировать границы материала", + "create.gui.terrainzapper.patternSection": "Шаблон", + "create.gui.terrainzapper.pattern.solid": "Сплошной", + "create.gui.terrainzapper.pattern.checkered": "Шахматный порядок", + "create.gui.terrainzapper.pattern.inversecheckered": "Обратный шахматный порядок", + "create.gui.terrainzapper.pattern.chance25": "25% заполнение", + "create.gui.terrainzapper.pattern.chance50": "50% заполнение", + "create.gui.terrainzapper.pattern.chance75": "75% заполнение", "create.gui.terrainzapper.placement": "Размещение", "create.gui.terrainzapper.placement.merged": "Слитый", "create.gui.terrainzapper.placement.attached": "Прикреплённый", @@ -771,6 +822,8 @@ "create.gui.terrainzapper.brush.cuboid": "Куб", "create.gui.terrainzapper.brush.sphere": "Сфера", "create.gui.terrainzapper.brush.cylinder": "Цилиндр", + "create.gui.terrainzapper.brush.surface": "Поверхность", + "create.gui.terrainzapper.brush.cluster": "Скопление", "create.gui.terrainzapper.tool": "Инструмент", "create.gui.terrainzapper.tool.fill": "Заполнить", "create.gui.terrainzapper.tool.place": "Поставить", @@ -780,23 +833,12 @@ "create.gui.terrainzapper.tool.flatten": "Выравнивание", "create.terrainzapper.shiftRightClickToSet": "ПКМ крадучись, чтобы выбрать форму", - - "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.terrainzapper.usingBlock": "Используется: %1$s", + "create.terrainzapper.leftClickToSet": "Левый клик по блоку, что бы использовать материал", "create.minecart_coupling.two_couplings_max": "Вагонетки могут иметь только две связи", "create.minecart_coupling.unloaded": "Кажется, часть вашего поезда в незагруженных чанках", - "create.minecart_coupling.no_loops": "Связыватели не могут образовывать петлю", + "create.minecart_coupling.no_loops": "Соединители не могут образовывать петлю", "create.minecart_coupling.removed": "Убраны все связи между вагонетками", "create.minecart_coupling.too_far": "Вагонетки слишком далеко друг от друга", @@ -823,12 +865,12 @@ "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_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.at_current_speed": "При текущей скорости", "create.gui.goggles.pole_length": "Длина поршня", "create.gui.goggles.fluid_container": "Информация о жидкостном контейнере:", "create.gui.goggles.fluid_container.capacity": "Ёмкость: ", @@ -836,17 +878,17 @@ "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": "Штуковина состоит из слишком большого количества Блоков.\nТекущий максимум: %1$s", - "create.gui.assembly.exception.tooManyPistonPoles": "Слишком много Удлинителей прикреплено к этому Поршню.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "Слишком много Удлинителей прикреплено к этому поршню.\nТекущий максимум: %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.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.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": "Настраиваемый компаратор", @@ -858,6 +900,7 @@ "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": "Временная задержка", @@ -865,7 +908,7 @@ "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.descriptive": "Ожидать нового Импульса редстоун Сигнала", "create.gui.sequenced_gearshift.instruction.await": "Ожидать", "create.gui.sequenced_gearshift.speed": "Скорость, Направление", "create.gui.sequenced_gearshift.speed.forward": "Скорость ввода, вперед", @@ -890,11 +933,11 @@ "create.schematic.rotation.cw90": "По час. стрелке 90", "create.schematic.rotation.cw180": "По час. стрелке 180", "create.schematic.rotation.cw270": "По час. стрелке 270", - "create.schematic.mirror": "Зеркало", + "create.schematic.mirror": "Отразить", "create.schematic.mirror.none": "Нет", "create.schematic.mirror.frontBack": "Спереди-сзади", "create.schematic.mirror.leftRight": "Влево-вправо", - "create.schematic.tool.deploy": "Развернуть", + "create.schematic.tool.deploy": "Развёртывание", "create.schematic.tool.move": "Подвинуть XZ", "create.schematic.tool.movey": "Подвинуть Y", "create.schematic.tool.rotate": "Вращать", @@ -920,7 +963,7 @@ "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.0": "Переверните схему вдоль выбранной стороны.", "create.schematic.tool.flip.description.1": "Наведите курсор на схему и [CTRL] + прокрутка, чтобы перевернуть ее.", "create.schematic.tool.flip.description.2": "", "create.schematic.tool.flip.description.3": "", @@ -951,10 +994,10 @@ "create.gui.schematicannon.option.skipMissing": "Пропускать отсутствующие блоки", "create.gui.schematicannon.option.skipTileEntities": "Защитить имущество", "create.gui.schematicannon.slot.gunpowder": "Добавьте порох чтобы запитать пушку", - "create.gui.schematicannon.slot.listPrinter": "Положите книгу чтобы создать список предметов для схематики", + "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.skipTileEntities.description": "Пушка не будет заменять блоки хранения, такие как сундуки.", "create.gui.schematicannon.option.dontReplaceSolid.description": "Пушка никогда не заменит целые блоки, только не целые и воздух.", "create.gui.schematicannon.option.replaceWithSolid.description": "Пушка будет заменять целый блок только в случае, если в схеме в этом месте расположен целый блок.", "create.gui.schematicannon.option.replaceWithAny.description": "Пушка будет заменять целые блоки, если в схеме в этом месте есть что-либо.", @@ -1022,6 +1065,11 @@ "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.shulker_level": "шалкер %1$s", + "create.item_attributes.shulker_level.inverted": "шалкер не %1$s", + "create.item_attributes.shulker_level.full": "полный", + "create.item_attributes.shulker_level.empty": "пустой", + "create.item_attributes.shulker_level.partial": "частично заполнен", "create.item_attributes.has_enchant": "зачарован на %1$s", "create.item_attributes.has_enchant.inverted": "не зачарован на %1$s", "create.item_attributes.color": "Покрашено в %1$s", @@ -1033,7 +1081,7 @@ "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_author.inverted": "не подписана %1$s", "create.item_attributes.book_copy_original": "оригинал", "create.item_attributes.book_copy_original.inverted": "не оригинал", "create.item_attributes.book_copy_first": "копия первого порядка", @@ -1071,12 +1119,12 @@ "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": "Создаваемая нагрузка: %1$s", + "create.tooltip.stressImpact.low": "Низкая", + "create.tooltip.stressImpact.medium": "Средняя", + "create.tooltip.stressImpact.high": "Высокая", "create.tooltip.stressImpact.overstressed": "Перегрузка", - "create.tooltip.capacityProvided": "Ёмкостный крутящий момент: %1$s", + "create.tooltip.capacityProvided": "Допустимая нагрузка: %1$s", "create.tooltip.capacityProvided.low": "Маленький", "create.tooltip.capacityProvided.medium": "Средний", "create.tooltip.capacityProvided.high": "Большой", @@ -1089,34 +1137,55 @@ "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.target_not_valid": "Бросает до ближайшего блока (Неподходящая Цель)", + "create.weighted_ejector.no_target": "Бросает до ближайшего блока (Цель не была Выбрана)", "create.weighted_ejector.targeting": "Бросает до [%1$s,%2$s,%3$s]", - "create.weighted_ejector.stack_size": "Размер Бросаемого Стака", + "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.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.prefer_nearest": "Предпочтительно ближайшее", "create.tunnel.selection_mode.randomize": "Случайно", "create.tunnel.selection_mode.synchronize": "Синхронизировать входы", - "create.tooltip.chute.header": "Инвормация о желобе", + "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.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.tooltip.brass_tunnel.contains": "В данный момент раздает(выдает):", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "ПКМ, чтобы получить", + + "create.linked_controller.bind_mode": "Режим привязки активирован", + "create.linked_controller.press_keybind": "Нажмите %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, чтобы привязать эту частоту к соответствующей клавише", + "create.linked_controller.key_bound": "Частота привязана к %1$s", + "create.linked_controller.frequency_slot_1": "Клавиша: %1$s, Частота #1", + "create.linked_controller.frequency_slot_2": "Клавиша: %1$s, Частота #2", + + "create.crafting_blueprint.crafting_slot": "Слот для ингредиентов", + "create.crafting_blueprint.filter_items_viable": "Продвинутые фильтры предметов применимы", + "create.crafting_blueprint.display_slot": "Отображаемая ячейка", + "create.crafting_blueprint.inferred": "Производные от рецепта", + "create.crafting_blueprint.manually_assigned": "Назначен вручную", + "create.crafting_blueprint.secondary_display_slot": "Дополнительная отображаемая ячейка", + "create.crafting_blueprint.optional": "Опциональна", + + "create.potato_cannon.ammo.attack_damage": "%1$s урона от атаки", + "create.potato_cannon.ammo.reload_ticks": "%1$s тиков перезагрузки", + "create.potato_cannon.ammo.knockback": "%1$s отбрасывания", "create.hint.hose_pulley.title": "Безграничное снабжение", "create.hint.hose_pulley": "Целевой водный резервуар считается бесконечным.", @@ -1144,16 +1213,47 @@ "create.command.killTPSCommand.status.usage.1": "[Create]: используйте /killtps start <Время тика>, чтобы искусственно замедлить тик сервера", "create.command.killTPSCommand.argument.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.contraption.minecart_contraption_too_big": "Эта вагонеточная штуковина кажется слишком большой, чтобы ее можно было поднять", + "create.contraption.minecart_contraption_illegal_pickup": "Мистическая сила связывает эту вагонеточную штуковину с миром", + + + "_": "->------------------------] Subtitles [------------------------<-", + + "create.subtitle.contraption_disassemble": "Штуковина останавливается", + "create.subtitle.peculiar_bell_use": "Особенный колокол звонит", + "create.subtitle.mixing": "Шум смешивания", + "create.subtitle.mechanical_press_activation_belt": "Механический пресс делает «бонк»", + "create.subtitle.fwoomp": "Картофельная пушка делает «Свомп»", + "create.subtitle.worldshaper_place": "Ручной редактор мира делает «Зап»", + "create.subtitle.crushing_1": "Шум разрушения", + "create.subtitle.depot_slide": "Шелест предметов", + "create.subtitle.saw_activate_stone": "Активируется механическая пила", "create.subtitle.blaze_munch": "Всполох радостно жуёт", + "create.subtitle.funnel_flap": "Занавески воронок хлопают", + "create.subtitle.schematicannon_finish": "Схематичная пушка закончила работу", + "create.subtitle.haunted_bell_use": "Призрачный колокол звонит", + "create.subtitle.scroll_value": "Щелчки колеса прокрутки", + "create.subtitle.crafter_craft": "Крафтер создаёт", + "create.subtitle.controller_put": "Контроллер стучит", + "create.subtitle.cranking": "Вращается рукоятка", + "create.subtitle.wrench_remove": "Компонент ломается", + "create.subtitle.cogs": "Шестерни грохочут", + "create.subtitle.slime_added": "Намазывание слизи", + "create.subtitle.wrench_rotate": "Использован гаечный ключ", + "create.subtitle.potato_hit": "Овощ врезается", + "create.subtitle.saw_activate_wood": "Активируется механическая пила", + "create.subtitle.haunted_bell_convert": "Призрачный колокол пробуждается", + "create.subtitle.deployer_polish": "Автономный активатор полирует", + "create.subtitle.deny": "Отрицательный «Буп»", + "create.subtitle.controller_click": "Клики контроллера", + "create.subtitle.schematicannon_launch_block": "Выстрелы схематичной пушки", + "create.subtitle.copper_armor_equip": "Позвякивание снаряжения для дайвинга", + "create.subtitle.controller_take": "Кафедра опустошается", + "create.subtitle.mechanical_press_activation": "Механический пресс активирован", + "create.subtitle.contraption_assemble": "Штуковина движется", + "create.subtitle.crafter_click": "Крафтер кликает", + "create.subtitle.depot_plop": "Предмет падает", + "create.subtitle.confirm": "Утвердительный «Динь»", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1167,88 +1267,21 @@ "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": "ДЕРЕВЯННАЯ СКОБА", "block.create.wooden_bracket.tooltip.summary": "_Украсьте_ ваши _валы, шестерни_ и _трубы_, используя уютное деревянное укрепление.", - "block.create.metal_bracket.tooltip": "METAL BRACKET", + "block.create.metal_bracket.tooltip": "МЕТАЛЛИЧЕСКАЯ СКОБА", "block.create.metal_bracket.tooltip.summary": "_Украсьте_ ваши _валы, шестерни_ и _трубы_, используя прочное индустриальное укрепление.", - "block.create.copper_casing.tooltip": "COPPER CASING", - "block.create.copper_casing.tooltip.summary": "Прочный машинный корпус для разнообразного использования. Безопасно для украшения.", - "block.create.copper_casing.tooltip.condition1": "При использовании на жидкостной трубе", - "block.create.copper_casing.tooltip.behaviour1": "Покрывает _жидкостную трубу_ _корпусом_. Трубы в корпусе _закрепят свои соединения_ и не будут соединятся с другими трубами, расположенными по соседству.", - - "block.create.encased_fluid_pipe.tooltip": "ENCASED FLUID PIPE", - "block.create.encased_fluid_pipe.tooltip.summary": "_Труба_ в _Медном корпусе_.", - - "block.create.seat.tooltip": "SEAT", + "block.create.seat.tooltip": "СИДЕНЬЕ", "block.create.seat.tooltip.summary": "Присядьте и насладитесь поездкой! Привязывает игроков к собранным _устройствам_. Отлично выглядит как простая мебель! Можно окрасить в разные цвета.", "block.create.seat.tooltip.condition1": "ПКМ по сиденью", - "block.create.seat.tooltip.behaviour1": "Сажает игрока на _Сиденье_. Нажмите _кнопку_ _приседания_ чтобы слезть.", + "block.create.seat.tooltip.behaviour1": "Сажает игрока на _Сиденье_. Нажмите _кнопку_ _приседания_ чтобы слезть (Shift по умолчанию).", - "item.create.blaze_cake.tooltip": "BLAZE CAKE", + "item.create.blaze_cake.tooltip": "ТОРТ ВСПОЛОХА", "item.create.blaze_cake.tooltip.summary": "Вкусное угощения для вашей трудяги _Горелки Всполоха_. Зажигает их всех!", - "block.create.fluid_pipe.tooltip": "FLUID PIPE", - "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": "HOSE PULLEY", - "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": "FLUID TANK", - "block.create.fluid_tank.tooltip.summary": "_Хранит_ ваши любимые _жидкости_. Скалируется в высоту и ширину.", - "block.create.fluid_tank.tooltip.condition1": "Правый клик с гаечным ключом", - "block.create.fluid_tank.tooltip.behaviour1": "Переключает опциональное отображение окна", - - "block.create.creative_fluid_tank.tooltip": "CREATIVE FLUID TANK", - "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": "FLUID VALVE", - "block.create.fluid_valve.tooltip.summary": "Останавливает поток жидкости по трубе.", - "block.create.fluid_valve.tooltip.condition1": "Контролируемый поток", - "block.create.fluid_valve.tooltip.behaviour1": "Приложенная _Вращательная сила_ заставит _клапан_ закрыться, останавливая поток _жидкости_. Измените направление _вращательной силы_, чтобы снова открыть клапан.", - - "block.create.mechanical_pump.tooltip": "MECHANICAL PUMP", - "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": "SMART FLUID PIPE", - "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": "SPOUT", - "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": "ITEM DRAIN", - "block.create.item_drain.tooltip.summary": "Депо с решёткой, которое может выкачивать _жидкость_ из ваших _предметов_", - "block.create.item_drain.tooltip.condition1": "Транспортировка жидкости", - "block.create.item_drain.tooltip.behaviour1": "Когда _предмет с жидкостью_, такой как _ведро_ или _бутылочка_ вставлены с боку, предметный осушитель будет автоматически извлекать жидкость, в свой собственный _бак_. Предмет будет выброшен с противоположной стороны.", - - "item.create.wand_of_symmetry.tooltip": "SYMMETRY WAND", + "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": "Остаётся активным", @@ -1259,16 +1292,7 @@ "item.create.wand_of_symmetry.tooltip.control3": "ПКМ крадучись", "item.create.wand_of_symmetry.tooltip.action3": "Открывает _интерфейс_ _конфигурации_", - "item.create.handheld_blockzapper.tooltip": "BLOCKZAPPER", - "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": "Открывает _интерфейс_ _конфигурации_", - - "item.create.handheld_worldshaper.tooltip": "HANDHELD WORLDSHAPER", + "item.create.handheld_worldshaper.tooltip": "РУЧНОЙ РЕДАКТОР МИРА", "item.create.handheld_worldshaper.tooltip.summary": "Удобный инструмент для создания _ландшафтов_ и _рельефа_ _местности_.", "item.create.handheld_worldshaper.tooltip.control1": "ЛКМ на блок", "item.create.handheld_worldshaper.tooltip.action1": "Устанавливает блоки, помещенные инструментом, в целевой блок.", @@ -1277,44 +1301,50 @@ "item.create.handheld_worldshaper.tooltip.control3": "ПКМ крадучись", "item.create.handheld_worldshaper.tooltip.action3": "Открывает _интерфейс_ _конфигурации_", - "item.create.tree_fertilizer.tooltip": "TREE FERTILIZER", + "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": "DEFORESTER", - "item.create.deforester.tooltip.summary": "_Уничтожитель_ _леса_, способен рубить деревья за доли секунды.", - - "item.create.extendo_grip.tooltip": "EXTENDO GRIP", + "item.create.extendo_grip.tooltip": "УДЛИНЕННАЯ РУКА", "item.create.extendo_grip.tooltip.summary": "Бойоиоинг! Значительно _увеличивает_ _досягаемость_ владельца.", "item.create.extendo_grip.tooltip.condition1": "Находясь в другой руке", - "item.create.extendo_grip.tooltip.behaviour1": "Увеличьте _расстояние_ _досягаемости_ предметов, используемых в _главной_ _руке_.", + "item.create.extendo_grip.tooltip.behaviour1": "Увеличивает _расстояние_ _досягаемости_ предметов, используемых в _главной_ _руке_.", + "item.create.extendo_grip.tooltip.condition2": "Когда надет Медный баллон", + "item.create.extendo_grip.tooltip.behaviour2": " _НЕ_ тратится _прочность_. Вместо этого будет тратиться _воздух_ из баллона.", - "item.create.filter.tooltip": "FILTER", + "item.create.potato_cannon.tooltip": "КАРТОФЕЛЬНАЯ ПУШКА", + "item.create.potato_cannon.tooltip.summary": "Свомп! Запускайте выращенные вами овощи в своих врагов. Может питаться от давления воздуха из _Медного_ _баллона_", + "item.create.potato_cannon.tooltip.condition1": "Нажимая ПКМ", + "item.create.potato_cannon.tooltip.behaviour1": "_Выстреливает_ подходящим предметом из вашего _инвентаря_.", + "item.create.potato_cannon.tooltip.condition2": "Когда надет Медный баллон", + "item.create.potato_cannon.tooltip.behaviour2": "_НЕ_ тратится _прочность_. Вместо этого будет тратиться _воздух_ из баллона.", + + "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": "ATTRIBUTE FILTER", + "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": "EMPTY SCHEMATIC", + "item.create.empty_schematic.tooltip": "ПУСТАЯ СХЕМАТИКА", "item.create.empty_schematic.tooltip.summary": "Используется в качестве ингредиента рецепта и для записи в _Схематичный столе_", - "item.create.schematic.tooltip": "SCHEMATIC", + "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": "SCHEMATIC AND QUILL", + "item.create.schematic_and_quill.tooltip": "СХЕМАТИКА И ПЕРО", "item.create.schematic_and_quill.tooltip.summary": "Используется для сохранения структуры в вашем мире в файл .nbt.", "item.create.schematic_and_quill.tooltip.condition1": "Шаг 1", "item.create.schematic_and_quill.tooltip.behaviour1": "Выберите две угловые точки, используя ПКМ.", @@ -1327,110 +1357,138 @@ "item.create.schematic_and_quill.tooltip.control3": "ПКМ крадучись", "item.create.schematic_and_quill.tooltip.action3": "_Сбрасывает_ и _удаляет_ выделение.", - "block.create.schematicannon.tooltip": "SCHEMATICANNON", + "block.create.schematicannon.tooltip": "СХЕМАТИЧНАЯ ПУШКА", "block.create.schematicannon.tooltip.summary": "_Ставит блоки_ для воссоздания _схематики_ в мире. Использует предметы из _соседнего_ _инвентаря_ и _порох_ в качестве _топлива_.", "block.create.schematicannon.tooltip.condition1": "ПКМ", "block.create.schematicannon.tooltip.behaviour1": "Открывает _Интерфейс_", - "block.create.schematic_table.tooltip": "SCHEMATIC TABLE", + "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": "GOGGLES", + "item.create.goggles.tooltip": "ИНЖЕНЕРНЫЕ ОЧКИ", "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.behaviour2": "Показывает подробную информацию о скорости или нагрузке сети, к которой подключён датчик.", "item.create.goggles.tooltip.condition3": "При взгляде на жидкостные контейнеры", "item.create.goggles.tooltip.behaviour3": "Показывает детализированную информацию о _Ёмкости_ блока и о хранящейся в нём хранится _Жидкости_.", - "item.create.wrench.tooltip": "WRENCH", + "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": "NOZZLE", + "block.create.nozzle.tooltip": "ФОРСУНКА", "block.create.nozzle.tooltip.summary": "Прикрепите к передней части _вентилятора_, чтобы распределить его влияние на сущностей _во_ _всех_ _направлениях_.", - "block.create.cuckoo_clock.tooltip": "CUCKOO CLOCK", + "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": "TURNTABLE", + "block.create.turntable.tooltip": "ПОВОРОТНЫЙ СТОЛ", "block.create.turntable.tooltip.summary": "Преобразует _силу_ _вращения_ прямиком в морскую болезнь.", - "block.create.portable_fluid_interface.tooltip": "PORTABLE FLUID INTERFACE", - "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": "stockpile_switch", - "block.create.stockpile_switch.tooltip.summary": "Подаёт сигнал красного камня в зависимости от _заполниности_ _прикреплённого_ _ящика_.", + "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": "CONTENT OBSERVER", + "block.create.content_observer.tooltip": "НАБЛЮДАТЕЛЬ ЗА СОДЕРЖИМЫМ", "block.create.content_observer.tooltip.summary": "_Обнаруживает элементы_ внутри _контейнеров_ и _конвейеров_, соответствующие настроенному _фильтру_. Если наблюдаемый инвентарь, ремень или шланг содержит совпадающий элемент, этот компонент излучает сигнал красного камня. Когда наблюдаемая _ воронка передает_ соответствующий предмет, этот компонент испускает _импульс_.", - "block.create.adjustable_crate.tooltip": "ADJUSTABLE CRATE", - "block.create.adjustable_crate.tooltip.summary": "Этот контейнер для хранения позволяет вручную контролировать его емкость. Он может вместить до 16 стэков любого предмета. Поддерживает компараторы.", + "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": "THE ENDLESS CRATE", + "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": "CONTROLLER RAIL", + "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.controller_rail.tooltip.behaviour1": "_Ускоряет_ или _замедляет_ _прошедшие вагонетки_, на величину зависящую от _силы сигнала_. Распространяя сигнал красного камня на соседние контролирующие рельсы. Питание двух контролирующих рельс с разной мощностью приведет к тому, что дорожки между ними будут интерполировать свой сигнал.", - "item.create.sand_paper.tooltip": "SAND PAPER", + "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": "BUILDERS TEA", + "item.create.builders_tea.tooltip": "ЧАЙ СТРОИТЕЛЯ", "item.create.builders_tea.tooltip.summary": "Идеальный напиток для начала дня. _Мотивирует и насыщает_.", - "item.create.refined_radiance.tooltip": "REFINED RADIANCE", + "item.create.refined_radiance.tooltip": "ИЗЫСКАННОЕ СИЯНИЕ", "item.create.refined_radiance.tooltip.summary": "Хроматический материал, _добытый_ _из_ _поглощенного_ _света_.", + "item.create.refined_radiance.tooltip.condition1": "Работа в процессе", + "item.create.refined_radiance.tooltip.behaviour1": "Использование этого материала будет доступно в следующем обновлении.", - "item.create.shadow_steel.tooltip": "SHADOW STEEL", + "item.create.shadow_steel.tooltip": "ВОЗВРАЩЕНИЕ ПУСТОТЫ", "item.create.shadow_steel.tooltip.summary": "Хроматический материал, _добытый_ _в_ _пустоте_.", + "item.create.shadow_steel.tooltip.condition1": "Работа в процессе", + "item.create.shadow_steel.tooltip.behaviour1": "Использование этого материала будет доступно в следующем обновлении.", - "item.create.minecart_coupling.tooltip": "MINECART COUPLING", + "item.create.linked_controller.tooltip": "ПОДКЛЮЧАЕМЫЙ КОНТРОЛЛЕР", + "item.create.linked_controller.tooltip.summary": "Предоставляет _ручной_ _контроль_ над частотами _Беспроводного передатчика редстоун сигнала_, присвоенные его _шести_ кнопкам.", + "item.create.linked_controller.tooltip.condition1": "ПКМ", + "item.create.linked_controller.tooltip.behaviour1": "Включает контроллер. _Управление_ _движением_ перехвачено, пока он активен.", + "item.create.linked_controller.tooltip.condition2": "ПКМ крадучись", + "item.create.linked_controller.tooltip.behaviour2": "Открывает _интерфейс_ _конфигурации_.", + "item.create.linked_controller.tooltip.condition3": "ПКМ по приемнику сигнала редстоуна", + "item.create.linked_controller.tooltip.behaviour3": "Включает _режим привязки_, нажмите одну из _шести кнопок_, чтобы привязать его к _частоте передатчика_.", + "item.create.linked_controller.tooltip.condition4": "ПКМ по кафедре", + "item.create.linked_controller.tooltip.behaviour4": "Помещает контроллер на кафедру для удобства использования. (ПКМ крадучись, чтобы забрать его)", + + "item.create.diving_helmet.tooltip": "ШЛЕМ ДЛЯ ДАЙВИНГА", + "item.create.diving_helmet.tooltip.summary": "Вместе с _медным_ _баллоном_, позволяет владельцу _дышать _ _под водой_ в течение длительного времени.", + "item.create.diving_helmet.tooltip.condition1": "При ношении", + "item.create.diving_helmet.tooltip.behaviour1": "Даёт эффект _Водного Дыхания_, медленно тратя _воздух_ из баллона.", + + "item.create.copper_backtank.tooltip": "МЕДНЫЙ БАЛЛОН", + "item.create.copper_backtank.tooltip.summary": "_Носимый_ _резервуар_ для транспортировки воздуха под давлением.", + "item.create.copper_backtank.tooltip.condition1": "При ношении", + "item.create.copper_backtank.tooltip.behaviour1": "Обеспечивает подачу _воздуха_ под _давлением_ к оборудованию, которое в этом нуждается.", + "item.create.copper_backtank.tooltip.condition2": "При размещении и питании от кинетической энергии", + "item.create.copper_backtank.tooltip.behaviour2": "Собирает и сжимает воздух со скоростью, зависящей от скорости вращения.", + + "item.create.diving_boots.tooltip": "БОТИНКИ ДЛЯ ДАЙВИНГА", + "item.create.diving_boots.tooltip.summary": "Пара _тяжелых_ _ботинок_, позволяющая лучше передвигаться по океанскому дну.", + "item.create.diving_boots.tooltip.condition1": "При ношении", + "item.create.diving_boots.tooltip.behaviour1": "Владелец _тонет_ _быстрее_ и _не_ может _плавать_. Ботинки дают возможность _ходить_ и _прыгать_ под водой. На владельца также больше не влияют механические ремни (передвижение по конвейеру).", + + "item.create.crafting_blueprint.tooltip": "СОЗДАНИЕ ЧЕРТЕЖА", + "item.create.crafting_blueprint.tooltip.summary": "_Разместив_ на стене, его можно использовать для _определения_ _расположения_ _компонентов_ (блоков) для более простого ручного создания предметов. Каждый слот показывает Рецепт.", + "item.create.crafting_blueprint.condition1": "ПКМ по пустому слоту", + "item.create.crafting_blueprint.behaviour1": "Открывает меню _крафта_, позволяющее _настроить_ _рецепт_ и отображаемые предметы.", + "item.create.crafting_blueprint.condition2": "ПКМ по настроенному слоту", + "item.create.crafting_blueprint.behaviour2": "_Применяет_ _заданный_ _рецепт_ с подходящими ингредиентами, из вашего _инвентаря_. _Shift_, чтобы создать целого до _стака_ предметов..", + + "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 секунд. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Поверьте мне, это бесполезно.", - "create.tooltip.randomWipDescription6": "Используя этот пункт, вы тем самым соглашаетесь с нашим отказом от ответственности и соглашаетесь с его условиями.", - "create.tooltip.randomWipDescription7": "Этот, возможно, но не для тебя. Как насчет этого?", - "create.tooltip.randomWipDescription8": "Используя его, вы немедленно пожалеете о своем решении.", + "block.create.peculiar_bell.tooltip": "СТРАННЫЙ КОЛОКОЛ", + "block.create.peculiar_bell.tooltip.summary": "Декоративный _латунный колокол_. Установка его прямо над горящем _Огнем душ_ может вызвать побочные эффекты...с", + + "block.create.haunted_bell.tooltip": "ПРИЗРАЧНЫЙ КОЛОКОЛ", + "block.create.haunted_bell.tooltip.summary": "_Проклятый колокол_ населенный потерянными душами Нижнего мира.", + "block.create.haunted_bell.tooltip.condition1": "При ношении или при звоне", + "block.create.haunted_bell.tooltip.behaviour1": "Подсвечивает ближайшие _места без света_ на которых могут появляться _враждебные мобы_..", "_": "->------------------------] Ponder Content [------------------------<-", - "create.ponder.hold_to_ponder": "Удерживайте [%1$s] для Размышления", + "create.ponder.hold_to_ponder": "Удерживайте [%1$s] для размышления", "create.ponder.subject": "Субъект этой сцены", - "create.ponder.pondering": "Размышляем о...", + "create.ponder.pondering": "Размышляем о/об...", "create.ponder.identify_mode": "Режим Идентификации включён.\nУбрать паузу: [%1$s]", "create.ponder.associated": "Связанные статьи", "create.ponder.close": "Закрыть", @@ -1440,40 +1498,46 @@ "create.ponder.replay": "Воспроизвести снова", "create.ponder.think_back": "Подумать о предыдущем", "create.ponder.slow_text": "Удобное чтение", - "create.ponder.shared.movement_anchors": "С помощью Суперклея или Шасси, более крупные структуры могут быть сдивинуты.", + "create.ponder.exit": "Выйти", + "create.ponder.welcome": "Добро пожаловать в размышления", + "create.ponder.categories": "Категории, доступные в Create", + "create.ponder.index_description": "Кликните по одной из иконок, чтобы узнать о связанных с ней предметах и блоках.", + "create.ponder.index_title": "Содержание размышлений", + "create.ponder.shared.movement_anchors": "С помощью суперклея или шасси, более крупные структуры могут быть сдвинуты.", "create.ponder.shared.rpm32": "32 об./мин.", "create.ponder.shared.sneak_and": "Красться +", - "create.ponder.shared.storage_on_contraption": "Присоединённые к Штуковине инвентари будут подбирать вещи автоматически", + "create.ponder.shared.storage_on_contraption": "Присоединённые к штуковине инвентари будут подбирать вещи автоматически", "create.ponder.shared.behaviour_modify_wrench": "Это поведение может быть изменено Ключом", "create.ponder.shared.rpm8": "8 об./мин.", "create.ponder.shared.ctrl_and": "Ctrl +", "create.ponder.shared.rpm16_source": "Источник: 16 об./мин.", "create.ponder.shared.rpm16": "16 об./мин.", "create.ponder.tag.kinetic_sources": "Кинетические источники", - "create.ponder.tag.kinetic_sources.description": "Компоненты, генерирующие Силу Вращения", + "create.ponder.tag.kinetic_sources.description": "Компоненты, генерирующие силу вращения", + "create.ponder.tag.contraption_actor": "Компоненты штуковин", "create.ponder.tag.contraption_actor.description": "Компоненты, проявляющие особое поведение когда прикреплены к двигающейся штуковине", - "create.ponder.tag.arm_targets": "Цели для Механической Руки", - "create.ponder.tag.arm_targets.description": "Компоненты, которые могут быть выбраны входами или выходами для Механической Руки", - "create.ponder.tag.logistics": "Транспортировка Предметов", + "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": "Опоры Движения", + "create.ponder.tag.movement_anchor": "Опоры движения", "create.ponder.tag.movement_anchor.description": "Компоненты, позволяющие создавать двигающиеся штуковины, оживляя прикрепленную структуру разными способами", "create.ponder.tag.creative": "Творческий режим", - "create.ponder.tag.creative.description": "Компоненты обычычно недоступные в Режиме Выживания", + "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.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.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": "Регулируемые импульсные повторители испускают короткий импульс с задержкой", @@ -1487,10 +1551,750 @@ "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.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_modes.text_3": "Если сборщик настроен на блокировку вращения, то ориентация штуковин никогда не изменится", + + "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": "В обоих случаях Цепные приводы в ряду всегда вращаются с 2x скоростью активированного Цепного механизма", + "create.ponder.chain_gearshift.text_5": "Используя аналоговые сигналы, это умножение может быть настроено более точно между 1 и 2", + "create.ponder.chain_gearshift.text_6": "12 об./мин.", + + "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": "Осмотр желобов в Инженерных очках открывает информацию о направлении движения", + "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": "Творческом жидкостном баке", + "create.ponder.creative_fluid_tank.text_1": "Творческий жидкостный бак может использоваться для обеспечения бесконечного запаса жидкости", + "create.ponder.creative_fluid_tank.text_2": "Щелкните ПКМ предметом, содержащим жидкость, чтобы настроить его", + "create.ponder.creative_fluid_tank.text_3": "Сети труб могут бесконечно вытягивать заданную жидкость из резервуара", + "create.ponder.creative_fluid_tank.text_4": "Любые жидкости, закачанные обратно в творческий жидкостный бак, будут уничтожены", + + "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": "Обработке элементов с помощью автономных активаторов", + "create.ponder.deployer_processing.text_1": "Держа подходящий предмет/инструмент, автономные активаторы могут обрабатывать предметы под собой", + "create.ponder.deployer_processing.text_2": "Принимаемые предметы можно бросить или положить на депо под автономным активатором", + "create.ponder.deployer_processing.text_3": "Когда предметы находятся на конвейере...", + "create.ponder.deployer_processing.text_4": "автономный активатор будет удерживать и обрабатывать их автоматически", + + "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.empty_blaze_burner.text_6": "Однако они не будут подходить для промышленного нагрева", + + "create.ponder.encased_fluid_pipe.header": "Обрамлении Жидкостных труб", + "create.ponder.encased_fluid_pipe.text_1": "Медный корпус можно использовать для украшения декорации труб.", + "create.ponder.encased_fluid_pipe.text_2": "Помимо того, что они скрываются, заключенные в обрамление трубы блокируются в текущем состоянии", + "create.ponder.encased_fluid_pipe.text_3": "Они больше не будут реагировать на добавление или удаление каких-либо соседних блоков", + + "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": "Перемещении жидкостей при помощи медных труб.", + "create.ponder.fluid_pipe_flow.text_1": "Жидкостные трубы могут соединять два или более источников и потребителей жидкости", + "create.ponder.fluid_pipe_flow.text_2": "При помощи гаечного ключа можно создать окно прямому отрезку трубы", + "create.ponder.fluid_pipe_flow.text_3": "Трубы с окнами не будут соединяться ни с какими другими рядом идущими отрезками труб", + "create.ponder.fluid_pipe_flow.text_4": "Приводимые в действие механическими помпами, трубы могут транспортировать жидкости", + "create.ponder.fluid_pipe_flow.text_5": "Сначала жидкость не выкачивается", + "create.ponder.fluid_pipe_flow.text_6": "Как только поток соединит концы, они постепенно перекачают свое содержимое", + "create.ponder.fluid_pipe_flow.text_7": "Таким образом, сами блоки труб никогда «физически» не содержат никакой жидкости", + + "create.ponder.fluid_pipe_interaction.header": "Опустошении и наполнении жидкостных контейнеров", + "create.ponder.fluid_pipe_interaction.text_1": "Концы сети труб могут взаимодействовать с различными блоками", + "create.ponder.fluid_pipe_interaction.text_2": "Любой блок с возможностью хранения жидкости может быть заполнен или опустошен", + "create.ponder.fluid_pipe_interaction.text_3": "Источники прямо перед открытым концом можно откачать...", + "create.ponder.fluid_pipe_interaction.text_4": "...в то время как выливание в незаполненное пространство может создать источники", + "create.ponder.fluid_pipe_interaction.text_5": "Трубы также могут извлекать жидкости непосредственно из нескольких других блоков", + + "create.ponder.fluid_tank_sizes.header": "Размерах жидкостного бака", + "create.ponder.fluid_tank_sizes.text_1": "Жидкостные баки можно объединить для увеличения общей вместимости", + "create.ponder.fluid_tank_sizes.text_2": "Их площадь основания может составлять до 3 блоков в ширину...", + "create.ponder.fluid_tank_sizes.text_3": "...и увеличиваются в высоту более чем на 30 дополнительных уровней", + "create.ponder.fluid_tank_sizes.text_4": "При помощи гаечного ключа можно создать окно на резервуаре", + + "create.ponder.fluid_tank_storage.header": "Хранении жидкостей в жидкостных баках", + "create.ponder.fluid_tank_storage.text_1": "Жидкостные баки можно использовать для хранения большого количества жидкости", + "create.ponder.fluid_tank_storage.text_2": "Трубы могут закачивать и выкачивать жидкости с любой стороны", + "create.ponder.fluid_tank_storage.text_3": "Содержащаяся жидкость может быть измерена с помощью компаратора", + "create.ponder.fluid_tank_storage.text_4": "Однако в режиме выживания жидкость нельзя добавлять или извлекать вручную", + "create.ponder.fluid_tank_storage.text_5": "Вы можете использовать чаши, предметные осушители и дозаторы для опустошения или наполнения содерж. жидкость предметов", + + "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": "Наполнении и осушении источников с помощью Шкива со шлангом", + "create.ponder.hose_pulley.text_1": "Шкивы со шлангом можно использовать для заполнения или осушения больших объёмов жидкости.", + "create.ponder.hose_pulley.text_2": "С помощью кинетической энергии можно регулировать длину шланга", + "create.ponder.hose_pulley.text_3": "Шкив сматывается, если обратить вращение", + "create.ponder.hose_pulley.text_4": "С противоположной стороны можно подключать трубы", + "create.ponder.hose_pulley.text_5": "Присоединённые сети труб могут либо подавать жидкость в шланг...", + "create.ponder.hose_pulley.text_6": "...либо вытягивать её, осушая водоем", + "create.ponder.hose_pulley.text_7": "Скорость заполнения и осушения шкивом полностью зависит от пропускной способности жидкостной сети", + + "create.ponder.hose_pulley_infinite.header": "Пассивном заполнении и осушении больших объёмов жидкости", + "create.ponder.hose_pulley_infinite.text_1": "При развертывании Шкива со шлангом в достаточно большой океан...", + "create.ponder.hose_pulley_infinite.text_2": "Он будет предоставлять/поглощать жидкости без влияния на источник", + "create.ponder.hose_pulley_infinite.text_3": "Сети труб могут неограниченно передавать жидкости из/в такие шкивы", + + "create.ponder.hose_pulley_level.header": "Уровне заполнения и осушения Шкива со шлангом", + "create.ponder.hose_pulley_level.text_1": "При полностью убранном рукаве шланга - он не может работать", + "create.ponder.hose_pulley_level.text_2": "Осушение происходит сверху вниз", + "create.ponder.hose_pulley_level.text_3": "Уровень поверхности окажется чуть ниже того места, где заканчивается шланг", + "create.ponder.hose_pulley_level.text_4": "Наполнение происходит снизу вверх", + "create.ponder.hose_pulley_level.text_5": "Заполняемый бассейн не будет наполняться выше уровня конца шланга", + + "create.ponder.item_drain.header": "Опустошении жидкостных резервуаров с помощью предметных осушителей", + "create.ponder.item_drain.text_1": "Предметные осушители могут извлекать жидкости из предметов", + "create.ponder.item_drain.text_2": "Щелкните ПКМ по нему, чтобы перелить в него жидкость из предмета в ваших руках", + "create.ponder.item_drain.text_3": "Когда предметы подаются со стороны...", + "create.ponder.item_drain.text_4": "...они переворачиваются, выливая содержащуюся в них жидкость", + "create.ponder.item_drain.text_5": "Сети труб теперь могут вытягивать жидкость из внутреннего хранилища осушителей", + + "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": "Транспортировке жидкости при помощи Механических помп", + "create.ponder.mechanical_pump_flow.text_1": "Механические помпы направляют поток в присоединённые сети из труб", + "create.ponder.mechanical_pump_flow.text_2": "Когда работает, стрелка указывает направление потока", + "create.ponder.mechanical_pump_flow.text_3": "Часть сети сзади теперь качает жидкости...", + "create.ponder.mechanical_pump_flow.text_4": "...в то время как часть сети спереди передаёт их наружу", + "create.ponder.mechanical_pump_flow.text_5": "Смена направления вращения изменяет направление потока", + "create.ponder.mechanical_pump_flow.text_6": "Используйте гаечный ключ, чтобы изменить направление помпы вручную", + + "create.ponder.mechanical_pump_speed.header": "Производительности механических помп", + "create.ponder.mechanical_pump_speed.text_1": "Независимо от скорости, Механические помпы оказывают влияние на трубы в радиусе 16 блоков", + "create.ponder.mechanical_pump_speed.text_2": "Ускорение подаваемого вращения изменяет скорость распространения потоков...", + "create.ponder.mechanical_pump_speed.text_3": "...также, как и скорость передачи жидкостей", + "create.ponder.mechanical_pump_speed.text_4": "Помпы могут объединять свою производительность в общих сетях труб", + "create.ponder.mechanical_pump_speed.text_5": "Изменение их направления может помочь сонаправить направление их потоков", + + "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.nixie_tube.text_3": "Щелкните ПКМ с красителем, чтобы изменить цвет их дисплея", + + "create.ponder.piston_pole.header": "Удлинителях Поршня", + "create.ponder.piston_pole.text_1": "Без присоединённых Удлинителей, Механический поршень не может двигаться", + "create.ponder.piston_pole.text_2": "Длина стержня, добавленного к его задней части, определяет Диапазон выдвижения.", + + "create.ponder.portable_fluid_interface.header": "Портативном жидкостном интерфейсе на штуковинах", + "create.ponder.portable_fluid_interface.text_1": "Жидкостные баки на движущихся штуковинах не могут быть доступны ни каким трубам", + "create.ponder.portable_fluid_interface.text_2": "Этот интерфейс может взаимодействовать с жидкостными баками без необходимости останавливать штуковину", + "create.ponder.portable_fluid_interface.text_3": "Установите второй с промежутком в 1 или 2 блока между ними", + "create.ponder.portable_fluid_interface.text_4": "Они установят соединение, когда встретятся", + "create.ponder.portable_fluid_interface.text_5": "Пока они соединены, стационарный интерфейс будет представлять собой ВСЕ баки на штуковине", + "create.ponder.portable_fluid_interface.text_6": "Теперь можно закачать жидкости...", + "create.ponder.portable_fluid_interface.text_7": "...или выкачать их из штуковины", + "create.ponder.portable_fluid_interface.text_8": "Если на какое-то время прекратится обмен содержимым - штуковина продолжит свой путь", + + "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": "Управлении сигналами при помощи Питаемого рычаг-переключателя", + "create.ponder.powered_toggle_latch.text_1": "Питаемый рычаг-переключатель - управляемый редстоуном рычаг", + "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": "Управлении жидкостным потоком с помощью Умных труб", + "create.ponder.smart_pipe.text_1": "Умные трубы могут помочь управлять потоками по типам жидкостей", + "create.ponder.smart_pipe.text_2": "Размещенные непосредственно у источника, они могут указывать тип извлекаемой жидкости", + "create.ponder.smart_pipe.text_3": "Просто щелкните ПКМ на слоте фильтра с любым предметом, содержащим нужную жидкость", + "create.ponder.smart_pipe.text_4": "И при размещении глубже по сети труб умные трубы будут пропускать только подходящие жидкости.", + + "create.ponder.speedometer.header": "Мониторинге Кинетической информации при помощи Спидометра", + "create.ponder.speedometer.text_1": "Спидометры отображают текущую скорость присоединённых компонентов", + "create.ponder.speedometer.text_2": "При ношении Инженерных очков игрок может получить более полную информацию от прибора", + "create.ponder.speedometer.text_3": "Компараторы могут испускать аналоговый Редстоун сигнал относительно измерений спидометра", + + "create.ponder.spout_filling.header": "Наполнении предметов при помощи дозатора", + "create.ponder.spout_filling.text_1": "Дозатор может заполнять подходящие предметы, расположенные под ним", + "create.ponder.spout_filling.text_2": "К содержимому дозатора невозможно получить доступ вручную.", + "create.ponder.spout_filling.text_3": "Вместо этого можно использовать трубы для подачи в него жидкостей", + "create.ponder.spout_filling.text_4": "Наполняемые предметы могут быть размещены на депо под дозатором", + "create.ponder.spout_filling.text_5": "Когда предметы подаются конвейером...", + "create.ponder.spout_filling.text_6": "Дозатор будет удерживать и обрабатывать их автоматически", + + "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": "При ношении Инженерных очков игрок может получить более полную информацию от прибора", + "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": "Управлении потоком жидкости с помощью вентилей", + "create.ponder.valve_pipe.text_1": "Жидкостные вентили помогают контролировать распространение жидкостей по сетям труб", + "create.ponder.valve_pipe.text_2": "Их входной вал контролирует, разрешена ли подача жидкости в данный момент", + "create.ponder.valve_pipe.text_3": "При вращении в направлении открытия - клапан откроется", + "create.ponder.valve_pipe.text_4": "Его можно снова закрыть, изменив направление входного вращения", + + "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/main/resources/assets/create/lang/zh_cn.json b/src/main/resources/assets/create/lang/zh_cn.json index 342ee9146..4880457e5 100644 --- a/src/main/resources/assets/create/lang/zh_cn.json +++ b/src/main/resources/assets/create/lang/zh_cn.json @@ -1,10 +1,6 @@ { - - - "_": "->------------------------] Game Elements [------------------------<-", - - "block.create.acacia_window": "金合欢窗户", - "block.create.acacia_window_pane": "金合欢窗户板", + "block.create.acacia_window": "金合欢木窗户", + "block.create.acacia_window_pane": "金合欢木窗户板", "block.create.adjustable_chain_gearshift": "可调节链式传动箱", "block.create.adjustable_crate": "可调节板条箱", "block.create.adjustable_pulse_repeater": "可调节脉冲中继器", @@ -26,12 +22,14 @@ "block.create.andesite_tunnel": "安山岩隧道", "block.create.basin": "工作盆", "block.create.belt": "传送带", - "block.create.birch_window": "白桦窗户", - "block.create.birch_window_pane": "白桦窗户板", + "block.create.birch_window": "白桦木窗户", + "block.create.birch_window_pane": "白桦木窗户板", + "block.create.black_nixie_tube": "黑色辉光管", "block.create.black_sail": "黑色风帆", "block.create.black_seat": "黑色坐垫", "block.create.black_valve_handle": "黑色阀门手轮", "block.create.blaze_burner": "烈焰人燃烧室", + "block.create.blue_nixie_tube": "蓝色辉光管", "block.create.blue_sail": "蓝色风帆", "block.create.blue_seat": "蓝色坐垫", "block.create.blue_valve_handle": "蓝色阀门手轮", @@ -41,6 +39,7 @@ "block.create.brass_encased_shaft": "黄铜传动杆箱", "block.create.brass_funnel": "黄铜漏斗", "block.create.brass_tunnel": "黄铜隧道", + "block.create.brown_nixie_tube": "棕色辉光管", "block.create.brown_sail": "棕色风帆", "block.create.brown_seat": "棕色坐垫", "block.create.brown_valve_handle": "棕色阀门手轮", @@ -53,11 +52,12 @@ "block.create.chiseled_weathered_limestone": "錾制风化石灰岩", "block.create.chocolate": "巧克力", "block.create.chute": "溜槽", - "block.create.clockwork_bearing": "时钟轴承", + "block.create.clockwork_bearing": "发条轴承", "block.create.clutch": "离合器", "block.create.cogwheel": "齿轮", "block.create.content_observer": "物品侦测器", "block.create.controller_rail": "控制铁轨", + "block.create.copper_backtank": "Copper Backtank", "block.create.copper_block": "铜块", "block.create.copper_casing": "铜机壳", "block.create.copper_ore": "铜矿石", @@ -67,11 +67,12 @@ "block.create.creative_crate": "创造板条箱", "block.create.creative_fluid_tank": "创造流体储罐", "block.create.creative_motor": "创造马达", - "block.create.crimson_window": "绯红窗户", - "block.create.crimson_window_pane": "绯红窗户板", + "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_nixie_tube": "青色辉光管", "block.create.cyan_sail": "青色风帆", "block.create.cyan_seat": "青色坐垫", "block.create.cyan_valve_handle": "青色阀门手轮", @@ -178,20 +179,23 @@ "block.create.granite_cobblestone_stairs": "花岗岩圆石楼梯", "block.create.granite_cobblestone_wall": "花岗岩圆石墙", "block.create.granite_pillar": "竖纹花岗岩", + "block.create.gray_nixie_tube": "灰色辉光管", "block.create.gray_sail": "灰色风帆", "block.create.gray_seat": "灰色坐垫", "block.create.gray_valve_handle": "灰色阀门手轮", + "block.create.green_nixie_tube": "绿色辉光管", "block.create.green_sail": "绿色风帆", "block.create.green_seat": "绿色坐垫", "block.create.green_valve_handle": "绿色阀门手轮", "block.create.hand_crank": "手摇曲柄", + "block.create.haunted_bell": "森魂钟", "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.jungle_window": "丛林木窗户", + "block.create.jungle_window_pane": "丛林木窗户板", "block.create.large_cogwheel": "大齿轮", "block.create.layered_andesite": "层叠安山岩", "block.create.layered_dark_scoria": "层叠深色熔渣", @@ -202,12 +206,16 @@ "block.create.layered_limestone": "层叠石灰岩", "block.create.layered_scoria": "层叠熔渣", "block.create.layered_weathered_limestone": "层叠风化石灰岩", + "block.create.lectern_controller": "遥控器讲台", + "block.create.light_blue_nixie_tube": "淡蓝色辉光管", "block.create.light_blue_sail": "淡蓝色风帆", "block.create.light_blue_seat": "淡蓝色坐垫", "block.create.light_blue_valve_handle": "淡蓝色阀门手轮", + "block.create.light_gray_nixie_tube": "淡灰色辉光管", "block.create.light_gray_sail": "淡灰色风帆", "block.create.light_gray_seat": "淡灰色坐垫", "block.create.light_gray_valve_handle": "淡灰色阀门手轮", + "block.create.lime_nixie_tube": "黄绿色辉光管", "block.create.lime_sail": "黄绿色风帆", "block.create.lime_seat": "黄绿色坐垫", "block.create.lime_valve_handle": "黄绿色阀门手轮", @@ -224,6 +232,7 @@ "block.create.limestone_pillar": "竖纹石灰岩", "block.create.linear_chassis": "机壳底盘", "block.create.lit_blaze_burner": "烈焰人燃烧室(已点燃)", + "block.create.magenta_nixie_tube": "品红色辉光管", "block.create.magenta_sail": "品红色风帆", "block.create.magenta_seat": "品红色坐垫", "block.create.magenta_valve_handle": "品红色阀门手轮", @@ -242,15 +251,15 @@ "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.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": "辉光管", @@ -262,15 +271,15 @@ "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.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": "安山岩铺路石楼梯", @@ -307,6 +316,8 @@ "block.create.paved_weathered_limestone_slab": "风化石灰岩铺路石台阶", "block.create.paved_weathered_limestone_stairs": "风化石灰岩铺路石楼梯", "block.create.paved_weathered_limestone_wall": "风化石灰岩铺路石墙", + "block.create.peculiar_bell": "奇异钟", + "block.create.pink_nixie_tube": "粉红色辉光管", "block.create.pink_sail": "粉红色风帆", "block.create.pink_seat": "粉红色坐垫", "block.create.pink_valve_handle": "粉红色阀门手轮", @@ -341,10 +352,12 @@ "block.create.powered_toggle_latch": "转换锁存器", "block.create.pulley_magnet": "滑轮磁铁", "block.create.pulse_repeater": "脉冲中继器", + "block.create.purple_nixie_tube": "紫色辉光管", "block.create.purple_sail": "紫色风帆", "block.create.purple_seat": "紫色坐垫", "block.create.purple_valve_handle": "紫色阀门手轮", "block.create.radial_chassis": "旋转底盘", + "block.create.red_nixie_tube": "红色辉光管", "block.create.red_sail": "红色风帆", "block.create.red_seat": "红色坐垫", "block.create.red_valve_handle": "红色阀门手轮", @@ -368,7 +381,7 @@ "block.create.scoria_cobblestone_stairs": "熔渣圆石楼梯", "block.create.scoria_cobblestone_wall": "熔渣圆石墙", "block.create.scoria_pillar": "竖纹熔渣", - "block.create.secondary_linear_chassis": "机壳底盘2号", + "block.create.secondary_linear_chassis": "机壳底盘 2 号", "block.create.sequenced_gearshift": "可编程齿轮箱", "block.create.shadow_steel_casing": "暗影机壳", "block.create.shaft": "传动杆", @@ -376,8 +389,8 @@ "block.create.smart_fluid_pipe": "智能流体管道", "block.create.speedometer": "速度表", "block.create.spout": "注液器", - "block.create.spruce_window": "云杉窗户", - "block.create.spruce_window_pane": "云杉窗户板", + "block.create.spruce_window": "云杉木窗户", + "block.create.spruce_window_pane": "云杉木窗户板", "block.create.sticker": "黏着器", "block.create.sticky_mechanical_piston": "黏性动力活塞", "block.create.stockpile_switch": "存量转换器", @@ -401,29 +414,29 @@ "block.create.weathered_limestone_cobblestone_wall": "风化石灰岩圆石墙", "block.create.weathered_limestone_pillar": "竖纹风化石灰岩", "block.create.weighted_ejector": "弹射置物台", + "block.create.white_nixie_tube": "白色辉光管", "block.create.white_sail": "白色风帆", "block.create.white_seat": "白色坐垫", "block.create.white_valve_handle": "白色阀门手轮", "block.create.windmill_bearing": "风车轴承", "block.create.wooden_bracket": "木质支架", + "block.create.yellow_nixie_tube": "黄色辉光管", "block.create.yellow_sail": "黄色风帆", "block.create.yellow_seat": "黄色坐垫", "block.create.yellow_valve_handle": "黄色阀门手轮", "block.create.zinc_block": "锌块", "block.create.zinc_ore": "锌矿石", - + "enchantment.create.capacity": "扩容", + "enchantment.create.potato_recovery": "土豆回收", "entity.create.contraption": "装置", + "entity.create.crafting_blueprint": "合成蓝图", "entity.create.gantry_contraption": "起重机装置", + "entity.create.potato_projectile": "被发射的土豆", "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": "巧克力棒", @@ -440,10 +453,13 @@ "item.create.chocolate_glazed_berries": "巧克力包层浆果", "item.create.chromatic_compound": "异彩化合物", "item.create.cinder_flour": "下界面粉", + "item.create.copper_backtank": "铜制背罐", "item.create.copper_ingot": "铜锭", "item.create.copper_nugget": "铜粒", "item.create.copper_sheet": "铜板", "item.create.crafter_slot_cover": "合成器盖板", + "item.create.crafting_blueprint": "合成蓝图", + "item.create.creative_blaze_cake": "创造模式烈焰蛋糕", "item.create.crushed_aluminum_ore": "粉碎铝矿石", "item.create.crushed_brass": "粉碎黄铜", "item.create.crushed_copper_ore": "粉碎铜矿石", @@ -458,7 +474,8 @@ "item.create.crushed_tin_ore": "粉碎锡矿石", "item.create.crushed_uranium_ore": "粉碎铀矿石", "item.create.crushed_zinc_ore": "粉碎锌矿石", - "item.create.deforester": "树林毁灭者", + "item.create.diving_boots": "潜水靴", + "item.create.diving_helmet": "潜水头盔", "item.create.dough": "面团", "item.create.electron_tube": "电子管", "item.create.empty_blaze_burner": "空的烈焰人燃烧室", @@ -468,17 +485,20 @@ "item.create.furnace_minecart_contraption": "装配过的动力矿车", "item.create.goggles": "工程师护目镜", "item.create.golden_sheet": "金板", - "item.create.handheld_blockzapper": "手持式方块放置器", "item.create.handheld_worldshaper": "手持式环境塑形器", "item.create.honey_bucket": "蜂蜜桶", "item.create.honeyed_apple": "蜜渍苹果", - "item.create.integrated_circuit": "集成电路板", + "item.create.incomplete_cogwheel": "齿轮(半成品)", + "item.create.incomplete_large_cogwheel": "大齿轮(半成品)", + "item.create.incomplete_precision_mechanism": "精密构件(半成品)", "item.create.iron_sheet": "铁板", - "item.create.lapis_sheet": "青金石板", + "item.create.linked_controller": "无线红石遥控器", "item.create.minecart_contraption": "装配过的矿车", "item.create.minecart_coupling": "矿车连轴器", "item.create.polished_rose_quartz": "磨制玫瑰石英", + "item.create.potato_cannon": "土豆加农炮", "item.create.powdered_obsidian": "黑曜石粉末", + "item.create.precision_mechanism": "精密构件", "item.create.propeller": "扇叶", "item.create.red_sand_paper": "红沙砂纸", "item.create.refined_radiance": "光辉石", @@ -497,23 +517,19 @@ "item.create.wrench": "扳手", "item.create.zinc_ingot": "锌锭", "item.create.zinc_nugget": "锌粒", - - - "_": "->------------------------] Advancements [------------------------<-", - "advancement.create.root": "欢迎来到机械动力", - "advancement.create.root.desc": "是时候来制作一些超赞的机械结构了!", - "advancement.create.andesite_alloy": "头韵狂魔(Alliterations Aplenty)", + "advancement.create.root.desc": "是时候来制作一些超赞的机械装置了!", + "advancement.create.andesite_alloy": "头韵狂魔(Alliterations Aplenty)", "advancement.create.andesite_alloy.desc": "机械动力的材料名字都很古怪,安山合金(Andesite Alloy)就是其中之一。", "advancement.create.its_alive": "鲜活的机械生命", - "advancement.create.its_alive.desc": "首次激活齿轮结构的旋转。", + "advancement.create.its_alive.desc": "首次激活动力学组件。", "advancement.create.shifting_gears": "换挡,加速,起飞!", - "advancement.create.shifting_gears.desc": "将大齿轮连接到小齿轮上,可以改变结构的转速。", + "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": "躲起来!", "advancement.create.tunnel.desc": "用隧道装饰传送带。", "advancement.create.splitter_tunnel": "分而治之", "advancement.create.splitter_tunnel.desc": "用黄铜隧道设计一个分流器。", @@ -530,7 +546,7 @@ "advancement.create.fan_lava": "地热取暖", "advancement.create.fan_lava.desc": "被熔炼气流烤的酥脆。", "advancement.create.fan_water": "奇妙的洗涤流程", - "advancement.create.fan_water.desc": "被洗涤气流洗了个澡。", + "advancement.create.fan_water.desc": "在洗涤气流里洗了个澡。", "advancement.create.fan_smoke": "动力风箱", "advancement.create.fan_smoke.desc": "被烟熏气流熏得满脸黑。", "advancement.create.wrench": "细节调整", @@ -541,25 +557,25 @@ "advancement.create.speedometer.desc": "放置一个速度表,并且带上工程师护目镜来读取速度数据", "advancement.create.stressometer": "精密的应力控制", "advancement.create.stressometer.desc": "放置一个应力表,并且带上工程师护目镜来读取应力数据", - "advancement.create.aesthetics": "美观,即是一切!", + "advancement.create.aesthetics": "什么叫美学,这就叫美学!", "advancement.create.aesthetics.desc": "将支架放在传动杆,管道和齿轮上。", - "advancement.create.reinforced": "Boom~ 加强!", + "advancement.create.reinforced": "什么叫强化,这就叫强化!", "advancement.create.reinforced.desc": "在传动杆,管道和传送带上使用机壳加固。", - "advancement.create.water_wheel": "治水", + "advancement.create.water_wheel": "掌控水流", "advancement.create.water_wheel.desc": "放置一个水车并且让它开始旋转", - "advancement.create.chocolate_wheel": "味美动力", + "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.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": "安山时代", "advancement.create.andesite_casing.desc": "使用安山合金和木头来合成一个安山机壳", "advancement.create.mechanical_drill": "坚如磐石,势如破竹", "advancement.create.mechanical_drill.desc": "放置一个动力钻头并且为其供能", @@ -581,13 +597,13 @@ "advancement.create.compact.desc": "使用辊压机在工作盆中压缩一些物品", "advancement.create.brass": "真正的合金", "advancement.create.brass.desc": "使用粉碎锌矿石和粉碎铜矿石来制作粉碎黄铜", - "advancement.create.brass_casing": "黄铜纪元", + "advancement.create.brass_casing": "黄铜时代", "advancement.create.brass_casing.desc": "用黄铜和木头制作一个黄铜机壳", - "advancement.create.copper_casing": "铜之纪元", + "advancement.create.copper_casing": "铜器时代", "advancement.create.copper_casing.desc": "使用铜和木头制作一个铜制机壳", "advancement.create.spout": "哗啦啦", "advancement.create.spout.desc": "观察注液器灌满物品。", - "advancement.create.spout_potion": "全球啤酒厂", + "advancement.create.spout_potion": "环球酿造厂", "advancement.create.spout_potion.desc": "观察注液器注入药水到玻璃瓶。", "advancement.create.chocolate": "幻想世界", "advancement.create.chocolate.desc": "获取一桶熔融巧克力。", @@ -603,29 +619,29 @@ "advancement.create.pipe_spill.desc": "观察管道的开口端将流体排放或放置到世界中。", "advancement.create.hose_pulley": "工业泄漏", "advancement.create.hose_pulley.desc": "放下一个软管滑轮,观察它排干或填充一大片液体。", - "advancement.create.infinite_water": "排干海洋", + "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": "美梦不饶人", "advancement.create.infinite_chocolate.desc": "从大到足以被被视为无限的巧克力海中抽取巧克力。", "advancement.create.crafter": "自动化装配", "advancement.create.crafter.desc": "放置一些机械合成台并且为其供能", "advancement.create.clockwork_bearing": "巧械时钟", - "advancement.create.clockwork_bearing.desc": "组装安装在发条轴承上的结构。", + "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": "工程师的眼中钉", "advancement.create.speed_controller.desc": "放置一个转速控制器,这是换档的终极装置。", "advancement.create.flywheel": "工厂之心", "advancement.create.flywheel.desc": "将引擎成功连接到飞轮。", - "advancement.create.overstress_flywheel": "高压", + "advancement.create.overstress_flywheel": "压力山大", "advancement.create.overstress_flywheel.desc": "过载熔炉引擎。", - "advancement.create.integrated_circuit": "复杂运算", - "advancement.create.integrated_circuit.desc": "组装集成电路。", - "advancement.create.mechanical_arm": "忙碌的手!", + "advancement.create.precision_mechanism": "高新技术", + "advancement.create.precision_mechanism.desc": "装配一个精密构件。", + "advancement.create.mechanical_arm": "飞转的手!", "advancement.create.mechanical_arm.desc": "制作机械臂,选择输入和输出,放置并给予它动力,然后看着它为你完成所有工作。", "advancement.create.musical_arm": "没人能在我的 BGM 里打败我!", "advancement.create.musical_arm.desc": "使用动力臂播放唱片。", @@ -645,39 +661,43 @@ "advancement.create.shadow_steel.desc": "制作一些暗影钢", "advancement.create.refined_radiance": "明亮而启灵", "advancement.create.refined_radiance.desc": "制作一个光辉石", - "advancement.create.chromatic_age": "异彩纪元", + "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": "biu biu biu!", "advancement.create.extendo_grip.desc": "获得一个伸缩机械手", + "advancement.create.potato_cannon": "Fwoomp!", + "advancement.create.potato_cannon.desc": "用土豆加农炮击杀一个生物。", "advancement.create.dual_extendo_grip": "biu——biu——biu——", "advancement.create.dual_extendo_grip.desc": "双持伸缩机械手,超人般的触碰距离。", "advancement.create.eob": "Beta 版结束", "advancement.create.eob.desc": "期待未来会有更多的内容。<3", - - - "_": "->------------------------] UI & Messages [------------------------<-", - "itemGroup.create.base": "机械动力", - "itemGroup.create.palettes": "机械动力建筑方块", - + "itemGroup.create.palettes": "机械动力丨建筑方块", "death.attack.create.crush": "%1$s被压扁了", + "death.attack.create.crush.player": "%1$s被%2$s推进了粉碎机", "death.attack.create.fan_fire": "%1$s试图接受热风的洗礼", + "death.attack.create.fan_fire.player": "%2$s给了%1$s一次热风的洗礼", "death.attack.create.fan_lava": "%1$s在接受热风的洗礼中浴火焚身", + "death.attack.create.fan_lava.player": "%1$s被%2$s火化了", "death.attack.create.mechanical_drill": "%1$s被钻头钻的坏掉了", + "death.attack.create.mechanical_drill.player": "%1$s因为%2$s和钻头来了一次亲密接触", "death.attack.create.mechanical_saw": "%1$s被圆锯切成了两截", + "death.attack.create.mechanical_saw.player": "%1$s被%2$s按在圆锯上切碎了", + "death.attack.create.potato_cannon": "%1$s被%2$s的土豆糊了一脸", + "death.attack.create.potato_cannon.item": "%1$s被%2$s用%3$s射死了", "death.attack.create.cuckoo_clock_explosion": "%1$s被布谷鸟钟炸得粉身碎骨", - + "death.attack.create.cuckoo_clock_explosion.player": "%1$s被布谷鸟钟炸得粉身碎骨", "create.block.deployer.damage_source_name": "二五仔机械手", "create.block.cart_assembler.invalid": "请将矿车装配器放置在铁轨上", - + "create.menu.return": "返回上一级菜单", + "create.menu.configure": "配置...", + "create.menu.ponder_index": "思索内容清单", + "create.menu.only_ingame": "仅在游戏内暂停菜单中可用", + "create.menu.project_page": "在CurseForge上查看", + "create.menu.report_bugs": "报告Create的漏洞", + "create.menu.support": "支持我们", "create.recipe.crushing": "粉碎", "create.recipe.milling": "研磨", "create.recipe.fan_washing": "批量洗涤", @@ -688,25 +708,34 @@ "create.recipe.fan_blasting.fan": "在熔岩后放置鼓风机", "create.recipe.pressing": "金属压片", "create.recipe.mixing": "混合搅拌", + "create.recipe.deploying": "使用", "create.recipe.automatic_shapeless": "自动搅拌", "create.recipe.automatic_brewing": "自动酿造", "create.recipe.packing": "压块塑形", "create.recipe.automatic_packing": "自动打包", - "create.recipe.sawing": "板材切割", - "create.recipe.mechanical_crafting": "自动合成", + "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.sequenced_assembly": "序列组装", + "create.recipe.assembly.next": "下一步:%1$s", + "create.recipe.assembly.step": "第%1$s步:", + "create.recipe.assembly.progress": "组装进度:%1$s/%2$s", + "create.recipe.assembly.pressing": "进行辊压", + "create.recipe.assembly.spout_filling_fluid": "注入%1$s", + "create.recipe.assembly.deploying_item": "安装%1$s", + "create.recipe.assembly.cutting": "用动力锯切割", + "create.recipe.assembly.repeat": "该序列需要重复 %1$s 次", + "create.recipe.assembly.junk": "随机废料", + "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": "宽度", @@ -720,54 +749,44 @@ "create.generic.unit.rpm": "RPM", "create.generic.unit.stress": "su", "create.generic.unit.degrees": "°", - "create.generic.unit.millibuckets":"%1$smB", + "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.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.searchDiagonal": "对角线延伸", + "create.gui.terrainzapper.searchFuzzy": "忽略质料分界", + "create.gui.terrainzapper.patternSection": "样式", + "create.gui.terrainzapper.pattern.solid": "填满", + "create.gui.terrainzapper.pattern.checkered": "棋盘格", + "create.gui.terrainzapper.pattern.inversecheckered": "反转棋盘格", + "create.gui.terrainzapper.pattern.chance25": "随机填充 25%", + "create.gui.terrainzapper.pattern.chance50": "随机填充 50%", + "create.gui.terrainzapper.pattern.chance75": "随机填充 75%", "create.gui.terrainzapper.placement": "放置模式", "create.gui.terrainzapper.placement.merged": "结合", "create.gui.terrainzapper.placement.attached": "依附", @@ -776,6 +795,8 @@ "create.gui.terrainzapper.brush.cuboid": "矩形体", "create.gui.terrainzapper.brush.sphere": "球体", "create.gui.terrainzapper.brush.cylinder": "圆柱体", + "create.gui.terrainzapper.brush.surface": "表面", + "create.gui.terrainzapper.brush.cluster": "簇状", "create.gui.terrainzapper.tool": "填充类型", "create.gui.terrainzapper.tool.fill": "填充", "create.gui.terrainzapper.tool.place": "复写", @@ -783,28 +804,14 @@ "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.terrainzapper.shiftRightClickToSet": "按住 Shift 右击以设置塑形类型", + "create.terrainzapper.usingBlock": "使用:%1$s", + "create.terrainzapper.leftClickToSet": "鼠标左击一个方块以设置填充材料", "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": "停止时只在初始位置才将装置方块化", @@ -813,38 +820,33 @@ "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": "始终面朝前进方向", "create.contraptions.cart_movement_mode.rotate_paused": "矿车转向时机器停止工作", - "create.contraptions.cart_movement_mode.rotation_locked": "装置方向保持不变", + "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.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": "无法组装该装置:", "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": "结构中的方块数量过多。\n配置中的最大数量限制为:%1$s", - "create.gui.assembly.exception.tooManyPistonPoles": "活塞加装的活塞杆数量过多。\n配置中的最大数量限制为:%1$s", + "create.gui.assembly.exception.chunkNotLoaded": "位于 [%1$s,%2$s,%3$s] 的方块未处于加载区块", + "create.gui.assembly.exception.structureTooLarge": "装置中的方块数量过多。", + "create.gui.assembly.exception.tooManyPistonPoles": "活塞加装的活塞杆数量过多。", "create.gui.assembly.exception.noPistonPoles": "活塞缺失部分活塞杆", - "create.gui.assembly.exception.not_enough_sails": "相接的结构所包含的类风帆方块的数量不足。%1$s\n最低需要 %2$s 个方块", - "create.gui.goggles.base_value": "应力基础值", + "create.gui.assembly.exception.not_enough_sails": "相接的结构所包含的类风帆方块的数量不足。%1$s", "create.gui.gauge.info_header": "仪表信息:", "create.gui.speedometer.title": "旋转速度", "create.gui.stressometer.title": "网络应力", @@ -871,8 +873,6 @@ "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.wait": "等待", - "create.gui.sequenced_gearshift.instruction.wait.duration": "间隔", "create.gui.sequenced_gearshift.instruction.end": "停止", "create.gui.sequenced_gearshift.instruction.await.descriptive": "等待新的红石脉冲", "create.gui.sequenced_gearshift.instruction.await": "等待", @@ -881,18 +881,16 @@ "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.noTarget": "按住 Ctrl 选择空气方块。", "create.schematicAndQuill.abort": "删除选择。", "create.schematicAndQuill.title": "蓝图名:", "create.schematicAndQuill.convert": "立即保存并部署", "create.schematicAndQuill.fallbackName": "我的蓝图", "create.schematicAndQuill.saved": "另存为%1$s", - - "create.schematic.invalid":"[!] 无效的项目", + "create.schematic.invalid": "[!] 无效的项目", "create.schematic.position": "位置", "create.schematic.rotation": "旋转", "create.schematic.rotation.none": "无", @@ -911,33 +909,31 @@ "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.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.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.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.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.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.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": "蓝图桌", @@ -957,7 +953,7 @@ "create.gui.schematicannon.option.replaceWithSolid": "用固体方块替换工作区域内的方块", "create.gui.schematicannon.option.replaceWithAny": "用任何方块替换工作区域内的方块", "create.gui.schematicannon.option.replaceWithEmpty": "用空气替换工作区域内的方块", - "create.gui.schematicannon.option.skipMissing": "绕过缺少的方块", + "create.gui.schematicannon.option.skipMissing": "跳过缺少的方块", "create.gui.schematicannon.option.skipTileEntities": "保护存储方块", "create.gui.schematicannon.slot.gunpowder": "向蓝图加农炮添加火药以提供动力", "create.gui.schematicannon.slot.listPrinter": "在此处放置书以打印蓝图所需的材料清单", @@ -968,28 +964,25 @@ "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.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.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.materialChecklist.blocksNotLoaded": "*免责声明* ", "create.gui.filter.deny_list": "黑名单", "create.gui.filter.deny_list.description": "只通过不在黑名单中的物品,如果黑名单为空,所有物品都可以通过", "create.gui.filter.allow_list": "白名单", @@ -998,7 +991,6 @@ "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": "可食用", @@ -1030,15 +1022,20 @@ "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.added_by.inverted": "不由%1$s添加", + "create.item_attributes.shulker_level": "潜影盒是%1$s的", + "create.item_attributes.shulker_level.inverted": "潜影盒不是%1$s的", + "create.item_attributes.shulker_level.full": "满", + "create.item_attributes.shulker_level.empty": "空", + "create.item_attributes.shulker_level.partial": "部分填充", "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": "已达到最高附魔等级", "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_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编写", @@ -1059,9 +1056,8 @@ "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.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": "任意匹配白名单(任何)", @@ -1071,11 +1067,8 @@ "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.holdKey": "按住 [%1$s]", - "create.tooltip.holdKeyOrKey": "按住 [%1$s] 或 [%2$s]", "create.tooltip.keyShift": "Shift", "create.tooltip.keyCtrl": "Ctrl", "create.tooltip.speedRequirement": "需求转速:%1$s", @@ -1091,27 +1084,21 @@ "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.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.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": "轮询调度", @@ -1119,30 +1106,39 @@ "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.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.tooltip.brass_tunnel.contains": "目前分配:", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "鼠标右击取出", + "create.linked_controller.bind_mode": "绑定模式激活", + "create.linked_controller.press_keybind": "按下%1$s、%2$s、%3$s、%4$s、%5$s或%6$s,可以将该频率绑定到按下的按键上。", + "create.linked_controller.key_bound": "该频率已绑定到%1$s", + "create.crafting_blueprint.crafting_slot": "原料槽", + "create.crafting_blueprint.filter_items_viable": "可以使用过滤器", + "create.crafting_blueprint.display_slot": "展示槽", + "create.crafting_blueprint.inferred": "已根据合成配方自动设定", + "create.crafting_blueprint.manually_assigned": "手动设定", + "create.crafting_blueprint.secondary_display_slot": "次要展示槽", + "create.crafting_blueprint.optional": "可选", + "create.potato_cannon.ammo.attack_damage": "%1$s 攻击伤害", + "create.potato_cannon.ammo.reload_ticks": "%1$s 装弹时间(Ticks)", + "create.potato_cannon.ammo.knockback": "%1$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.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.empty_bearing": "_空手右击_轴承,可以将你新建造的结构_接到_轴承上。", "create.hint.full_deployer.title": "机械手物品溢出", "create.hint.full_deployer": "_机械手_包含_过剩的物品,_需要被_提取。你需要_使用_料斗,__漏斗_或其他方法将溢出释放出来。", - "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "这是一个实例层", "create.gui.config.overlay3": "点击拖拽你的鼠标", @@ -1151,31 +1147,50 @@ "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]: 服务器恢复到正常速度 :D", - "create.command.killTPSCommand.status.usage.0": "[Create]: 用 /killtps stop 来让服务器的TPS速度变回正常", - "create.command.killTPSCommand.status.usage.1": "[Create]: 用 /killtps start 来手动降低服务器TPS速度", + "create.command.killTPSCommand.status.slowed_by.0": "[Create]: 服务器现在的 TPS 速度被降低为 %s ms :o", + "create.command.killTPSCommand.status.slowed_by.1": "[Create]: 服务器现在的 TPS 速度被降低为 >:)", + "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": "这一矿车装置似乎太大了,无法变为拾捡状态", - - "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.contraption.minecart_contraption_illegal_pickup": "一股神秘的力量将这一装置与世界牢牢绑定在了一起。", + "create.subtitle.contraption_disassemble": "结构:停止移动", + "create.subtitle.peculiar_bell_use": "奇异钟:鸣响", + "create.subtitle.mixing": "搅拌器:搅拌声", + "create.subtitle.mechanical_press_activation_belt": "辊压机:撞击传送带", + "create.subtitle.fwoomp": "土豆加农炮:发射", + "create.subtitle.worldshaper_place": "环境塑型器:放置方块", + "create.subtitle.crushing_1": "磨碎声", + "create.subtitle.depot_slide": "物品:滑入", + "create.subtitle.saw_activate_stone": "动力锯:切割", "create.subtitle.blaze_munch": "烈焰人:咀嚼", - - - "_": "->------------------------] Item Descriptions [------------------------<-", - + "create.subtitle.funnel_flap": "漏斗:垂帘碰撞", + "create.subtitle.schematicannon_finish": "蓝图加农炮:叮", + "create.subtitle.haunted_bell_use": "森魂钟:鸣响", + "create.subtitle.scroll_value": "拨码输入:咔哒", + "create.subtitle.crafter_craft": "动力合成器:合成中", + "create.subtitle.controller_put": "遥控器:放进讲台", + "create.subtitle.cranking": "手摇曲柄:转动", + "create.subtitle.wrench_remove": "组件:被破坏", + "create.subtitle.cogs": "齿轮:嘎吱作响", + "create.subtitle.slime_added": "粘液:挤碎声", + "create.subtitle.wrench_rotate": "扳手:拧动", + "create.subtitle.potato_hit": "土豆:击中", + "create.subtitle.saw_activate_wood": "动力锯:切割", + "create.subtitle.haunted_bell_convert": "奇异钟:转化", + "create.subtitle.deployer_polish": "机械手:打磨物品", + "create.subtitle.deny": "提示声:出错", + "create.subtitle.controller_click": "遥控器:按下按钮", + "create.subtitle.schematicannon_launch_block": "蓝图加农炮:发射", + "create.subtitle.copper_armor_equip": "潜水装备:铿锵", + "create.subtitle.controller_take": "讲台:取走物品", + "create.subtitle.mechanical_press_activation": "辊压机:工作中", + "create.subtitle.contraption_assemble": "结构:开始移动", + "create.subtitle.crafter_click": "动力合成器:咔哒声", + "create.subtitle.depot_plop": "物品:着地", + "create.subtitle.confirm": "提示声:接受", "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", @@ -1184,162 +1199,16 @@ "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": "会使得玩家坐在_坐垫_上,L-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": "可以在_置物台_放置或取出物品。可以与_传送带_交互的方块或装置也可以与_置物台_交互。", - + "block.create.seat.tooltip.behaviour1": "会使得玩家坐在_坐垫_上,按下左 Shift 可离开_坐垫_。", "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": "当在快捷栏时", @@ -1350,16 +1219,6 @@ "item.create.wand_of_symmetry.tooltip.action2": "_删除_镜面。", "item.create.wand_of_symmetry.tooltip.control3": "当潜行右击时", "item.create.wand_of_symmetry.tooltip.action3": "打开_配置界面_。", - - "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": "打开_配置界面_。", - "item.create.handheld_worldshaper.tooltip": "手持式环境塑形器", "item.create.handheld_worldshaper.tooltip.summary": "_创造_大陆和山脉的手持工具", "item.create.handheld_worldshaper.tooltip.control1": "当左击方块时", @@ -1368,44 +1227,42 @@ "item.create.handheld_worldshaper.tooltip.action2": "_放置_或_替换_目标方块。", "item.create.handheld_worldshaper.tooltip.control3": "当潜行右击时", "item.create.handheld_worldshaper.tooltip.action3": "打开工具的_配置界面_。", - "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.extendo_grip.tooltip.condition2": "当装备铜制背罐时", + "item.create.extendo_grip.tooltip.behaviour2": "使用罐中_气压_来_抵消_伸缩机械手的_耐久_损耗。", + "item.create.potato_cannon.tooltip": "土豆加农炮", + "item.create.potato_cannon.tooltip.summary": "噗!把你亲手栽培的蔬菜砸向你的敌人。可以使用_铜制背罐_供能。", + "item.create.potato_cannon.tooltip.condition1": "当右击时", + "item.create.potato_cannon.tooltip.behaviour1": "_发射_你_物品栏_中任一可作为弹药的物品。", + "item.create.potato_cannon.tooltip.condition2": "当装备铜制背罐时", + "item.create.potato_cannon.tooltip.behaviour2": "使用罐中_气压_来_抵消_土豆加农炮的_耐久_损耗。", "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": "第一步", @@ -1418,59 +1275,14 @@ "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": "打开_界面_", - + "block.create.schematicannon.tooltip.condition1": "When R-Clicked", + "block.create.schematicannon.tooltip.behaviour1": "Opens the _Interface_", "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": "工程师护目镜", "item.create.goggles.tooltip.summary": "一副可以扩增显示_动力学信息_的实用眼镜。", "item.create.goggles.tooltip.condition1": "当装备时", @@ -1479,363 +1291,96 @@ "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.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": "微量的_液体_以及_火焰_会被吹入气流中,这种气流可以用于_处理物品_。", - "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_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": "当放置于铁轨上时,将会_装配_或者_卸载_穿越它的矿车运动结构。按下 [Ctrl] 可以查阅它在不同轨道上的行为。", - "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": "对掉落或放置在其上方的方块应用_板材切割_以及_石材切割配方_。当可能出现多种产物时,它会进行循环输出,除非使用_过滤器_指定其输出产物。", - "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": "一个精致,且有红石能量激活的_数值_和_文本_显示器。", - "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.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.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": "一个简单的电路元件,将通过的红石信号变为 1 tick。", - - "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": "一种单次 1 tick 的红石脉冲器,可以调节延时至30 min。", - - "block.create.analog_lever.tooltip": "模拟拉杆", - "block.create.analog_lever.tooltip.summary": "一种可以调节任意信号强度的推杆。", - - "block.create.powered_toggle_latch.tooltip": "转换锁存器", - "block.create.powered_toggle_latch.tooltip.summary": "一种拉杆,在红石电路中可以用作转换锁存器。", - - "block.create.powered_latch.tooltip": "锁存器", - "block.create.powered_latch.tooltip.summary": "一种拉杆,在红石电路中用作锁存器,从后方输入将会启用这个拉杆,从侧边输入将会重置这个拉杆。", - + "item.create.creative_blaze_cake.tooltip": "创造蛋糕", + "item.create.creative_blaze_cake.tooltip.summary": "为_烈焰人燃烧室_特制的小食,可以让你_控制燃烧室的热量等级_。吃下这个蛋糕之后,烈焰人燃烧室将_不再耗尽燃料_。", + "item.create.creative_blaze_cake.tooltip.condition1": "对着烈焰人燃烧室使用", + "item.create.creative_blaze_cake.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": "根据信号强度_加速_或_减速_经过的矿车。还会将红石信号传递到相邻的控制铁轨。向两个控制铁轨通入不同等级的红石信号,两者中间的轨道会受到以此为区间的连续等级的红石信号的激活。", - - "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.builders_tea.tooltip.summary": "饮下这杯完美茶饮,开启神清气爽的一天。可以恢复_饥饿值_并获得_急迫_效果。", "item.create.refined_radiance.tooltip": "光辉石", "item.create.refined_radiance.tooltip.summary": "一种用_光辉_锻造的化合物材料。", - + "item.create.refined_radiance.tooltip.condition1": "尚未完工", + "item.create.refined_radiance.tooltip.behaviour1": "该材料在未来可能会有更多的用途。", "item.create.shadow_steel.tooltip": "暗影钢", "item.create.shadow_steel.tooltip.summary": "一种用_虚空_锻造的化合物材料。", - + "item.create.shadow_steel.tooltip.condition1": "尚未完工", + "item.create.shadow_steel.tooltip.behaviour1": "该材料在未来可能会有更多的用途。", + "item.create.linked_controller.tooltip": "无线红石遥控器", + "item.create.linked_controller.tooltip.summary": "提供_六个_可以绑定_无线红石_频道的按钮,用于_遥控_附近的_无线红石信号终端_。", + "item.create.linked_controller.tooltip.condition1": "右击时", + "item.create.linked_controller.tooltip.behaviour1": "_拿起_或_放下_遥控器。拿起遥控器时,_控制移动_将被用来_操作遥控器_,而不是移动玩家。", + "item.create.linked_controller.tooltip.condition2": "潜行右击时", + "item.create.linked_controller.tooltip.behaviour2": "打开手动_配置界面_。", + "item.create.linked_controller.tooltip.condition3": "右击无线红石信号终端时", + "item.create.linked_controller.tooltip.behaviour3": "启用_绑定模式_,按下_六个按键_中的一个,即可将此按键与_无线红石信号终端的频率_绑定。", + "item.create.linked_controller.tooltip.condition4": "右击讲台时", + "item.create.linked_controller.tooltip.behaviour4": "将遥控器放在讲台上以便使用(潜行右击来取回遥控器)。", + "item.create.diving_helmet.tooltip": "潜水头盔", + "item.create.diving_helmet.tooltip.summary": "与_铜制背罐_配合使用,为穿戴者提供在_水下_行动一段时间所需的_空气_。", + "item.create.diving_helmet.tooltip.condition1": "戴在头上时", + "item.create.diving_helmet.tooltip.behaviour1": "提供_水下呼吸_效果。缓慢消耗背罐中的_压缩空气_。", + "item.create.copper_backtank.tooltip": "铜制背罐", + "item.create.copper_backtank.tooltip.summary": "一个可以_背在背上_的_铜罐_,用于携带一定量的压缩空气。", + "item.create.copper_backtank.tooltip.condition1": "背在背上时", + "item.create.copper_backtank.tooltip.behaviour1": "为其他需要_压缩空气_的装备提供所需的空气。", + "item.create.copper_backtank.tooltip.condition2": "当放下并接入动力时", + "item.create.copper_backtank.tooltip.behaviour2": "基于转速从周围环境中_收集_并_加压空气_。", + "item.create.diving_boots.tooltip": "潜水靴", + "item.create.diving_boots.tooltip.summary": "一双_沉重的靴子_,让穿戴者可以更方便的探索海底。", + "item.create.diving_boots.tooltip.condition1": "穿在脚上时", + "item.create.diving_boots.tooltip.behaviour1": "穿戴者_下沉更快_并_无法游泳_。穿戴者可以在水下_行走_和_跳跃_。穿戴者不会被_传送带_移走。", + "item.create.crafting_blueprint.tooltip": "合成蓝图", + "item.create.crafting_blueprint.tooltip.summary": "_放在_墙上,便可用它来设置特定的_原料排布_,以便更快地制作物品。每个格子都可以设定一个配方。", + "item.create.crafting_blueprint.condition1": "当右击空的格子时", + "item.create.crafting_blueprint.behaviour1": "打开一个_配方设置界面_,用于_设置_一个_合成配方_以及展示的物品。", + "item.create.crafting_blueprint.condition2": "当右击设置好的格子时", + "item.create.crafting_blueprint.behaviour2": "使用_物品栏_中的物品制作_设置的配方_。_潜行_可以一次合成_一组_。", "item.create.minecart_coupling.tooltip": "矿车连轴器", - "item.create.minecart_coupling.tooltip.summary": "将多个_矿车_或运输结构链接在一起,构成雄伟的火车。", + "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": "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 [------------------------<-", - + "block.create.peculiar_bell.tooltip": "奇异钟", + "block.create.peculiar_bell.tooltip.summary": "装饰用的_黄铜质钟_。放在_灵魂火_的正上方可能会产生意料之外的后果......", + "block.create.haunted_bell.tooltip": "森魂钟", + "block.create.haunted_bell.tooltip.summary": "_被诅咒_的钟,来自下界的迷失的灵魂缠绕于其上。", + "block.create.haunted_bell.tooltip.condition1": "当手持或鸣响时", + "block.create.haunted_bell.tooltip.behaviour1": "标识出附近可能生成_敌对生物_的_亮度不足_之处。", "create.ponder.hold_to_ponder": "按住 [%1$s] 开始思索", "create.ponder.subject": "情景主题", "create.ponder.pondering": "思索...", @@ -1848,65 +1393,65 @@ "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.exit": "退出", + "create.ponder.welcome": "欢迎来到思索界面", + "create.ponder.categories": "机械动力中包含的条目", + "create.ponder.index_description": "点击一个图标来查看相关的物品和方块。", + "create.ponder.index_title": "思索索引", + "create.ponder.shared.rpm16": "16 RPM", "create.ponder.shared.behaviour_modify_wrench": "可以用扳手调整它的行为。", + "create.ponder.shared.storage_on_contraption": "与装置相接的存储空间,会自动将装置遇到的掉落物拾取到空间内。", + "create.ponder.shared.sneak_and": "潜行 +", "create.ponder.shared.rpm8": "8 RPM", "create.ponder.shared.ctrl_and": "Ctrl +", - "create.ponder.shared.rpm16_source": "动力源:16 R", - "create.ponder.shared.rpm16": "16 RPM", - "create.ponder.tag.kinetic_sources": "动力源", - "create.ponder.tag.kinetic_sources.description": "能够发生动力的组件。", - "create.ponder.tag.contraption_actor": "装置执行组件", - "create.ponder.tag.contraption_actor.description": "能在移动的装置上执行特殊功能的组件", - "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": "运动源泉", - "create.ponder.tag.movement_anchor.description": "有了它,运动装置才得以可能,它可以以数种方式使相接的结构运动起来。", - "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.shared.rpm32": "32 RPM", + "create.ponder.shared.rpm16_source": "动力源:16 RPM", + "create.ponder.shared.movement_anchors": "有了底盘和强力胶,移动起大型结构轻轻松松。", "create.ponder.tag.redstone": "逻辑组件", "create.ponder.tag.redstone.description": "这些组件会在红石工程中发挥大用处。", + "create.ponder.tag.contraption_assembly": "方块连接功能", + "create.ponder.tag.contraption_assembly.description": "将各个组件连接以便同时运动的工具以及组件", "create.ponder.tag.fluids": "流体操纵器械", "create.ponder.tag.fluids.description": "这些组件可以用于传递流体,以及利用流体进行工作。", - + "create.ponder.tag.decoration": "装饰", + "create.ponder.tag.decoration.description": "装饰是这些组件的常见用法。", + "create.ponder.tag.windmill_sails": "风车轴承的帆", + "create.ponder.tag.windmill_sails.description": "在进行风车组装时会被算入风车旋转力的方块,这些方块的效能都是一样的。", + "create.ponder.tag.arm_targets": "机械臂的工作目标", + "create.ponder.tag.arm_targets.description": "该组件可做为机械臂的输入或者输出点。", + "create.ponder.tag.kinetic_appliances": "动力设备", + "create.ponder.tag.kinetic_appliances.description": "这些组件可以利用旋转力进行工作。", + "create.ponder.tag.kinetic_sources": "动力源", + "create.ponder.tag.kinetic_sources.description": "能够发生动力的组件。", + "create.ponder.tag.movement_anchor": "运动源泉", + "create.ponder.tag.movement_anchor.description": "有了它,运动装置才得以可能,它可以以数种方式使相接的结构运动起来。", + "create.ponder.tag.kinetic_relays": "动力方块", + "create.ponder.tag.kinetic_relays.description": "用于传递旋转力的组件。", + "create.ponder.tag.contraption_actor": "装置执行组件", + "create.ponder.tag.contraption_actor.description": "能在移动的装置上执行特殊功能的组件", + "create.ponder.tag.creative": "创造模式", + "create.ponder.tag.creative.description": "总有些东西是生存模式得不到的。", + "create.ponder.tag.logistics": "物品运输", + "create.ponder.tag.logistics.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": "处理完毕后,工作盆会尝试从它的底面进行产物输出", @@ -1917,15 +1462,12 @@ "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_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": "如果不小心选错了,潜行右击即可取消选择", @@ -1933,7 +1475,6 @@ "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. 可以水平连接", @@ -1941,23 +1482,19 @@ "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": "隧道的每一个开口面都有过滤槽", @@ -1967,7 +1504,6 @@ "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": "“同步输入”是黄铜隧道的一种特殊设定", @@ -1981,32 +1517,27 @@ "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.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.header": "组装连接运输装置", "create.ponder.cart_assembler_dual.text_1": "若两个装配矿车分享了同一个结构", - "create.ponder.cart_assembler_dual.text_2": "给其中的任意一方的矿车装配站通入红石信号,都会创建出连接装置", + "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_modes.text_2": "矿车装置上的箭头表明了哪一侧是“前面”", + "create.ponder.cart_assembler_modes.text_3": "如果装配站的配置为“旋转锁定”,那么装置的方向将不会改变", "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": "当被充能时,它将会把旋转力以双倍转速传动至其他链式传动箱", @@ -2014,50 +1545,46 @@ "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": "佩戴工程师护目镜时,你可以看见物品的移动方向", "create.ponder.chute_upward.text_3": "在溜槽“被挡住的”底端,物品只能从侧边进行提取或输入", - - "create.ponder.clockwork_bearing.header": "使用时钟轴承来移动结构", - "create.ponder.clockwork_bearing.text_1": "时钟轴承黏附其正前方的方块", + "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_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": "创造流体储罐", + "create.ponder.creative_fluid_tank.text_1": "创造流体储罐可以提供无限量的流体", + "create.ponder.creative_fluid_tank.text_2": "使用一个含有流体的容器右击它,即可指定它提供特定的流体", + "create.ponder.creative_fluid_tank.text_3": "流体管道可以从中无限提取指定的流体", + "create.ponder.creative_fluid_tank.text_4": "任何被输入创造流体储罐的液体都将被销毁", "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": "对着机械手的前部右击,即可将手上的物品给予它使用", @@ -2074,38 +1601,41 @@ "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_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": "使用机械手处理物品", + "create.ponder.deployer_processing.text_1": "当机械手持有合适的物品时,它可以自动处理下方的物品", + "create.ponder.deployer_processing.text_2": "物品可以被丢在机械手下方,或放在置物台上", + "create.ponder.deployer_processing.text_3": "当传送带上的物品经过机械手下方时...", + "create.ponder.deployer_processing.text_4": "...机械手会使物品停下,然后处理这个物品", "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.empty_blaze_burner.text_5": "你可以使用注入了灵魂的物品转化这种火焰", + "create.ponder.empty_blaze_burner.text_6": "但是,没有烈焰人,这样的火焰并不足以用于工业级加热工作", + "create.ponder.encased_fluid_pipe.header": "流体管道箱", + "create.ponder.encased_fluid_pipe.text_1": "铜机壳可以用于装饰流体管道", + "create.ponder.encased_fluid_pipe.text_2": "除了遮掩流体管道之外,装箱的流体管道将不会改变其连接状态", + "create.ponder.encased_fluid_pipe.text_3": "它将不会对旁边新增加或移除的管道做出反应", "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": "热气流中的物品会被冶炼", @@ -2115,88 +1645,119 @@ "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": "使用管道运输流体", + "create.ponder.fluid_pipe_flow.text_1": "流体管道可以用于连接两个或多个流体容器", + "create.ponder.fluid_pipe_flow.text_2": "使用扳手,可以为直管道安装观察窗", + "create.ponder.fluid_pipe_flow.text_3": "带有观察窗的管道不会建立侧向管道连接", + "create.ponder.fluid_pipe_flow.text_4": "使用动力泵,流体管道可以传输流体", + "create.ponder.fluid_pipe_flow.text_5": "一开始,流体不会真正地被抽出", + "create.ponder.fluid_pipe_flow.text_6": "只有当管道内的液体流彻底连通之后,流体才会开始逐渐从一个容器中转移到另一个", + "create.ponder.fluid_pipe_flow.text_7": "这意味着流体管道本身并不真正存储任何流体", + "create.ponder.fluid_pipe_interaction.header": "抽取和填充流体容器", + "create.ponder.fluid_pipe_interaction.text_1": "流体管道的末端可以与许多种容器连接", + "create.ponder.fluid_pipe_interaction.text_2": "任何可以容纳流体的容器都可以被填充或从中抽取", + "create.ponder.fluid_pipe_interaction.text_3": "开放的管道口可以吸走流体源方块...", + "create.ponder.fluid_pipe_interaction.text_4": "...或者将流体源排放出来", + "create.ponder.fluid_pipe_interaction.text_5": "管道也可以从许多种其他方块中直接抽取流体", + "create.ponder.fluid_tank_sizes.header": "流体储罐的大小", + "create.ponder.fluid_tank_sizes.text_1": "流体储罐可以多格连接,提供更大的存储量", + "create.ponder.fluid_tank_sizes.text_2": "流体储罐最大横截面为 3x3...", + "create.ponder.fluid_tank_sizes.text_3": "...并且可以超过 30 格高", + "create.ponder.fluid_tank_sizes.text_4": "使用扳手可以打开或关闭观察窗", + "create.ponder.fluid_tank_storage.header": "使用流体储罐存储流体", + "create.ponder.fluid_tank_storage.text_1": "流体储罐可以存储大量的流体", + "create.ponder.fluid_tank_storage.text_2": "流体管道可以在流体储罐的任何一面将流体输入/输出", + "create.ponder.fluid_tank_storage.text_3": "使用比较器可以检测储罐中的流体储量", + "create.ponder.fluid_tank_storage.text_4": "在生存模式中,无法直接用容器向储罐中存入流体,或是取出流体", + "create.ponder.fluid_tank_storage.text_5": "要装满/倒空流体容器,可以使用工作盆,分液池或注液器。", "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.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": "使用软管滑轮抽取或排放流体", + "create.ponder.hose_pulley.text_1": "软管滑轮可以用于方便地对一个较大区域进行抽取液体或填满液体的操作", + "create.ponder.hose_pulley.text_2": "通过输入动力可以调节软管末端的高度", + "create.ponder.hose_pulley.text_3": "翻转动力输入的方向可以收起软管", + "create.ponder.hose_pulley.text_4": "管道可以连接在另一侧", + "create.ponder.hose_pulley.text_5": "连接的管道可以将流体输入到软管滑轮中,软管会在下方排出口处放置流体源...", + "create.ponder.hose_pulley.text_6": "...或者提供吸力来抽取世界中的流体", + "create.ponder.hose_pulley.text_7": "软管滑轮的抽取/排放速度取决于连接管道中流体的流速", + "create.ponder.hose_pulley_infinite.header": "被动抽取或排放从大体量流体中", + "create.ponder.hose_pulley_infinite.text_1": "当软管被放进足够大的流体中时...", + "create.ponder.hose_pulley_infinite.text_2": "...它在抽取或排放液体时将不会影响流体源", + "create.ponder.hose_pulley_infinite.text_3": "可以从这些软管滑轮中无限量地抽取或向其排放流体", + "create.ponder.hose_pulley_level.header": "软管滑轮的排水/抽水机制", + "create.ponder.hose_pulley_level.text_1": "当软管彻底收回时,软管滑轮无法工作。", + "create.ponder.hose_pulley_level.text_2": "抽取流体的顺序为从上到下", + "create.ponder.hose_pulley_level.text_3": "流体表面最终将会被抽取到刚好低于软管开口", + "create.ponder.hose_pulley_level.text_4": "填充流体的顺序为从下到上", + "create.ponder.hose_pulley_level.text_5": "流体最多只能被填充至软管开口所在的高度", + "create.ponder.item_drain.header": "使用分液池提取物品中的流体", + "create.ponder.item_drain.text_1": "分液池可以提取物品中的流体", + "create.ponder.item_drain.text_2": "右击可以将手持物品中的流体倒入分液池中", + "create.ponder.item_drain.text_3": "当物品从侧面输入时...", + "create.ponder.item_drain.text_4": "...物品将会经过分液池顶部,并在此过程中将其包含的液体排入分液池内", + "create.ponder.item_drain.text_5": "流体管道可以从分液池中抽取液体", "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": "再次点击黏性面,可以将它的相反面也变得具有黏性", @@ -2206,12 +1767,10 @@ "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": "手持动力臂右击某个存储空间,可以将其指定为目标", @@ -2221,7 +1780,6 @@ "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": "输出", @@ -2229,7 +1787,6 @@ "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": "输出", @@ -2240,16 +1797,13 @@ "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": "使用扳手可以调控合成器的合成通路", @@ -2259,120 +1813,120 @@ "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.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.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": "使用动力泵传输流体", + "create.ponder.mechanical_pump_flow.text_1": "动力泵可以控制管道网络中的流体", + "create.ponder.mechanical_pump_flow.text_2": "当接入动力时,其上的箭头指示流体流向", + "create.ponder.mechanical_pump_flow.text_3": "泵后的管道网络正在抽取流体...", + "create.ponder.mechanical_pump_flow.text_4": "...而泵前的网络则把这些液体排到世界当中", + "create.ponder.mechanical_pump_flow.text_5": "反转动力方向将会改变流体流向", + "create.ponder.mechanical_pump_flow.text_6": "使用扳手可以手动改变动力泵的朝向", + "create.ponder.mechanical_pump_speed.header": "动力泵的传输机制", + "create.ponder.mechanical_pump_speed.text_1": "动力泵的压力最多沿管线传递 16 格,与输入动力无关", + "create.ponder.mechanical_pump_speed.text_2": "提高输入动力,可以加快流的蔓延速度...", + "create.ponder.mechanical_pump_speed.text_3": "...以及流体的传输速度", + "create.ponder.mechanical_pump_speed.text_4": "同一管道网络中的多个并联动力泵,它们的传输量可以叠加", + "create.ponder.mechanical_pump_speed.text_5": "使泵的传输方向相互交替,可以方便地控制流体流向", "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_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.nixie_tube.text_2": "在着它使用更改过名称的命名牌,可以自定义它的显示文本", + "create.ponder.nixie_tube.text_3": "使用染料右击,便可更改辉光管的显示颜色", "create.ponder.piston_pole.header": "活塞延长杆", "create.ponder.piston_pole.text_1": "若无相接的延长杆,动力活塞无法移动其他方块", "create.ponder.piston_pole.text_2": "在其背面安装的延长杆长度,决定了活塞的推动范围", - + "create.ponder.portable_fluid_interface.header": "装置流体交换", + "create.ponder.portable_fluid_interface.text_1": "管道无法与运动装置内的流体储罐直接交互", + "create.ponder.portable_fluid_interface.text_2": "这一组件可以在不停止装置的情况下与装置内的流体存储进行交互", + "create.ponder.portable_fluid_interface.text_3": "放置第二个接口时,记得要与装置接口相隔 1 格或者 2 格的距离", + "create.ponder.portable_fluid_interface.text_4": "当它们彼此经过时,它们会连接在一起", + "create.ponder.portable_fluid_interface.text_5": "连接状态下,固定侧接口便会作为整个装置的流体存储代理", + "create.ponder.portable_fluid_interface.text_6": "流体可被泵入到装置内....", + "create.ponder.portable_fluid_interface.text_7": "...或是从装置中抽取出来", + "create.ponder.portable_fluid_interface.text_8": "如果一小段时间内没有流体交换,接口将会断开连接,然后装置重新开始运动", "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_6": "物品可被输入到装置内...", "create.ponder.portable_storage_interface.text_7": "...或是从装置中提取出来", - "create.ponder.portable_storage_interface.text_8": "物品交换完毕后,装置仍然会停留在原地一小会,然后才会继续前行", - + "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": "使用转换锁存器控制信号", "create.ponder.powered_toggle_latch.text_1": "转换锁存器是一种可以用红石信号控制的拉杆", "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": "当其中的一个底盘被装置带动时,其余的底盘也会被带动", @@ -2383,11 +1937,9 @@ "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": "潜行右击可以改变其接收模式", @@ -2395,95 +1947,94 @@ "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": "使用智能流体管道控制流体流动", + "create.ponder.smart_pipe.text_1": "智能流体管道可以限制通过它的流体种类", + "create.ponder.smart_pipe.text_2": "当紧邻流体源放置时,管道只会抽取设置的流体种类", + "create.ponder.smart_pipe.text_3": "使用任何包含流体的容器右击过滤槽,可以标记过滤的流体", + "create.ponder.smart_pipe.text_4": "当放在管道网络中时,只有匹配过滤器的流体才能通过此管道", "create.ponder.speedometer.header": "使用速度表来监测转速", "create.ponder.speedometer.text_1": "速度表能显示相接组件的转速", "create.ponder.speedometer.text_2": "当佩戴工程师护目镜时,可以看到仪表所显示的更详细的数据", "create.ponder.speedometer.text_3": "红石比较器可以根据速度表的数值输出不同强弱的红石信号", - + "create.ponder.spout_filling.header": "使用注液器填充物品", + "create.ponder.spout_filling.text_1": "注液器可以将流体装入下方经过且可以接受该流体的物品", + "create.ponder.spout_filling.text_2": "注液器的流体存储无法直接手动交互", + "create.ponder.spout_filling.text_3": "使用管道可以将流体输入到注液器内", + "create.ponder.spout_filling.text_4": "输入的物品可以被放置在其下方的置物台上", + "create.ponder.spout_filling.text_5": "当传送带上的物品经过注液器下方时...", + "create.ponder.spout_filling.text_6": "注液器会使物品停下,然后自动处理这一物品", "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.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": "当佩戴工程师护目镜时,可以看到仪表所显示的更详细的数据", "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": "使用阀门管道控制液体流", + "create.ponder.valve_pipe.text_1": "阀门管道可以控制管道网络中流体的蔓延", + "create.ponder.valve_pipe.text_2": "通过其上的传动杆输入动力可以控制它的开关", + "create.ponder.valve_pipe.text_3": "提供向“打开”方向的旋转力会打开阀门,使得流体可以通过", + "create.ponder.valve_pipe.text_4": "提供另一方向的旋转力可以关闭阀门,阻止流体通过", "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": "现在,只有等被放置的物品数量等于所设定数量时,弹射置物台才会弹射物品", @@ -2496,18 +2047,15 @@ "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": "如果有足够多的风帆方块黏附于其上,那么整体结构便可被视为风车", @@ -2515,11 +2063,6 @@ "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!" - -} + "create.ponder.windmill_structure.text_1": "任何有至少 8 个风帆方块的结构,都被视为一个有效的风车" + } \ 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..70b74b490 100644 --- a/src/main/resources/assets/create/lang/zh_tw.json +++ b/src/main/resources/assets/create/lang/zh_tw.json @@ -1,1792 +1,2286 @@ -{ - - "_": "->------------------------] 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.2a", + + "_": "->------------------------] 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_nixie_tube": "黑色真空管", + "block.create.black_sail": "黑色風帆", + "block.create.black_seat": "黑色坐墊", + "block.create.black_valve_handle": "黑色閥門開關", + "block.create.blaze_burner": "烈焰使者動力爐", + "block.create.blue_nixie_tube": "藍色真空管", + "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_nixie_tube": "棕色真空管", + "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_backtank": "銅製後背包", + "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_nixie_tube": "青色真空管", + "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_nixie_tube": "灰色真空管", + "block.create.gray_sail": "灰色風帆", + "block.create.gray_seat": "灰色坐墊", + "block.create.gray_valve_handle": "灰色閥門開關", + "block.create.green_nixie_tube": "綠色真空管", + "block.create.green_sail": "綠色風帆", + "block.create.green_seat": "綠色坐墊", + "block.create.green_valve_handle": "綠色閥門開關", + "block.create.hand_crank": "手搖把手", + "block.create.haunted_bell": "靈魂鐘", + "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.lectern_controller": "講台遙控器", + "block.create.light_blue_nixie_tube": "亮藍色真空管", + "block.create.light_blue_sail": "淡藍色風帆", + "block.create.light_blue_seat": "淡藍色坐墊", + "block.create.light_blue_valve_handle": "淡藍色閥門開關", + "block.create.light_gray_nixie_tube": "亮灰色真空管", + "block.create.light_gray_sail": "淡灰色風帆", + "block.create.light_gray_seat": "淡灰色坐墊", + "block.create.light_gray_valve_handle": "淡灰色閥門開關", + "block.create.lime_nixie_tube": "淺綠色真空管", + "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_nixie_tube": "洋紅色真空管", + "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.peculiar_bell": "黃銅鐘", + "block.create.pink_nixie_tube": "粉紅色真空管", + "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_nixie_tube": "紫色真空管", + "block.create.purple_sail": "紫色風帆", + "block.create.purple_seat": "紫色坐墊", + "block.create.purple_valve_handle": "紫色閥門開關", + "block.create.radial_chassis": "旋轉底盤", + "block.create.red_nixie_tube": "紅色真空管", + "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_nixie_tube": "白色真空管", + "block.create.white_sail": "白色風帆", + "block.create.white_seat": "白色坐墊", + "block.create.white_valve_handle": "白色閥門開關", + "block.create.windmill_bearing": "風車軸承", + "block.create.wooden_bracket": "木製支架", + "block.create.yellow_nixie_tube": "黃色真空管", + "block.create.yellow_sail": "黃色風帆", + "block.create.yellow_seat": "黃色坐墊", + "block.create.yellow_valve_handle": "黃色閥門開關", + "block.create.zinc_block": "鋅磚", + "block.create.zinc_ore": "鋅礦石", + + "enchantment.create.capacity": "容量", + "enchantment.create.potato_recovery": "馬鈴薯恢復", + + "entity.create.contraption": "結構", + "entity.create.crafting_blueprint": "合成藍圖", + "entity.create.gantry_contraption": "門式結構", + "entity.create.potato_projectile": "馬鈴薯彈藥", + "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_backtank": "銅製後背包", + "item.create.copper_ingot": "銅錠", + "item.create.copper_nugget": "銅粒", + "item.create.copper_sheet": "銅板", + "item.create.crafter_slot_cover": "合成器蓋板", + "item.create.crafting_blueprint": "合成藍圖", + "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.diving_boots": "潛水鞋", + "item.create.diving_helmet": "潛水頭盔", + "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_worldshaper": "地形雕塑器", + "item.create.honey_bucket": "蜂蜜桶", + "item.create.honeyed_apple": "蜂蜜蘋果", + "item.create.incomplete_cogwheel": "未完成的小齒輪", + "item.create.incomplete_large_cogwheel": "未完成的大齒輪", + "item.create.incomplete_precision_mechanism": "未完成的精確控制器", + "item.create.iron_sheet": "鐵板", + "item.create.linked_controller": "遙控器", + "item.create.minecart_contraption": "裝修過的礦車", + "item.create.minecart_coupling": "礦車連結器", + "item.create.polished_rose_quartz": "磨製玫瑰石英", + "item.create.potato_cannon": "馬鈴薯大砲", + "item.create.powdered_obsidian": "黑曜石粉末", + "item.create.precision_mechanism": " 精確控制器", + "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.precision_mechanism": "複雜的好奇心", + "advancement.create.precision_mechanism.desc": "組裝一個精確控制器", + "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.wand_of_symmetry": "簡單的鏡面幾何學", + "advancement.create.wand_of_symmetry.desc": "製作一個對稱杖", + "advancement.create.extendo_grip": "piu piu piu!", + "advancement.create.extendo_grip.desc": "拿到一個伸縮機械手", + "advancement.create.potato_cannon": "噗~碰", + "advancement.create.potato_cannon.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.crush.player": "%1$s 被 %2$s 打包丟進粉碎輪", + "death.attack.create.fan_fire": "%1$s想接受熱風的洗禮", + "death.attack.create.fan_fire.player": "%1$s 被 %2$s 推入火坑", + "death.attack.create.fan_lava": "%1$s想接受熱風的洗禮但走火入魔", + "death.attack.create.fan_lava.player": "%1$s 被 %2$s 推進岩漿", + "death.attack.create.mechanical_drill": "%1$s被鑽頭鑽爆腦袋", + "death.attack.create.mechanical_drill.player": "%1$s 被 %2$s 當成礦物放在鑽頭前面而死", + "death.attack.create.mechanical_saw": "%1$s被鋸切成了兩半", + "death.attack.create.mechanical_saw.player": "%1$s 被 %2$s 鋸掉了", + "death.attack.create.potato_cannon": "%1$s 被 %2$s 的馬鈴薯大砲餵飽了", + "death.attack.create.potato_cannon.item": "%1$s 被 %2$s 用馬鈴薯大砲塞了滿肚子 %3$s", + "death.attack.create.cuckoo_clock_explosion": "%1$s 被布穀鳥鐘炸得粉身碎骨", + "death.attack.create.cuckoo_clock_explosion.player": "%1$s 被布穀鳥鐘炸得粉身碎骨", + + "create.block.deployer.damage_source_name": "機械手", + "create.block.cart_assembler.invalid": "將您的礦車裝修站放在鐵軌上", + + "create.menu.return": "回到選單", + "create.menu.configure": "設定", + "create.menu.ponder_index": "示範目錄", + "create.menu.project_page": "專案頁面", + "create.menu.report_bugs": "回報問題", + "create.menu.support": "支持我們", + + "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.sandpaper_polishing": "砂紙打磨", + "create.recipe.mystery_conversion": "神秘轉化", + "create.recipe.spout_filling": "注液", + "create.recipe.draining": "分液", + "create.recipe.sequenced_assembly": "排序中的步驟", + "create.recipe.assembly.next": "下一步:%1$s", + "create.recipe.assembly.step": "步驟 %1$s:", + "create.recipe.assembly.progress": "進度:%1$s/%2$s", + "create.recipe.assembly.spout_filling_fluid": "注入:%1$s", + "create.recipe.assembly.deploying_item": "使用:%1$s", + "create.recipe.assembly.cutting": "用鋸子切", + "create.recipe.assembly.repeat": "重複 %1$s 次", + "create.recipe.assembly.junk": "有機率得到垃圾", + "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.terrainzapper.title": "地形雕塑器", + "create.gui.terrainzapper.searchDiagonal": "跟隨對角線", + "create.gui.terrainzapper.searchFuzzy": "忽略材質邊界", + "create.gui.terrainzapper.pattern.solid": "填滿", + "create.gui.terrainzapper.pattern.checkered": "棋盤狀", + "create.gui.terrainzapper.pattern.inversecheckered": "反轉棋盤狀", + "create.gui.terrainzapper.pattern.chance25": "隨機填滿 25% 的面積", + "create.gui.terrainzapper.pattern.chance50": "隨機填滿 50% 的面積", + "create.gui.terrainzapper.pattern.chance75": "隨機填滿 75% 的面積", + "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.brush.surface": "表面", + "create.gui.terrainzapper.brush.cluster": "群組", + "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.terrainzapper.usingBlock": "使用:%1$s", + "create.terrainzapper.leftClickToSet": "左鍵點擊方塊可以設定材質", + + "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.shulker_level": "界伏盒是 %1$s", + "create.item_attributes.shulker_level.inverted": "界伏盒不是 %1$s", + "create.item_attributes.shulker_level.full": "滿的", + "create.item_attributes.shulker_level.empty": "空的", + "create.item_attributes.shulker_level.partial": "有裝東西但沒滿", + "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.tooltip.brass_tunnel.contains": "正在處理", + "create.tooltip.brass_tunnel.contains_entry": "> %1$s x%2$s", + "create.tooltip.brass_tunnel.retrieve": "右鍵取回", + + "create.linked_controller.bind_mode": "綁定模式", + "create.linked_controller.press_keybind": "按 %1$s, %2$s, %3$s, %4$s, %5$s 或 %6$s 來綁定這個頻率到對應按鍵上", + "create.linked_controller.key_bound": "頻率綁定到 %1$s 鍵", + "create.linked_controller.frequency_slot_1": "按鍵:%1$s 頻道 #1", + "create.linked_controller.frequency_slot_2": "按鍵:%1$s 頻道 #2", + + "create.crafting_blueprint.crafting_slot": "材料格", + "create.crafting_blueprint.display_slot": "顯示格", + "create.crafting_blueprint.inferred": "根據配方推論", + "create.crafting_blueprint.manually_assigned": "手動設定", + "create.crafting_blueprint.secondary_display_slot": "次要顯示格", + "create.crafting_blueprint.optional": "可選的", + + "create.potato_cannon.ammo.attack_damage": "%1$s 攻擊傷害", + "create.potato_cannon.ammo.reload_ticks": "%1$s 攻擊速度", + "create.potato_cannon.ammo.knockback": "%1$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": "這個礦車結構太大了而無法撿取", + "create.contraption.minecart_contraption_illegal_pickup": "一股神秘的力量將這個礦車結構與世界綁在一起", + + + "_": "->------------------------] Subtitles [------------------------<-", + + "create.subtitle.contraption_disassemble": "結構停止", + "create.subtitle.peculiar_bell_use": "黃銅鐘聲", + "create.subtitle.mixing": "攪拌機噪音", + "create.subtitle.mechanical_press_activation_belt": "液壓機工作", + "create.subtitle.fwoomp": "馬鈴薯大砲發射", + "create.subtitle.worldshaper_place": "地形塑造器發射聲", + "create.subtitle.crushing_1": "粉碎機咀嚼聲", + "create.subtitle.depot_slide": "物品滑動聲", + "create.subtitle.saw_activate_stone": "機械鋸子聲", + "create.subtitle.blaze_munch": "烈焰使者開心地吃著", + "create.subtitle.schematicannon_finish": "藍圖大炮完成任務", + "create.subtitle.haunted_bell_use": "靈魂鐘敲響", + "create.subtitle.scroll_value": "滾動輸入聲", + "create.subtitle.crafter_craft": "機械合成器合成聲", + "create.subtitle.controller_put": "遙控器放置聲", + "create.subtitle.cranking": "手搖把手轉動聲", + "create.subtitle.wrench_remove": "零件移除聲", + "create.subtitle.cogs": "齒輪隆隆聲", + "create.subtitle.slime_added": "黏液擠壓", + "create.subtitle.potato_hit": "食物撞擊聲", + "create.subtitle.saw_activate_wood": "機械鋸子運作聲", + "create.subtitle.haunted_bell_convert": "靈魂鐘轉化聲", + "create.subtitle.deployer_polish": "機械手拋光聲", + "create.subtitle.controller_click": "遙控器按鍵聲", + "create.subtitle.schematicannon_launch_block": "藍圖大炮發射", + "create.subtitle.copper_armor_equip": "潛水裝裝備聲", + "create.subtitle.controller_take": "拿下遙控器", + "create.subtitle.mechanical_press_activation": "液壓機工作", + "create.subtitle.contraption_assemble": "結構移動", + "create.subtitle.crafter_click": "機械合成器工作聲", + + + "_": "->------------------------] 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.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": "對辛苦的_烈焰使者_的美味款待。讓他們興奮起來吧!", + + "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_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.extendo_grip.tooltip": "伸縮機械手", + "item.create.extendo_grip.tooltip.summary": "biubiubiu! 大幅度_增加了_使用者的_觸碰距離_。", + "item.create.extendo_grip.tooltip.condition1": "放置於副手欄時", + "item.create.extendo_grip.tooltip.behaviour1": "大幅增加_主手_的觸碰距離,與_主手_的伸縮機械手攜同使用,可進一步增加_觸碰距離_。", + "item.create.extendo_grip.tooltip.condition2": "當裝備銅製後背包時", + "item.create.extendo_grip.tooltip.behaviour2": "_不會消耗耐久_ 但是會抽取銅製後背包裡的_壓縮空氣_", + + "item.create.potato_cannon.tooltip": "馬鈴薯大砲", + "item.create.potato_cannon.tooltip.summary": "噗~碰!用你種的蔬菜來攻擊敵人。可以用_銅製後背包_的壓縮空氣驅動", + "item.create.potato_cannon.tooltip.condition1": "當點擊右鍵時", + "item.create.potato_cannon.tooltip.behaviour1": "從_物品欄_中_發射_一顆彈藥", + "item.create.potato_cannon.tooltip.condition2": "當裝備銅製後背包時", + "item.create.potato_cannon.tooltip.behaviour2": "_不會消耗耐久_ 但是會抽取銅製後背包裡的_壓縮空氣_", + + "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.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.refined_radiance.tooltip.condition1": "工作進度", + "item.create.refined_radiance.tooltip.behaviour1": "在未來的更新中會更新更多用途", + + "item.create.shadow_steel.tooltip": "暗影鋼", + "item.create.shadow_steel.tooltip.summary": "一種用_虛空_鍛造的化合物材料。", + "item.create.shadow_steel.tooltip.condition1": "工作進度", + "item.create.shadow_steel.tooltip.behaviour1": "在未來的更新中會更新更多用途", + + "item.create.linked_controller.tooltip": "遙控器", + "item.create.linked_controller.tooltip.summary": "提供_六個_連接到相對應_按鍵_的_無線紅石訊號機_ _手持的控制_", + "item.create.linked_controller.tooltip.condition1": "點擊右鍵時", + "item.create.linked_controller.tooltip.behaviour1": "_切換_遙控器,當遙控器啟動時你會失去_移動控制_", + "item.create.linked_controller.tooltip.condition2": "當右鍵時", + "item.create.linked_controller.tooltip.behaviour2": "打開_設定面板_", + "item.create.linked_controller.tooltip.condition3": "當對無線紅石訊號機點右鍵時", + "item.create.linked_controller.tooltip.behaviour3": "開啟_綁定模式_。按_六個控制鍵_的其中一個來綁定_頻率_到遙控器上", + "item.create.linked_controller.tooltip.condition4": "當對講台按右鍵時", + "item.create.linked_controller.tooltip.behaviour4": "把遙控器放到講台上,可以更方便的控制它。(蹲下右鍵取回)", + + "item.create.diving_helmet.tooltip": "潛水頭盔", + "item.create.diving_helmet.tooltip.summary": "和_銅製後背包_一起裝備時可以延長在_水下呼吸_的時間", + "item.create.diving_helmet.tooltip.condition1": "當裝備時", + "item.create.diving_helmet.tooltip.behaviour1": "提昇_水下呼吸效果_,會緩慢的抽取銅製後背包中的_壓縮空氣_", + + "item.create.copper_backtank.tooltip": "銅製後背包", + "item.create.copper_backtank.tooltip.summary": "可裝備的氣罐,用來攜帶壓縮空氣", + "item.create.copper_backtank.tooltip.condition1": "當裝備時", + "item.create.copper_backtank.tooltip.behaviour1": "提供_壓縮空氣_給需要的裝備", + "item.create.copper_backtank.tooltip.condition2": "當放置時,由轉動來補充驅動", + "item.create.copper_backtank.tooltip.behaviour2": "旋轉的速度決定收集_壓縮空氣_的速率", + + "item.create.diving_boots.tooltip": "潛水鞋", + "item.create.diving_boots.tooltip.summary": "一雙_沈重的鞋子_,提供更好的水下移動", + "item.create.diving_boots.tooltip.condition1": "當裝備時", + "item.create.diving_boots.tooltip.behaviour1": "你可以在水下走得更快而且可以跳躍,但是不能游泳。穿著者不會被輸送帶移動。", + + "item.create.crafting_blueprint.tooltip": "合成藍圖", + "item.create.crafting_blueprint.tooltip.summary": "可以被放置在牆上、地上和天花板。指定一個合成配方,你可以更快速的合成物品。每一格代表一個合成配方", + "item.create.crafting_blueprint.condition1": "右鍵點擊空格", + "item.create.crafting_blueprint.behaviour1": "打開_合成界面_讓你_指定配方_和要顯示的物品", + "item.create.crafting_blueprint.condition2": "右鍵點擊編輯過的格子", + "item.create.crafting_blueprint.behaviour2": "根據_物品欄_內的物品_使用_這個_配方_合成。_蹲下_點擊可以一次合成_一組_的物品", + + "item.create.minecart_coupling.tooltip": "礦車連軸器", + "item.create.minecart_coupling.tooltip.summary": "將多個_礦車_或運輸結構鏈接在一起,構成雄偉的火車。", + "item.create.minecart_coupling.tooltip.condition1": "作用與礦車時", + "item.create.minecart_coupling.tooltip.behaviour1": "將兩個礦車耦合在一起,在移動時將它們保持_恒定的距離_。", + + "block.create.peculiar_bell.tooltip": "黃銅鐘", + "block.create.peculiar_bell.tooltip.summary": "一個裝飾性的_鐘_,放在_靈魂火_正上方會有意想不到的副作用", + + "block.create.haunted_bell.tooltip": "靈魂鐘", + "block.create.haunted_bell.tooltip.summary": "一個受到地獄亡魂_詛咒的鐘_", + "block.create.haunted_bell.tooltip.condition1": "當拿者或是被敲響時", + "block.create.haunted_bell.tooltip.behaviour1": "標示附近_不夠亮_、會生成_敵對生物_的地方", + + + "_": "->------------------------] 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.exit": "離開", + "create.ponder.welcome": "歡迎來到教學", + "create.ponder.categories": "Create 中的分類", + "create.ponder.index_description": "點擊其中一個圖像查看和他相關的物品以及方塊", + "create.ponder.index_title": "教學首頁", + "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": "特殊方塊", + "create.ponder.tag.contraption_actor.description": "附加到移動裝置上時表現出特殊行為的方塊", + "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": "運動錨點", + "create.ponder.tag.movement_anchor.description": "允許建立移動裝置的元件,以各種方式為連接的結構設置動畫", + "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_modes.text_3": "如果在裝修站鎖定其方向,則結構方向不會隨礦車方向改變", + + "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": "創造液體除存罐", + "create.ponder.creative_fluid_tank.text_1": "創造液體除存罐可以提供無限的液體", + "create.ponder.creative_fluid_tank.text_2": "拿著一個液體物品點擊可以設定它", + "create.ponder.creative_fluid_tank.text_3": "現在管線網路可以無限制的從它抽取液體", + "create.ponder.creative_fluid_tank.text_4": "任何被抽進創造液體除存罐的液體都會消失", + + "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": "用機器手處理物品", + "create.ponder.deployer_processing.text_1": "拿著適當物品的機器手可以處理下面的物品", + "create.ponder.deployer_processing.text_2": "待處理的物品可以是掉落狀態或是被放在置物台上", + "create.ponder.deployer_processing.text_3": "當物品被放在輸送帶上時...", + "create.ponder.deployer_processing.text_4": "機器手會抓住他並且自動處理", + + "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.empty_blaze_burner.text_6": "但是,這樣的熱源不足以給機器提加工供足夠的熱量", + + "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": "始用銅製管道來移動液體", + "create.ponder.fluid_pipe_flow.text_1": "液體管可以連接兩個或更多的液體來源與目標", + "create.ponder.fluid_pipe_flow.text_2": "使用扳手可以在一段直管線上開窗戶", + "create.ponder.fluid_pipe_flow.text_3": "有窗戶的管線側面不會連接到其他管線", + "create.ponder.fluid_pipe_flow.text_4": "機械幫浦可以讓管線運輸液體", + "create.ponder.fluid_pipe_flow.text_5": "一開始不會有液體被抽出來", + "create.ponder.fluid_pipe_flow.text_6": "直到兩端被連接起來,才會有液體被抽過去", + "create.ponder.fluid_pipe_flow.text_7": "因此,管線裡不會『物理上的』含有液體", + + "create.ponder.fluid_pipe_interaction.header": "抽取並填滿液體罐", + "create.ponder.fluid_pipe_interaction.text_1": "管線網路的終端可以和很多東西互動", + "create.ponder.fluid_pipe_interaction.text_2": "任何有意體容量的方塊都可以被抽取和填滿", + "create.ponder.fluid_pipe_interaction.text_3": "在開放端口前的液體源方塊可以被抽走", + "create.ponder.fluid_pipe_interaction.text_4": "當液體被排放出來時會產生新的液體源方塊", + "create.ponder.fluid_pipe_interaction.text_5": "管線也可以直接從其他方塊中抽取流體", + + "create.ponder.fluid_tank_sizes.header": "液體罐的尺寸", + "create.ponder.fluid_tank_sizes.text_1": "可以組合液體罐以增加總容量", + "create.ponder.fluid_tank_sizes.text_2": "底部最多可以是 3x3 的正方形 ......", + "create.ponder.fluid_tank_sizes.text_3": "...... 最多可以堆疊 30 層", + "create.ponder.fluid_tank_sizes.text_4": "扳手可以用來開關窗戶", + + "create.ponder.fluid_tank_storage.header": "在液體罐中儲存液體", + "create.ponder.fluid_tank_storage.text_1": "液體罐中可儲存大量的液體", + "create.ponder.fluid_tank_storage.text_2": "管線體網路可以從任何一邊抽取或是輸入液體", + "create.ponder.fluid_tank_storage.text_3": "紅石比較器可以輸出液體容量", + "create.ponder.fluid_tank_storage.text_4": "但是,在生存模式你不能直接存入、取出液體", + "create.ponder.fluid_tank_storage.text_5": "你可以用作業盆、分液池或液體灌注器和管線網路互動", + + "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": "使用軟管滑輪抽取、填滿液體", + "create.ponder.hose_pulley.text_1": "軟管滑輪可以用來抽取、填滿大量的液體", + "create.ponder.hose_pulley.text_2": "你可以透過輸入轉動來控制軟管的高度", + "create.ponder.hose_pulley.text_3": "反轉時可以收回軟管", + "create.ponder.hose_pulley.text_4": "另一邊可以連接管線", + "create.ponder.hose_pulley.text_5": "相連的管線網路可以提供液體 ......", + "create.ponder.hose_pulley.text_6": "...... 或是從池子裡抽取液體", + "create.ponder.hose_pulley.text_7": "抽取或填滿的速度取決於管線系統的吞吐量", + + "create.ponder.hose_pulley_infinite.header": "被動填充和排放大量液體", + "create.ponder.hose_pulley_infinite.text_1": "將軟管滑輪接觸到足夠大的海洋中時 ......", + "create.ponder.hose_pulley_infinite.text_2": "海洋會被視為無限液體源", + "create.ponder.hose_pulley_infinite.text_3": "管線網路可以無限的抽取、排放液體到海洋中而不影響海洋", + + "create.ponder.hose_pulley_level.header": "軟管滑輪抽取、填滿水平面", + "create.ponder.hose_pulley_level.text_1": "完全縮回時,軟管滑輪無法操作", + "create.ponder.hose_pulley_level.text_2": "抽取工作將由上而下進行", + "create.ponder.hose_pulley_level.text_3": "水平面將停在軟管末端的正下方", + "create.ponder.hose_pulley_level.text_4": "而填充工作將由下而上進行將由上而下進行", + "create.ponder.hose_pulley_level.text_5": "水平面不會超過軟管末端", + + "create.ponder.item_drain.header": "使用分液池清空液體容器", + "create.ponder.item_drain.text_1": "分液池可以從液體容器中清空抽取液體", + "create.ponder.item_drain.text_2": "點擊右鍵可以把你手上的液體倒進去", + "create.ponder.item_drain.text_3": "當從旁邊輸入物品 ......", + "create.ponder.item_drain.text_4": "...... 他會從上方滑過,並清空裡面的液體", + "create.ponder.item_drain.text_5": "現在液體網路可以抽取分液池中的液體了", + + "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": "使用機械幫浦抽運送液體", + "create.ponder.mechanical_pump_flow.text_1": "機械幫浦為與其連接的管線提供動力", + "create.ponder.mechanical_pump_flow.text_2": "轉動時,箭頭指向液體的方向", + "create.ponder.mechanical_pump_flow.text_3": "在他後面的網路現在可以抽取液體 ......", + "create.ponder.mechanical_pump_flow.text_4": "...... 當前面的網絡向外傳輸時", + "create.ponder.mechanical_pump_flow.text_5": "反轉輸入的動力可以反轉液體的方向", + "create.ponder.mechanical_pump_flow.text_6": "扳手可以手動調整方向", + + "create.ponder.mechanical_pump_speed.header": "機械幫浦的吞吐量", + "create.ponder.mechanical_pump_speed.text_1": "無論轉速如何,機械幫浦都只能影響相連的 16 個方塊以內的管線", + "create.ponder.mechanical_pump_speed.text_2": "加快旋轉速度會改變液動傳播的速度 ......", + "create.ponder.mechanical_pump_speed.text_3": "...... 以及流體轉移的速度", + "create.ponder.mechanical_pump_speed.text_4": "在同一個管線網路中機械幫浦可以結合他們的吞吐量", + "create.ponder.mechanical_pump_speed.text_5": "改變它們的方向可以對齊它們的流動方向", + + "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.nixie_tube.text_3": "使用染料右鍵點擊可以上色", + + "create.ponder.piston_pole.header": "活塞延長杆", + "create.ponder.piston_pole.text_1": "若無相接的延長杆,動力活塞無法移動其他方塊", + "create.ponder.piston_pole.text_2": "在其背面安裝的延長杆長度,決定了活塞的推動範圍", + + "create.ponder.portable_fluid_interface.header": "移動式液體口", + "create.ponder.portable_fluid_interface.text_1": "任何管道線都無法與移動裝置上的液體罐連接", + "create.ponder.portable_fluid_interface.text_2": "該元件可以與液體罐相互作用,而無需停止裝置", + "create.ponder.portable_fluid_interface.text_3": "放置第二個,中間間隔 1 或 2 個方塊", + "create.ponder.portable_fluid_interface.text_4": "每當他們擦身而過時,他們就會建立聯繫", + "create.ponder.portable_fluid_interface.text_5": "啟用時,移動式液體口將代表裝置上的『所有』水箱", + "create.ponder.portable_fluid_interface.text_6": "現在可以輸入液體 ......", + "create.ponder.portable_fluid_interface.text_7": "...... 或從裝置中抽取", + "create.ponder.portable_fluid_interface.text_8": "一段時間沒有液體交換後,裝置將繼續前進", + + "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": "使用智慧液體管道控制液體", + "create.ponder.smart_pipe.text_1": "智慧液體管道可以按照液體類型控制液體流", + "create.ponder.smart_pipe.text_2": "當直接放置在源頭時,他們可以指定要提取的液體類型", + "create.ponder.smart_pipe.text_3": "只需用包含所需液體的任何項目右鍵點擊其過濾槽", + "create.ponder.smart_pipe.text_4": "在管網裡時,智慧液體管道只會讓匹配的液體經過", + + "create.ponder.speedometer.header": "使用速度計來監測轉速", + "create.ponder.speedometer.text_1": "速度計能顯示相接組件的轉速", + "create.ponder.speedometer.text_2": "當佩戴MR護目鏡時,可以看到儀表所顯示的更詳細的數據", + "create.ponder.speedometer.text_3": "紅石比較器可以根據速度計的數值輸出不同強弱的紅石訊號", + + "create.ponder.spout_filling.header": "使用液體灌注器填充物品", + "create.ponder.spout_filling.text_1": "液體灌注器可以填充下方的液體容器", + "create.ponder.spout_filling.text_2": "無法手動接觸液體灌注器中的液體", + "create.ponder.spout_filling.text_3": "管道可用於為其提供液體", + "create.ponder.spout_filling.text_4": "輸入物品可以是掉落狀態或是被放在置物台上", + "create.ponder.spout_filling.text_5": "當物品放在輸送帶上時 ......", + "create.ponder.spout_filling.text_6": "液體灌注器會停下他並且自動填滿", + + "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": "使用液體閥門控制液體流量", + "create.ponder.valve_pipe.text_1": "閥門管道有助於控制通過管線網路傳播的液體", + "create.ponder.valve_pipe.text_2": "用轉動輸入控制現在是否允許液體通過", + "create.ponder.valve_pipe.text_3": "打開方向旋轉,液體閥門將會打開", + "create.ponder.valve_pipe.text_4": "反方向的旋轉會關閉閥門", + + "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/main/resources/assets/create/models/block/bell_base/block_ceiling.json b/src/main/resources/assets/create/models/block/bell_base/block_ceiling.json new file mode 100644 index 000000000..33e494968 --- /dev/null +++ b/src/main/resources/assets/create/models/block/bell_base/block_ceiling.json @@ -0,0 +1,34 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "2": "create:block/bell_frame_side", + "particle": "create:block/bell" + }, + "elements": [ + { + "from": [0, 5, 5], + "to": [2, 16, 11], + "faces": { + "north": {"uv": [14, 5, 12, 16], "texture": "#2"}, + "east": {"uv": [12, 5, 6, 16], "texture": "#2"}, + "south": {"uv": [14, 5, 16, 16], "texture": "#2"}, + "west": {"uv": [0, 5, 6, 16], "texture": "#2"}, + "up": {"uv": [6, 0, 0, 2], "rotation": 270, "texture": "#2"}, + "down": {"uv": [12, 2, 6, 0], "rotation": 90, "texture": "#2"} + } + }, + { + "from": [14, 5, 5], + "to": [16, 16, 11], + "faces": { + "north": {"uv": [14, 5, 16, 16], "texture": "#2"}, + "east": {"uv": [0, 5, 6, 16], "texture": "#2"}, + "south": {"uv": [14, 5, 12, 16], "texture": "#2"}, + "west": {"uv": [12, 5, 6, 16], "texture": "#2"}, + "up": {"uv": [6, 0, 0, 2], "rotation": 90, "texture": "#2"}, + "down": {"uv": [12, 2, 6, 0], "rotation": 270, "texture": "#2"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/bell_base/block_double_wall.json b/src/main/resources/assets/create/models/block/bell_base/block_double_wall.json new file mode 100644 index 000000000..1e0510948 --- /dev/null +++ b/src/main/resources/assets/create/models/block/bell_base/block_double_wall.json @@ -0,0 +1,40 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "1": "create:block/bell_frame_side", + "particle": "create:block/bell" + }, + "elements": [ + { + "from": [5, 5, 0], + "to": [11, 11, 2], + "faces": { + "north": {"uv": [0, 10, 6, 16], "texture": "#1"}, + "east": {"uv": [14, 5, 12, 11], "texture": "#1"}, + "south": {"uv": [12, 10, 6, 16], "texture": "#1"}, + "west": {"uv": [14, 5, 16, 11], "texture": "#1"}, + "up": {"uv": [6, 0, 0, 2], "texture": "#1"}, + "down": {"uv": [12, 0, 6, 2], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [5, 5, 14], + "to": [11, 11, 16], + "faces": { + "north": {"uv": [12, 10, 6, 16], "texture": "#1"}, + "east": {"uv": [14, 5, 16, 11], "texture": "#1"}, + "south": {"uv": [0, 10, 6, 16], "texture": "#1"}, + "west": {"uv": [14, 5, 12, 11], "texture": "#1"}, + "up": {"uv": [6, 0, 0, 2], "rotation": 180, "texture": "#1"}, + "down": {"uv": [12, 0, 6, 2], "texture": "#1"} + } + } + ], + "groups": [ + { + "name": "Frame", + "origin": [8, 8, 8], + "color": 0, + "children": [] + }, 0, 1] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/bell_base/block_floor.json b/src/main/resources/assets/create/models/block/bell_base/block_floor.json new file mode 100644 index 000000000..9714a848e --- /dev/null +++ b/src/main/resources/assets/create/models/block/bell_base/block_floor.json @@ -0,0 +1,34 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "2": "create:block/bell_frame", + "particle": "create:block/bell" + }, + "elements": [ + { + "from": [0, 0, 5], + "to": [2, 11, 11], + "faces": { + "north": {"uv": [14, 5, 12, 16], "texture": "#2"}, + "east": {"uv": [12, 5, 6, 16], "texture": "#2"}, + "south": {"uv": [14, 5, 16, 16], "texture": "#2"}, + "west": {"uv": [0, 5, 6, 16], "texture": "#2"}, + "up": {"uv": [6, 0, 0, 2], "rotation": 270, "texture": "#2"}, + "down": {"uv": [12, 2, 6, 0], "rotation": 90, "texture": "#2"} + } + }, + { + "from": [14, 0, 5], + "to": [16, 11, 11], + "faces": { + "north": {"uv": [14, 5, 16, 16], "texture": "#2"}, + "east": {"uv": [0, 5, 6, 16], "texture": "#2"}, + "south": {"uv": [14, 5, 12, 16], "texture": "#2"}, + "west": {"uv": [12, 5, 6, 16], "texture": "#2"}, + "up": {"uv": [6, 0, 0, 2], "rotation": 90, "texture": "#2"}, + "down": {"uv": [12, 2, 6, 0], "rotation": 270, "texture": "#2"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/bell_base/block_single_wall.json b/src/main/resources/assets/create/models/block/bell_base/block_single_wall.json new file mode 100644 index 000000000..bccf3bff3 --- /dev/null +++ b/src/main/resources/assets/create/models/block/bell_base/block_single_wall.json @@ -0,0 +1,28 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "1": "create:block/bell_frame_side", + "particle": "create:block/bell" + }, + "elements": [ + { + "from": [5, 5, 0], + "to": [11, 11, 2], + "faces": { + "north": {"uv": [0, 10, 6, 16], "texture": "#1"}, + "east": {"uv": [14, 5, 12, 11], "texture": "#1"}, + "south": {"uv": [12, 10, 6, 16], "texture": "#1"}, + "west": {"uv": [14, 5, 16, 11], "texture": "#1"}, + "up": {"uv": [6, 0, 0, 2], "texture": "#1"}, + "down": {"uv": [12, 0, 6, 2], "rotation": 180, "texture": "#1"} + } + } + ], + "groups": [ + { + "name": "Frame", + "origin": [8, 8, 8], + "color": 0, + "children": [] + }, 0] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/blaze_burner/block_with_soul_fire.json b/src/main/resources/assets/create/models/block/blaze_burner/block_with_soul_fire.json new file mode 100644 index 000000000..acddfcbd3 --- /dev/null +++ b/src/main/resources/assets/create/models/block/blaze_burner/block_with_soul_fire.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/blaze_burner/block_with_fire", + "textures": { + "fire": "block/soul_campfire_fire" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/cart_assembler/block.json b/src/main/resources/assets/create/models/block/cart_assembler/block.json index e0ea99754..c57969a30 100644 --- a/src/main/resources/assets/create/models/block/cart_assembler/block.json +++ b/src/main/resources/assets/create/models/block/cart_assembler/block.json @@ -2,12 +2,12 @@ "credit": "Made with Blockbench", "parent": "block/block", "textures": { - "4": "create:block/bearing_top", + "4": "create:block/cart_assembler_top", "5": "create:block/mechanical_bearing_side", - "clutch_off": "create:block/clutch_off", + "6": "create:block/cart_assembler_side_off", "rail": "block/powered_rail", - "translation_chassis_side": "create:block/cart_assembler_side", - "particle": "create:block/cart_assembler_side" + "particle": "create:block/cart_assembler_side", + "translation_chassis_side": "create:block/cart_assembler_side" }, "elements": [ { @@ -24,12 +24,12 @@ "from": [13.875, 0.062, 1.125], "to": [17.875, 13.937, 14.875], "faces": { - "north": {"uv": [1, 4, 15, 0], "rotation": 90, "texture": "#translation_chassis_side"}, - "east": {"uv": [1, 1, 15, 15], "rotation": 90, "texture": "#translation_chassis_side"}, - "south": {"uv": [1, 0, 15, 4], "rotation": 90, "texture": "#translation_chassis_side"}, + "north": {"uv": [1, 14.875, 5, 1], "texture": "#6"}, + "east": {"uv": [1, 15, 15, 1], "rotation": 180, "texture": "#6"}, + "south": {"uv": [11, 14.875, 15, 1], "texture": "#6"}, "west": {"uv": [1, 1, 15, 15], "rotation": 90, "texture": "#translation_chassis_side"}, - "up": {"uv": [5, 1, 9, 15], "texture": "#translation_chassis_side"}, - "down": {"uv": [2, 1, 6, 15], "texture": "#translation_chassis_side"} + "up": {"uv": [1, 5, 14.75, 1], "rotation": 270, "texture": "#6"}, + "down": {"uv": [1, 15, 14.75, 11], "rotation": 90, "texture": "#6"} } }, { @@ -37,12 +37,12 @@ "from": [-1.875, 0.062, 1.125], "to": [2.125, 13.937, 14.875], "faces": { - "north": {"uv": [1, 0, 15, 4], "rotation": 90, "texture": "#translation_chassis_side"}, + "north": {"uv": [11, 14.875, 15, 1], "texture": "#6"}, "east": {"uv": [1, 15, 15, 1], "rotation": 90, "texture": "#translation_chassis_side"}, - "south": {"uv": [1, 4, 15, 0], "rotation": 90, "texture": "#translation_chassis_side"}, - "west": {"uv": [1, 15, 15, 1], "rotation": 90, "texture": "#translation_chassis_side"}, - "up": {"uv": [9, 1, 5, 15], "texture": "#translation_chassis_side"}, - "down": {"uv": [6, 1, 2, 15], "texture": "#translation_chassis_side"} + "south": {"uv": [1, 14.875, 5, 1], "texture": "#6"}, + "west": {"uv": [1, 15, 15, 1], "rotation": 180, "texture": "#6"}, + "up": {"uv": [1, 5, 14.75, 1], "rotation": 90, "texture": "#6"}, + "down": {"uv": [1, 15, 14.75, 11], "rotation": 270, "texture": "#6"} } }, { @@ -50,23 +50,13 @@ "to": [16, 16, 16], "rotation": {"angle": 0, "axis": "y", "origin": [8, 23, 8]}, "faces": { - "north": {"uv": [0, 0, 16, 4], "texture": "#5"}, + "north": {"uv": [0, 0, 16, 4], "texture": "#translation_chassis_side"}, "east": {"uv": [0, 0, 16, 4], "texture": "#5"}, - "south": {"uv": [0, 0, 16, 4], "texture": "#5"}, + "south": {"uv": [0, 0, 16, 4], "texture": "#translation_chassis_side"}, "west": {"uv": [0, 0, 16, 4], "texture": "#5"}, "up": {"uv": [0, 0, 16, 16], "texture": "#4"}, "down": {"uv": [0, 0, 16, 16], "texture": "#translation_chassis_side"} } - }, - { - "from": [2, 10, 1], - "to": [14, 12, 15], - "rotation": {"angle": 0, "axis": "y", "origin": [18, 22, 10]}, - "faces": { - "north": {"uv": [2, 7, 14, 9], "texture": "#clutch_off"}, - "south": {"uv": [2, 7, 14, 9], "texture": "#clutch_off"}, - "down": {"uv": [2, 1, 14, 15], "texture": "#translation_chassis_side"} - } } ], "display": { diff --git a/src/main/resources/assets/create/models/block/cart_assembler/block_activator_rail_powered.json b/src/main/resources/assets/create/models/block/cart_assembler/block_activator_rail_powered.json index 157de2851..f2eecdb6b 100644 --- a/src/main/resources/assets/create/models/block/cart_assembler/block_activator_rail_powered.json +++ b/src/main/resources/assets/create/models/block/cart_assembler/block_activator_rail_powered.json @@ -1,7 +1,7 @@ { "parent": "create:block/cart_assembler/block", "textures": { - "clutch_off": "create:block/clutch_on", + "6": "create:block/cart_assembler_side_on", "rail": "block/activator_rail_on" } } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/cart_assembler/block_controller_rail_powered.json b/src/main/resources/assets/create/models/block/cart_assembler/block_controller_rail_powered.json index c4666ebba..66f0184ce 100644 --- a/src/main/resources/assets/create/models/block/cart_assembler/block_controller_rail_powered.json +++ b/src/main/resources/assets/create/models/block/cart_assembler/block_controller_rail_powered.json @@ -1,7 +1,7 @@ { "parent": "create:block/cart_assembler/block", "textures": { - "clutch_off": "create:block/clutch_on", + "6": "create:block/cart_assembler_side_on", "rail": "create:block/controller_rail_powered" } } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/cart_assembler/block_detector_rail_powered.json b/src/main/resources/assets/create/models/block/cart_assembler/block_detector_rail_powered.json index e17faee3e..23f295187 100644 --- a/src/main/resources/assets/create/models/block/cart_assembler/block_detector_rail_powered.json +++ b/src/main/resources/assets/create/models/block/cart_assembler/block_detector_rail_powered.json @@ -1,7 +1,7 @@ { "parent": "create:block/cart_assembler/block", "textures": { - "clutch_off": "create:block/clutch_on", + "6": "create:block/cart_assembler_side_on", "rail": "block/detector_rail_on" } } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/cart_assembler/block_powered_rail_powered.json b/src/main/resources/assets/create/models/block/cart_assembler/block_powered_rail_powered.json index 04f11d8c9..a1e7a2393 100644 --- a/src/main/resources/assets/create/models/block/cart_assembler/block_powered_rail_powered.json +++ b/src/main/resources/assets/create/models/block/cart_assembler/block_powered_rail_powered.json @@ -1,7 +1,7 @@ { "parent": "create:block/cart_assembler/block", "textures": { - "clutch_off": "create:block/clutch_on", + "6": "create:block/cart_assembler_side_on", "rail": "block/powered_rail_on" } } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/cart_assembler/block_regular_powered.json b/src/main/resources/assets/create/models/block/cart_assembler/block_regular_powered.json index 132b8ead6..ac436750d 100644 --- a/src/main/resources/assets/create/models/block/cart_assembler/block_regular_powered.json +++ b/src/main/resources/assets/create/models/block/cart_assembler/block_regular_powered.json @@ -1,7 +1,7 @@ { "parent": "create:block/cart_assembler/block", "textures": { - "clutch_off": "create:block/clutch_on", + "6": "create:block/cart_assembler_side_on", "rail": "block/rail" } } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/cart_assembler/item.json b/src/main/resources/assets/create/models/block/cart_assembler/item.json index cb19247f7..4aee19b0f 100644 --- a/src/main/resources/assets/create/models/block/cart_assembler/item.json +++ b/src/main/resources/assets/create/models/block/cart_assembler/item.json @@ -2,11 +2,11 @@ "credit": "Made with Blockbench", "parent": "block/block", "textures": { - "4": "create:block/bearing_top", "5": "create:block/mechanical_bearing_side", - "clutch_off": "create:block/clutch_off", + "6": "create:block/cart_assembler_side_off", + "particle": "create:block/cart_assembler_side", "translation_chassis_side": "create:block/cart_assembler_side", - "particle": "create:block/cart_assembler_side" + "1_4": "create:block/cart_assembler_top" }, "elements": [ { @@ -14,12 +14,12 @@ "from": [13.875, 0.062, 1.125], "to": [17.875, 13.937, 14.875], "faces": { - "north": {"uv": [1, 4, 15, 0], "rotation": 90, "texture": "#translation_chassis_side"}, - "east": {"uv": [1, 1, 15, 15], "rotation": 90, "texture": "#translation_chassis_side"}, - "south": {"uv": [1, 0, 15, 4], "rotation": 90, "texture": "#translation_chassis_side"}, + "north": {"uv": [1, 14.875, 5, 1], "texture": "#6"}, + "east": {"uv": [1, 15, 15, 1], "rotation": 180, "texture": "#6"}, + "south": {"uv": [11, 14.875, 15, 1], "texture": "#6"}, "west": {"uv": [1, 1, 15, 15], "rotation": 90, "texture": "#translation_chassis_side"}, - "up": {"uv": [5, 1, 9, 15], "texture": "#translation_chassis_side"}, - "down": {"uv": [2, 1, 6, 15], "texture": "#translation_chassis_side"} + "up": {"uv": [1, 5, 14.75, 1], "rotation": 270, "texture": "#6"}, + "down": {"uv": [1, 15, 14.75, 11], "rotation": 90, "texture": "#6"} } }, { @@ -27,12 +27,12 @@ "from": [-1.875, 0.062, 1.125], "to": [2.125, 13.937, 14.875], "faces": { - "north": {"uv": [1, 0, 15, 4], "rotation": 90, "texture": "#translation_chassis_side"}, + "north": {"uv": [11, 14.875, 15, 1], "texture": "#6"}, "east": {"uv": [1, 15, 15, 1], "rotation": 90, "texture": "#translation_chassis_side"}, - "south": {"uv": [1, 4, 15, 0], "rotation": 90, "texture": "#translation_chassis_side"}, - "west": {"uv": [1, 15, 15, 1], "rotation": 90, "texture": "#translation_chassis_side"}, - "up": {"uv": [9, 1, 5, 15], "texture": "#translation_chassis_side"}, - "down": {"uv": [6, 1, 2, 15], "texture": "#translation_chassis_side"} + "south": {"uv": [1, 14.875, 5, 1], "texture": "#6"}, + "west": {"uv": [1, 15, 15, 1], "rotation": 180, "texture": "#6"}, + "up": {"uv": [1, 5, 14.75, 1], "rotation": 90, "texture": "#6"}, + "down": {"uv": [1, 15, 14.75, 11], "rotation": 270, "texture": "#6"} } }, { @@ -40,23 +40,13 @@ "to": [16, 16, 16], "rotation": {"angle": 0, "axis": "y", "origin": [8, 23, 8]}, "faces": { - "north": {"uv": [0, 0, 16, 4], "texture": "#5"}, + "north": {"uv": [0, 0, 16, 4], "texture": "#translation_chassis_side"}, "east": {"uv": [0, 0, 16, 4], "texture": "#5"}, - "south": {"uv": [0, 0, 16, 4], "texture": "#5"}, + "south": {"uv": [0, 0, 16, 4], "texture": "#translation_chassis_side"}, "west": {"uv": [0, 0, 16, 4], "texture": "#5"}, - "up": {"uv": [0, 0, 16, 16], "texture": "#4"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#1_4"}, "down": {"uv": [0, 0, 16, 16], "texture": "#translation_chassis_side"} } - }, - { - "from": [2, 10, 1], - "to": [14, 12, 15], - "rotation": {"angle": 0, "axis": "y", "origin": [18, 22, 10]}, - "faces": { - "north": {"uv": [2, 7, 14, 9], "texture": "#clutch_off"}, - "south": {"uv": [2, 7, 14, 9], "texture": "#clutch_off"}, - "down": {"uv": [2, 1, 14, 15], "texture": "#translation_chassis_side"} - } } ], "display": { @@ -89,5 +79,12 @@ "fixed": { "scale": [0.5, 0.5, 0.5] } - } + }, + "groups": [ + { + "name": "block", + "origin": [8, 8, 8], + "children": [0, 1, 2] + } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/fluid_pipe/item.json b/src/main/resources/assets/create/models/block/fluid_pipe/item.json index 3860db36a..c68b548bd 100644 --- a/src/main/resources/assets/create/models/block/fluid_pipe/item.json +++ b/src/main/resources/assets/create/models/block/fluid_pipe/item.json @@ -66,5 +66,11 @@ "down": {"uv": [6, 5, 11, 6], "texture": "#1"} } } - ] + ], + "display": { + "fixed": { + "rotation": [0, 90, 0], + "scale": [0.5, 0.5, 0.5] + } + } } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/haunted_bell.json b/src/main/resources/assets/create/models/block/haunted_bell.json new file mode 100644 index 000000000..7acde1c60 --- /dev/null +++ b/src/main/resources/assets/create/models/block/haunted_bell.json @@ -0,0 +1,96 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "create:block/bell_anim" + }, + "elements": [ + { + "from": [12.99, 6.99, 6.99], + "to": [16.01, 9.01, 9.01], + "rotation": {"angle": 0, "axis": "y", "origin": [7, 8, 8]}, + "faces": { + "north": {"uv": [11, 6, 9.5, 7], "texture": "#0"}, + "east": {"uv": [11, 7, 12, 8], "texture": "#0"}, + "south": {"uv": [9.5, 6, 11, 7], "texture": "#0"}, + "west": {"uv": [10, 7, 10.5, 7.5], "texture": "#0"}, + "up": {"uv": [9.5, 5, 11, 6], "texture": "#0"}, + "down": {"uv": [9.5, 7, 11, 8], "texture": "#0"} + } + }, + { + "from": [-0.01, 6.99, 6.99], + "to": [3.01, 9.01, 9.01], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 8, 8]}, + "faces": { + "north": {"uv": [9.5, 6, 11, 7], "texture": "#0"}, + "east": {"uv": [10, 7, 10.5, 7.5], "texture": "#0"}, + "south": {"uv": [11, 6, 9.5, 7], "texture": "#0"}, + "west": {"uv": [11, 7, 12, 8], "texture": "#0"}, + "up": {"uv": [9.5, 5, 11, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9.5, 7, 11, 8], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [3, 1, 3], + "to": [13, 3, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 9, 8]}, + "faces": { + "north": {"uv": [0, 15, 5, 16], "texture": "#0"}, + "east": {"uv": [0, 15, 5, 16], "texture": "#0"}, + "south": {"uv": [0, 15, 5, 16], "texture": "#0"}, + "west": {"uv": [0, 15, 5, 16], "texture": "#0"}, + "up": {"uv": [0, 10, 5, 15], "texture": "#0"}, + "down": {"uv": [5, 10, 10, 15], "texture": "#0"} + } + }, + { + "from": [4, 3, 4], + "to": [12, 12, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 9, 8]}, + "faces": { + "north": {"uv": [8, 0, 12, 4.5], "texture": "#0"}, + "east": {"uv": [12, 4, 16, 8.5], "texture": "#0"}, + "south": {"uv": [8, 0, 12, 4.5], "texture": "#0"}, + "west": {"uv": [12, 4, 16, 8.5], "texture": "#0"}, + "up": {"uv": [12, 0, 16, 4], "texture": "#0"} + } + }, + { + "from": [7, 11, 7], + "to": [9, 15, 9], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 9, 8]}, + "faces": { + "north": {"uv": [8, 6, 9, 8], "texture": "#0"}, + "east": {"uv": [8, 6, 9, 8], "texture": "#0"}, + "south": {"uv": [8, 6, 9, 8], "texture": "#0"}, + "west": {"uv": [8, 6, 9, 8], "texture": "#0"}, + "up": {"uv": [8, 5, 9, 6], "texture": "#0"} + } + }, + { + "from": [0, 0, 8], + "to": [16, 16, 9], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8.5]}, + "faces": { + "north": {"uv": [0, 0, 8, 8], "texture": "#0"} + } + }, + { + "from": [0, 0, 7], + "to": [16, 16, 8], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8.5]}, + "faces": { + "south": {"uv": [0, 0, 8, 8], "texture": "#0"} + } + } + ], + "groups": [ + { + "name": "Bell", + "origin": [8, 8, 8], + "color": 0, + "children": [0, 1, 2, 3, 4, 5, 6] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/mechanical_mixer/item.json b/src/main/resources/assets/create/models/block/mechanical_mixer/item.json index d53ce5844..0c912b445 100644 --- a/src/main/resources/assets/create/models/block/mechanical_mixer/item.json +++ b/src/main/resources/assets/create/models/block/mechanical_mixer/item.json @@ -9,7 +9,8 @@ "6": "create:block/mixer_head", "11": "create:block/mechanical_press_top", "1_2": "create:block/cogwheel", - "mechanical_press_pole": "create:block/mechanical_press_pole" + "mechanical_press_pole": "create:block/mechanical_press_pole", + "particle": "create:block/andesite_casing" }, "elements": [ { diff --git a/src/main/resources/assets/create/models/block/peculiar_bell.json b/src/main/resources/assets/create/models/block/peculiar_bell.json new file mode 100644 index 000000000..1c828adf2 --- /dev/null +++ b/src/main/resources/assets/create/models/block/peculiar_bell.json @@ -0,0 +1,94 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "create:block/bell", + "particle": "create:block/bell" + }, + "elements": [ + { + "from": [12.99, 6.99, 6.99], + "to": [16.01, 9.01, 9.01], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [11, 6, 9.5, 7], "texture": "#0"}, + "east": {"uv": [11, 7, 12, 8], "texture": "#0"}, + "south": {"uv": [9.5, 6, 11, 7], "texture": "#0"}, + "west": {"uv": [10, 7, 10.5, 7.5], "texture": "#0"}, + "up": {"uv": [9.5, 5, 11, 6], "texture": "#0"}, + "down": {"uv": [9.5, 7, 11, 8], "texture": "#0"} + } + }, + { + "from": [-0.01, 6.99, 6.99], + "to": [3.01, 9.01, 9.01], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [9.5, 6, 11, 7], "texture": "#0"}, + "east": {"uv": [10, 7, 10.5, 7.5], "texture": "#0"}, + "south": {"uv": [11, 6, 9.5, 7], "texture": "#0"}, + "west": {"uv": [11, 7, 12, 8], "texture": "#0"}, + "up": {"uv": [9.5, 5, 11, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9.5, 7, 11, 8], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [3, 1, 3], + "to": [13, 3, 13], + "faces": { + "north": {"uv": [0, 15, 5, 16], "texture": "#0"}, + "east": {"uv": [0, 15, 5, 16], "texture": "#0"}, + "south": {"uv": [0, 15, 5, 16], "texture": "#0"}, + "west": {"uv": [0, 15, 5, 16], "texture": "#0"}, + "up": {"uv": [0, 10, 5, 15], "texture": "#0"}, + "down": {"uv": [5, 10, 10, 15], "texture": "#0"} + } + }, + { + "from": [4, 3, 4], + "to": [12, 12, 12], + "faces": { + "north": {"uv": [8, 0, 12, 4.5], "texture": "#0"}, + "east": {"uv": [8, 0, 12, 4.5], "texture": "#0"}, + "south": {"uv": [8, 0, 12, 4.5], "texture": "#0"}, + "west": {"uv": [8, 0, 12, 4.5], "texture": "#0"}, + "up": {"uv": [12, 0, 16, 4], "texture": "#0"} + } + }, + { + "from": [7, 11, 7], + "to": [9, 15, 9], + "faces": { + "north": {"uv": [8, 6, 9, 8], "texture": "#0"}, + "east": {"uv": [8, 6, 9, 8], "texture": "#0"}, + "south": {"uv": [8, 6, 9, 8], "texture": "#0"}, + "west": {"uv": [8, 6, 9, 8], "texture": "#0"}, + "up": {"uv": [8, 5, 9, 6], "texture": "#0"} + } + }, + { + "from": [0, 0, 8], + "to": [16, 16, 9], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8.5]}, + "faces": { + "north": {"uv": [0, 0, 8, 8], "texture": "#0"} + } + }, + { + "from": [0, 0, 7], + "to": [16, 16, 8], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8.5]}, + "faces": { + "south": {"uv": [0, 0, 8, 8], "texture": "#0"} + } + } + ], + "groups": [ + { + "name": "Bell", + "origin": [8, 8, 8], + "color": 0, + "children": [0, 1, 2, 3, 4, 5, 6] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/block.json b/src/main/resources/assets/create/models/block/toolbox/block.json new file mode 100644 index 000000000..167aac73e --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/block.json @@ -0,0 +1,24 @@ +{ + "credit": "Made with Blockbench", + "texture_size": [32, 32], + "textures": { + "0": "create:block/toolbox/brown", + "particle": "block/dark_oak_planks" + }, + "elements": [ + { + "from": [1, 0, 4], + "to": [15, 6, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1.5, 7, 4.5], "texture": "#0"}, + "east": {"uv": [6, 6, 10, 9], "texture": "#0"}, + "south": {"uv": [7, 1.5, 14, 4.5], "texture": "#0"}, + "west": {"uv": [6, 6, 10, 9], "texture": "#0"}, + "up": {"uv": [0, 11.5, 7, 15.5], "texture": "#0"}, + "down": {"uv": [7, 11.5, 14, 15.5], "texture": "#0"} + } + } + ], + "display": {} +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/drawer.json b/src/main/resources/assets/create/models/block/toolbox/drawer.json new file mode 100644 index 000000000..9989cb82d --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/drawer.json @@ -0,0 +1,23 @@ +{ + "credit": "Made with Blockbench", + "texture_size": [32, 32], + "textures": { + "0": "create:block/toolbox/brown", + "particle": "block/dark_oak_planks" + }, + "elements": [ + { + "from": [2, 1, 4], + "to": [14, 3, 10], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 4.5, 6, 5.5], "texture": "#0"}, + "east": {"uv": [6, 9, 9, 10], "texture": "#0"}, + "west": {"uv": [9, 9, 6, 10], "texture": "#0"}, + "up": {"uv": [0, 5.5, 6, 8.5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 8.5, 6, 11.5], "texture": "#0"} + } + } + ], + "display": {} +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/item.json b/src/main/resources/assets/create/models/block/toolbox/item.json new file mode 100644 index 000000000..c47819e0a --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/item.json @@ -0,0 +1,132 @@ +{ + "credit": "Made with Blockbench", + "texture_size": [32, 32], + "textures": { + "0": "create:block/toolbox/brown", + "particle": "block/dark_oak_planks" + }, + "elements": [ + { + "from": [1, 0, 4], + "to": [15, 6, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 1.5, 7, 4.5], "texture": "#0"}, + "east": {"uv": [6, 6, 10, 9], "texture": "#0"}, + "south": {"uv": [7, 1.5, 14, 4.5], "texture": "#0"}, + "west": {"uv": [6, 6, 10, 9], "texture": "#0"}, + "up": {"uv": [0, 11.5, 7, 15.5], "texture": "#0"}, + "down": {"uv": [7, 11.5, 14, 15.5], "texture": "#0"} + } + }, + { + "from": [1, 6, 4], + "to": [15, 9, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 7, 1.5], "texture": "#0"}, + "east": {"uv": [6, 4.5, 10, 6], "texture": "#0"}, + "south": {"uv": [7, 0, 14, 1.5], "texture": "#0"}, + "west": {"uv": [6, 4.5, 10, 6], "texture": "#0"}, + "up": {"uv": [10, 4.5, 14, 11.5], "rotation": 90, "texture": "#0"}, + "down": {"uv": [7, 11.5, 14, 15.5], "texture": "#0"} + } + }, + { + "from": [11, 5, 3], + "to": [13, 8, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [9, 9, 10, 10.5], "texture": "#0"}, + "east": {"uv": [9, 9, 9.5, 10.5], "texture": "#0"}, + "south": {"uv": [10, 9, 9, 10.5], "texture": "#0"}, + "west": {"uv": [9.5, 9, 10, 10.5], "texture": "#0"}, + "up": {"uv": [9, 9, 10, 9.5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 10, 10, 10.5], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 9, 8], + "to": [12, 11, 8], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [6, 10.5, 10, 11.5], "texture": "#0"}, + "south": {"uv": [6, 10.5, 10, 11.5], "texture": "#0"} + } + }, + { + "from": [1.95, 1.1, 3.7], + "to": [14.05, 3, 9.7], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 4.5, 6, 5.5], "texture": "#0"}, + "east": {"uv": [6, 9, 9, 10], "texture": "#0"}, + "west": {"uv": [9, 9, 6, 10], "texture": "#0"}, + "up": {"uv": [0, 5.5, 6, 8.5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 8.5, 6, 11.5], "texture": "#0"} + } + }, + { + "from": [1.95, 3, 3.7], + "to": [14.05, 5.05, 9.7], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 4.5, 6, 5.5], "texture": "#0"}, + "east": {"uv": [6, 9, 9, 10], "texture": "#0"}, + "west": {"uv": [9, 9, 6, 10], "texture": "#0"}, + "up": {"uv": [0, 5.5, 6, 8.5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 8.5, 6, 11.5], "texture": "#0"} + } + }, + { + "from": [3, 5, 3], + "to": [5, 8, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [9, 9, 10, 10.5], "texture": "#0"}, + "east": {"uv": [9, 9, 9.5, 10.5], "texture": "#0"}, + "south": {"uv": [10, 9, 9, 10.5], "texture": "#0"}, + "west": {"uv": [9.5, 9, 10, 10.5], "texture": "#0"}, + "up": {"uv": [9, 9, 10, 9.5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 10, 10, 10.5], "rotation": 180, "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, -77, 2], + "translation": [0, -2.5, -0.75], + "scale": [0.64, 0.64, 0.64] + }, + "thirdperson_lefthand": { + "rotation": [75, -77, 2], + "translation": [0, -2.5, -0.75], + "scale": [0.64, 0.64, 0.64] + }, + "firstperson_righthand": { + "rotation": [-5, 86, 0], + "translation": [1, -1.25, 0], + "scale": [0.88, 0.88, 0.88] + }, + "firstperson_lefthand": { + "rotation": [-5, 86, 0], + "translation": [1, -1.25, 0], + "scale": [0.88, 0.88, 0.88] + }, + "ground": { + "translation": [0, 2, 0], + "scale": [0.5, 0.5, 0.5] + }, + "gui": { + "rotation": [30, 225, 0], + "translation": [0.25, 2.25, 0], + "scale": [0.79, 0.79, 0.79] + }, + "head": { + "translation": [0, 2.75, 0] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/black.json b/src/main/resources/assets/create/models/block/toolbox/lid/black.json new file mode 100644 index 000000000..f7da955c6 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/black.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/black" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/blue.json b/src/main/resources/assets/create/models/block/toolbox/lid/blue.json new file mode 100644 index 000000000..bdd1e4c64 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/blue.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/blue" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/brown.json b/src/main/resources/assets/create/models/block/toolbox/lid/brown.json new file mode 100644 index 000000000..f352cd396 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/brown.json @@ -0,0 +1,59 @@ +{ + "credit": "Made with Blockbench", + "texture_size": [32, 32], + "textures": { + "0": "create:block/toolbox/brown", + "particle": "block/dark_oak_planks" + }, + "elements": [ + { + "from": [1, 6, 4], + "to": [15, 9, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 7, 1.5], "texture": "#0"}, + "east": {"uv": [6, 4.5, 10, 6], "texture": "#0"}, + "south": {"uv": [7, 0, 14, 1.5], "texture": "#0"}, + "west": {"uv": [6, 4.5, 10, 6], "texture": "#0"}, + "up": {"uv": [10, 4.5, 14, 11.5], "rotation": 90, "texture": "#0"}, + "down": {"uv": [7, 11.5, 14, 15.5], "texture": "#0"} + } + }, + { + "from": [11, 5, 3], + "to": [13, 8, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [9, 9, 10, 10.5], "texture": "#0"}, + "east": {"uv": [9, 9, 9.5, 10.5], "texture": "#0"}, + "south": {"uv": [10, 9, 9, 10.5], "texture": "#0"}, + "west": {"uv": [9.5, 9, 10, 10.5], "texture": "#0"}, + "up": {"uv": [9, 9, 10, 9.5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 10, 10, 10.5], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [4, 9, 8], + "to": [12, 11, 8], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [6, 10.5, 10, 11.5], "texture": "#0"}, + "south": {"uv": [6, 10.5, 10, 11.5], "texture": "#0"} + } + }, + { + "from": [3, 5, 3], + "to": [5, 8, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [9, 9, 10, 10.5], "texture": "#0"}, + "east": {"uv": [9, 9, 9.5, 10.5], "texture": "#0"}, + "south": {"uv": [10, 9, 9, 10.5], "texture": "#0"}, + "west": {"uv": [9.5, 9, 10, 10.5], "texture": "#0"}, + "up": {"uv": [9, 9, 10, 9.5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 10, 10, 10.5], "rotation": 180, "texture": "#0"} + } + } + ], + "display": {} +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/cyan.json b/src/main/resources/assets/create/models/block/toolbox/lid/cyan.json new file mode 100644 index 000000000..f1039e0fd --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/cyan.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/cyan" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/gray.json b/src/main/resources/assets/create/models/block/toolbox/lid/gray.json new file mode 100644 index 000000000..d08ce0c8a --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/gray.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/gray" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/green.json b/src/main/resources/assets/create/models/block/toolbox/lid/green.json new file mode 100644 index 000000000..7f80e0ff3 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/green.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/green" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/light_blue.json b/src/main/resources/assets/create/models/block/toolbox/lid/light_blue.json new file mode 100644 index 000000000..dedde2b36 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/light_blue.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/light_blue" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/light_gray.json b/src/main/resources/assets/create/models/block/toolbox/lid/light_gray.json new file mode 100644 index 000000000..4d027b16e --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/light_gray.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/light_gray" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/lime.json b/src/main/resources/assets/create/models/block/toolbox/lid/lime.json new file mode 100644 index 000000000..a5db407ba --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/lime.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/lime" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/magenta.json b/src/main/resources/assets/create/models/block/toolbox/lid/magenta.json new file mode 100644 index 000000000..317905db9 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/magenta.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/magenta" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/orange.json b/src/main/resources/assets/create/models/block/toolbox/lid/orange.json new file mode 100644 index 000000000..8f7330474 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/orange.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/orange" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/pink.json b/src/main/resources/assets/create/models/block/toolbox/lid/pink.json new file mode 100644 index 000000000..c220c295d --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/pink.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/pink" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/purple.json b/src/main/resources/assets/create/models/block/toolbox/lid/purple.json new file mode 100644 index 000000000..ad6f5d08d --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/purple.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/purple" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/red.json b/src/main/resources/assets/create/models/block/toolbox/lid/red.json new file mode 100644 index 000000000..e0b76f46f --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/red.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/red" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/white.json b/src/main/resources/assets/create/models/block/toolbox/lid/white.json new file mode 100644 index 000000000..22831e820 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/white.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/white" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/toolbox/lid/yellow.json b/src/main/resources/assets/create/models/block/toolbox/lid/yellow.json new file mode 100644 index 000000000..497aaf812 --- /dev/null +++ b/src/main/resources/assets/create/models/block/toolbox/lid/yellow.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/toolbox/lid/brown", + "textures": { + "0": "create:block/toolbox/yellow" + } +} \ 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/incomplete_cogwheel.json b/src/main/resources/assets/create/models/item/incomplete_cogwheel.json new file mode 100644 index 000000000..50438130a --- /dev/null +++ b/src/main/resources/assets/create/models/item/incomplete_cogwheel.json @@ -0,0 +1,53 @@ +{ + "credit": "Made with Blockbench", + "parent": "create:block/large_wheels", + "texture_size": [32, 32], + "textures": { + "0": "create:block/axis", + "3": "create:block/axis_top", + "1_2": "create:block/cogwheel", + "particle": "block/stripped_spruce_log" + }, + "elements": [ + { + "name": "Axis", + "from": [6, 0, 6], + "to": [10, 16, 10], + "shade": false, + "faces": { + "north": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "east": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "south": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "west": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "up": {"uv": [6, 6, 10, 10], "texture": "#3"}, + "down": {"uv": [6, 6, 10, 10], "texture": "#3"} + } + }, + { + "name": "GearCaseInner", + "from": [2, 7, 2], + "to": [14, 9, 14], + "faces": { + "north": {"uv": [0, 6, 6, 7], "texture": "#1_2"}, + "east": {"uv": [0, 6, 6, 7], "texture": "#1_2"}, + "south": {"uv": [0, 6, 6, 7], "texture": "#1_2"}, + "west": {"uv": [0, 6, 6, 7], "texture": "#1_2"}, + "up": {"uv": [4, 0, 10, 6], "texture": "#1_2"}, + "down": {"uv": [4, 0, 10, 6], "texture": "#1_2"} + } + }, + { + "name": "GearCaseOuter", + "from": [4, 6, 4], + "to": [12, 10, 12], + "faces": { + "north": {"uv": [0, 4, 4, 6], "texture": "#1_2"}, + "east": {"uv": [0, 4, 4, 6], "texture": "#1_2"}, + "south": {"uv": [0, 4, 4, 6], "texture": "#1_2"}, + "west": {"uv": [0, 4, 4, 6], "texture": "#1_2"}, + "up": {"uv": [0, 0, 4, 4], "texture": "#1_2"}, + "down": {"uv": [0, 0, 4, 4], "texture": "#1_2"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/incomplete_large_cogwheel.json b/src/main/resources/assets/create/models/item/incomplete_large_cogwheel.json new file mode 100644 index 000000000..1a9e884e1 --- /dev/null +++ b/src/main/resources/assets/create/models/item/incomplete_large_cogwheel.json @@ -0,0 +1,105 @@ +{ + "credit": "Made with Blockbench", + "parent": "create:block/large_wheels", + "texture_size": [32, 32], + "textures": { + "0": "create:block/axis", + "3": "create:block/axis_top", + "4": "create:block/large_cogwheel", + "particle": "block/stripped_spruce_log" + }, + "elements": [ + { + "name": "Axis", + "from": [6, 0, 6], + "to": [10, 16, 10], + "shade": false, + "faces": { + "north": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "east": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "south": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "west": {"uv": [6, 0, 10, 16], "texture": "#0"}, + "up": {"uv": [6, 6, 10, 10], "texture": "#3"}, + "down": {"uv": [6, 6, 10, 10], "texture": "#3"} + } + }, + { + "name": "GearCaseInner", + "from": [-2, 7, -2], + "to": [18, 9, 18], + "faces": { + "north": {"uv": [0, 10, 10, 11], "texture": "#4"}, + "east": {"uv": [0, 10, 10, 11], "texture": "#4"}, + "south": {"uv": [0, 10, 10, 11], "texture": "#4"}, + "west": {"uv": [0, 10, 10, 11], "texture": "#4"}, + "up": {"uv": [0, 0, 10, 10], "texture": "#4"}, + "down": {"uv": [0, 0, 10, 10], "texture": "#4"} + } + }, + { + "name": "GearCaseOuter", + "from": [1, 5.5, 1], + "to": [15, 10.5, 15], + "faces": { + "north": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "east": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "south": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "west": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "up": {"uv": [1.5, 1.5, 8.5, 8.5], "texture": "#4"}, + "down": {"uv": [1.5, 1.5, 8.5, 8.5], "texture": "#4"} + } + }, + { + "name": "GearCaseOuter", + "from": [-1, 5.5, 1], + "to": [1, 10.5, 15], + "faces": { + "north": {"uv": [10, 0, 12.5, 1], "rotation": 90, "texture": "#4"}, + "east": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "south": {"uv": [10, 6, 12.5, 7], "rotation": 90, "texture": "#4"}, + "west": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "up": {"uv": [7, 15, 14, 16], "rotation": 90, "texture": "#4"}, + "down": {"uv": [7, 15, 14, 16], "rotation": 90, "texture": "#4"} + } + }, + { + "name": "GearCaseOuter", + "from": [15, 5.5, 1], + "to": [17, 10.5, 15], + "faces": { + "north": {"uv": [10, 6, 12.5, 7], "rotation": 90, "texture": "#4"}, + "east": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "south": {"uv": [10, 0, 12.5, 1], "rotation": 90, "texture": "#4"}, + "west": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "up": {"uv": [0, 15, 7, 16], "rotation": 270, "texture": "#4"}, + "down": {"uv": [0, 15, 7, 16], "rotation": 270, "texture": "#4"} + } + }, + { + "name": "GearCaseOuter", + "from": [1, 5.5, -1], + "to": [15, 10.5, 1], + "faces": { + "north": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "east": {"uv": [10, 0, 12.5, 1], "rotation": 90, "texture": "#4"}, + "south": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "west": {"uv": [10, 6, 12.5, 7], "rotation": 90, "texture": "#4"}, + "up": {"uv": [7, 14, 14, 15], "rotation": 180, "texture": "#4"}, + "down": {"uv": [0, 14, 7, 15], "texture": "#4"} + } + }, + { + "name": "GearCaseOuter", + "from": [1, 5.5, 15], + "to": [15, 10.5, 17], + "faces": { + "north": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "east": {"uv": [10, 6, 12.5, 7], "rotation": 90, "texture": "#4"}, + "south": {"uv": [10, 0, 12.5, 7], "rotation": 90, "texture": "#4"}, + "west": {"uv": [10, 0, 12.5, 1], "rotation": 90, "texture": "#4"}, + "up": {"uv": [0, 14, 7, 15], "texture": "#4"}, + "down": {"uv": [7, 14, 14, 15], "rotation": 180, "texture": "#4"} + } + } + ] +} \ No newline at end of file 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/potato_cannon/base.bbmodel b/src/main/resources/assets/create/models/item/potato_cannon/base.bbmodel new file mode 100644 index 000000000..ac8d214b3 --- /dev/null +++ b/src/main/resources/assets/create/models/item/potato_cannon/base.bbmodel @@ -0,0 +1 @@ +{"meta":{"format_version":"3.6","creation_time":1624660393,"model_format":"java_block","box_uv":false},"name":"item","parent":"create:item/potato_cannon/item","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"resolution":{"width":16,"height":16},"elements":[{"name":"cube","rescale":false,"from":[7,7,-2.5],"to":[9,10,6.5],"autouv":0,"color":0,"locked":false,"origin":[7,7.6,11],"faces":{"north":{"uv":[7.5,1,9.5,4],"texture":0},"east":{"uv":[0.5,6,3.5,15],"rotation":90,"texture":0},"south":{"uv":[7.5,1,9.5,4],"texture":0},"west":{"uv":[0.5,6,3.5,15],"rotation":270,"texture":0},"up":{"uv":[1,6,3,15],"texture":0},"down":{"uv":[1,6,3,15],"rotation":180,"texture":0}},"uuid":"5e678c6f-f4df-6c89-5094-cf6f159d76f1"},{"name":"cube","rescale":false,"from":[7,7,9.5],"to":[9,10,10.5],"autouv":0,"color":3,"locked":false,"origin":[8,7.6,11],"faces":{"north":{"uv":[0,0,0,0],"texture":null},"east":{"uv":[0.5,6,3.5,7],"rotation":90,"texture":0},"south":{"uv":[0,0,0,0],"texture":null},"west":{"uv":[0.5,6,3.5,7],"rotation":270,"texture":0},"up":{"uv":[1,6,3,7],"texture":0},"down":{"uv":[1,6,3,7],"rotation":180,"texture":0}},"uuid":"26a67f2c-179c-2879-8433-8e3568b818d3"},{"name":"cube","rescale":false,"from":[6,7,10.5],"to":[10,11,16.5],"autouv":0,"color":5,"locked":false,"origin":[8,9.6,11],"faces":{"north":{"uv":[7,7,15,15],"rotation":270,"texture":1},"east":{"uv":[4,4,12,16],"rotation":270,"texture":2},"south":{"uv":[7,7,15,15],"rotation":270,"texture":1},"west":{"uv":[4,4,12,16],"rotation":90,"texture":2},"up":{"uv":[4,4,12,16],"rotation":180,"texture":2},"down":{"uv":[4,4,12,16],"texture":2}},"uuid":"4c11c0a3-218a-f5f1-5ef1-42e94ee9aacd"},{"name":"cube","rescale":false,"from":[7,4,11.5],"to":[9,6,15.5],"autouv":0,"color":7,"locked":false,"origin":[8,7.6,11],"faces":{"north":{"uv":[13,13,15,15],"texture":0},"east":{"uv":[1,6,3,10],"rotation":90,"texture":0},"south":{"uv":[0,0,0,0],"texture":null},"west":{"uv":[1,6,3,10],"rotation":270,"texture":0},"up":{"uv":[1,6,3,10],"texture":0},"down":{"uv":[1,6,3,10],"rotation":180,"texture":0}},"uuid":"ea1494fd-ebef-b708-b9a4-92593f90d620"},{"name":"cube","rescale":false,"from":[6.5,3.5,9.5],"to":[9.5,6.5,14.5],"autouv":0,"color":0,"locked":false,"rotation":[0,0,-45],"origin":[8,5,11.5],"faces":{"north":{"uv":[12.5,12.5,15.5,15.5],"texture":0},"east":{"uv":[0.5,6,3.5,11],"rotation":90,"texture":0},"south":{"uv":[12.5,12.5,15.5,15.5],"texture":0},"west":{"uv":[0.5,6,3.5,11],"rotation":270,"texture":0},"up":{"uv":[0.5,6,3.5,11],"texture":0},"down":{"uv":[0.5,6,3.5,11],"rotation":180,"texture":0}},"uuid":"c9ee0469-c584-6987-c27a-d6591c119e4a"},{"name":"cube","rescale":false,"from":[7,4,15.5],"to":[9,10,17.5],"autouv":0,"color":7,"locked":false,"origin":[8,7.6,11],"faces":{"north":{"uv":[3,7,1,13],"rotation":180,"texture":0},"east":{"uv":[1,9,3,15],"texture":0},"south":{"uv":[3,7,1,13],"rotation":180,"texture":0},"west":{"uv":[3,9,1,15],"texture":0},"up":{"uv":[1,7,3,9],"rotation":180,"texture":0},"down":{"uv":[1,7,3,9],"texture":0}},"uuid":"7116c2c4-a219-6979-364f-792a4eec68c2"},{"name":"Cog","rescale":false,"from":[5.5,8,6.5],"to":[10.5,9,9.5],"autouv":0,"color":4,"locked":false,"rotation":[0,0,45],"origin":[8,8.5,8.5],"faces":{"north":{"uv":[6,15,11,16],"texture":3},"east":{"uv":[7,13,8,16],"rotation":270,"texture":3},"south":{"uv":[6,14,11,15],"texture":3},"west":{"uv":[9,13,10,16],"rotation":90,"texture":3},"up":{"uv":[6,13,11,16],"rotation":180,"texture":3},"down":{"uv":[6,13,11,16],"texture":3}},"uuid":"9c6e556e-3af0-8367-5c8c-2eda35106e6a"},{"name":"Cog","rescale":false,"from":[5.5,8,6.5],"to":[10.5,9,9.5],"autouv":0,"color":7,"locked":false,"rotation":[0,0,-45],"origin":[8,8.5,8.5],"faces":{"north":{"uv":[6,15,11,16],"texture":3},"east":{"uv":[7,13,8,16],"rotation":270,"texture":3},"south":{"uv":[6,14,11,15],"texture":3},"west":{"uv":[9,13,10,16],"rotation":90,"texture":3},"up":{"uv":[6,13,11,16],"rotation":180,"texture":3},"down":{"uv":[6,13,11,16],"texture":3}},"uuid":"b79ea326-3102-0b62-7b79-2a938ad44e69"},{"name":"Cog","rescale":false,"from":[7.5,6,6.5],"to":[8.5,11,9.5],"autouv":0,"color":6,"locked":false,"origin":[8,8.5,8.5],"faces":{"north":{"uv":[6,15,11,16],"rotation":270,"texture":3},"east":{"uv":[6,13,11,16],"rotation":270,"texture":3},"south":{"uv":[6,14,11,15],"rotation":90,"texture":3},"west":{"uv":[6,13,11,16],"rotation":90,"texture":3},"up":{"uv":[8,13,9,16],"rotation":180,"texture":3},"down":{"uv":[6,13,7,16],"texture":3}},"uuid":"aec1402d-fc45-fc7e-0144-520a7ceddb0d"},{"name":"Cog","rescale":false,"from":[5.5,8,6.5],"to":[10.5,9,9.5],"autouv":0,"color":0,"locked":false,"origin":[8,11,3.5],"faces":{"north":{"uv":[6,15,11,16],"texture":3},"east":{"uv":[6,13,7,16],"rotation":270,"texture":3},"south":{"uv":[6,14,11,15],"texture":3},"west":{"uv":[8,13,9,16],"rotation":90,"texture":3},"up":{"uv":[6,13,11,16],"rotation":180,"texture":3},"down":{"uv":[6,13,11,16],"texture":3}},"uuid":"6cd0eeca-26e6-bf33-2ad3-5d0185d8f13e"}],"outliner":["5e678c6f-f4df-6c89-5094-cf6f159d76f1","26a67f2c-179c-2879-8433-8e3568b818d3","4c11c0a3-218a-f5f1-5ef1-42e94ee9aacd","ea1494fd-ebef-b708-b9a4-92593f90d620","c9ee0469-c584-6987-c27a-d6591c119e4a","7116c2c4-a219-6979-364f-792a4eec68c2",{"name":"cog","origin":[8,8,8],"uuid":"0fed5b4f-08c1-81df-64e3-c2a1410f906c","export":true,"isOpen":false,"locked":false,"visibility":true,"autouv":0,"children":[{"name":"accelerator","origin":[8,8,8],"uuid":"f3e38ac1-88e9-9ad4-6331-f44b7424a494","export":true,"isOpen":false,"locked":false,"visibility":true,"autouv":0,"children":["9c6e556e-3af0-8367-5c8c-2eda35106e6a","b79ea326-3102-0b62-7b79-2a938ad44e69","aec1402d-fc45-fc7e-0144-520a7ceddb0d","6cd0eeca-26e6-bf33-2ad3-5d0185d8f13e"]}]}],"textures":[{"path":"C:\\Users\\simon\\Desktop\\Modding\\Forgespace 1.16\\Create\\src\\main\\resources\\assets\\create\\textures\\block\\fluid_pipe.png","name":"fluid_pipe.png","folder":"block","namespace":"create","id":"2","particle":false,"visible":true,"mode":"bitmap","saved":true,"uuid":"b1f94f74-864a-5d8e-db7c-abf1e7f25c9a","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFlklEQVRYR61XXWhcRRg9d5PNbna7d7ObbNI2SWMttgY1Koi0mrZiS8GgYAo+lKAPRUoF/0CkfSh5KH3wB4RS8akIKkGk9Qd/KgQVNX0o6kNJlfoX2jTbZJPsbppsNsnNJrly5va7mb3ZNElxXmbv3NmZM993zvnmGsf3PW7nFwywhX226qXJuDwvFAp4oGEdIvGAGoqGQ6ovq3aes9fGVJ/LWhifBqKVi2v1jc6gs/sHZyOtGQTQEA0gUGGgIuwsFAgAlgXM5i31zPHc2Awuj+Sxs6VabRyvT6h34zMT7nLRoIns9VGM56cUiJbtW9Uz537+Ve/yALYkgriSn8OFiSlnwwq/6mdnC6rfboawOVyOi8lJBWDz1ia14I/9yaLTPNbUgPanWnDl734FQBqjkV2Yw7Evuo1Lp161t+6ogZUfhrn7lKEiQAAfXssiHK5EwO+HGTExkXNOZhUKyOen8dymOHoGJnDgkSYV8s7T573RVM8nX2xTp2aT1PRfTKkDEsD5tw/azVsiGDTSuK+9axHAx0MTiIRDyN6YwIP3NmNsPIerA0nEq0zk8lNoqzLRm14bAAGhA/jpaIfdtDGApH8YrS98YxhH9u6xW+oC+DQzrU7f1FAPy5pFlRnBtGWhP3ldATiwwXQjwJy+8u65khE4/nwr5jOW4gEb+ZIcGHMj8OVL7XZdzI9c9Ab2vtZtGId3tdp77k7gg39HUROPIVARQCwaURGwZi1YluUCIAee3NGoSLUSgJGsA6A2XgzgzKF2uz4IpGoz2H/sZwfAw3URfJbJFaUgNZrG0PCom4JD9yTQ05tZNQkVf6ylALo62uy6SDmGakbw7IkLTgq2xSrwSWoMfn+5UgBTIQSkEgqFOZeEbfcnXBmKBCk/aSJDhr4UCd9/5gm7utKPofWDOPzWbw6Ah+408ddIHj0Zh/kEwsaN2R6tDIFKoQp2NprKiLgB86ybEY1Il58uw/SkY0Tv7W+zYz4bo/VpvHzy18UIlGSUNjhYmEcyO7UmAKWM6MTT++w6zCFTM4mjp39xOLDS5vr7hngIcZ8TIVqtNev8fWbeQLDMVj1Nh3NKWTF9JxT0YT6awpGPfjcMIuLkRI1jw2y0YN29dAAkkbcWuKG+KT2moaPr3BLf5zymPOKbx4KZQufZP50U8MVyhejN774vudBaoqbPfX33LtuED/lEBm+cvbQYAYZLTibVTPz7djcr9T+mPDpfhkIsjXe+/mPRilnxaBpsNBGmYbkS+n8CMqhLlmKePr4pptamlRIEpckCcqsNmUKmzxcqx8LUHFjapVE5bBv9ZUVjnMfG+4YLQCJAm2U5pYutFgCNTL9P6GQWlURiwSKSczw5bjkA+KZmfVCZCt1r6J+bN5uxGRw88+2KEWAx8ypDihHXlnX1IkWesUQrGW6rDatbkLgaw88bENtKALz/F/v1pk1uSxwnOImwAsDbTkNjTJ2eKNn6+rKrAsAIMrwksHdzqRGsGVxXf88o85BLAKyVhKUA6JvJgbg5AQkYibKbAp6ABOQEFpXVklBPgaiIh5A1+FvSKyBYMUVlioQMISfxsinl9HYBCNHkVk22e1NEcOnUDChTNwIb7oqpEBGAKIFmRKbqOvZqnPwRCesckhPKfK8XyHgRAMm/zlSC4AbsRdNezeshljXkHihGpP9H1nIjoKtAJ4oAEbT6JUS/dMp7YTnToAPg+volhvNdH2B9br4jWiQjXT5ePXNxIavOcGU4HpbTSdm8PlPkAzoJ9XucbCySks1kcx2YV++yweWr46o2CAnlCsfeJaF8GelWWuquJ5bKXrdrb/71D1QSmM2bAlGIsmL945SThXDyoSonlQ9V/eQisVJzpNiwSlIBpYqRIuGtyqm+mZRWr6w4zg3093q5jaxzSvFyMvwPaYjs9h/DqboAAAAASUVORK5CYII="},{"path":"C:\\Users\\simon\\Desktop\\Modding\\Forgespace 1.16\\Create\\src\\main\\resources\\assets\\create\\textures\\block\\andesite_casing_very_short.png","name":"andesite_casing_very_short.png","folder":"block","namespace":"create","id":"4","particle":false,"visible":true,"mode":"bitmap","saved":true,"uuid":"85220030-0179-1a36-8ed9-8a2cd4d94045","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB0ElEQVQ4T91TPUscQRh+Zj9vct7tnglRiBauH4WXFHYWNvkBadIEDlIJQUipKP6QdLGzFqwEWxtJEERNQsAEBBsTLt6a253d2V1HZnTOVe8X+Dbzvs/MPLP7PO9LlldXhO/5yIsChTDAohCylpELAYsQ/O9ewHEoTNNQOOc5nlAXnbADMv9hXigUAGMMlFJd3lnlno7yGdJ63xJxxMCzDIblIksj2JYNIQTiNEW9WgVLYhiGjSzj6gHGUtCKg7pXA3kEv1AWsZ9698XTQutVuTAeTCBmKRzHUhxFcQnOGWoD9Z6VEpe20aoHk1zCMk0cfTsEWVxZFE8bz7C78UldrlYcRAnva2UZnGstYX/vy3Uf+A0ff75uYnTYx9/zLs7aXQQjg6g4FhKeI2JcYdPBc7TDWOWzbz/efgGt1HCys45Bz8W/MEXYTRQBdW2wNEO7EyusOT6E07NQ5T0CrcGP7bUHBEIUIMTsEYy98HoPTL5+h875TStLEe8TjA75sCyBPCe4iBL1aplAavDz+yFUKwfBFA62Pt8RzrVNpFmhMJnLkLXOZ94s4Nfv42uCl81XykYd9cbNNCa3AyT39Bk5iTKUjbqRdMOUJ63fBJYxSXIFRuc4bJLxudoAAAAASUVORK5CYII="},{"path":"C:\\Users\\simon\\Desktop\\Modding\\Forgespace 1.16\\Create\\src\\main\\resources\\assets\\create\\textures\\block\\andesite_casing_short.png","name":"andesite_casing_short.png","folder":"block","namespace":"create","id":"5","particle":false,"visible":true,"mode":"bitmap","saved":true,"uuid":"5f28a2dc-5511-6bd0-cc23-537b005e1fff","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB7UlEQVQ4T61TvYvUUBD/veTtS97Fze6qHNeIuH7hx9oJdnaCjYLlgVis2Gh34OH/oZ121lcIItjaiCDIraco3oLYCCLmVpOXz30yL8maXfY6p5nMTOY3834zw+4/2NTdThd5UaDQFlS4B7JJcq3BGcPvPxMIIWHblvGnaY4V6SDYC8CGd4baeAEopSClrM05TbFamv+w9ZvrOgoV0iyDxR1kSYgWb0FrjShJ4HseVBzBslrIstQUUCqBdAX8Thvsvz5hWe+LrdfPrLXh4Hj/BCKVQAhuMIpiijRVaB/wZ0SSn0iTXgc2m4LbNt7vjEoSCeD11iOT7LnCTCTJiqVk1s4LV29jPP5cApw+O8Do2cNZgu+5SPMccZLPgbgOh+AckzDGmStD7I6/gG1sbuhDvcP4+PIJjqyV84/idC4xy6YG0JPC+H8GEQbX7uHd2zdlB91eF5Pt5yZIVanSYvUmIsWPXb5VckAdSLeNr6+e4uTRVQg+26t9OdjZ/WGeMEciPeFgx4FXbWJYbR7ZtFQkjDGjv30PsHrxOoJf1SrTFGoAM4kFkGYrFCMA4uDThxHMKvf7p7D94vG+LTst28RotPRN+tKNu+UUCOD8uYFZpFr8XnWN8b8DMtOp/qFLJJlxQEa9ss1LW3aBTR/l/QWX8QNstMA25AAAAABJRU5ErkJggg=="},{"path":"C:\\Users\\simon\\Desktop\\Modding\\Forgespace 1.16\\Create\\src\\main\\resources\\assets\\create\\textures\\block\\andesite_bricks.png","name":"andesite_bricks.png","folder":"block","namespace":"create","id":"particle","particle":true,"visible":true,"mode":"bitmap","saved":true,"uuid":"0a732870-6ee2-5b2b-13e2-0eadb56af61a","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACqElEQVQ4TzVTuUqzQRQ94xbjlsQkKCoqGg2E2AiBWEafwEKwsRA7KwvBwnewsRHEB5BUgiBYKYYohERcQIka4y7u+67zcw78Ax/zMXPvPeeee8Ykk0n79/eH5+dneDwebGxsoKGhAbe3t2hvb8fR0RG4Hh4eUFlZqd3n8+H9/R3MM/F43DLw4uIC1dXVeHp6QllZmZK4/v/z3Ov1Cuj+/h4vLy/Y29uDmZqasgwsKChQclFRkVBKSkp0ZozBz8+PEKuqqvD6+orCwkJ8fHzg8/MTpr+/39bX14tBaWmpaH19fen/+/tbyRUVFfj9/dXncDhUnCwYY6anp202m1XfbIGU6+rqRPH09FTB1CGXyyEWi+m+paUFmUxGAGZiYsLe3NyociQSEeXm5mbt19fXOD8/x8HBAfb399Hd3Q2Xy4W2tja1u76+DjM+Pm7Pzs7Q0dEh1ZlAVPZK+nd3dyp0cnKCsbEx5PN5gR0eHoql6evrs1SXwewxEAiALb29vcHtdksPakBGj4+Pos0C1KqpqQlmfn5eIq6srChhZ2dHegSDQfkilUphbW0Nvb29Up93iUQCTqdTOpjZ2Vnb2dkpmul0GsfHx4hGoxpnOBzWSCcnJ9HT0yMD1dbWCj2ZTEpYMzMzY0mJY6QwW1tbGB0d1SVRdnd3cXl5ieHhYSwvL4sldeIZPzM0NGRpCiJSOO6cL/Wg4ixCAAYXFxeDE2Nr1MxaCzM3NycGfr9f/XKtrq5KzMbGRnmCiSzOIoy9urrSm+FYzcLCgqVNW1tbVXFpaQmbm5vqv6amRv6nLxhD99EPZLG9vY2BgQGYxcVFS8cxmSgUk313dXUhFArJRGyFr5P3nD29wWIjIyMwg4ODlo+C4vCQo6LaFJRalJeXa2ci42g6sqM29MU/xiWmDH0vZeMAAAAASUVORK5CYII="}],"display":{"thirdperson_righthand":{"rotation":[0,90,0],"translation":[0,3.25,0]},"thirdperson_lefthand":{"translation":[0,3.75,0]},"firstperson_righthand":{"rotation":[-4.5,100.25,10],"translation":[1,4,1]},"firstperson_lefthand":{"rotation":[17.25,267,10],"translation":[1,4,1]},"ground":{"rotation":[-90,0,0],"translation":[0,-2.3,0],"scale":[0.76914,0.76914,0.76914]},"gui":{"rotation":[28,-163,43],"translation":[0.5,0,0],"scale":[1.09453,1.09453,1.09453]},"head":{"translation":[0,8,0],"scale":[1.4,1.4,1.4]},"fixed":{"rotation":[0,160.5,0],"translation":[0.5,0.5,0]}}} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/potato_cannon/cog.json b/src/main/resources/assets/create/models/item/potato_cannon/cog.json new file mode 100644 index 000000000..7a630b442 --- /dev/null +++ b/src/main/resources/assets/create/models/item/potato_cannon/cog.json @@ -0,0 +1,116 @@ +{ + "credit": "Made with Blockbench", + "parent": "create:item/potato_cannon/item", + "texture_size": [32, 32], + "textures": { + "1": "create:item/potato_cannon" + }, + "elements": [ + { + "name": "Cog", + "from": [5.5, 8, 6.5], + "to": [10.5, 9, 9.5], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8.5, 7.5]}, + "faces": { + "north": {"uv": [6.5, 9.75, 9, 10], "texture": "#1"}, + "east": {"uv": [8.75, 10, 9, 8.5], "rotation": 90, "texture": "#1"}, + "south": {"uv": [6.5, 8.5, 9, 8.75], "texture": "#1"}, + "west": {"uv": [8.75, 8.5, 9, 10], "rotation": 90, "texture": "#1"}, + "up": {"uv": [6.5, 8.5, 9, 10], "rotation": 180, "texture": "#1"}, + "down": {"uv": [6.5, 8.5, 9, 10], "texture": "#1"} + } + }, + { + "name": "Cog", + "from": [7.5, 6, 6.5], + "to": [8.5, 11, 9.5], + "rotation": {"angle": 0, "axis": "z", "origin": [8, 8.5, 7.5]}, + "faces": { + "north": {"uv": [6.5, 9.75, 9, 10], "rotation": 90, "texture": "#1"}, + "east": {"uv": [6.5, 8.5, 9, 10], "rotation": 270, "texture": "#1"}, + "south": {"uv": [6.5, 8.5, 9, 8.75], "rotation": 270, "texture": "#1"}, + "west": {"uv": [6.5, 8.5, 9, 10], "rotation": 90, "texture": "#1"}, + "up": {"uv": [8.75, 10, 9, 8.5], "texture": "#1"}, + "down": {"uv": [8.75, 8.5, 9, 10], "texture": "#1"} + } + }, + { + "name": "Cog", + "from": [7.5, 6, 6.5], + "to": [8.5, 11, 9.5], + "rotation": {"angle": 45, "axis": "z", "origin": [8, 8.5, 7.5]}, + "faces": { + "north": {"uv": [6.5, 9.75, 9, 10], "rotation": 90, "texture": "#1"}, + "east": {"uv": [6.5, 8.5, 9, 10], "rotation": 270, "texture": "#1"}, + "south": {"uv": [6.5, 8.5, 9, 8.75], "rotation": 270, "texture": "#1"}, + "west": {"uv": [6.5, 8.5, 9, 10], "rotation": 90, "texture": "#1"}, + "up": {"uv": [8.75, 10, 9, 8.5], "texture": "#1"}, + "down": {"uv": [8.75, 8.5, 9, 10], "texture": "#1"} + } + }, + { + "name": "Cog", + "from": [5.5, 8, 6.5], + "to": [10.5, 9, 9.5], + "rotation": {"angle": 45, "axis": "z", "origin": [8, 8.5, 7.5]}, + "faces": { + "north": {"uv": [6.5, 9.75, 9, 10], "texture": "#1"}, + "east": {"uv": [8.75, 10, 9, 8.5], "rotation": 90, "texture": "#1"}, + "south": {"uv": [6.5, 8.5, 9, 8.75], "texture": "#1"}, + "west": {"uv": [8.75, 8.5, 9, 10], "rotation": 90, "texture": "#1"}, + "up": {"uv": [6.5, 8.5, 9, 10], "rotation": 180, "texture": "#1"}, + "down": {"uv": [6.5, 8.5, 9, 10], "texture": "#1"} + } + } + ], + "display": { + "thirdperson_righthand": { + "translation": [0, 1.75, 0] + }, + "thirdperson_lefthand": { + "translation": [0, 1.75, 0] + }, + "firstperson_righthand": { + "rotation": [5, 4, 5], + "translation": [0.25, 4, 0.75] + }, + "firstperson_lefthand": { + "rotation": [5, 4, 5], + "translation": [0.25, 4, 0.75] + }, + "ground": { + "rotation": [0, 0, 90], + "translation": [0, -1.3, 0], + "scale": [0.76914, 0.76914, 0.76914] + }, + "gui": { + "rotation": [64, 47, -47], + "translation": [0.5, 0, 0], + "scale": [0.86, 0.86, 0.86] + }, + "head": { + "translation": [0, 8, 0], + "scale": [1.4, 1.4, 1.4] + }, + "fixed": { + "rotation": [0, 90, 0], + "translation": [0.5, 0.5, -1], + "scale": [0.72, 0.72, 0.72] + } + }, + "groups": [ + { + "name": "cog", + "origin": [8, 8, 8], + "color": 0, + "children": [ + { + "name": "accelerator", + "origin": [8, 8, 8], + "color": 0, + "children": [0, 1, 2, 3] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/potato_cannon/item.json b/src/main/resources/assets/create/models/item/potato_cannon/item.json new file mode 100644 index 000000000..ece021b34 --- /dev/null +++ b/src/main/resources/assets/create/models/item/potato_cannon/item.json @@ -0,0 +1,132 @@ +{ + "credit": "Made with Blockbench", + "texture_size": [32, 32], + "textures": { + "1": "create:item/potato_cannon", + "particle": "create:block/copper_casing" + }, + "elements": [ + { + "from": [6.5, 7, -1.5], + "to": [9.5, 10, 6.5], + "rotation": {"angle": 0, "axis": "y", "origin": [7, 7.6, 11]}, + "faces": { + "east": {"uv": [4, 2, 0, 3.5], "texture": "#1"}, + "south": {"uv": [10, 6, 11.5, 7.5], "texture": "#1"}, + "west": {"uv": [0, 2, 4, 3.5], "texture": "#1"}, + "up": {"uv": [0, 0, 4, 1.5], "rotation": 90, "texture": "#1"}, + "down": {"uv": [0, 4, 4, 5.5], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [6, 6.5, -2.5], + "to": [10, 10.5, -1.5], + "rotation": {"angle": 0, "axis": "y", "origin": [7, 7.6, 11]}, + "faces": { + "north": {"uv": [4, 0.5, 6, 2.5], "texture": "#1"}, + "east": {"uv": [6.25, 0.5, 5.75, 2.5], "texture": "#1"}, + "south": {"uv": [4, 3.5, 6, 5.5], "texture": "#1"}, + "west": {"uv": [5.75, 0.5, 6.25, 2.5], "texture": "#1"}, + "up": {"uv": [4, 0.75, 6, 0.25], "texture": "#1"}, + "down": {"uv": [4, 2.75, 6, 2.25], "texture": "#1"} + } + }, + { + "from": [6.5, 7, 9.5], + "to": [9.5, 10, 10.5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.6, 11]}, + "faces": { + "north": {"uv": [0, 6, 1.5, 7.5], "texture": "#1"}, + "east": {"uv": [4, 2, 3.5, 3.5], "texture": "#1"}, + "west": {"uv": [3.5, 2, 4, 3.5], "texture": "#1"}, + "up": {"uv": [3.5, 0, 4, 1.5], "rotation": 90, "texture": "#1"}, + "down": {"uv": [3.5, 4, 4, 5.5], "texture": "#1"} + } + }, + { + "from": [6, 7, 10.5], + "to": [10, 11, 15.5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 9.6, 11]}, + "faces": { + "north": {"uv": [10, 3.5, 12, 5.5], "texture": "#1"}, + "east": {"uv": [9.5, 1, 7, 3], "texture": "#1"}, + "south": {"uv": [10, 1, 12, 3], "texture": "#1"}, + "west": {"uv": [7, 1, 9.5, 3], "texture": "#1"}, + "up": {"uv": [7, 3.5, 9.5, 5.5], "rotation": 90, "texture": "#1"}, + "down": {"uv": [7, 6, 9.5, 8], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [7, 4, 14.5], + "to": [9, 6, 15.5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.6, 11]}, + "faces": { + "east": {"uv": [0.5, 10, 1, 11], "texture": "#1"}, + "west": {"uv": [0.5, 10, 1, 11], "texture": "#1"}, + "up": {"uv": [0.5, 10, 1, 10.25], "rotation": 90, "texture": "#1"}, + "down": {"uv": [1.5, 10.75, 2.5, 11], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [6.5, 3.5, 8.5], + "to": [9.5, 6.5, 14.5], + "rotation": {"angle": -45, "axis": "z", "origin": [8, 5, 11.5]}, + "faces": { + "north": {"uv": [3, 6, 4.5, 7.5], "rotation": 90, "texture": "#1"}, + "east": {"uv": [6, 9.25, 3, 10.75], "texture": "#1"}, + "south": {"uv": [5, 6, 6.5, 7.5], "texture": "#1"}, + "west": {"uv": [3, 8, 6, 9.5], "texture": "#1"}, + "up": {"uv": [3, 9.5, 6, 8], "rotation": 90, "texture": "#1"}, + "down": {"uv": [6, 10.75, 3, 9.25], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [7, 4, 15.5], + "to": [9, 10, 17.5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.6, 11]}, + "faces": { + "north": {"uv": [1.25, 8, 0.25, 11], "texture": "#1"}, + "east": {"uv": [2, 8, 1, 11], "texture": "#1"}, + "south": {"uv": [3, 8, 2, 11], "texture": "#1"}, + "west": {"uv": [1, 8, 2, 11], "texture": "#1"}, + "up": {"uv": [2, 7, 3, 8], "texture": "#1"}, + "down": {"uv": [1.5, 10.75, 2.5, 11], "rotation": 90, "texture": "#1"} + } + } + ], + "display": { + "thirdperson_righthand": { + "translation": [0, 1.75, 0] + }, + "thirdperson_lefthand": { + "translation": [0, 1.75, 0] + }, + "firstperson_righthand": { + "rotation": [5, 4, 5], + "translation": [0.25, 4, 0.75] + }, + "firstperson_lefthand": { + "rotation": [5, 4, 5], + "translation": [0.25, 4, 0.75] + }, + "ground": { + "rotation": [0, 0, 90], + "translation": [0, -1.3, 0], + "scale": [0.76914, 0.76914, 0.76914] + }, + "gui": { + "rotation": [64, 47, -47], + "translation": [0.5, 0, 0], + "scale": [0.86, 0.86, 0.86] + }, + "head": { + "translation": [0, 8, 0], + "scale": [1.4, 1.4, 1.4] + }, + "fixed": { + "rotation": [0, 90, 0], + "translation": [0.5, 0.5, -1], + "scale": [0.72, 0.72, 0.72] + } + } +} \ 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/particles/soul.json b/src/main/resources/assets/create/particles/soul.json new file mode 100644 index 000000000..6c9f647f4 --- /dev/null +++ b/src/main/resources/assets/create/particles/soul.json @@ -0,0 +1,59 @@ +{ + "textures": [ + "create:soul_sprite_start_1", + "create:soul_sprite_start_2", + "create:soul_sprite_start_3", + "create:soul_sprite_start_4", + "create:soul_sprite_start_5", + "create:soul_sprite_start_6", + "create:soul_sprite_start_7", + "create:soul_sprite_start_8", + "create:soul_sprite_start_9", + "create:soul_sprite_start_10", + "create:soul_sprite_start_11", + "create:soul_sprite_start_12", + "create:soul_sprite_start_13", + "create:soul_sprite_start_14", + "create:soul_sprite_start_15", + "create:soul_sprite_start_16", + "create:soul_sprite_start_17", + + "create:soul_sprite_anim_1", + "create:soul_sprite_anim_2", + "create:soul_sprite_anim_3", + "create:soul_sprite_anim_4", + "create:soul_sprite_anim_5", + "create:soul_sprite_anim_6", + "create:soul_sprite_anim_7", + "create:soul_sprite_anim_8", + "create:soul_sprite_anim_9", + "create:soul_sprite_anim_10", + "create:soul_sprite_anim_11", + "create:soul_sprite_anim_12", + "create:soul_sprite_anim_13", + "create:soul_sprite_anim_14", + "create:soul_sprite_anim_15", + "create:soul_sprite_anim_16", + + "create:soul_sprite_end_1", + "create:soul_sprite_end_2", + "create:soul_sprite_end_3", + "create:soul_sprite_end_4", + "create:soul_sprite_end_5", + "create:soul_sprite_end_6", + "create:soul_sprite_end_7", + "create:soul_sprite_end_8", + "create:soul_sprite_end_9", + "create:soul_sprite_end_10", + "create:soul_sprite_end_11", + "create:soul_sprite_end_12", + "create:soul_sprite_end_13", + "create:soul_sprite_end_14", + "create:soul_sprite_end_15", + "create:soul_sprite_end_16", + "create:soul_sprite_end_17", + "create:soul_sprite_end_18", + "create:soul_sprite_end_19", + "create:soul_sprite_end_20" + ] +} diff --git a/src/main/resources/assets/create/particles/soul_base.json b/src/main/resources/assets/create/particles/soul_base.json new file mode 100644 index 000000000..92b9f65be --- /dev/null +++ b/src/main/resources/assets/create/particles/soul_base.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "create:soul_base_0", + "create:soul_base_1", + "create:soul_base_2", + "create:soul_base_3", + "create:soul_base_4", + "create:soul_base_5", + "create:soul_base_6", + "create:soul_base_7" + ] +} diff --git a/src/main/resources/assets/create/particles/soul_expanding_perimeter.json b/src/main/resources/assets/create/particles/soul_expanding_perimeter.json new file mode 100644 index 000000000..3274e5921 --- /dev/null +++ b/src/main/resources/assets/create/particles/soul_expanding_perimeter.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "create:soul_base_0", + "create:soul_base_1", + "create:soul_base_2", + "create:soul_base_3", + "create:soul_base_2", + "create:soul_base_1", + "create:soul_base_0", + "create:soul_base_0" + ] +} diff --git a/src/main/resources/assets/create/particles/soul_perimeter.json b/src/main/resources/assets/create/particles/soul_perimeter.json new file mode 100644 index 000000000..92b9f65be --- /dev/null +++ b/src/main/resources/assets/create/particles/soul_perimeter.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "create:soul_base_0", + "create:soul_base_1", + "create:soul_base_2", + "create:soul_base_3", + "create:soul_base_4", + "create:soul_base_5", + "create:soul_base_6", + "create:soul_base_7" + ] +} diff --git a/src/main/resources/ponder/adjustable_pulse_repeater.nbt b/src/main/resources/assets/create/ponder/adjustable_pulse_repeater.nbt similarity index 100% rename from src/main/resources/ponder/adjustable_pulse_repeater.nbt rename to src/main/resources/assets/create/ponder/adjustable_pulse_repeater.nbt diff --git a/src/main/resources/ponder/adjustable_repeater.nbt b/src/main/resources/assets/create/ponder/adjustable_repeater.nbt similarity index 100% rename from src/main/resources/ponder/adjustable_repeater.nbt rename to src/main/resources/assets/create/ponder/adjustable_repeater.nbt diff --git a/src/main/resources/ponder/analog_lever.nbt b/src/main/resources/assets/create/ponder/analog_lever.nbt similarity index 100% rename from src/main/resources/ponder/analog_lever.nbt rename to src/main/resources/assets/create/ponder/analog_lever.nbt diff --git a/src/main/resources/ponder/basin.nbt b/src/main/resources/assets/create/ponder/basin.nbt similarity index 100% rename from src/main/resources/ponder/basin.nbt rename to src/main/resources/assets/create/ponder/basin.nbt diff --git a/src/main/resources/ponder/belt/connect.nbt b/src/main/resources/assets/create/ponder/belt/connect.nbt similarity index 100% rename from src/main/resources/ponder/belt/connect.nbt rename to src/main/resources/assets/create/ponder/belt/connect.nbt diff --git a/src/main/resources/ponder/belt/directions.nbt b/src/main/resources/assets/create/ponder/belt/directions.nbt similarity index 100% rename from src/main/resources/ponder/belt/directions.nbt rename to src/main/resources/assets/create/ponder/belt/directions.nbt diff --git a/src/main/resources/ponder/belt/encasing.nbt b/src/main/resources/assets/create/ponder/belt/encasing.nbt similarity index 100% rename from src/main/resources/ponder/belt/encasing.nbt rename to src/main/resources/assets/create/ponder/belt/encasing.nbt diff --git a/src/main/resources/ponder/belt/transport.nbt b/src/main/resources/assets/create/ponder/belt/transport.nbt similarity index 100% rename from src/main/resources/ponder/belt/transport.nbt rename to src/main/resources/assets/create/ponder/belt/transport.nbt diff --git a/src/main/resources/ponder/blaze_burner.nbt b/src/main/resources/assets/create/ponder/blaze_burner.nbt similarity index 100% rename from src/main/resources/ponder/blaze_burner.nbt rename to src/main/resources/assets/create/ponder/blaze_burner.nbt diff --git a/src/main/resources/ponder/cart_assembler/anchor.nbt b/src/main/resources/assets/create/ponder/cart_assembler/anchor.nbt similarity index 100% rename from src/main/resources/ponder/cart_assembler/anchor.nbt rename to src/main/resources/assets/create/ponder/cart_assembler/anchor.nbt diff --git a/src/main/resources/ponder/cart_assembler/dual.nbt b/src/main/resources/assets/create/ponder/cart_assembler/dual.nbt similarity index 100% rename from src/main/resources/ponder/cart_assembler/dual.nbt rename to src/main/resources/assets/create/ponder/cart_assembler/dual.nbt diff --git a/src/main/resources/ponder/cart_assembler/modes.nbt b/src/main/resources/assets/create/ponder/cart_assembler/modes.nbt similarity index 100% rename from src/main/resources/ponder/cart_assembler/modes.nbt rename to src/main/resources/assets/create/ponder/cart_assembler/modes.nbt diff --git a/src/main/resources/ponder/cart_assembler/rails.nbt b/src/main/resources/assets/create/ponder/cart_assembler/rails.nbt similarity index 100% rename from src/main/resources/ponder/cart_assembler/rails.nbt rename to src/main/resources/assets/create/ponder/cart_assembler/rails.nbt diff --git a/src/main/resources/ponder/chain_drive/gearshift.nbt b/src/main/resources/assets/create/ponder/chain_drive/gearshift.nbt similarity index 100% rename from src/main/resources/ponder/chain_drive/gearshift.nbt rename to src/main/resources/assets/create/ponder/chain_drive/gearshift.nbt diff --git a/src/main/resources/ponder/chain_drive/relay.nbt b/src/main/resources/assets/create/ponder/chain_drive/relay.nbt similarity index 100% rename from src/main/resources/ponder/chain_drive/relay.nbt rename to src/main/resources/assets/create/ponder/chain_drive/relay.nbt diff --git a/src/main/resources/ponder/chassis/linear_attachment.nbt b/src/main/resources/assets/create/ponder/chassis/linear_attachment.nbt similarity index 100% rename from src/main/resources/ponder/chassis/linear_attachment.nbt rename to src/main/resources/assets/create/ponder/chassis/linear_attachment.nbt diff --git a/src/main/resources/ponder/chassis/linear_group.nbt b/src/main/resources/assets/create/ponder/chassis/linear_group.nbt similarity index 100% rename from src/main/resources/ponder/chassis/linear_group.nbt rename to src/main/resources/assets/create/ponder/chassis/linear_group.nbt diff --git a/src/main/resources/ponder/chassis/radial.nbt b/src/main/resources/assets/create/ponder/chassis/radial.nbt similarity index 100% rename from src/main/resources/ponder/chassis/radial.nbt rename to src/main/resources/assets/create/ponder/chassis/radial.nbt diff --git a/src/main/resources/ponder/chute/downward.nbt b/src/main/resources/assets/create/ponder/chute/downward.nbt similarity index 100% rename from src/main/resources/ponder/chute/downward.nbt rename to src/main/resources/assets/create/ponder/chute/downward.nbt diff --git a/src/main/resources/ponder/chute/smart.nbt b/src/main/resources/assets/create/ponder/chute/smart.nbt similarity index 100% rename from src/main/resources/ponder/chute/smart.nbt rename to src/main/resources/assets/create/ponder/chute/smart.nbt diff --git a/src/main/resources/ponder/chute/upward.nbt b/src/main/resources/assets/create/ponder/chute/upward.nbt similarity index 100% rename from src/main/resources/ponder/chute/upward.nbt rename to src/main/resources/assets/create/ponder/chute/upward.nbt diff --git a/src/main/resources/ponder/clockwork_bearing.nbt b/src/main/resources/assets/create/ponder/clockwork_bearing.nbt similarity index 100% rename from src/main/resources/ponder/clockwork_bearing.nbt rename to src/main/resources/assets/create/ponder/clockwork_bearing.nbt diff --git a/src/main/resources/ponder/clutch.nbt b/src/main/resources/assets/create/ponder/clutch.nbt similarity index 100% rename from src/main/resources/ponder/clutch.nbt rename to src/main/resources/assets/create/ponder/clutch.nbt diff --git a/src/main/resources/ponder/cog/large.nbt b/src/main/resources/assets/create/ponder/cog/large.nbt similarity index 100% rename from src/main/resources/ponder/cog/large.nbt rename to src/main/resources/assets/create/ponder/cog/large.nbt diff --git a/src/main/resources/ponder/cog/small.nbt b/src/main/resources/assets/create/ponder/cog/small.nbt similarity index 100% rename from src/main/resources/ponder/cog/small.nbt rename to src/main/resources/assets/create/ponder/cog/small.nbt diff --git a/src/main/resources/ponder/cog/speedup.nbt b/src/main/resources/assets/create/ponder/cog/speedup.nbt similarity index 100% rename from src/main/resources/ponder/cog/speedup.nbt rename to src/main/resources/assets/create/ponder/cog/speedup.nbt diff --git a/src/main/resources/ponder/creative_motor.nbt b/src/main/resources/assets/create/ponder/creative_motor.nbt similarity index 100% rename from src/main/resources/ponder/creative_motor.nbt rename to src/main/resources/assets/create/ponder/creative_motor.nbt diff --git a/src/main/resources/ponder/crushing_wheel.nbt b/src/main/resources/assets/create/ponder/crushing_wheel.nbt similarity index 100% rename from src/main/resources/ponder/crushing_wheel.nbt rename to src/main/resources/assets/create/ponder/crushing_wheel.nbt diff --git a/src/main/resources/ponder/debug/scene_1.nbt b/src/main/resources/assets/create/ponder/debug/scene_1.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_1.nbt rename to src/main/resources/assets/create/ponder/debug/scene_1.nbt diff --git a/src/main/resources/assets/create/ponder/debug/scene_10.nbt b/src/main/resources/assets/create/ponder/debug/scene_10.nbt new file mode 100644 index 000000000..41e45e42d Binary files /dev/null and b/src/main/resources/assets/create/ponder/debug/scene_10.nbt differ diff --git a/src/main/resources/ponder/debug/scene_2.nbt b/src/main/resources/assets/create/ponder/debug/scene_2.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_2.nbt rename to src/main/resources/assets/create/ponder/debug/scene_2.nbt diff --git a/src/main/resources/ponder/debug/scene_3.nbt b/src/main/resources/assets/create/ponder/debug/scene_3.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_3.nbt rename to src/main/resources/assets/create/ponder/debug/scene_3.nbt diff --git a/src/main/resources/ponder/debug/scene_4.nbt b/src/main/resources/assets/create/ponder/debug/scene_4.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_4.nbt rename to src/main/resources/assets/create/ponder/debug/scene_4.nbt diff --git a/src/main/resources/ponder/debug/scene_5.nbt b/src/main/resources/assets/create/ponder/debug/scene_5.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_5.nbt rename to src/main/resources/assets/create/ponder/debug/scene_5.nbt diff --git a/src/main/resources/ponder/debug/scene_6.nbt b/src/main/resources/assets/create/ponder/debug/scene_6.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_6.nbt rename to src/main/resources/assets/create/ponder/debug/scene_6.nbt diff --git a/src/main/resources/ponder/debug/scene_7.nbt b/src/main/resources/assets/create/ponder/debug/scene_7.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_7.nbt rename to src/main/resources/assets/create/ponder/debug/scene_7.nbt diff --git a/src/main/resources/ponder/debug/scene_8.nbt b/src/main/resources/assets/create/ponder/debug/scene_8.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_8.nbt rename to src/main/resources/assets/create/ponder/debug/scene_8.nbt diff --git a/src/main/resources/ponder/debug/scene_9.nbt b/src/main/resources/assets/create/ponder/debug/scene_9.nbt similarity index 100% rename from src/main/resources/ponder/debug/scene_9.nbt rename to src/main/resources/assets/create/ponder/debug/scene_9.nbt diff --git a/src/main/resources/ponder/deployer/contraption.nbt b/src/main/resources/assets/create/ponder/deployer/contraption.nbt similarity index 100% rename from src/main/resources/ponder/deployer/contraption.nbt rename to src/main/resources/assets/create/ponder/deployer/contraption.nbt diff --git a/src/main/resources/ponder/deployer/filter.nbt b/src/main/resources/assets/create/ponder/deployer/filter.nbt similarity index 100% rename from src/main/resources/ponder/deployer/filter.nbt rename to src/main/resources/assets/create/ponder/deployer/filter.nbt diff --git a/src/main/resources/ponder/deployer/modes.nbt b/src/main/resources/assets/create/ponder/deployer/modes.nbt similarity index 100% rename from src/main/resources/ponder/deployer/modes.nbt rename to src/main/resources/assets/create/ponder/deployer/modes.nbt diff --git a/src/main/resources/assets/create/ponder/deployer/processing.nbt b/src/main/resources/assets/create/ponder/deployer/processing.nbt new file mode 100644 index 000000000..daa9f2845 Binary files /dev/null and b/src/main/resources/assets/create/ponder/deployer/processing.nbt differ diff --git a/src/main/resources/ponder/deployer/redstone.nbt b/src/main/resources/assets/create/ponder/deployer/redstone.nbt similarity index 100% rename from src/main/resources/ponder/deployer/redstone.nbt rename to src/main/resources/assets/create/ponder/deployer/redstone.nbt diff --git a/src/main/resources/ponder/depot.nbt b/src/main/resources/assets/create/ponder/depot.nbt similarity index 100% rename from src/main/resources/ponder/depot.nbt rename to src/main/resources/assets/create/ponder/depot.nbt diff --git a/src/main/resources/ponder/empty_blaze_burner.nbt b/src/main/resources/assets/create/ponder/empty_blaze_burner.nbt similarity index 100% rename from src/main/resources/ponder/empty_blaze_burner.nbt rename to src/main/resources/assets/create/ponder/empty_blaze_burner.nbt diff --git a/src/main/resources/ponder/fan/direction.nbt b/src/main/resources/assets/create/ponder/fan/direction.nbt similarity index 100% rename from src/main/resources/ponder/fan/direction.nbt rename to src/main/resources/assets/create/ponder/fan/direction.nbt diff --git a/src/main/resources/ponder/fan/processing.nbt b/src/main/resources/assets/create/ponder/fan/processing.nbt similarity index 100% rename from src/main/resources/ponder/fan/processing.nbt rename to src/main/resources/assets/create/ponder/fan/processing.nbt diff --git a/src/main/resources/ponder/fan/source.nbt b/src/main/resources/assets/create/ponder/fan/source.nbt similarity index 100% rename from src/main/resources/ponder/fan/source.nbt rename to src/main/resources/assets/create/ponder/fan/source.nbt diff --git a/src/main/resources/assets/create/ponder/fluid_pipe/encasing.nbt b/src/main/resources/assets/create/ponder/fluid_pipe/encasing.nbt new file mode 100644 index 000000000..c6e1d76e6 Binary files /dev/null and b/src/main/resources/assets/create/ponder/fluid_pipe/encasing.nbt differ diff --git a/src/main/resources/assets/create/ponder/fluid_pipe/flow.nbt b/src/main/resources/assets/create/ponder/fluid_pipe/flow.nbt new file mode 100644 index 000000000..f3dd374bc Binary files /dev/null and b/src/main/resources/assets/create/ponder/fluid_pipe/flow.nbt differ diff --git a/src/main/resources/assets/create/ponder/fluid_pipe/interaction.nbt b/src/main/resources/assets/create/ponder/fluid_pipe/interaction.nbt new file mode 100644 index 000000000..1779c5bf8 Binary files /dev/null and b/src/main/resources/assets/create/ponder/fluid_pipe/interaction.nbt differ diff --git a/src/main/resources/assets/create/ponder/fluid_tank/sizes.nbt b/src/main/resources/assets/create/ponder/fluid_tank/sizes.nbt new file mode 100644 index 000000000..03d1a80d2 Binary files /dev/null and b/src/main/resources/assets/create/ponder/fluid_tank/sizes.nbt differ diff --git a/src/main/resources/assets/create/ponder/fluid_tank/sizes_creative.nbt b/src/main/resources/assets/create/ponder/fluid_tank/sizes_creative.nbt new file mode 100644 index 000000000..0c739ab96 Binary files /dev/null and b/src/main/resources/assets/create/ponder/fluid_tank/sizes_creative.nbt differ diff --git a/src/main/resources/assets/create/ponder/fluid_tank/storage.nbt b/src/main/resources/assets/create/ponder/fluid_tank/storage.nbt new file mode 100644 index 000000000..9192a5bea Binary files /dev/null and b/src/main/resources/assets/create/ponder/fluid_tank/storage.nbt differ diff --git a/src/main/resources/assets/create/ponder/fluid_tank/storage_creative.nbt b/src/main/resources/assets/create/ponder/fluid_tank/storage_creative.nbt new file mode 100644 index 000000000..5fc77449b Binary files /dev/null and b/src/main/resources/assets/create/ponder/fluid_tank/storage_creative.nbt differ diff --git a/src/main/resources/assets/create/ponder/fluid_valve.nbt b/src/main/resources/assets/create/ponder/fluid_valve.nbt new file mode 100644 index 000000000..5b36f7c05 Binary files /dev/null and b/src/main/resources/assets/create/ponder/fluid_valve.nbt differ diff --git a/src/main/resources/ponder/funnels/brass.nbt b/src/main/resources/assets/create/ponder/funnels/brass.nbt similarity index 100% rename from src/main/resources/ponder/funnels/brass.nbt rename to src/main/resources/assets/create/ponder/funnels/brass.nbt diff --git a/src/main/resources/ponder/funnels/compat.nbt b/src/main/resources/assets/create/ponder/funnels/compat.nbt similarity index 100% rename from src/main/resources/ponder/funnels/compat.nbt rename to src/main/resources/assets/create/ponder/funnels/compat.nbt diff --git a/src/main/resources/ponder/funnels/direction.nbt b/src/main/resources/assets/create/ponder/funnels/direction.nbt similarity index 100% rename from src/main/resources/ponder/funnels/direction.nbt rename to src/main/resources/assets/create/ponder/funnels/direction.nbt diff --git a/src/main/resources/ponder/funnels/intro.nbt b/src/main/resources/assets/create/ponder/funnels/intro.nbt similarity index 100% rename from src/main/resources/ponder/funnels/intro.nbt rename to src/main/resources/assets/create/ponder/funnels/intro.nbt diff --git a/src/main/resources/ponder/funnels/redstone.nbt b/src/main/resources/assets/create/ponder/funnels/redstone.nbt similarity index 100% rename from src/main/resources/ponder/funnels/redstone.nbt rename to src/main/resources/assets/create/ponder/funnels/redstone.nbt diff --git a/src/main/resources/ponder/funnels/transposer.nbt b/src/main/resources/assets/create/ponder/funnels/transposer.nbt similarity index 100% rename from src/main/resources/ponder/funnels/transposer.nbt rename to src/main/resources/assets/create/ponder/funnels/transposer.nbt diff --git a/src/main/resources/ponder/furnace_engine.nbt b/src/main/resources/assets/create/ponder/furnace_engine.nbt similarity index 100% rename from src/main/resources/ponder/furnace_engine.nbt rename to src/main/resources/assets/create/ponder/furnace_engine.nbt diff --git a/src/main/resources/ponder/gantry/direction.nbt b/src/main/resources/assets/create/ponder/gantry/direction.nbt similarity index 100% rename from src/main/resources/ponder/gantry/direction.nbt rename to src/main/resources/assets/create/ponder/gantry/direction.nbt diff --git a/src/main/resources/ponder/gantry/intro.nbt b/src/main/resources/assets/create/ponder/gantry/intro.nbt similarity index 100% rename from src/main/resources/ponder/gantry/intro.nbt rename to src/main/resources/assets/create/ponder/gantry/intro.nbt diff --git a/src/main/resources/ponder/gantry/redstone.nbt b/src/main/resources/assets/create/ponder/gantry/redstone.nbt similarity index 100% rename from src/main/resources/ponder/gantry/redstone.nbt rename to src/main/resources/assets/create/ponder/gantry/redstone.nbt diff --git a/src/main/resources/ponder/gantry/subgantry.nbt b/src/main/resources/assets/create/ponder/gantry/subgantry.nbt similarity index 100% rename from src/main/resources/ponder/gantry/subgantry.nbt rename to src/main/resources/assets/create/ponder/gantry/subgantry.nbt diff --git a/src/main/resources/ponder/gauges.nbt b/src/main/resources/assets/create/ponder/gauges.nbt similarity index 100% rename from src/main/resources/ponder/gauges.nbt rename to src/main/resources/assets/create/ponder/gauges.nbt diff --git a/src/main/resources/ponder/gearbox.nbt b/src/main/resources/assets/create/ponder/gearbox.nbt similarity index 100% rename from src/main/resources/ponder/gearbox.nbt rename to src/main/resources/assets/create/ponder/gearbox.nbt diff --git a/src/main/resources/ponder/gearshift.nbt b/src/main/resources/assets/create/ponder/gearshift.nbt similarity index 100% rename from src/main/resources/ponder/gearshift.nbt rename to src/main/resources/assets/create/ponder/gearshift.nbt diff --git a/src/main/resources/ponder/hand_crank.nbt b/src/main/resources/assets/create/ponder/hand_crank.nbt similarity index 100% rename from src/main/resources/ponder/hand_crank.nbt rename to src/main/resources/assets/create/ponder/hand_crank.nbt diff --git a/src/main/resources/ponder/harvester.nbt b/src/main/resources/assets/create/ponder/harvester.nbt similarity index 100% rename from src/main/resources/ponder/harvester.nbt rename to src/main/resources/assets/create/ponder/harvester.nbt diff --git a/src/main/resources/assets/create/ponder/hose_pulley/infinite.nbt b/src/main/resources/assets/create/ponder/hose_pulley/infinite.nbt new file mode 100644 index 000000000..614e4c007 Binary files /dev/null and b/src/main/resources/assets/create/ponder/hose_pulley/infinite.nbt differ diff --git a/src/main/resources/assets/create/ponder/hose_pulley/intro.nbt b/src/main/resources/assets/create/ponder/hose_pulley/intro.nbt new file mode 100644 index 000000000..3ebb4e6e0 Binary files /dev/null and b/src/main/resources/assets/create/ponder/hose_pulley/intro.nbt differ diff --git a/src/main/resources/assets/create/ponder/hose_pulley/level.nbt b/src/main/resources/assets/create/ponder/hose_pulley/level.nbt new file mode 100644 index 000000000..6c115dab4 Binary files /dev/null and b/src/main/resources/assets/create/ponder/hose_pulley/level.nbt differ diff --git a/src/main/resources/assets/create/ponder/item_drain.nbt b/src/main/resources/assets/create/ponder/item_drain.nbt new file mode 100644 index 000000000..c62eeff0a Binary files /dev/null and b/src/main/resources/assets/create/ponder/item_drain.nbt differ diff --git a/src/main/resources/ponder/mechanical_arm/filter.nbt b/src/main/resources/assets/create/ponder/mechanical_arm/filter.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_arm/filter.nbt rename to src/main/resources/assets/create/ponder/mechanical_arm/filter.nbt diff --git a/src/main/resources/ponder/mechanical_arm/modes.nbt b/src/main/resources/assets/create/ponder/mechanical_arm/modes.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_arm/modes.nbt rename to src/main/resources/assets/create/ponder/mechanical_arm/modes.nbt diff --git a/src/main/resources/ponder/mechanical_arm/redstone.nbt b/src/main/resources/assets/create/ponder/mechanical_arm/redstone.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_arm/redstone.nbt rename to src/main/resources/assets/create/ponder/mechanical_arm/redstone.nbt diff --git a/src/main/resources/ponder/mechanical_arm/setup.nbt b/src/main/resources/assets/create/ponder/mechanical_arm/setup.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_arm/setup.nbt rename to src/main/resources/assets/create/ponder/mechanical_arm/setup.nbt diff --git a/src/main/resources/ponder/mechanical_bearing/anchor.nbt b/src/main/resources/assets/create/ponder/mechanical_bearing/anchor.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_bearing/anchor.nbt rename to src/main/resources/assets/create/ponder/mechanical_bearing/anchor.nbt diff --git a/src/main/resources/ponder/mechanical_bearing/modes.nbt b/src/main/resources/assets/create/ponder/mechanical_bearing/modes.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_bearing/modes.nbt rename to src/main/resources/assets/create/ponder/mechanical_bearing/modes.nbt diff --git a/src/main/resources/ponder/mechanical_bearing/stabilized.nbt b/src/main/resources/assets/create/ponder/mechanical_bearing/stabilized.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_bearing/stabilized.nbt rename to src/main/resources/assets/create/ponder/mechanical_bearing/stabilized.nbt diff --git a/src/main/resources/ponder/mechanical_crafter/connect.nbt b/src/main/resources/assets/create/ponder/mechanical_crafter/connect.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_crafter/connect.nbt rename to src/main/resources/assets/create/ponder/mechanical_crafter/connect.nbt diff --git a/src/main/resources/ponder/mechanical_crafter/covers.nbt b/src/main/resources/assets/create/ponder/mechanical_crafter/covers.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_crafter/covers.nbt rename to src/main/resources/assets/create/ponder/mechanical_crafter/covers.nbt diff --git a/src/main/resources/ponder/mechanical_crafter/setup.nbt b/src/main/resources/assets/create/ponder/mechanical_crafter/setup.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_crafter/setup.nbt rename to src/main/resources/assets/create/ponder/mechanical_crafter/setup.nbt diff --git a/src/main/resources/ponder/mechanical_drill/breaker.nbt b/src/main/resources/assets/create/ponder/mechanical_drill/breaker.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_drill/breaker.nbt rename to src/main/resources/assets/create/ponder/mechanical_drill/breaker.nbt diff --git a/src/main/resources/ponder/mechanical_drill/contraption.nbt b/src/main/resources/assets/create/ponder/mechanical_drill/contraption.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_drill/contraption.nbt rename to src/main/resources/assets/create/ponder/mechanical_drill/contraption.nbt diff --git a/src/main/resources/ponder/mechanical_mixer/mixing.nbt b/src/main/resources/assets/create/ponder/mechanical_mixer/mixing.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_mixer/mixing.nbt rename to src/main/resources/assets/create/ponder/mechanical_mixer/mixing.nbt diff --git a/src/main/resources/ponder/mechanical_piston/anchor.nbt b/src/main/resources/assets/create/ponder/mechanical_piston/anchor.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_piston/anchor.nbt rename to src/main/resources/assets/create/ponder/mechanical_piston/anchor.nbt diff --git a/src/main/resources/ponder/mechanical_piston/modes.nbt b/src/main/resources/assets/create/ponder/mechanical_piston/modes.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_piston/modes.nbt rename to src/main/resources/assets/create/ponder/mechanical_piston/modes.nbt diff --git a/src/main/resources/ponder/mechanical_piston/piston_pole.nbt b/src/main/resources/assets/create/ponder/mechanical_piston/piston_pole.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_piston/piston_pole.nbt rename to src/main/resources/assets/create/ponder/mechanical_piston/piston_pole.nbt diff --git a/src/main/resources/ponder/mechanical_press/compacting.nbt b/src/main/resources/assets/create/ponder/mechanical_press/compacting.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_press/compacting.nbt rename to src/main/resources/assets/create/ponder/mechanical_press/compacting.nbt diff --git a/src/main/resources/ponder/mechanical_press/pressing.nbt b/src/main/resources/assets/create/ponder/mechanical_press/pressing.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_press/pressing.nbt rename to src/main/resources/assets/create/ponder/mechanical_press/pressing.nbt diff --git a/src/main/resources/assets/create/ponder/mechanical_pump/flow.nbt b/src/main/resources/assets/create/ponder/mechanical_pump/flow.nbt new file mode 100644 index 000000000..2ecaed7a4 Binary files /dev/null and b/src/main/resources/assets/create/ponder/mechanical_pump/flow.nbt differ diff --git a/src/main/resources/assets/create/ponder/mechanical_pump/speed.nbt b/src/main/resources/assets/create/ponder/mechanical_pump/speed.nbt new file mode 100644 index 000000000..4f2c3da3b Binary files /dev/null and b/src/main/resources/assets/create/ponder/mechanical_pump/speed.nbt differ diff --git a/src/main/resources/ponder/mechanical_saw/breaker.nbt b/src/main/resources/assets/create/ponder/mechanical_saw/breaker.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_saw/breaker.nbt rename to src/main/resources/assets/create/ponder/mechanical_saw/breaker.nbt diff --git a/src/main/resources/ponder/mechanical_saw/contraption.nbt b/src/main/resources/assets/create/ponder/mechanical_saw/contraption.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_saw/contraption.nbt rename to src/main/resources/assets/create/ponder/mechanical_saw/contraption.nbt diff --git a/src/main/resources/ponder/mechanical_saw/processing.nbt b/src/main/resources/assets/create/ponder/mechanical_saw/processing.nbt similarity index 100% rename from src/main/resources/ponder/mechanical_saw/processing.nbt rename to src/main/resources/assets/create/ponder/mechanical_saw/processing.nbt diff --git a/src/main/resources/ponder/millstone.nbt b/src/main/resources/assets/create/ponder/millstone.nbt similarity index 100% rename from src/main/resources/ponder/millstone.nbt rename to src/main/resources/assets/create/ponder/millstone.nbt diff --git a/src/main/resources/ponder/nixie_tube.nbt b/src/main/resources/assets/create/ponder/nixie_tube.nbt similarity index 100% rename from src/main/resources/ponder/nixie_tube.nbt rename to src/main/resources/assets/create/ponder/nixie_tube.nbt diff --git a/src/main/resources/ponder/plough.nbt b/src/main/resources/assets/create/ponder/plough.nbt similarity index 100% rename from src/main/resources/ponder/plough.nbt rename to src/main/resources/assets/create/ponder/plough.nbt diff --git a/src/main/resources/ponder/portable_interface/redstone.nbt b/src/main/resources/assets/create/ponder/portable_interface/redstone.nbt similarity index 100% rename from src/main/resources/ponder/portable_interface/redstone.nbt rename to src/main/resources/assets/create/ponder/portable_interface/redstone.nbt diff --git a/src/main/resources/assets/create/ponder/portable_interface/redstone_fluid.nbt b/src/main/resources/assets/create/ponder/portable_interface/redstone_fluid.nbt new file mode 100644 index 000000000..9b2e12b72 Binary files /dev/null and b/src/main/resources/assets/create/ponder/portable_interface/redstone_fluid.nbt differ diff --git a/src/main/resources/ponder/portable_interface/transfer.nbt b/src/main/resources/assets/create/ponder/portable_interface/transfer.nbt similarity index 100% rename from src/main/resources/ponder/portable_interface/transfer.nbt rename to src/main/resources/assets/create/ponder/portable_interface/transfer.nbt diff --git a/src/main/resources/assets/create/ponder/portable_interface/transfer_fluid.nbt b/src/main/resources/assets/create/ponder/portable_interface/transfer_fluid.nbt new file mode 100644 index 000000000..93fa112e0 Binary files /dev/null and b/src/main/resources/assets/create/ponder/portable_interface/transfer_fluid.nbt differ diff --git a/src/main/resources/ponder/powered_latch.nbt b/src/main/resources/assets/create/ponder/powered_latch.nbt similarity index 100% rename from src/main/resources/ponder/powered_latch.nbt rename to src/main/resources/assets/create/ponder/powered_latch.nbt diff --git a/src/main/resources/ponder/powered_toggle_latch.nbt b/src/main/resources/assets/create/ponder/powered_toggle_latch.nbt similarity index 100% rename from src/main/resources/ponder/powered_toggle_latch.nbt rename to src/main/resources/assets/create/ponder/powered_toggle_latch.nbt diff --git a/src/main/resources/ponder/pulse_repeater.nbt b/src/main/resources/assets/create/ponder/pulse_repeater.nbt similarity index 100% rename from src/main/resources/ponder/pulse_repeater.nbt rename to src/main/resources/assets/create/ponder/pulse_repeater.nbt diff --git a/src/main/resources/ponder/redstone_contact.nbt b/src/main/resources/assets/create/ponder/redstone_contact.nbt similarity index 100% rename from src/main/resources/ponder/redstone_contact.nbt rename to src/main/resources/assets/create/ponder/redstone_contact.nbt diff --git a/src/main/resources/ponder/redstone_link.nbt b/src/main/resources/assets/create/ponder/redstone_link.nbt similarity index 100% rename from src/main/resources/ponder/redstone_link.nbt rename to src/main/resources/assets/create/ponder/redstone_link.nbt diff --git a/src/main/resources/ponder/rope_pulley/anchor.nbt b/src/main/resources/assets/create/ponder/rope_pulley/anchor.nbt similarity index 100% rename from src/main/resources/ponder/rope_pulley/anchor.nbt rename to src/main/resources/assets/create/ponder/rope_pulley/anchor.nbt diff --git a/src/main/resources/ponder/rope_pulley/attachment.nbt b/src/main/resources/assets/create/ponder/rope_pulley/attachment.nbt similarity index 100% rename from src/main/resources/ponder/rope_pulley/attachment.nbt rename to src/main/resources/assets/create/ponder/rope_pulley/attachment.nbt diff --git a/src/main/resources/ponder/rope_pulley/modes.nbt b/src/main/resources/assets/create/ponder/rope_pulley/modes.nbt similarity index 100% rename from src/main/resources/ponder/rope_pulley/modes.nbt rename to src/main/resources/assets/create/ponder/rope_pulley/modes.nbt diff --git a/src/main/resources/ponder/sail.nbt b/src/main/resources/assets/create/ponder/sail.nbt similarity index 100% rename from src/main/resources/ponder/sail.nbt rename to src/main/resources/assets/create/ponder/sail.nbt diff --git a/src/main/resources/ponder/sequenced_gearshift.nbt b/src/main/resources/assets/create/ponder/sequenced_gearshift.nbt similarity index 100% rename from src/main/resources/ponder/sequenced_gearshift.nbt rename to src/main/resources/assets/create/ponder/sequenced_gearshift.nbt diff --git a/src/main/resources/ponder/shaft/encasing.nbt b/src/main/resources/assets/create/ponder/shaft/encasing.nbt similarity index 100% rename from src/main/resources/ponder/shaft/encasing.nbt rename to src/main/resources/assets/create/ponder/shaft/encasing.nbt diff --git a/src/main/resources/ponder/shaft/relay.nbt b/src/main/resources/assets/create/ponder/shaft/relay.nbt similarity index 100% rename from src/main/resources/ponder/shaft/relay.nbt rename to src/main/resources/assets/create/ponder/shaft/relay.nbt diff --git a/src/main/resources/assets/create/ponder/smart_pipe.nbt b/src/main/resources/assets/create/ponder/smart_pipe.nbt new file mode 100644 index 000000000..155e1aa56 Binary files /dev/null and b/src/main/resources/assets/create/ponder/smart_pipe.nbt differ diff --git a/src/main/resources/ponder/speed_controller.nbt b/src/main/resources/assets/create/ponder/speed_controller.nbt similarity index 100% rename from src/main/resources/ponder/speed_controller.nbt rename to src/main/resources/assets/create/ponder/speed_controller.nbt diff --git a/src/main/resources/assets/create/ponder/spout.nbt b/src/main/resources/assets/create/ponder/spout.nbt new file mode 100644 index 000000000..90421509a Binary files /dev/null and b/src/main/resources/assets/create/ponder/spout.nbt differ diff --git a/src/main/resources/ponder/sticker.nbt b/src/main/resources/assets/create/ponder/sticker.nbt similarity index 100% rename from src/main/resources/ponder/sticker.nbt rename to src/main/resources/assets/create/ponder/sticker.nbt diff --git a/src/main/resources/ponder/super_glue.nbt b/src/main/resources/assets/create/ponder/super_glue.nbt similarity index 100% rename from src/main/resources/ponder/super_glue.nbt rename to src/main/resources/assets/create/ponder/super_glue.nbt diff --git a/src/main/resources/ponder/tunnels/andesite.nbt b/src/main/resources/assets/create/ponder/tunnels/andesite.nbt similarity index 100% rename from src/main/resources/ponder/tunnels/andesite.nbt rename to src/main/resources/assets/create/ponder/tunnels/andesite.nbt diff --git a/src/main/resources/ponder/tunnels/brass.nbt b/src/main/resources/assets/create/ponder/tunnels/brass.nbt similarity index 100% rename from src/main/resources/ponder/tunnels/brass.nbt rename to src/main/resources/assets/create/ponder/tunnels/brass.nbt diff --git a/src/main/resources/ponder/tunnels/brass_modes.nbt b/src/main/resources/assets/create/ponder/tunnels/brass_modes.nbt similarity index 100% rename from src/main/resources/ponder/tunnels/brass_modes.nbt rename to src/main/resources/assets/create/ponder/tunnels/brass_modes.nbt diff --git a/src/main/resources/ponder/valve_handle.nbt b/src/main/resources/assets/create/ponder/valve_handle.nbt similarity index 100% rename from src/main/resources/ponder/valve_handle.nbt rename to src/main/resources/assets/create/ponder/valve_handle.nbt diff --git a/src/main/resources/ponder/water_wheel.nbt b/src/main/resources/assets/create/ponder/water_wheel.nbt similarity index 100% rename from src/main/resources/ponder/water_wheel.nbt rename to src/main/resources/assets/create/ponder/water_wheel.nbt diff --git a/src/main/resources/ponder/weighted_ejector/eject.nbt b/src/main/resources/assets/create/ponder/weighted_ejector/eject.nbt similarity index 100% rename from src/main/resources/ponder/weighted_ejector/eject.nbt rename to src/main/resources/assets/create/ponder/weighted_ejector/eject.nbt diff --git a/src/main/resources/ponder/weighted_ejector/redstone.nbt b/src/main/resources/assets/create/ponder/weighted_ejector/redstone.nbt similarity index 100% rename from src/main/resources/ponder/weighted_ejector/redstone.nbt rename to src/main/resources/assets/create/ponder/weighted_ejector/redstone.nbt diff --git a/src/main/resources/ponder/weighted_ejector/split.nbt b/src/main/resources/assets/create/ponder/weighted_ejector/split.nbt similarity index 100% rename from src/main/resources/ponder/weighted_ejector/split.nbt rename to src/main/resources/assets/create/ponder/weighted_ejector/split.nbt diff --git a/src/main/resources/ponder/windmill_bearing/source.nbt b/src/main/resources/assets/create/ponder/windmill_bearing/source.nbt similarity index 100% rename from src/main/resources/ponder/windmill_bearing/source.nbt rename to src/main/resources/assets/create/ponder/windmill_bearing/source.nbt diff --git a/src/main/resources/ponder/windmill_bearing/structure.nbt b/src/main/resources/assets/create/ponder/windmill_bearing/structure.nbt similarity index 100% rename from src/main/resources/ponder/windmill_bearing/structure.nbt rename to src/main/resources/assets/create/ponder/windmill_bearing/structure.nbt diff --git a/src/main/resources/assets/create/sounds/fwoomp.ogg b/src/main/resources/assets/create/sounds/fwoomp.ogg new file mode 100644 index 000000000..546953741 Binary files /dev/null and b/src/main/resources/assets/create/sounds/fwoomp.ogg differ diff --git a/src/main/resources/assets/create/sounds/haunted_bell_convert.ogg b/src/main/resources/assets/create/sounds/haunted_bell_convert.ogg new file mode 100644 index 000000000..171df3dc9 Binary files /dev/null and b/src/main/resources/assets/create/sounds/haunted_bell_convert.ogg differ diff --git a/src/main/resources/assets/create/sounds/haunted_bell_use.ogg b/src/main/resources/assets/create/sounds/haunted_bell_use.ogg new file mode 100644 index 000000000..a82907e9c Binary files /dev/null and b/src/main/resources/assets/create/sounds/haunted_bell_use.ogg differ diff --git a/src/main/resources/assets/create/textures/block/bell.png b/src/main/resources/assets/create/textures/block/bell.png new file mode 100644 index 000000000..fedafba91 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/bell.png differ diff --git a/src/main/resources/assets/create/textures/block/bell_anim.png b/src/main/resources/assets/create/textures/block/bell_anim.png new file mode 100644 index 000000000..8feae441b Binary files /dev/null and b/src/main/resources/assets/create/textures/block/bell_anim.png differ diff --git a/src/main/resources/assets/create/textures/block/bell_anim.png.mcmeta b/src/main/resources/assets/create/textures/block/bell_anim.png.mcmeta new file mode 100644 index 000000000..c6f8b9bd5 --- /dev/null +++ b/src/main/resources/assets/create/textures/block/bell_anim.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": true, + "frametime": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/block/bell_frame.png b/src/main/resources/assets/create/textures/block/bell_frame.png new file mode 100644 index 000000000..c624f8e08 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/bell_frame.png differ diff --git a/src/main/resources/assets/create/textures/block/bell_frame_side.png b/src/main/resources/assets/create/textures/block/bell_frame_side.png new file mode 100644 index 000000000..5dd3a79b4 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/bell_frame_side.png differ diff --git a/src/main/resources/assets/create/textures/block/cart_assembler_side_off.png b/src/main/resources/assets/create/textures/block/cart_assembler_side_off.png new file mode 100644 index 000000000..9c1916225 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/cart_assembler_side_off.png differ diff --git a/src/main/resources/assets/create/textures/block/cart_assembler_side_on.png b/src/main/resources/assets/create/textures/block/cart_assembler_side_on.png new file mode 100644 index 000000000..a47932c63 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/cart_assembler_side_on.png differ diff --git a/src/main/resources/assets/create/textures/block/cart_assembler_top.png b/src/main/resources/assets/create/textures/block/cart_assembler_top.png new file mode 100644 index 000000000..aa7d9238e Binary files /dev/null and b/src/main/resources/assets/create/textures/block/cart_assembler_top.png differ diff --git a/src/main/resources/assets/create/textures/block/fluid_tank_connected.png b/src/main/resources/assets/create/textures/block/fluid_tank_connected.png index f2b205b60..ef34d1e99 100644 Binary files a/src/main/resources/assets/create/textures/block/fluid_tank_connected.png and b/src/main/resources/assets/create/textures/block/fluid_tank_connected.png differ diff --git a/src/main/resources/assets/create/textures/block/hose_pulley_magnet.png b/src/main/resources/assets/create/textures/block/hose_pulley_magnet.png index 357678581..807b9df75 100644 Binary files a/src/main/resources/assets/create/textures/block/hose_pulley_magnet.png and b/src/main/resources/assets/create/textures/block/hose_pulley_magnet.png differ diff --git a/src/main/resources/assets/create/textures/block/sail/canvas_yellow.png b/src/main/resources/assets/create/textures/block/sail/canvas_yellow.png index aac06569f..c5a9690b0 100644 Binary files a/src/main/resources/assets/create/textures/block/sail/canvas_yellow.png and b/src/main/resources/assets/create/textures/block/sail/canvas_yellow.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/black.png b/src/main/resources/assets/create/textures/block/toolbox/black.png new file mode 100644 index 000000000..ec7b672b7 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/black.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/blue.png b/src/main/resources/assets/create/textures/block/toolbox/blue.png new file mode 100644 index 000000000..6200e6cdf Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/blue.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/brown.png b/src/main/resources/assets/create/textures/block/toolbox/brown.png new file mode 100644 index 000000000..629932887 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/brown.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/cyan.png b/src/main/resources/assets/create/textures/block/toolbox/cyan.png new file mode 100644 index 000000000..d62c31e8d Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/cyan.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/gray.png b/src/main/resources/assets/create/textures/block/toolbox/gray.png new file mode 100644 index 000000000..59b7dc071 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/gray.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/green.png b/src/main/resources/assets/create/textures/block/toolbox/green.png new file mode 100644 index 000000000..42ec577a0 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/green.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/light_blue.png b/src/main/resources/assets/create/textures/block/toolbox/light_blue.png new file mode 100644 index 000000000..2fc08d37d Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/light_blue.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/light_gray.png b/src/main/resources/assets/create/textures/block/toolbox/light_gray.png new file mode 100644 index 000000000..8b3f2973d Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/light_gray.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/lime.png b/src/main/resources/assets/create/textures/block/toolbox/lime.png new file mode 100644 index 000000000..7c4427d07 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/lime.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/magenta.png b/src/main/resources/assets/create/textures/block/toolbox/magenta.png new file mode 100644 index 000000000..14ad51fd6 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/magenta.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/orange.png b/src/main/resources/assets/create/textures/block/toolbox/orange.png new file mode 100644 index 000000000..446e437b4 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/orange.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/pink.png b/src/main/resources/assets/create/textures/block/toolbox/pink.png new file mode 100644 index 000000000..679517a76 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/pink.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/purple.png b/src/main/resources/assets/create/textures/block/toolbox/purple.png new file mode 100644 index 000000000..c523b2e96 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/purple.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/red.png b/src/main/resources/assets/create/textures/block/toolbox/red.png new file mode 100644 index 000000000..0a2472917 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/red.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/white.png b/src/main/resources/assets/create/textures/block/toolbox/white.png new file mode 100644 index 000000000..699b4090b Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/white.png differ diff --git a/src/main/resources/assets/create/textures/block/toolbox/yellow.png b/src/main/resources/assets/create/textures/block/toolbox/yellow.png new file mode 100644 index 000000000..f51f47776 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/toolbox/yellow.png differ diff --git a/src/main/resources/assets/create/textures/block/valve_handle/valve_handle_yellow.png b/src/main/resources/assets/create/textures/block/valve_handle/valve_handle_yellow.png index 92e38ccb6..bf8466e66 100644 Binary files a/src/main/resources/assets/create/textures/block/valve_handle/valve_handle_yellow.png and b/src/main/resources/assets/create/textures/block/valve_handle/valve_handle_yellow.png differ 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/curiosities_2.png b/src/main/resources/assets/create/textures/gui/curiosities_2.png new file mode 100644 index 000000000..10b4a353c Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/curiosities_2.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..503558349 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..4fd7a2316 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..4ebeb81fe 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..8a2b80290 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..1efdd5c7e 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..6fdd8f281 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..608c0f8e8 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/toolbox.png b/src/main/resources/assets/create/textures/gui/toolbox.png new file mode 100644 index 000000000..167920df5 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/toolbox.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..ac4b8fdb9 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/creative_blaze_cake.png b/src/main/resources/assets/create/textures/item/creative_blaze_cake.png new file mode 100644 index 000000000..900ef50db Binary files /dev/null and b/src/main/resources/assets/create/textures/item/creative_blaze_cake.png differ diff --git a/src/main/resources/assets/create/textures/item/incomplete_precision_mechanism.png b/src/main/resources/assets/create/textures/item/incomplete_precision_mechanism.png new file mode 100644 index 000000000..96db614cb Binary files /dev/null and b/src/main/resources/assets/create/textures/item/incomplete_precision_mechanism.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/potato_cannon.png b/src/main/resources/assets/create/textures/item/potato_cannon.png new file mode 100644 index 000000000..ad75120cd Binary files /dev/null and b/src/main/resources/assets/create/textures/item/potato_cannon.png differ diff --git a/src/main/resources/assets/create/textures/item/precision_mechanism.png b/src/main/resources/assets/create/textures/item/precision_mechanism.png new file mode 100644 index 000000000..a4023a69f Binary files /dev/null and b/src/main/resources/assets/create/textures/item/precision_mechanism.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/assets/create/textures/particle/soul_base_0.png b/src/main/resources/assets/create/textures/particle/soul_base_0.png new file mode 100644 index 000000000..9f5053af5 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_base_0.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_base_1.png b/src/main/resources/assets/create/textures/particle/soul_base_1.png new file mode 100644 index 000000000..5e00fff62 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_base_1.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_base_2.png b/src/main/resources/assets/create/textures/particle/soul_base_2.png new file mode 100644 index 000000000..1b5c6a7ec Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_base_2.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_base_3.png b/src/main/resources/assets/create/textures/particle/soul_base_3.png new file mode 100644 index 000000000..8f36415b3 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_base_3.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_base_4.png b/src/main/resources/assets/create/textures/particle/soul_base_4.png new file mode 100644 index 000000000..dcf7bef26 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_base_4.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_base_5.png b/src/main/resources/assets/create/textures/particle/soul_base_5.png new file mode 100644 index 000000000..2e1cb95f6 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_base_5.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_base_6.png b/src/main/resources/assets/create/textures/particle/soul_base_6.png new file mode 100644 index 000000000..04e3e0b74 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_base_6.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_base_7.png b/src/main/resources/assets/create/textures/particle/soul_base_7.png new file mode 100644 index 000000000..5e4988e6b Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_base_7.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_1.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_1.png new file mode 100644 index 000000000..b2fa5c916 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_1.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_10.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_10.png new file mode 100644 index 000000000..8283eba63 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_10.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_11.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_11.png new file mode 100644 index 000000000..ff9aca275 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_11.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_12.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_12.png new file mode 100644 index 000000000..60d14009f Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_12.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_13.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_13.png new file mode 100644 index 000000000..eee68ca21 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_13.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_14.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_14.png new file mode 100644 index 000000000..6f636f32f Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_14.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_15.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_15.png new file mode 100644 index 000000000..c385dcb7a Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_15.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_16.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_16.png new file mode 100644 index 000000000..8901df045 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_16.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_2.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_2.png new file mode 100644 index 000000000..35108a724 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_2.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_3.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_3.png new file mode 100644 index 000000000..6ce9222a4 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_3.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_4.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_4.png new file mode 100644 index 000000000..e622a65a4 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_4.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_5.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_5.png new file mode 100644 index 000000000..22d79d61a Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_5.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_6.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_6.png new file mode 100644 index 000000000..90f7df871 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_6.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_7.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_7.png new file mode 100644 index 000000000..a98feffec Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_7.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_8.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_8.png new file mode 100644 index 000000000..78e791f3d Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_8.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_anim_9.png b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_9.png new file mode 100644 index 000000000..ffc3a4c9c Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_anim_9.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_1.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_1.png new file mode 100644 index 000000000..1fd2d0ffc Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_1.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_10.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_10.png new file mode 100644 index 000000000..6d8d8271c Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_10.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_11.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_11.png new file mode 100644 index 000000000..cec57364c Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_11.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_12.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_12.png new file mode 100644 index 000000000..f803afad4 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_12.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_13.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_13.png new file mode 100644 index 000000000..ee98d0369 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_13.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_14.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_14.png new file mode 100644 index 000000000..0ef97152f Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_14.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_15.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_15.png new file mode 100644 index 000000000..6c793aedf Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_15.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_16.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_16.png new file mode 100644 index 000000000..6c7ee5e2a Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_16.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_17.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_17.png new file mode 100644 index 000000000..ff276dee1 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_17.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_18.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_18.png new file mode 100644 index 000000000..09694512a Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_18.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_19.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_19.png new file mode 100644 index 000000000..5b0cc36b6 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_19.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_2.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_2.png new file mode 100644 index 000000000..35108a724 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_2.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_20.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_20.png new file mode 100644 index 000000000..ae900c3b4 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_20.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_3.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_3.png new file mode 100644 index 000000000..6ce9222a4 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_3.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_4.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_4.png new file mode 100644 index 000000000..e622a65a4 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_4.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_5.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_5.png new file mode 100644 index 000000000..082819541 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_5.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_6.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_6.png new file mode 100644 index 000000000..4559083f4 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_6.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_7.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_7.png new file mode 100644 index 000000000..f31245f3f Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_7.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_8.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_8.png new file mode 100644 index 000000000..42e8f61d8 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_8.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_end_9.png b/src/main/resources/assets/create/textures/particle/soul_sprite_end_9.png new file mode 100644 index 000000000..03335242f Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_end_9.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_1.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_1.png new file mode 100644 index 000000000..b75006f49 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_1.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_10.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_10.png new file mode 100644 index 000000000..ffc3a4c9c Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_10.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_11.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_11.png new file mode 100644 index 000000000..8283eba63 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_11.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_12.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_12.png new file mode 100644 index 000000000..ff9aca275 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_12.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_13.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_13.png new file mode 100644 index 000000000..60d14009f Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_13.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_14.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_14.png new file mode 100644 index 000000000..eee68ca21 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_14.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_15.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_15.png new file mode 100644 index 000000000..6f636f32f Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_15.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_16.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_16.png new file mode 100644 index 000000000..c385dcb7a Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_16.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_17.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_17.png new file mode 100644 index 000000000..8901df045 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_17.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_2.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_2.png new file mode 100644 index 000000000..3b1033453 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_2.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_3.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_3.png new file mode 100644 index 000000000..531b0c2bb Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_3.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_4.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_4.png new file mode 100644 index 000000000..a03737c71 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_4.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_5.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_5.png new file mode 100644 index 000000000..a4b46efc6 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_5.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_6.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_6.png new file mode 100644 index 000000000..2653b522c Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_6.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_7.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_7.png new file mode 100644 index 000000000..f309ed505 Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_7.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_8.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_8.png new file mode 100644 index 000000000..d295cb67a Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_8.png differ diff --git a/src/main/resources/assets/create/textures/particle/soul_sprite_start_9.png b/src/main/resources/assets/create/textures/particle/soul_sprite_start_9.png new file mode 100644 index 000000000..1d1216aab Binary files /dev/null and b/src/main/resources/assets/create/textures/particle/soul_sprite_start_9.png differ diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 0938f8534..19029a55a 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -5,19 +5,14 @@ "compatibilityLevel": "JAVA_8", "refmap": "create.refmap.json", "mixins": [ + "PlayerListMixin" ], "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/cutting/stripped_aspen_log.json b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_aspen_log.json index 5f72d093b..9d2a5bfe6 100644 --- a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_aspen_log.json +++ b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_aspen_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "atmospheric:aspen_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_grimwood_log.json b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_grimwood_log.json index 861940bad..74840a8f1 100644 --- a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_grimwood_log.json +++ b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_grimwood_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "atmospheric:grimwood_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_kousa_log.json b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_kousa_log.json index c6cf8fae3..3451f9019 100644 --- a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_kousa_log.json +++ b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_kousa_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "atmospheric:kousa_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_rosewood_log.json b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_rosewood_log.json index e8e3b4902..019a88bac 100644 --- a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_rosewood_log.json +++ b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_rosewood_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "atmospheric:rosewood_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_yucca_log.json b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_yucca_log.json index 2a0c23af8..8f1105198 100644 --- a/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_yucca_log.json +++ b/src/main/resources/data/create/recipes/compat/atmospheric/cutting/stripped_yucca_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "atmospheric:yucca_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ 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/autumnity/cutting/stripped_maple_log.json b/src/main/resources/data/create/recipes/compat/autumnity/cutting/stripped_maple_log.json index 18a07715c..74cfa54af 100644 --- a/src/main/resources/data/create/recipes/compat/autumnity/cutting/stripped_maple_log.json +++ b/src/main/resources/data/create/recipes/compat/autumnity/cutting/stripped_maple_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "autumnity:maple_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ 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/bloomful/cutting/stripped_wisteria_log.json b/src/main/resources/data/create/recipes/compat/bloomful/cutting/stripped_wisteria_log.json index f939c1e5b..7d71013cd 100644 --- a/src/main/resources/data/create/recipes/compat/bloomful/cutting/stripped_wisteria_log.json +++ b/src/main/resources/data/create/recipes/compat/bloomful/cutting/stripped_wisteria_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "bloomful:wisteria_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_cherry_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_cherry_log.json index 8061be745..a138be111 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_cherry_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_cherry_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:cherry_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_dead_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_dead_log.json index ffd900338..aabb0b0fb 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_dead_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_dead_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:dead_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_fir_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_fir_log.json index 149eb504a..b1387f163 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_fir_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_fir_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:fir_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_hellbark_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_hellbark_log.json index bbac5da4e..d1533fbf1 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_hellbark_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_hellbark_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:hellbark_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_jacaranda_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_jacaranda_log.json index 4032c3779..a46d1db69 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_jacaranda_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_jacaranda_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:jacaranda_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_magic_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_magic_log.json index fe1b2fcd8..4a48c17a7 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_magic_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_magic_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:magic_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_mahogany_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_mahogany_log.json index 4e4d2f531..48d13fff8 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_mahogany_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_mahogany_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:mahogany_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_palm_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_palm_log.json index bbc5da5fa..e06bd1c2f 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_palm_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_palm_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:palm_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_redwood_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_redwood_log.json index a235bdf37..304dbecf1 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_redwood_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_redwood_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:redwood_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_umbran_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_umbran_log.json index 718cf57ea..69c3d4b2a 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_umbran_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_umbran_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:umbran_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_willow_log.json b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_willow_log.json index 431885d1e..3ffbdf854 100644 --- a/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_willow_log.json +++ b/src/main/resources/data/create/recipes/compat/bop/cutting/stripped_willow_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "biomesoplenty:willow_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ 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/druidcraft/cutting/stripped_darkwood_log.json b/src/main/resources/data/create/recipes/compat/druidcraft/cutting/stripped_darkwood_log.json index 6d3244f85..19a15e8fd 100644 --- a/src/main/resources/data/create/recipes/compat/druidcraft/cutting/stripped_darkwood_log.json +++ b/src/main/resources/data/create/recipes/compat/druidcraft/cutting/stripped_darkwood_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "druidcraft:darkwood_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/druidcraft/cutting/stripped_elder_log.json b/src/main/resources/data/create/recipes/compat/druidcraft/cutting/stripped_elder_log.json index e5a2c5084..fd3bbf015 100644 --- a/src/main/resources/data/create/recipes/compat/druidcraft/cutting/stripped_elder_log.json +++ b/src/main/resources/data/create/recipes/compat/druidcraft/cutting/stripped_elder_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "druidcraft:elder_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/cutting/stripped_poise_stem.json b/src/main/resources/data/create/recipes/compat/endergetic/cutting/stripped_poise_stem.json index 0599cce9d..3fa18d40e 100644 --- a/src/main/resources/data/create/recipes/compat/endergetic/cutting/stripped_poise_stem.json +++ b/src/main/resources/data/create/recipes/compat/endergetic/cutting/stripped_poise_stem.json @@ -14,8 +14,8 @@ "results": [ { "item": "endergetic:poise_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file 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..6248dee4b --- /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": "minecraft:milk", + "amount": 250 + } + ] +} 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/projectvibrantjourneys/cutting/stripped_aspen_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_aspen_log.json index 2679b5538..de7ab1983 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_aspen_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_aspen_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:aspen_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_baobab_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_baobab_log.json index 1f5799d13..99b154419 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_baobab_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_baobab_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:baobab_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_cottonwood_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_cottonwood_log.json index 8dd22e6bb..fab0bc42a 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_cottonwood_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_cottonwood_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:cottonwood_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_fir_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_fir_log.json index f84e6acc1..8bb909152 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_fir_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_fir_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:fir_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_juniper_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_juniper_log.json index 24b6e1d3a..1bf3205e8 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_juniper_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_juniper_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:juniper_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_mangrove_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_mangrove_log.json index a7e11054b..386805201 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_mangrove_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_mangrove_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:mangrove_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_maple_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_maple_log.json index c82ebf136..d1d630b6a 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_maple_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_maple_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:maple_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_palm_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_palm_log.json index a6299ce69..87ec633da 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_palm_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_palm_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:palm_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_pine_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_pine_log.json index 2ca583202..0a168c62d 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_pine_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_pine_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:pine_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_redwood_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_redwood_log.json index b37f06e20..b9ab0965f 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_redwood_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_redwood_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:redwood_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_willow_log.json b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_willow_log.json index 66b6aa646..f70c5f243 100644 --- a/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_willow_log.json +++ b/src/main/resources/data/create/recipes/compat/projectvibrantjourneys/cutting/stripped_willow_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "projectvibrantjourneys:willow_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ 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/swampexpansion/cutting/stripped_willow_log.json b/src/main/resources/data/create/recipes/compat/swampexpansion/cutting/stripped_willow_log.json index 943443551..1d9c996ef 100644 --- a/src/main/resources/data/create/recipes/compat/swampexpansion/cutting/stripped_willow_log.json +++ b/src/main/resources/data/create/recipes/compat/swampexpansion/cutting/stripped_willow_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "swampexpansion:willow_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ 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/data/create/recipes/compat/traverse/cutting/fir_log.json b/src/main/resources/data/create/recipes/compat/traverse/cutting/fir_log.json new file mode 100644 index 000000000..a8bce8050 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/traverse/cutting/fir_log.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "traverse" + } + ], + "type": "create:cutting", + "ingredients": [ + { + "item": "traverse:fir_log" + } + ], + "results": [ + { + "item": "traverse:stripped_fir_log", + "count": 1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/traverse/cutting/fir_wood.json b/src/main/resources/data/create/recipes/compat/traverse/cutting/fir_wood.json new file mode 100644 index 000000000..9e7060b9d --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/traverse/cutting/fir_wood.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "traverse" + } + ], + "type": "create:cutting", + "ingredients": [ + { + "item": "traverse:fir_wood" + } + ], + "results": [ + { + "item": "traverse:stripped_fir_wood", + "count": 1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/traverse/cutting/stripped_fir_log.json b/src/main/resources/data/create/recipes/compat/traverse/cutting/stripped_fir_log.json new file mode 100644 index 000000000..6b13ccb1d --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/traverse/cutting/stripped_fir_log.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "traverse" + } + ], + "type": "create:cutting", + "ingredients": [ + { + "item": "traverse:stripped_fir_log" + } + ], + "results": [ + { + "item": "traverse:fir_planks", + "count": 6 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/traverse/cutting/stripped_fir_wood.json b/src/main/resources/data/create/recipes/compat/traverse/cutting/stripped_fir_wood.json new file mode 100644 index 000000000..71046bb70 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/traverse/cutting/stripped_fir_wood.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "traverse" + } + ], + "type": "create:cutting", + "ingredients": [ + { + "item": "traverse:stripped_fir_wood" + } + ], + "results": [ + { + "item": "traverse:fir_planks", + "count": 6 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/upgrade_aquatic/cutting/stripped_driftwood_log.json b/src/main/resources/data/create/recipes/compat/upgrade_aquatic/cutting/stripped_driftwood_log.json index 648d7c3ff..02ec056eb 100644 --- a/src/main/resources/data/create/recipes/compat/upgrade_aquatic/cutting/stripped_driftwood_log.json +++ b/src/main/resources/data/create/recipes/compat/upgrade_aquatic/cutting/stripped_driftwood_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "upgrade_aquatic:driftwood_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/upgrade_aquatic/cutting/stripped_river_log.json b/src/main/resources/data/create/recipes/compat/upgrade_aquatic/cutting/stripped_river_log.json index faae38dff..61433a68c 100644 --- a/src/main/resources/data/create/recipes/compat/upgrade_aquatic/cutting/stripped_river_log.json +++ b/src/main/resources/data/create/recipes/compat/upgrade_aquatic/cutting/stripped_river_log.json @@ -14,8 +14,8 @@ "results": [ { "item": "upgrade_aquatic:river_planks", - "count": 5 + "count": 6 } ], - "processingTime": 100 + "processingTime": 50 } \ No newline at end of file diff --git a/src/main/resources/data/create/tags/blocks/non_movable.json b/src/main/resources/data/create/tags/blocks/non_movable.json index 974dda4c5..1ded5b887 100644 --- a/src/main/resources/data/create/tags/blocks/non_movable.json +++ b/src/main/resources/data/create/tags/blocks/non_movable.json @@ -1,7 +1,6 @@ { "replace": false, "values": [ - "minecraft:obsidian" ], "optional": [ "immersiveengineering:connector_lv", 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 } }