Compare commits

..

28 Commits

Author SHA1 Message Date
octarine-noise
78c7b53595 bump version to 2.6.5 2021-06-02 16:41:26 +02:00
octarine-noise
3a04099fc2 fix chinese lang file 2021-05-29 23:47:13 +02:00
octarine-noise
d6038dd072 add PackNameDecorator to avoid NPE
Forge allows pack hiding, but just in case
2021-05-29 23:43:14 +02:00
octarine-noise
4ebb7f2d35 fix blocks with flat lighting 2021-05-29 23:27:20 +02:00
octarine-noise
14a8600552 fix rising soul particle texture 2021-05-29 16:24:05 +02:00
octarine-noise
b3ffb7e4d6 Merge remote-tracking branch 'local/forge-1.15' into forge-1.16
# Conflicts:
#	src/main/kotlin/mods/betterfoliage/BetterFoliageMod.kt
2021-05-22 19:22:10 +02:00
octarine-noise
fc7f2be15c language key fixes 2021-05-22 19:20:34 +02:00
octarine-noise
b7bdd438e4 upgrade to Cloth Config v4 2021-05-22 19:00:54 +02:00
octarine-noise
65c9596a14 Merge remote-tracking branch 'local/forge-1.15' into forge-1.16
# Conflicts:
#	build.gradle.kts
#	src/main/kotlin/mods/betterfoliage/BetterFoliageMod.kt
#	src/main/kotlin/mods/betterfoliage/config/Config.kt
#	src/main/resources/assets/betterfoliage/lang/en_us.lang
2021-05-22 18:38:10 +02:00
octarine-noise
25b8896a25 log config GUI registration 2021-05-22 18:34:18 +02:00
octarine-noise
f1f811219e Merge remote-tracking branch 'local/forge-1.14' into forge-1.15
# Conflicts:
#	build.gradle.kts
#	gradle.properties
#	src/main/kotlin/mods/betterfoliage/BetterFoliageMod.kt
#	src/main/kotlin/mods/betterfoliage/client/Client.kt
#	src/main/kotlin/mods/betterfoliage/client/integration/ForestryIntegration.kt
#	src/main/kotlin/mods/betterfoliage/client/integration/RubberIntegration.kt
#	src/main/kotlin/mods/betterfoliage/client/render/EntityRisingSoulFX.kt
#	src/main/kotlin/mods/betterfoliage/client/render/RenderCactus.kt
#	src/main/kotlin/mods/betterfoliage/client/render/RenderGrass.kt
#	src/main/kotlin/mods/betterfoliage/client/render/RenderLeaves.kt
#	src/main/kotlin/mods/betterfoliage/client/render/RenderLilypad.kt
#	src/main/kotlin/mods/betterfoliage/client/render/RenderLog.kt
#	src/main/kotlin/mods/betterfoliage/client/render/RenderMycelium.kt
#	src/main/kotlin/mods/betterfoliage/client/render/RenderNetherrack.kt
#	src/main/kotlin/mods/betterfoliage/client/render/RenderReeds.kt
#	src/main/kotlin/mods/betterfoliage/client/texture/GrassRegistry.kt
#	src/main/kotlin/mods/betterfoliage/client/texture/LeafParticleRegistry.kt
#	src/main/kotlin/mods/betterfoliage/client/texture/LeafRegistry.kt
#	src/main/kotlin/mods/betterfoliage/client/texture/Utils.kt
#	src/main/kotlin/mods/betterfoliage/config/Config.kt
#	src/main/kotlin/mods/betterfoliage/config/DelegatingConfig.kt
#	src/main/kotlin/mods/betterfoliage/config/MainConfig.kt
#	src/main/kotlin/mods/betterfoliage/resource/discovery/Delegate.kt
#	src/main/kotlin/mods/betterfoliage/resource/generated/CenteringTextureGenerator.kt
#	src/main/kotlin/mods/betterfoliage/resource/generated/GeneratedGrass.kt
#	src/main/kotlin/mods/octarinecore/client/resource/AsyncSpriteProviderManager.kt
#	src/main/kotlin/mods/octarinecore/client/resource/ModelDiscovery.kt
#	src/main/kotlin/mods/octarinecore/client/resource/ResourceGeneration.kt
#	src/main/kotlin/mods/octarinecore/client/resource/ResourceHandler.kt
2021-05-22 18:07:32 +02:00
octarine-noise
57dc83f1af config GUI misc fixes 2021-05-22 17:49:57 +02:00
octarine-noise
180c2bf230 bump version to 2.5.2 2021-05-22 17:29:13 +02:00
octarine-noise
ff89aa7a13 add client-only version tester 2021-05-22 17:27:51 +02:00
octarine-noise
25cea8633c Integrate ClothConfig for Forge 2021-05-22 17:27:28 +02:00
octarine-noise
eeabc1922e translations JSON conversion
+ some cleanup
2021-05-22 17:25:48 +02:00
XiLaiTL
d7e16d603f Add files via upload
(cherry picked from commit ce8afacb019336962848ade302e7fe76c2654ebd)
2021-05-22 16:39:09 +02:00
octarine-noise
b1a08ab500 Merge remote-tracking branch 'local/forge-1.15' into forge-1.16
# Conflicts:
#	gradle.properties
#	src/main/kotlin/mods/betterfoliage/integration/ShadersModIntegration.kt
#	src/main/kotlin/mods/betterfoliage/model/HalfBaked.kt
#	src/main/kotlin/mods/betterfoliage/render/lighting/VanillaAoCalculation.kt
2021-05-16 12:30:07 +02:00
octarine-noise
fae9e9dfa9 adopt AO calculation tweak from Indigo 2021-05-16 12:02:42 +02:00
octarine-noise
512cd786f7 fix diffuse shading being too dark with shaders 2021-05-16 12:01:59 +02:00
octarine-noise
b96a17fdb9 clean up access transformer 2021-05-16 11:49:04 +02:00
octarine-noise
3d78ecce22 fix unbaked block model coords not being zero-centered 2021-05-16 11:48:34 +02:00
octarine-noise
6219e9353d fix crash with Abnormals Core
change random display tick mixin injection type from @Redirect to @Inject
2021-05-14 18:55:10 +02:00
octarine-noise
e3eb222d93 deburr build script 2021-05-14 18:52:22 +02:00
octarine-noise
8f82fefbb7 Port to 1.16.5
Kottle -> KotlinForForge
2021-05-14 14:44:29 +02:00
octarine-noise
8a303a1a29 update Gradle wrapper to 6.8.1
ForgeGradle dependency for FG4 onwards
2021-05-14 14:40:16 +02:00
octarine-noise
a97a575dd5 fix missing Optifine shader wind effects
+minor cleanup
2021-05-14 14:36:48 +02:00
octarine-noise
49d4f8aa31 remove some Fabric aliases 2021-04-30 12:28:34 +02:00
71 changed files with 1503 additions and 1459 deletions

View File

@@ -1,26 +1,20 @@
plugins { plugins {
kotlin("jvm").version("1.3.61") kotlin("jvm").version("1.4.20")
id("net.minecraftforge.gradle").version("3.0.194") id("net.minecraftforge.gradle").version("4.1.12")
id("org.spongepowered.mixin").version("0.7-SNAPSHOT") id("org.spongepowered.mixin").version("0.7-SNAPSHOT")
} }
apply(plugin = "org.spongepowered.mixin")
repositories { repositories {
maven("http://files.minecraftforge.net/maven") maven("https://files.minecraftforge.net/maven")
maven("https://repo.spongepowered.org/maven") maven("https://repo.spongepowered.org/maven")
maven("https://minecraft.curseforge.com/api/maven")
maven("https://maven.shedaniel.me/")
maven("https://www.cursemaven.com") maven("https://www.cursemaven.com")
maven("https://thedarkcolour.github.io/KotlinForForge/")
} }
dependencies { dependencies {
"minecraft"("net.minecraftforge:forge:${properties["mcVersion"]}-${properties["forgeVersion"]}") "minecraft"("net.minecraftforge:forge:${properties["mcVersion"]}-${properties["forgeVersion"]}")
"implementation"("thedarkcolour:kotlinforforge:1.7.0")
"api"(fg.deobf("curse.maven:clothconfig-348521:2938583")) "api"(fg.deobf("curse.maven:clothconfig-348521:3311352"))
"implementation"(fg.deobf("curse.maven:biomesoplenty-220318:2988999"))
"implementation"("kottle:Kottle:${properties["kottleVersion"]}")
// "implementation"("org.spongepowered:mixin:0.8-SNAPSHOT")
} }
configurations["annotationProcessor"].extendsFrom(configurations["implementation"]) configurations["annotationProcessor"].extendsFrom(configurations["implementation"])
@@ -51,7 +45,6 @@ kotlin {
target.compilations.configureEach { target.compilations.configureEach {
kotlinOptions.jvmTarget = "1.8" kotlinOptions.jvmTarget = "1.8"
kotlinOptions.freeCompilerArgs += listOf("-Xno-param-assertions", "-Xno-call-assertions") kotlinOptions.freeCompilerArgs += listOf("-Xno-param-assertions", "-Xno-call-assertions")
} }
} }

View File

@@ -4,11 +4,11 @@ org.gradle.daemon=false
group = com.github.octarine-noise group = com.github.octarine-noise
jarName = BetterFoliage-Forge jarName = BetterFoliage-Forge
version = 2.6.0 version = 2.6.5
mcVersion = 1.15.2 mcVersion = 1.16.5
forgeVersion = 31.2.44 forgeVersion = 36.1.17
mappingsChannel = snapshot mappingsChannel = official
mappingsVersion = 20200514-1.15.1 mappingsVersion = 1.16.5
kottleVersion = 1.4.0 #kottleVersion = 1.4.0

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

53
gradlew vendored
View File

@@ -1,5 +1,21 @@
#!/usr/bin/env sh #!/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 ## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` 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. # 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. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
@@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; 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\"" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi fi
# For Cygwin, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if $cygwin ; then if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath
@@ -138,19 +156,19 @@ if $cygwin ; then
else else
eval `echo args$i`="\"$arg\"" eval `echo args$i`="\"$arg\""
fi fi
i=$((i+1)) i=`expr $i + 1`
done done
case $i in case $i in
(0) set -- ;; 0) set -- ;;
(1) set -- "$args0" ;; 1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;; 2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;; 3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
@@ -159,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " " echo " "
} }
APP_ARGS=$(save "$@") APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules # 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" 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" "$@" exec "$JAVACMD" "$@"

43
gradlew.bat vendored
View File

@@ -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 @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% 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. @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 @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 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_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail 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 :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @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 :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View File

@@ -1,6 +1,6 @@
pluginManagement { pluginManagement {
repositories { repositories {
maven("http://files.minecraftforge.net/maven") maven("https://files.minecraftforge.net/maven")
maven("https://repo.spongepowered.org/maven") maven("https://repo.spongepowered.org/maven")
gradlePluginPortal() gradlePluginPortal()
} }

View File

@@ -21,7 +21,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
*/ */
@Mixin(Block.class) @Mixin(Block.class)
public class MixinBlock { public class MixinBlock {
private static final String shouldSideBeRendered = "Lnet/minecraft/block/Block;shouldSideBeRendered(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Z"; private static final String shouldSideBeRendered = "Lnet/minecraft/block/Block;shouldRenderFace(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Z";
private static final String getVoxelShape = "Lnet/minecraft/block/BlockState;func_215702_a(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Lnet/minecraft/util/math/shapes/VoxelShape;"; private static final String getVoxelShape = "Lnet/minecraft/block/BlockState;func_215702_a(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Lnet/minecraft/util/math/shapes/VoxelShape;";
private static final String getFaceOcclusionShape = "Lnet/minecraft/block/BlockState;getFaceOcclusionShape(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Lnet/minecraft/util/math/shapes/VoxelShape;"; private static final String getFaceOcclusionShape = "Lnet/minecraft/block/BlockState;getFaceOcclusionShape(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Lnet/minecraft/util/math/shapes/VoxelShape;";
private static final String isOpaqueCube = "Lnet/minecraft/block/Block;isOpaqueCube(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)Z"; private static final String isOpaqueCube = "Lnet/minecraft/block/Block;isOpaqueCube(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)Z";

View File

@@ -8,7 +8,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BlockModelRenderer; import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader; import net.minecraft.world.IBlockDisplayReader;
import net.minecraftforge.client.model.data.IModelData; import net.minecraftforge.client.model.data.IModelData;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -19,12 +19,12 @@ import java.util.Random;
@Mixin(BlockModelRenderer.class) @Mixin(BlockModelRenderer.class)
public class MixinBlockModelRenderer { public class MixinBlockModelRenderer {
private static final String renderModel = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModel(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z"; private static final String renderModel = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModel(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
private static final String renderModelFlat = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModelFlat(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z"; private static final String renderModelFlat = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModelFlat(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
private static final String renderModelSmooth = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModelSmooth(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z"; private static final String renderModelSmooth = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModelSmooth(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
@Redirect(method = renderModel, at = @At(value = "INVOKE", target = renderModelSmooth), remap = false) @Redirect(method = renderModel, at = @At(value = "INVOKE", target = renderModelSmooth), remap = false)
public boolean onRenderModelSmooth(BlockModelRenderer renderer, ILightReader world, IBakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, IVertexBuilder buffer, boolean checkSides, Random random, long rand, int combinedOverlay, IModelData modelData) { public boolean onRenderModelSmooth(BlockModelRenderer renderer, IBlockDisplayReader world, IBakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, IVertexBuilder buffer, boolean checkSides, Random random, long rand, int combinedOverlay, IModelData modelData) {
if (model instanceof SpecialRenderModel) if (model instanceof SpecialRenderModel)
return RenderCtxVanilla.render(renderer, world, (SpecialRenderModel) model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData, true); return RenderCtxVanilla.render(renderer, world, (SpecialRenderModel) model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData, true);
else else
@@ -32,10 +32,10 @@ public class MixinBlockModelRenderer {
} }
@Redirect(method = renderModel, at = @At(value = "INVOKE", target = renderModelFlat), remap = false) @Redirect(method = renderModel, at = @At(value = "INVOKE", target = renderModelFlat), remap = false)
public boolean onRenderModelFlat(BlockModelRenderer renderer, ILightReader world, IBakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, IVertexBuilder buffer, boolean checkSides, Random random, long rand, int combinedOverlay, IModelData modelData) { public boolean onRenderModelFlat(BlockModelRenderer renderer, IBlockDisplayReader world, IBakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, IVertexBuilder buffer, boolean checkSides, Random random, long rand, int combinedOverlay, IModelData modelData) {
if (model instanceof SpecialRenderModel) if (model instanceof SpecialRenderModel)
return RenderCtxVanilla.render(renderer, world, (SpecialRenderModel) model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData, false); return RenderCtxVanilla.render(renderer, world, (SpecialRenderModel) model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData, false);
else else
return renderer.renderModelSmooth(world, model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData); return renderer.renderModelFlat(world, model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData);
} }
} }

View File

@@ -1,12 +1,15 @@
package mods.betterfoliage.mixin; package mods.betterfoliage.mixin;
import mods.betterfoliage.Hooks; import mods.betterfoliage.Hooks;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import org.spongepowered.asm.mixin.Debug;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Coerce;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
/** /**
@@ -14,14 +17,15 @@ import org.spongepowered.asm.mixin.injection.Redirect;
* *
* Needed to avoid excessive darkening of Round Logs at the corners, now that they are not full blocks. * Needed to avoid excessive darkening of Round Logs at the corners, now that they are not full blocks.
*/ */
@Mixin(BlockState.class) @Mixin(AbstractBlock.AbstractBlockState.class)
@SuppressWarnings({"deprecation"}) @SuppressWarnings({"deprecation"})
public class MixinBlockState { public class MixinBlockState {
private static final String callFrom = "Lnet/minecraft/block/BlockState;getAmbientOcclusionLightValue(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F"; private static final String callFrom = "Lnet/minecraft/block/AbstractBlock$AbstractBlockState;getShadeBrightness(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F";
private static final String callTo = "Lnet/minecraft/block/Block;getAmbientOcclusionLightValue(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F"; // why is the INVOKEVIRTUAL target class Block in the bytecode, not AbstractBlock?
private static final String callTo = "Lnet/minecraft/block/Block;getShadeBrightness(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F";
@Redirect(method = callFrom, at = @At(value = "INVOKE", target = callTo)) @Redirect(method = callFrom, at = @At(value = "INVOKE", target = callTo))
float getAmbientOcclusionValue(Block block, BlockState state, IBlockReader reader, BlockPos pos) { float getAmbientOcclusionValue(Block block, BlockState state, IBlockReader reader, BlockPos pos) {
return Hooks.getAmbientOcclusionLightValueOverride(block.getAmbientOcclusionLightValue(state, reader, pos), state); return Hooks.getAmbientOcclusionLightValueOverride(block.getShadeBrightness(state, reader, pos), state);
} }
} }

View File

@@ -1,35 +1,34 @@
package mods.betterfoliage.mixin; package mods.betterfoliage.mixin;
import mods.betterfoliage.Hooks; import mods.betterfoliage.Hooks;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random; import java.util.Random;
@Mixin(ClientWorld.class) @Mixin(ClientWorld.class)
public class MixinClientWorld { public class MixinClientWorld {
private static final String worldAnimateTick = "Lnet/minecraft/client/world/ClientWorld;animateTick(IIIILjava/util/Random;ZLnet/minecraft/util/math/BlockPos$Mutable;)V"; private static final String worldAnimateTick = "Lnet/minecraft/client/world/ClientWorld;doAnimateTick(IIIILjava/util/Random;ZLnet/minecraft/util/math/BlockPos$Mutable;)V";
private static final String blockAnimateTick = "Lnet/minecraft/block/Block;animateTick(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Ljava/util/Random;)V"; private static final String blockAnimateTick = "Lnet/minecraft/block/Block;animateTick(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Ljava/util/Random;)V";
private static final String worldNotify = "Lnet/minecraft/client/world/ClientWorld;notifyBlockUpdate(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/BlockState;I)V"; private static final String worldNotify = "Lnet/minecraft/client/world/ClientWorld;sendBlockUpdated(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/BlockState;I)V";
private static final String rendererNotify = "Lnet/minecraft/client/renderer/WorldRenderer;notifyBlockUpdate(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/BlockState;I)V"; private static final String rendererNotify = "Lnet/minecraft/client/renderer/WorldRenderer;blockChanged(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/BlockState;I)V";
/** /**
* Inject a callback to call for every random display tick. Used for adding custom particle effects to blocks. * Inject a callback to call for every random display tick. Used for adding custom particle effects to blocks.
*/ */
@Redirect(method = worldAnimateTick, at = @At(value = "INVOKE", target = blockAnimateTick)) @Inject(method = worldAnimateTick, at = @At(value = "INVOKE", target = blockAnimateTick))
void onAnimateTick(Block block, BlockState state, World world, BlockPos pos, Random random) { void onAnimateTick(int x, int y, int z, int range, Random random, boolean doBarrier, BlockPos.Mutable pos, CallbackInfo ci) {
Hooks.onRandomDisplayTick(block, state, world, pos, random); Hooks.onRandomDisplayTick((ClientWorld) (Object) this, pos, random);
block.animateTick(state, world, pos, random);
} }
/** /**
@@ -39,6 +38,6 @@ public class MixinClientWorld {
@Redirect(method = worldNotify, at = @At(value = "INVOKE", target = rendererNotify)) @Redirect(method = worldNotify, at = @At(value = "INVOKE", target = rendererNotify))
void onClientBlockChanged(WorldRenderer renderer, IBlockReader world, BlockPos pos, BlockState oldState, BlockState newState, int flags) { void onClientBlockChanged(WorldRenderer renderer, IBlockReader world, BlockPos pos, BlockState oldState, BlockState newState, int flags) {
Hooks.onClientBlockChanged((ClientWorld) world, pos, oldState, newState, flags); Hooks.onClientBlockChanged((ClientWorld) world, pos, oldState, newState, flags);
renderer.notifyBlockUpdate(world, pos, oldState, newState, flags); renderer.blockChanged(world, pos, oldState, newState, flags);
} }
} }

View File

@@ -1,12 +1,12 @@
package mods.betterfoliage.mixin; package mods.betterfoliage.mixin;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import mods.betterfoliage.render.pipeline.RenderCtxForge;
import mods.betterfoliage.model.SpecialRenderModel; import mods.betterfoliage.model.SpecialRenderModel;
import mods.betterfoliage.render.pipeline.RenderCtxForge;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader; import net.minecraft.world.IBlockDisplayReader;
import net.minecraftforge.client.model.data.IModelData; import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.pipeline.ForgeBlockModelRenderer; import net.minecraftforge.client.model.pipeline.ForgeBlockModelRenderer;
import net.minecraftforge.client.model.pipeline.VertexLighterFlat; import net.minecraftforge.client.model.pipeline.VertexLighterFlat;
@@ -19,14 +19,14 @@ import java.util.Random;
@Mixin(ForgeBlockModelRenderer.class) @Mixin(ForgeBlockModelRenderer.class)
public class MixinForgeBlockModelRenderer { public class MixinForgeBlockModelRenderer {
private static final String renderModelFlat = "renderModelFlat(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z"; private static final String renderModelFlat = "Lnet/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer;renderModelFlat(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
private static final String renderModelSmooth = "renderModelSmooth(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z"; private static final String renderModelSmooth = "Lnet/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer;renderModelSmooth(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
private static final String render = "Lnet/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer;render(Lnet/minecraftforge/client/model/pipeline/VertexLighterFlat;Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;ZLjava/util/Random;JLnet/minecraftforge/client/model/data/IModelData;)Z"; private static final String render = "Lnet/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer;render(Lnet/minecraftforge/client/model/pipeline/VertexLighterFlat;Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;ZLjava/util/Random;JLnet/minecraftforge/client/model/data/IModelData;)Z";
@Redirect(method = {renderModelFlat, renderModelSmooth}, at = @At(value = "INVOKE", target = render), remap = false) @Redirect(method = {renderModelFlat, renderModelSmooth}, at = @At(value = "INVOKE", target = render), remap = false)
public boolean render( public boolean render(
VertexLighterFlat lighter, VertexLighterFlat lighter,
ILightReader world, IBlockDisplayReader world,
IBakedModel model, IBakedModel model,
BlockState state, BlockState state,
BlockPos pos, BlockPos pos,

View File

@@ -20,13 +20,13 @@ abstract public class MixinModelBakery {
private static final String processLoading = "Lnet/minecraft/client/renderer/model/ModelBakery;processLoading(Lnet/minecraft/profiler/IProfiler;I)V"; private static final String processLoading = "Lnet/minecraft/client/renderer/model/ModelBakery;processLoading(Lnet/minecraft/profiler/IProfiler;I)V";
private static final String stitch = "Lnet/minecraft/client/renderer/texture/AtlasTexture;stitch(Lnet/minecraft/resources/IResourceManager;Ljava/util/stream/Stream;Lnet/minecraft/profiler/IProfiler;I)Lnet/minecraft/client/renderer/texture/AtlasTexture$SheetData;"; private static final String stitch = "Lnet/minecraft/client/renderer/texture/AtlasTexture;stitch(Lnet/minecraft/resources/IResourceManager;Ljava/util/stream/Stream;Lnet/minecraft/profiler/IProfiler;I)Lnet/minecraft/client/renderer/texture/AtlasTexture$SheetData;";
private static final String profilerSection = "Lnet/minecraft/profiler/IProfiler;endStartSection(Ljava/lang/String;)V"; private static final String profilerSection = "Lnet/minecraft/profiler/IProfiler;popPush(Ljava/lang/String;)V";
private static final String getBakedModel = "Lnet/minecraft/client/renderer/model/ModelBakery;getBakedModel(Lnet/minecraft/util/ResourceLocation;Lnet/minecraft/client/renderer/model/IModelTransform;Ljava/util/function/Function;)Lnet/minecraft/client/renderer/model/IBakedModel;"; private static final String getBakedModel = "Lnet/minecraft/client/renderer/model/ModelBakery;getBakedModel(Lnet/minecraft/util/ResourceLocation;Lnet/minecraft/client/renderer/model/IModelTransform;Ljava/util/function/Function;)Lnet/minecraft/client/renderer/model/IBakedModel;";
private static final String bakeModel = "Lnet/minecraft/client/renderer/model/IUnbakedModel;bakeModel(Lnet/minecraft/client/renderer/model/ModelBakery;Ljava/util/function/Function;Lnet/minecraft/client/renderer/model/IModelTransform;Lnet/minecraft/util/ResourceLocation;)Lnet/minecraft/client/renderer/model/IBakedModel;"; private static final String bakeModel = "Lnet/minecraft/client/renderer/model/IUnbakedModel;bake(Lnet/minecraft/client/renderer/model/ModelBakery;Ljava/util/function/Function;Lnet/minecraft/client/renderer/model/IModelTransform;Lnet/minecraft/util/ResourceLocation;)Lnet/minecraft/client/renderer/model/IBakedModel;";
@Inject(method = processLoading, at = @At(value = "INVOKE", target = profilerSection, ordinal = 4)) @Inject(method = processLoading, at = @At(value = "INVOKE", target = profilerSection, ordinal = 4))
void onBeforeTextures(IProfiler profiler, int maxMipmapLevel, CallbackInfo ci) { void onBeforeTextures(IProfiler profiler, int maxMipmapLevel, CallbackInfo ci) {
profiler.endStartSection("betterfoliage"); profiler.popPush("betterfoliage");
BetterFoliageMod.INSTANCE.getBus().post(new ModelDefinitionsLoadedEvent(ModelBakery.class.cast(this))); BetterFoliageMod.INSTANCE.getBus().post(new ModelDefinitionsLoadedEvent(ModelBakery.class.cast(this)));
} }
@@ -34,7 +34,7 @@ abstract public class MixinModelBakery {
IBakedModel onBakeModel( IBakedModel onBakeModel(
IUnbakedModel unbaked, IUnbakedModel unbaked,
ModelBakery bakery, ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter, Function<RenderMaterial, TextureAtlasSprite> spriteGetter,
IModelTransform transform, IModelTransform transform,
ResourceLocation locationIn ResourceLocation locationIn
) { ) {

View File

@@ -31,6 +31,7 @@ import mods.betterfoliage.resource.discovery.ModelDefinitionsLoadedEvent
import mods.betterfoliage.resource.generated.GeneratedTexturePack import mods.betterfoliage.resource.generated.GeneratedTexturePack
import mods.betterfoliage.render.particle.LeafParticleRegistry import mods.betterfoliage.render.particle.LeafParticleRegistry
import mods.betterfoliage.render.particle.RisingSoulParticle import mods.betterfoliage.render.particle.RisingSoulParticle
import mods.betterfoliage.util.resourceManager
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.resources.IReloadableResourceManager import net.minecraft.resources.IReloadableResourceManager
@@ -51,7 +52,7 @@ object BetterFoliage {
// discoverers // discoverers
BetterFoliageMod.bus.register(BakeWrapperManager) BetterFoliageMod.bus.register(BakeWrapperManager)
BetterFoliageMod.bus.register(LeafParticleRegistry) BetterFoliageMod.bus.register(LeafParticleRegistry)
(Minecraft.getInstance().resourceManager as IReloadableResourceManager).addReloadListener(LeafParticleRegistry) resourceManager.registerReloadListener(LeafParticleRegistry)
ChunkOverlayManager.layers.add(RoundLogOverlayLayer) ChunkOverlayManager.layers.add(RoundLogOverlayLayer)

View File

@@ -1,25 +1,37 @@
package mods.betterfoliage package mods.betterfoliage
import mods.betterfoliage.config.BlockConfig import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config import mods.betterfoliage.config.MainConfig
import net.alexwells.kottle.FMLKotlinModLoadingContext import mods.betterfoliage.util.tryDefault
import mods.betterfoliage.config.clothGuiRoot
import mods.betterfoliage.config.forgeSpecRoot
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.gui.screen.Screen
import net.minecraft.util.ResourceLocation
import net.minecraftforge.fml.ExtensionPoint.CONFIGGUIFACTORY
import net.minecraftforge.fml.ExtensionPoint.DISPLAYTEST
import net.minecraftforge.fml.ModLoadingContext import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.Mod
import net.minecraftforge.fml.config.ModConfig import net.minecraftforge.fml.config.ModConfig
import org.apache.commons.lang3.tuple.Pair
import org.apache.logging.log4j.Level import org.apache.logging.log4j.Level
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.simple.SimpleLogger import org.apache.logging.log4j.simple.SimpleLogger
import org.apache.logging.log4j.util.PropertiesUtil import org.apache.logging.log4j.util.PropertiesUtil
import thedarkcolour.kotlinforforge.forge.MOD_BUS
import java.io.File import java.io.File
import java.io.PrintStream import java.io.PrintStream
import java.util.Properties import java.util.Properties
import java.util.function.BiFunction
import java.util.function.BiPredicate
import java.util.function.Supplier
@Mod(BetterFoliageMod.MOD_ID) @Mod(BetterFoliageMod.MOD_ID)
object BetterFoliageMod { object BetterFoliageMod {
const val MOD_ID = "betterfoliage" const val MOD_ID = "betterfoliage"
val bus = FMLKotlinModLoadingContext.get().modEventBus val bus = MOD_BUS
val config = MainConfig()
val detailLogStream = PrintStream(File("logs/betterfoliage.log").apply { val detailLogStream = PrintStream(File("logs/betterfoliage.log").apply {
parentFile.mkdirs() parentFile.mkdirs()
@@ -32,8 +44,34 @@ object BetterFoliageMod {
) )
init { init {
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.build()) val ctx = ModLoadingContext.get()
Minecraft.getInstance().resourcePackList.addPackFinder(BetterFoliage.generatedPack.finder)
val configSpec = config.forgeSpecRoot()
ctx.registerConfig(ModConfig.Type.CLIENT, configSpec)
// Add config GUI extension if Cloth Config is available
val clothLoaded = tryDefault(false) { Class.forName("me.shedaniel.clothconfig2.forge.api.ConfigBuilder"); true }
if (clothLoaded) {
logger(this).log(Level.INFO, "Cloth Config found, registering GUI")
ctx.registerExtensionPoint(CONFIGGUIFACTORY) { BiFunction<Minecraft, Screen, Screen> { client, parent ->
config.clothGuiRoot(
parentScreen = parent,
prefix = listOf(MOD_ID),
background = ResourceLocation("minecraft:textures/block/spruce_log.png"),
saveAction = { configSpec.save() }
)
} }
}
// Accept-all version tester (we are client-only)
ctx.registerExtensionPoint(DISPLAYTEST) {
Pair.of(
Supplier { "Honk if you see this!" },
BiPredicate<String, Boolean> { _, _ -> true }
)
}
Minecraft.getInstance().resourcePackRepository.addPackFinder(BetterFoliage.generatedPack.finder)
bus.register(BlockConfig) bus.register(BlockConfig)
BetterFoliage.init() BetterFoliage.init()
} }

View File

@@ -17,11 +17,13 @@ import net.minecraft.client.renderer.model.ModelBakery
import net.minecraft.client.renderer.texture.TextureAtlasSprite import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockDisplayReader
import net.minecraft.world.IBlockReader import net.minecraft.world.IBlockReader
import net.minecraft.world.ILightReader
import net.minecraftforge.client.model.pipeline.BlockInfo import net.minecraftforge.client.model.pipeline.BlockInfo
import net.minecraftforge.client.model.pipeline.VertexLighterFlat import net.minecraftforge.client.model.pipeline.VertexLighterFlat
import java.util.* import java.util.Random
typealias Sprite = TextureAtlasSprite
// Java // Java
val String = ClassRef<String>("java.lang.String") val String = ClassRef<String>("java.lang.String")
@@ -32,7 +34,7 @@ fun <K, V> mapRefMutable() = ClassRef<MutableMap<K, V>>("java.util.Map")
// Minecraft // Minecraft
val IBlockReader = ClassRef<IBlockReader>("net.minecraft.world.IBlockReader") val IBlockReader = ClassRef<IBlockReader>("net.minecraft.world.IBlockReader")
val ILightReader = ClassRef<ILightReader>("net.minecraft.world.ILightReader") val ILightReader = ClassRef<IBlockDisplayReader>("net.minecraft.world.IBlockDisplayReader")
val BlockState = ClassRef<BlockState>("net.minecraft.block.BlockState") val BlockState = ClassRef<BlockState>("net.minecraft.block.BlockState")
val BlockPos = ClassRef<BlockPos>("net.minecraft.util.math.BlockPos") val BlockPos = ClassRef<BlockPos>("net.minecraft.util.math.BlockPos")
val Block = ClassRef<Block>("net.minecraft.block.Block") val Block = ClassRef<Block>("net.minecraft.block.Block")
@@ -77,6 +79,13 @@ object CustomColors : ClassRef<Any>("net.optifine.CustomColors") {
} }
// Optifine shaders // Optifine shaders
object Shaders : ClassRef<Any>("net.optifine.shaders.Shaders") {
val shaderPackLoaded = FieldRef(this, "shaderPackLoaded", boolean)
val blockLightLevel05 = FieldRef(this, "blockLightLevel05", float)
val blockLightLevel06 = FieldRef(this, "blockLightLevel06", float)
val blockLightLevel08 = FieldRef(this, "blockLightLevel08", float)
}
object SVertexBuilder : ClassRef<Any>("net.optifine.shaders.SVertexBuilder") { object SVertexBuilder : ClassRef<Any>("net.optifine.shaders.SVertexBuilder") {
val pushState = MethodRef(this, "pushEntity", void, long) val pushState = MethodRef(this, "pushEntity", void, long)
val popState = MethodRef(this, "popEntity", void) val popState = MethodRef(this, "popEntity", void)

View File

@@ -20,8 +20,8 @@ import net.minecraft.util.Direction.UP
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.shapes.VoxelShape import net.minecraft.util.math.shapes.VoxelShape
import net.minecraft.util.math.shapes.VoxelShapes import net.minecraft.util.math.shapes.VoxelShapes
import net.minecraft.world.IBlockDisplayReader
import net.minecraft.world.IBlockReader import net.minecraft.world.IBlockReader
import net.minecraft.world.ILightReader
import net.minecraft.world.World import net.minecraft.world.World
import java.util.Random import java.util.Random
@@ -35,11 +35,12 @@ fun onClientBlockChanged(worldClient: ClientWorld, pos: BlockPos, oldState: Bloc
ChunkOverlayManager.onBlockChange(worldClient, pos) ChunkOverlayManager.onBlockChange(worldClient, pos)
} }
fun onRandomDisplayTick(block: Block, state: BlockState, world: World, pos: BlockPos, random: Random) { fun onRandomDisplayTick(world: ClientWorld, pos: BlockPos, random: Random) {
val state = world.getBlockState(pos)
if (Config.enabled && if (Config.enabled &&
Config.risingSoul.enabled && Config.risingSoul.enabled &&
state.block == Blocks.SOUL_SAND && state.block == Blocks.SOUL_SAND &&
world.isAirBlock(pos.offset(UP)) && world.getBlockState(pos.relative(UP)).isAir &&
Math.random() < Config.risingSoul.chance) { Math.random() < Config.risingSoul.chance) {
RisingSoulParticle(world, pos).addIfValid() RisingSoulParticle(world, pos).addIfValid()
} }
@@ -47,7 +48,7 @@ fun onRandomDisplayTick(block: Block, state: BlockState, world: World, pos: Bloc
if (Config.enabled && if (Config.enabled &&
Config.fallingLeaves.enabled && Config.fallingLeaves.enabled &&
random.nextDouble() < Config.fallingLeaves.chance && random.nextDouble() < Config.fallingLeaves.chance &&
world.isAirBlock(pos.offset(DOWN)) world.getBlockState(pos.relative(DOWN)).isAir
) { ) {
(getActualRenderModel(world, pos, state, random) as? LeafBlockModel)?.let { leafModel -> (getActualRenderModel(world, pos, state, random) as? LeafBlockModel)?.let { leafModel ->
val blockColor = Minecraft.getInstance().blockColors.getColor(state, world, pos, 0) val blockColor = Minecraft.getInstance().blockColors.getColor(state, world, pos, 0)
@@ -63,13 +64,13 @@ fun getVoxelShapeOverride(state: BlockState, reader: IBlockReader, pos: BlockPos
} }
fun shouldForceSideRenderOF(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction) = fun shouldForceSideRenderOF(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction) =
world.getBlockState(pos.offset(face)).let { neighbor -> BetterFoliage.blockTypes.hasTyped<RoundLogKey>(neighbor) } world.getBlockState(pos.relative(face)).let { neighbor -> BetterFoliage.blockTypes.hasTyped<RoundLogKey>(neighbor) }
fun getActualRenderModel(world: ILightReader, pos: BlockPos, state: BlockState, random: Random): SpecialRenderModel? { fun getActualRenderModel(world: IBlockDisplayReader, pos: BlockPos, state: BlockState, random: Random): SpecialRenderModel? {
val model = Minecraft.getInstance().blockRendererDispatcher.blockModelShapes.getModel(state) as? SpecialRenderModel val model = Minecraft.getInstance().blockRenderer.blockModelShaper.getBlockModel(state) as? SpecialRenderModel
?: return null ?: return null
if (model is WeightedModelWrapper) { if (model is WeightedModelWrapper) {
random.setSeed(state.getPositionRandom(pos)) random.setSeed(state.getSeed(pos))
return model.getModel(random).model return model.getModel(random).model
} }
return model return model

View File

@@ -1,7 +1,6 @@
package mods.betterfoliage.chunk package mods.betterfoliage.chunk
import mods.betterfoliage.util.Int3 import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.allDirections
import mods.betterfoliage.util.offset import mods.betterfoliage.util.offset
import mods.betterfoliage.util.plus import mods.betterfoliage.util.plus
import mods.betterfoliage.util.semiRandom import mods.betterfoliage.util.semiRandom
@@ -10,7 +9,7 @@ import net.minecraft.block.BlockState
import net.minecraft.client.renderer.chunk.ChunkRenderCache import net.minecraft.client.renderer.chunk.ChunkRenderCache
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader import net.minecraft.world.IBlockDisplayReader
import net.minecraft.world.IWorldReader import net.minecraft.world.IWorldReader
import net.minecraft.world.biome.Biome import net.minecraft.world.biome.Biome
import net.minecraft.world.level.ColorResolver import net.minecraft.world.level.ColorResolver
@@ -20,7 +19,7 @@ import net.minecraft.world.level.ColorResolver
* block-relative coordinates. * block-relative coordinates.
*/ */
interface BlockCtx { interface BlockCtx {
val world: ILightReader val world: IBlockDisplayReader
val pos: BlockPos val pos: BlockPos
fun offset(dir: Direction) = offset(dir.offset) fun offset(dir: Direction) = offset(dir.offset)
@@ -35,13 +34,13 @@ interface BlockCtx {
val biome: Biome? get() = val biome: Biome? get() =
(world as? IWorldReader)?.getBiome(pos) ?: (world as? IWorldReader)?.getBiome(pos) ?:
(world as? ChunkRenderCache)?.world?.getBiome(pos) (world as? ChunkRenderCache)?.level?.getBiome(pos)
val isNormalCube: Boolean get() = state.isNormalCube(world, pos) val isFullBlock: Boolean get() = state.isCollisionShapeFullBlock(world, pos)
fun isNeighborSolid(dir: Direction) = offset(dir).let { it.state.isSolidSide(it.world, it.pos, dir.opposite) } fun isNeighborSturdy(dir: Direction) = offset(dir).let { it.state.isFaceSturdy(it.world, it.pos, dir.opposite) }
fun shouldSideBeRendered(side: Direction) = Block.shouldSideBeRendered(state, world, pos, side) fun shouldSideBeRendered(side: Direction) = Block.shouldRenderFace(state, world, pos, side)
/** Get a semi-random value based on the block coordinate and the given seed. */ /** Get a semi-random value based on the block coordinate and the given seed. */
fun semiRandom(seed: Int) = pos.semiRandom(seed) fun semiRandom(seed: Int) = pos.semiRandom(seed)
@@ -49,11 +48,11 @@ interface BlockCtx {
/** Get an array of semi-random values based on the block coordinate. */ /** Get an array of semi-random values based on the block coordinate. */
fun semiRandomArray(num: Int): Array<Int> = Array(num) { semiRandom(it) } fun semiRandomArray(num: Int): Array<Int> = Array(num) { semiRandom(it) }
fun color(resolver: ColorResolver) = world.getBlockColor(pos, resolver) fun color(resolver: ColorResolver) = world.getBlockTint(pos, resolver)
} }
class BasicBlockCtx( class BasicBlockCtx(
override val world: ILightReader, override val world: IBlockDisplayReader,
override val pos: BlockPos override val pos: BlockPos
) : BlockCtx { ) : BlockCtx {
override val state: BlockState = world.getBlockState(pos) override val state: BlockState = world.getBlockState(pos)

View File

@@ -1,32 +1,26 @@
package mods.betterfoliage.chunk package mods.betterfoliage.chunk
import mods.octarinecore.ChunkCacheOF
import mods.betterfoliage.util.get import mods.betterfoliage.util.get
import mods.betterfoliage.util.isInstance import mods.betterfoliage.util.isInstance
import mods.octarinecore.ChunkCacheOF
import net.minecraft.client.renderer.chunk.ChunkRenderCache import net.minecraft.client.renderer.chunk.ChunkRenderCache
import net.minecraft.client.world.ClientWorld import net.minecraft.client.world.ClientWorld
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.ChunkPos import net.minecraft.util.math.ChunkPos
import net.minecraft.world.ILightReader import net.minecraft.world.DimensionType
import net.minecraft.world.IBlockDisplayReader
import net.minecraft.world.IWorldReader import net.minecraft.world.IWorldReader
import net.minecraft.world.dimension.DimensionType
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.world.ChunkEvent import net.minecraftforge.event.world.ChunkEvent
import net.minecraftforge.event.world.WorldEvent import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.eventbus.api.SubscribeEvent
import java.util.* import java.util.*
import kotlin.collections.List
import kotlin.collections.MutableMap
import kotlin.collections.associateWith
import kotlin.collections.forEach
import kotlin.collections.mutableListOf
import kotlin.collections.mutableMapOf
import kotlin.collections.set import kotlin.collections.set
val ILightReader.dimType: DimensionType get() = when { val IBlockDisplayReader.dimType: DimensionType get() = when {
this is IWorldReader -> dimension.type this is IWorldReader -> dimensionType()
this is ChunkRenderCache -> world.dimension.type this is ChunkRenderCache -> level.dimensionType()
this.isInstance(ChunkCacheOF) -> this[ChunkCacheOF.chunkCache].world.dimension.type this.isInstance(ChunkCacheOF) -> this[ChunkCacheOF.chunkCache].level.dimensionType()
else -> throw IllegalArgumentException("DimensionType of world with class ${this::class.qualifiedName} cannot be determined!") else -> throw IllegalArgumentException("DimensionType of world with class ${this::class.qualifiedName} cannot be determined!")
} }
@@ -35,7 +29,7 @@ val ILightReader.dimType: DimensionType get() = when {
*/ */
interface ChunkOverlayLayer<T> { interface ChunkOverlayLayer<T> {
fun calculate(ctx: BlockCtx): T fun calculate(ctx: BlockCtx): T
fun onBlockUpdate(world: ILightReader, pos: BlockPos) fun onBlockUpdate(world: IBlockDisplayReader, pos: BlockPos)
} }
/** /**

View File

@@ -6,150 +6,6 @@ import mods.betterfoliage.resource.discovery.ModelTextureListConfiguration
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.config.ModConfig import net.minecraftforge.fml.config.ModConfig
import java.util.Random
private fun featureEnable() = boolean(true).lang("enabled")
abstract class PopulationConfigCategory() : ConfigCategory() {
abstract val enabled: Boolean
abstract val population: Int
fun enabled(random: Random) = random.nextInt(64) < population && enabled
}
// Config singleton
object Config : DelegatingConfig(BetterFoliageMod.MOD_ID, BetterFoliageMod.MOD_ID) {
val enabled by boolean(true)
val nVidia by boolean(false)
object leaves : ConfigCategory() {
val enabled by featureEnable()
val snowEnabled by boolean(true)
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
val vOffset by double(max=0.4, default=0.1).lang("vOffset")
val size by double(min=0.75, max=2.5, default=1.4).lang("size")
val dense by boolean(false)
val hideInternal by boolean(true)
val saturationThreshold by double(default=0.1)
}
object shortGrass : PopulationConfigCategory(){
override val enabled by featureEnable()
val myceliumEnabled by boolean(true)
val snowEnabled by boolean(true)
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
val heightMin by double(min=0.1, max=2.5, default=0.6).lang("heightMin")
val heightMax by double(min=0.1, max=2.5, default=0.8).lang("heightMax")
val size by double(min=0.5, max=1.5, default=1.0).lang("size")
override val population by int(max=64, default=64).lang("population")
val useGenerated by boolean(false)
val shaderWind by boolean(true).lang("shaderWind")
val saturationThreshold by double(default=0.1)
}
object connectedGrass : ConfigCategory(){
val enabled by featureEnable()
val snowEnabled by boolean(false)
}
object roundLogs : ConfigCategory(){
val enabled by featureEnable()
val radiusSmall by double(max=0.5, default=0.25)
val radiusLarge by double(max=0.5, default=0.44)
val dimming by double(default = 0.7)
val connectSolids by boolean(false)
val lenientConnect by boolean(true)
val connectPerpendicular by boolean(true)
val connectGrass by boolean(true)
val defaultY by boolean(false)
val zProtection by double(min = 0.9, default = 0.99)
}
object cactus : ConfigCategory(){
val enabled by featureEnable()
val size by double(min=1.0, max=2.0, default=1.3).lang("size")
val sizeVariation by double(max=0.5, default=0.1)
val hOffset by double(max=0.5, default=0.1).lang("hOffset")
}
object lilypad : PopulationConfigCategory(){
override val enabled by featureEnable()
val hOffset by double(max=0.25, default=0.1).lang("hOffset")
override val population by int(max=64, default=16, min=0)
val shaderWind by boolean(true).lang("shaderWind")
}
object reed : PopulationConfigCategory(){
override val enabled by featureEnable()
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
val heightMin by double(min=1.5, max=3.5, default=1.7).lang("heightMin")
val heightMax by double(min=1.5, max=3.5, default=2.2).lang("heightMax")
override val population by int(max=64, default=32).lang("population")
val minBiomeTemp by double(default=0.4)
val minBiomeRainfall by double(default=0.4)
// val biomes by biomeList { it.filterTemp(0.4f, null) && it.filterRain(0.4f, null) }
val shaderWind by boolean(true).lang("shaderWind")
}
object algae : PopulationConfigCategory(){
override val enabled by featureEnable()
val hOffset by double(max=0.25, default=0.1).lang("hOffset")
val size by double(min=0.5, max=1.5, default=1.0).lang("size")
val heightMin by double(min=0.1, max=1.5, default=0.5).lang("heightMin")
val heightMax by double(min=0.1, max=1.5, default=1.0).lang("heightMax")
override val population by int(max=64, default=48).lang("population")
// val biomes by biomeList { it.filterClass("river", "ocean") }
val shaderWind by boolean(true).lang("shaderWind")
}
object coral : PopulationConfigCategory(){
override val enabled by featureEnable()
val shallowWater by boolean(false)
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
val vOffset by double(max=0.4, default=0.1).lang("vOffset")
val size by double(min=0.5, max=1.5, default=0.7).lang("size")
val crustSize by double(min=0.5, max=1.5, default=1.4)
val chance by int(max=64, default=32)
override val population by int(max=64, default=48).lang("population")
// val biomes by biomeList { it.filterClass("river", "ocean", "beach") }
}
object netherrack : ConfigCategory(){
val enabled by featureEnable()
val hOffset by double(max=0.4, default=0.2).lang("hOffset")
val heightMin by double(min=0.1, max=1.5, default=0.2).lang("heightMin")
val heightMax by double(min=0.1, max=1.5, default=0.5).lang("heightMax")
val size by double(min=0.5, max=1.5, default=1.0).lang("size")
}
object fallingLeaves : ConfigCategory(){
val enabled by featureEnable()
val speed by double(min=0.01, max=0.15, default=0.05)
val windStrength by double(min=0.1, max=2.0, default=0.5)
val stormStrength by double(min=0.1, max=2.0, default=0.8)
val size by double(min=0.25, max=1.5, default=0.75).lang("size")
val chance by double(min=0.001, max=1.0, default=0.02)
val perturb by double(min=0.01, max=1.0, default=0.25)
val lifetime by double(min=1.0, max=15.0, default=5.0)
val opacityHack by boolean(true)
}
object risingSoul : ConfigCategory(){
val enabled by featureEnable()
val chance by double(min=0.001, max=1.0, default=0.02)
val perturb by double(min=0.01, max=0.25, default=0.05)
val headSize by double(min=0.25, max=1.5, default=1.0)
val trailSize by double(min=0.25, max=1.5, default=0.75)
val opacity by double(min=0.05, max=1.0, default=0.5)
val sizeDecay by double(min=0.5, max=1.0, default=0.97)
val opacityDecay by double(min=0.5, max=1.0, default=0.97)
val lifetime by double(min=1.0, max=15.0, default=4.0)
val trailLength by int(min=2, max=128, default=48)
val trailDensity by int(min=1, max=16, default=3)
}
}
object BlockConfig { object BlockConfig {
private val list = mutableListOf<Any>() private val list = mutableListOf<Any>()

View File

@@ -0,0 +1,170 @@
package mods.betterfoliage.config
import me.shedaniel.clothconfig2.forge.api.AbstractConfigListEntry
import me.shedaniel.clothconfig2.forge.api.ConfigBuilder
import me.shedaniel.clothconfig2.forge.api.ConfigEntryBuilder
import me.shedaniel.clothconfig2.forge.gui.entries.SubCategoryListEntry
import mods.betterfoliage.util.asText
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.resources.I18n
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.ForgeConfigSpec
import java.util.Optional
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
const val MAX_LINE_LEN = 30
fun DelegatingConfigGroup.forgeSpecRoot() =
ForgeConfigSpec.Builder()
.also { createForgeNode(it) }
.build()
fun DelegatingConfigGroup.clothGuiRoot(
parentScreen: Screen,
prefix: List<String>,
background: ResourceLocation,
saveAction: ()->Unit
) = ConfigBuilder.create()
.setParentScreen(parentScreen)
.setTitle(I18n.get((prefix + "title").joinToString(".")).asText())
.setDefaultBackgroundTexture(background)
.setSavingRunnable(saveAction)
.also { builder ->
createClothNode(prefix).value.forEach { rootCategory ->
builder.getOrCreateCategory("main".asText()).addEntry(rootCategory)
}
}
.build()
sealed class DelegatingConfigNode {
abstract fun createClothNode(path: List<String>): AbstractConfigListEntry<*>
}
abstract class DelegatingConfigValue<T> : DelegatingConfigNode(), ReadOnlyProperty<DelegatingConfigGroup, T> {
lateinit var forgeValue: ForgeConfigSpec.ConfigValue<T>
abstract fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String)
}
open class DelegatingConfigGroup : DelegatingConfigNode() {
val children = mutableMapOf<String, DelegatingConfigNode>()
fun createForgeNode(builder: ForgeConfigSpec.Builder) {
children.forEach { (name, node) ->
when(node) {
is DelegatingConfigGroup -> {
builder.push(name)
node.createForgeNode(builder)
builder.pop()
}
is DelegatingConfigValue<*> -> node.createForgeNode(builder, name)
}
}
}
override fun createClothNode(path: List<String>): SubCategoryListEntry {
val builder = ConfigEntryBuilder.create()
.startSubCategory(path.joinToString(".").translate())
.setTooltip(*path.joinToString(".").translateTooltip())
.setExpanded(false)
children.forEach { (name, node) -> builder.add(node.createClothNode(path + name)) }
return builder.build()
}
}
interface DelegatingConfigGroupFactory<T> {
operator fun provideDelegate(parent: DelegatingConfigGroup, property: KProperty<*>): ReadOnlyProperty<DelegatingConfigGroup, T>
}
fun <T: DelegatingConfigGroup> subNode(factory: ()->T) = object : DelegatingConfigGroupFactory<T> {
override operator fun provideDelegate(parent: DelegatingConfigGroup, property: KProperty<*>): ReadOnlyProperty<DelegatingConfigGroup, T> {
val child = factory()
parent.children[property.name] = child
return ReadOnlyProperty { _, _ -> child }
}
}
interface DelegatingConfigValueFactory<T> {
fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String): ForgeConfigSpec.ConfigValue<T>
fun createClothNode(prop: CachingConfigProperty<T>, path: List<String>): AbstractConfigListEntry<T>
operator fun provideDelegate(parent: DelegatingConfigGroup, property: KProperty<*>): ReadOnlyProperty<DelegatingConfigGroup, T> {
return object : CachingConfigProperty<T>(parent, property) {
override fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String) {
forgeValue = this@DelegatingConfigValueFactory.createForgeNode(builder, name)
}
override fun createClothNode(path: List<String>): AbstractConfigListEntry<*> = createClothNode(this, path)
}.apply { parent.children[property.name] = this }
}
}
abstract class CachingConfigProperty<T>(parent: DelegatingConfigGroup, property: KProperty<*>) : DelegatingConfigValue<T>() {
var value: T? = null
override fun getValue(thisRef: DelegatingConfigGroup, property: KProperty<*>) =
value ?: forgeValue.get().apply { value = this }
}
fun String.translate() = I18n.get(this).asText()
fun String.translateTooltip(lineLength: Int = MAX_LINE_LEN) =
I18n.get("$this.tooltip").splitToSequence(" ").fold(mutableListOf("")) { tooltips, word ->
if (tooltips.last().length + word.length < lineLength) {
tooltips[tooltips.lastIndex] += "$word "
} else {
tooltips.add("$word ")
}
tooltips
}.map { it.trim().asText() }.toTypedArray()
fun boolean(
default: Boolean,
langKey: (List<String>)->String = { it.joinToString(".") },
valueOverride: (Boolean)->Boolean = { it }
) = object : DelegatingConfigValueFactory<Boolean> {
override fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String) =
builder.define(name, default)
override fun createClothNode(prop: CachingConfigProperty<Boolean>, path: List<String>) = ConfigEntryBuilder.create()
.startBooleanToggle(langKey(path).translate(), prop.forgeValue.get())
.setTooltip(langKey(path).let { if (I18n.exists("$it.tooltip")) Optional.of(it.translateTooltip()) else Optional.empty() })
.setSaveConsumer { prop.forgeValue.set(valueOverride(it)); prop.value = null }
.build()
}
fun integer(
default: Int = 0, min: Int = 0, max: Int,
langKey: (List<String>)->String = { it.joinToString(".") },
valueOverride: (Int)->Int = { it }
) = object : DelegatingConfigValueFactory<Int> {
override fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String) =
builder.defineInRange(name, default, min, max)
override fun createClothNode(prop: CachingConfigProperty<Int>, path: List<String>) = ConfigEntryBuilder.create()
.startIntField(langKey(path).translate(), prop.forgeValue.get())
.setTooltip(langKey(path).let { if (I18n.exists("$it.tooltip")) Optional.of(it.translateTooltip()) else Optional.empty() })
.setMin(min).setMax(max)
.setSaveConsumer { prop.forgeValue.set(valueOverride(it)); prop.value = null }
.build()
}
fun double(
default: Double = 0.0, min: Double = 0.0, max: Double = 1.0,
langKey: (List<String>)->String = { it.joinToString(".") },
valueOverride: (Double)->Double = { it }
) = object : DelegatingConfigValueFactory<Double> {
override fun createForgeNode(builder: ForgeConfigSpec.Builder, name: String) =
builder.defineInRange(name, default, min, max)
override fun createClothNode(prop: CachingConfigProperty<Double>, path: List<String>) = ConfigEntryBuilder.create()
.startDoubleField(langKey(path).translate(), prop.forgeValue.get())
.setTooltip(langKey(path).let { if (I18n.exists("$it.tooltip")) Optional.of(it.translateTooltip()) else Optional.empty() })
.setMin(min).setMax(max)
.setSaveConsumer { prop.forgeValue.set(valueOverride(it)); prop.value = null }
.build()
}
val recurring = { path: List<String> -> "${path.first()}.${path.last()}" }
fun fakeCategory(name: String) = { names: List<String> ->
(listOf(names.first(), name) + names.drop(1)).joinToString(".")
}

View File

@@ -1,89 +0,0 @@
@file:JvmName("DelegatingConfigKt")
package mods.betterfoliage.config
import mods.betterfoliage.util.reflectDelegates
import mods.betterfoliage.util.reflectNestedObjects
import net.minecraftforge.common.ForgeConfigSpec
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
open class DelegatingConfig(val modId: String, val langPrefix: String) {
fun build() = ForgeConfigSpec.Builder().apply { ConfigBuildContext(langPrefix, emptyList(), this).addCategory(this@DelegatingConfig) }.build()
}
class ConfigBuildContext(val langPrefix: String, val path: List<String>, val builder: ForgeConfigSpec.Builder) {
fun addCategory(configObj: Any) {
configObj.reflectNestedObjects.forEach { (name, category) ->
builder.push(name)
descend(name).addCategory(category)
builder.pop()
}
configObj.reflectDelegates(ConfigDelegate::class.java).forEach { (name, delegate) ->
descend(name).apply { delegate.addToBuilder(this) }
}
}
fun descend(pathName: String) = ConfigBuildContext(langPrefix, path + pathName, builder)
}
open class ConfigCategory(val comment: String? = null) {
}
abstract class ConfigDelegate<T> : ReadOnlyProperty<Any, T> {
lateinit var configValue: ForgeConfigSpec.ConfigValue<T>
var cachedValue: T? = null
override fun getValue(thisRef: Any, property: KProperty<*>): T {
if (cachedValue == null) cachedValue = configValue.get()
return cachedValue!!
}
abstract fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder): ForgeConfigSpec.ConfigValue<T>
fun addToBuilder(ctx: ConfigBuildContext) {
val langKey = ctx.langPrefix + "." + (langPrefixOverride ?: ctx.path.joinToString("."))
ctx.builder.translation(langKey)
configValue = getConfigValue(ctx.path.last(), ctx.builder)
}
var langPrefixOverride: String? = null
fun lang(prefix: String) = apply { langPrefixOverride = prefix }
}
class DelegatingBooleanValue(val defaultValue: Boolean) : ConfigDelegate<Boolean>() {
override fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder) = builder.define(name, defaultValue)
}
class DelegatingIntValue(
val minValue: Int = 0,
val maxValue: Int = 1,
val defaultValue: Int = 0
) : ConfigDelegate<Int>() {
override fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder) = builder.defineInRange(name, defaultValue, minValue, maxValue)
}
class DelegatingLongValue(
val minValue: Long = 0,
val maxValue: Long = 1,
val defaultValue: Long = 0
) : ConfigDelegate<Long>() {
override fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder) = builder.defineInRange(name, defaultValue, minValue, maxValue)
}
class DelegatingDoubleValue(
val minValue: Double = 0.0,
val maxValue: Double = 1.0,
val defaultValue: Double = 0.0
) : ConfigDelegate<Double>() {
override fun getConfigValue(name: String, builder: ForgeConfigSpec.Builder) = builder.defineInRange(name, defaultValue, minValue, maxValue)
}
// ============================
// Delegate factory methods
// ============================
fun double(min: Double = 0.0, max: Double = 1.0, default: Double) = DelegatingDoubleValue(min, max, default)
fun int(min: Int = 0, max: Int, default: Int) = DelegatingIntValue(min, max, default)
fun long(min: Long = 0, max: Long, default: Long) = DelegatingLongValue(min, max, default)
fun boolean(default: Boolean) = DelegatingBooleanValue(default)

View File

@@ -0,0 +1,158 @@
package mods.betterfoliage.config
import mods.betterfoliage.BetterFoliageMod
import java.util.Random
fun featureEnable(default: Boolean = true) = boolean(default, langKey = recurring)
val Config get() = BetterFoliageMod.config
abstract class PopulationConfigGroup : DelegatingConfigGroup() {
abstract val enabled: Boolean
abstract val population: Int
fun enabled(random: Random) = random.nextInt(64) < population && enabled
}
class MainConfig : DelegatingConfigGroup() {
val enabled by boolean(true, langKey = { "betterfoliage.global.enabled" })
val nVidia by boolean(false)
val leaves by subNode(::LeavesConfig)
val shortGrass by subNode(::ShortGrassConfig)
val connectedGrass by subNode(::ConnectedGrassConfig)
val roundLogs by subNode(::RoundLogConfig)
val cactus by subNode(::CactusConfig)
val lilypad by subNode(::LilypadConfig)
val reed by subNode(::ReedConfig)
val algae by subNode(::AlgaeConfig)
val coral by subNode(::CoralConfig)
val netherrack by subNode(::NetherrackConfig)
val fallingLeaves by subNode(::FallingLeavesConfig)
val risingSoul by subNode(::RisingSoulConfig)
}
class LeavesConfig : DelegatingConfigGroup() {
val enabled by featureEnable()
val snowEnabled by boolean(true)
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
val vOffset by double(max=0.4, default=0.1, langKey = recurring)
val size by double(min=0.75, max=2.5, default=1.4, langKey = recurring)
val dense by boolean(false)
val hideInternal by boolean(true)
val saturationThreshold by double(default=0.1, langKey = recurring)
}
class ShortGrassConfig : PopulationConfigGroup() {
override val enabled by featureEnable()
val grassEnabled by boolean(true)
val myceliumEnabled by boolean(true)
val snowEnabled by boolean(true)
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
val heightMin by double(min=0.1, max=2.5, default=0.6, langKey = recurring)
val heightMax by double(min=0.1, max=2.5, default=0.8, langKey = recurring)
val size by double(min=0.5, max=1.5, default=1.0, langKey = recurring)
override val population by integer(max=64, default=64, langKey = recurring)
val useGenerated by boolean(false)
val shaderWind by boolean(true, langKey = recurring)
val saturationThreshold by double(default=0.1, langKey = recurring)
}
class ConnectedGrassConfig : DelegatingConfigGroup() {
val enabled by boolean(true)
val snowEnabled by boolean(false)
}
class RoundLogConfig : DelegatingConfigGroup() {
val enabled by featureEnable()
val plantsOnly by boolean(true)
val radiusSmall by double(max=0.5, default=0.25)
val radiusLarge by double(max=0.5, default=0.44)
val dimming by double(default = 0.7)
val connectSolids by boolean(false)
val lenientConnect by boolean(true)
val connectPerpendicular by boolean(true)
val connectGrass by boolean(true)
val defaultY by boolean(false)
val zProtection by double(min = 0.9, default = 0.99)
}
class CactusConfig : DelegatingConfigGroup() {
val enabled by featureEnable()
val size by double(min=0.5, max=1.5, default=0.8, langKey = recurring)
val sizeVariation by double(max=0.5, default=0.1)
val hOffset by double(max=0.5, default=0.1, langKey = recurring)
}
class LilypadConfig : PopulationConfigGroup() {
override val enabled by featureEnable()
val hOffset by double(max=0.25, default=0.1, langKey = recurring)
override val population by integer(max=64, default=16, min=0, langKey = recurring)
val shaderWind by boolean(true, langKey = recurring)
}
class ReedConfig : PopulationConfigGroup() {
override val enabled by featureEnable()
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
val heightMin by double(min=1.5, max=3.5, default=1.7, langKey = recurring)
val heightMax by double(min=1.5, max=3.5, default=2.2, langKey = recurring)
override val population by integer(max=64, default=32, langKey = recurring)
val minBiomeTemp by double(default=0.4)
val minBiomeRainfall by double(default=0.4)
val shaderWind by boolean(true, langKey = recurring)
}
class AlgaeConfig : PopulationConfigGroup() {
override val enabled by featureEnable()
val hOffset by double(max=0.25, default=0.1, langKey = recurring)
val size by double(min=0.5, max=1.5, default=1.0, langKey = recurring)
val heightMin by double(min=0.1, max=1.5, default=0.5, langKey = recurring)
val heightMax by double(min=0.1, max=1.5, default=1.0, langKey = recurring)
override val population by integer(max=64, default=48, langKey = recurring)
val shaderWind by boolean(true, langKey = recurring)
}
class CoralConfig : PopulationConfigGroup() {
override val enabled by featureEnable()
val shallowWater by boolean(false)
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
val vOffset by double(max=0.4, default=0.1, langKey = recurring)
val size by double(min=0.5, max=1.5, default=0.7, langKey = recurring)
val crustSize by double(min=0.5, max=1.5, default=1.4)
val chance by integer(max=64, default=32)
override val population by integer(max=64, default=48, langKey = recurring)
}
class NetherrackConfig : DelegatingConfigGroup() {
val enabled by featureEnable()
val hOffset by double(max=0.4, default=0.2, langKey = recurring)
val heightMin by double(min=0.1, max=1.5, default=0.6, langKey = recurring)
val heightMax by double(min=0.1, max=1.5, default=0.8, langKey = recurring)
val size by double(min=0.5, max=1.5, default=1.0, langKey = recurring)
}
class FallingLeavesConfig : DelegatingConfigGroup() {
val enabled by featureEnable()
val speed by double(min=0.01, max=0.15, default=0.05)
val windStrength by double(min=0.1, max=2.0, default=0.5)
val stormStrength by double(min=0.1, max=2.0, default=0.8)
val size by double(min=0.25, max=1.5, default=0.75, langKey = recurring)
val chance by double(min=0.001, max=1.0, default=0.02)
val perturb by double(min=0.01, max=1.0, default=0.25)
val lifetime by double(min=1.0, max=15.0, default=5.0)
val opacityHack by boolean(true)
}
class RisingSoulConfig : DelegatingConfigGroup() {
val enabled by featureEnable()
val chance by double(min=0.001, max=1.0, default=0.02)
val perturb by double(min=0.01, max=0.25, default=0.05)
val headSize by double(min=0.25, max=1.5, default=1.0)
val trailSize by double(min=0.25, max=1.5, default=0.75)
val opacity by double(min=0.05, max=1.0, default=0.5)
val sizeDecay by double(min=0.5, max=1.0, default=0.97)
val opacityDecay by double(min=0.5, max=1.0, default=0.97)
val lifetime by double(min=1.0, max=15.0, default=4.0)
val trailLength by integer(min=2, max=128, default=48)
val trailDensity by integer(min=1, max=16, default=3)
}

View File

@@ -0,0 +1,20 @@
package mods.betterfoliage.config
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.block.material.Material
import net.minecraft.world.biome.Biome
val CACTUS_BLOCKS = listOf(Blocks.CACTUS)
val DIRT_BLOCKS = listOf(Blocks.DIRT, Blocks.COARSE_DIRT, Blocks.PODZOL)
val SAND_BLOCKS = listOf(Blocks.SAND, Blocks.RED_SAND)
val NETHERRACK_BLOCKS = listOf(Blocks.NETHERRACK)
val LILYPAD_BLOCKS = listOf(Blocks.LILY_PAD)
val MYCELIUM_BLOCKS = listOf(Blocks.MYCELIUM)
val SALTWATER_BIOMES = listOf(Biome.Category.BEACH, Biome.Category.OCEAN)
val SNOW_MATERIALS = listOf(Material.TOP_SNOW, Material.SNOW)
val BlockState.isSnow: Boolean get() = material in SNOW_MATERIALS
val ACCEPTED_ROUND_LOG_MATERIALS = listOf(Material.WOOD, Material.GRASS)

View File

@@ -34,7 +34,7 @@ object OptifineCustomColors {
val fakeQuad = BakedQuad(IntArray(0), 1, UP, null, true) val fakeQuad = BakedQuad(IntArray(0), 1, UP, null, true)
fun getBlockColor(ctx: BlockCtx, resolver: ColorResolver): Int { fun getBlockColor(ctx: BlockCtx, resolver: ColorResolver): Int {
val ofColor = if (isColorAvailable && Minecraft.getInstance().gameSettings.reflectField<Boolean>("ofCustomColors") == true) { val ofColor = if (isColorAvailable && Minecraft.getInstance().options.reflectField<Boolean>("ofCustomColors") == true) {
renderEnv.reset(ctx.state, ctx.pos) renderEnv.reset(ctx.state, ctx.pos)
CustomColors.getColorMultiplier.invokeStatic(fakeQuad, ctx.state, ctx.world, ctx.pos, renderEnv.wrapped) as? Int CustomColors.getColorMultiplier.invokeStatic(fakeQuad, ctx.state, ctx.world, ctx.pos, renderEnv.wrapped) as? Int
} else null } else null

View File

@@ -1,48 +1,75 @@
package mods.betterfoliage.integration package mods.betterfoliage.integration
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.render.pipeline.RenderCtxBase import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.render.pipeline.RenderCtxForge
import mods.betterfoliage.render.pipeline.RenderCtxVanilla import mods.betterfoliage.render.pipeline.RenderCtxVanilla
import mods.betterfoliage.resource.discovery.BakeWrapperManager
import mods.betterfoliage.util.HasLogger import mods.betterfoliage.util.HasLogger
import mods.betterfoliage.util.allAvailable import mods.betterfoliage.util.allAvailable
import mods.betterfoliage.util.get import mods.betterfoliage.util.get
import mods.betterfoliage.util.mapArray
import mods.octarinecore.* import mods.octarinecore.*
import net.minecraft.block.BlockRenderType import net.minecraft.block.BlockRenderType
import net.minecraft.block.BlockRenderType.MODEL import net.minecraft.block.BlockRenderType.MODEL
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Blocks import net.minecraft.block.Blocks
import net.minecraft.client.renderer.BufferBuilder import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.util.Direction
import net.minecraft.util.Direction.DOWN
import net.minecraft.util.Direction.EAST
import net.minecraft.util.Direction.NORTH
import net.minecraft.util.Direction.SOUTH
import net.minecraft.util.Direction.WEST
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader import net.minecraft.world.IBlockDisplayReader
import net.minecraftforge.client.model.pipeline.LightUtil
import org.apache.logging.log4j.Level.INFO import org.apache.logging.log4j.Level.INFO
/** /**
* Integration for ShadersMod. * Integration for ShadersMod.
*/ */
object ShadersModIntegration : HasLogger() { object ShadersModIntegration : HasLogger() {
@JvmStatic val isAvailable = allAvailable(SVertexBuilder, SVertexBuilder.pushState, SVertexBuilder.popState, BlockAliases.getAliasBlockId) @JvmStatic val isEffectsAvailable = allAvailable(SVertexBuilder.pushState, SVertexBuilder.popState, BlockAliases.getAliasBlockId)
@JvmStatic val isDiffuseAvailable = allAvailable(Shaders.shaderPackLoaded, Shaders.blockLightLevel05, Shaders.blockLightLevel06, Shaders.blockLightLevel08)
val defaultLeaves = Blocks.OAK_LEAVES.defaultState @JvmStatic val defaultLeaves = Blocks.OAK_LEAVES.defaultBlockState()
val defaultGrass = Blocks.GRASS.defaultState @JvmStatic val defaultGrass = Blocks.GRASS.defaultBlockState()
@JvmStatic var diffuseShades = Direction.values().mapArray { LightUtil.diffuseLight(it) }
/** /**
* Called from transformed ShadersMod code. * Called from transformed ShadersMod code.
* @see mods.betterfoliage.loader.BetterFoliageTransformer * @see mods.betterfoliage.loader.BetterFoliageTransformer
*/ */
@JvmStatic fun getBlockStateOverride(state: BlockState, world: ILightReader, pos: BlockPos): BlockState { @JvmStatic fun getBlockStateOverride(state: BlockState, world: IBlockDisplayReader, pos: BlockPos): BlockState {
// if (LeafRegistry[state, world, pos] != null) return defaultLeaves // if (LeafRegistry[state, world, pos] != null) return defaultLeaves
// if (BlockConfig.crops.matchesClass(state.block)) return defaultGrass // if (BlockConfig.crops.matchesClass(state.block)) return defaultGrass
return state return state
} }
init { init {
logger.log(INFO, "ShadersMod integration is ${if (isAvailable) "enabled" else "disabled" }") logger.log(INFO, "ShadersMod diffuse shading integration is ${if (isDiffuseAvailable) "enabled" else "disabled" }")
logger.log(INFO, "ShadersMod vertex shader integration is ${if (isEffectsAvailable) "enabled" else "disabled" }")
// Recalculate the diffsuse shading values used when resources are reloaded
if (isDiffuseAvailable) BakeWrapperManager.onInvalidate {
if (Shaders.shaderPackLoaded.getStatic()) {
diffuseShades = Direction.values().mapArray { face ->
when(face) {
DOWN -> Shaders.blockLightLevel05.getStatic()
WEST, EAST -> Shaders.blockLightLevel06.getStatic()
NORTH, SOUTH -> Shaders.blockLightLevel08.getStatic()
else -> LightUtil.diffuseLight(face)
}
}
} else {
diffuseShades = Direction.values().mapArray { LightUtil.diffuseLight(it) }
}
}
} }
/** Quads rendered inside this block will use the given block entity data in shader programs. */ /** Quads rendered inside this block will use the given block entity data in shader programs. */
inline fun renderAs(buffer: BufferBuilder, state: BlockState, renderType: BlockRenderType, enabled: Boolean = true, func: ()->Unit) { inline fun renderAs(buffer: BufferBuilder, state: BlockState, renderType: BlockRenderType, enabled: Boolean = true, func: ()->Unit) {
if (isAvailable && enabled) { if (isEffectsAvailable && enabled) {
val aliasBlockId = BlockAliases.getAliasBlockId.invokeStatic(state) val aliasBlockId = BlockAliases.getAliasBlockId.invokeStatic(state)
val sVertexBuilder = buffer[BufferBuilder_sVertexBuilder] val sVertexBuilder = buffer[BufferBuilder_sVertexBuilder]
SVertexBuilder.pushState.invoke(sVertexBuilder, aliasBlockId) SVertexBuilder.pushState.invoke(sVertexBuilder, aliasBlockId)

View File

@@ -68,8 +68,8 @@ fun List<Quad>.bake(applyDiffuseLighting: Boolean) = map { quad ->
) )
// don't fill lightmap UV coords // don't fill lightmap UV coords
element.usage == VertexFormatElement.Usage.UV && element.type == VertexFormatElement.Type.FLOAT -> builder.put(idx, element.usage == VertexFormatElement.Usage.UV && element.type == VertexFormatElement.Type.FLOAT -> builder.put(idx,
quad.sprite.minU + (quad.sprite.maxU - quad.sprite.minU) * (vertex.uv.u + 0.5).toFloat(), quad.sprite.u0 + (quad.sprite.u1 - quad.sprite.u0) * (vertex.uv.u + 0.5).toFloat(),
quad.sprite.minV + (quad.sprite.maxV - quad.sprite.minV) * (vertex.uv.v + 0.5).toFloat(), quad.sprite.v0 + (quad.sprite.v1 - quad.sprite.v0) * (vertex.uv.v + 0.5).toFloat(),
0.0f, 1.0f 0.0f, 1.0f
) )
element.usage == VertexFormatElement.Usage.COLOR -> builder.put(idx, element.usage == VertexFormatElement.Usage.COLOR -> builder.put(idx,
@@ -96,18 +96,18 @@ fun Array<List<Quad>>.bake(applyDiffuseLighting: Boolean) = mapArray { it.bake(a
fun BakedQuad.unbake(): HalfBakedQuad { fun BakedQuad.unbake(): HalfBakedQuad {
val size = DefaultVertexFormats.BLOCK.integerSize val size = DefaultVertexFormats.BLOCK.integerSize
val verts = Array(4) { vIdx -> val verts = Array(4) { vIdx ->
val x = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 0]) val x = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 0]) - 0.5f
val y = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 1]) val y = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 1]) - 0.5f
val z = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 2]) val z = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 2]) - 0.5f
val color = vertexData[vIdx * size + 3] val color = vertices[vIdx * size + 3]
val u = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 4]) val u = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 4])
val v = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 5]) val v = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 5])
Vertex(Double3(x, y, z), UV(u.toDouble(), v.toDouble()), Color(color)) Vertex(Double3(x, y, z), UV(u.toDouble(), v.toDouble()), Color(color))
} }
val unbaked = Quad( val unbaked = Quad(
verts[0], verts[1], verts[2], verts[3], verts[0], verts[1], verts[2], verts[3],
colorIndex = if (hasTintIndex()) tintIndex else -1, colorIndex = if (isTinted) tintIndex else -1,
face = face face = direction
) )
return HalfBakedQuad(unbaked, this) return HalfBakedQuad(unbaked, this)
} }

View File

@@ -1,17 +1,9 @@
package mods.betterfoliage.model package mods.betterfoliage.model
import mods.betterfoliage.render.pipeline.RenderCtxBase import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.util.HasLogger
import net.minecraft.client.renderer.model.IBakedModel import net.minecraft.client.renderer.model.IBakedModel
import net.minecraft.client.renderer.model.Material
import net.minecraft.client.renderer.model.ModelBakery
import net.minecraft.client.renderer.model.VariantList
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.ResourceLocation
import net.minecraft.util.WeightedRandom import net.minecraft.util.WeightedRandom
import org.apache.logging.log4j.Level.WARN
import java.util.Random import java.util.Random
import java.util.function.Function
/** /**
* Model that makes use of advanced rendering features. * Model that makes use of advanced rendering features.
@@ -24,9 +16,9 @@ class WeightedModelWrapper(
val models: List<WeightedModel>, baseModel: SpecialRenderModel val models: List<WeightedModel>, baseModel: SpecialRenderModel
): IBakedModel by baseModel, SpecialRenderModel { ): IBakedModel by baseModel, SpecialRenderModel {
class WeightedModel(val model: SpecialRenderModel, weight: Int) : WeightedRandom.Item(weight) class WeightedModel(val model: SpecialRenderModel, weight: Int) : WeightedRandom.Item(weight)
val totalWeight = models.sumBy { it.itemWeight } val totalWeight = models.sumBy { it.weight }
fun getModel(random: Random) = WeightedRandom.getRandomItem(models, random.nextInt(totalWeight)) fun getModel(random: Random) = WeightedRandom.getWeightedItem(models, random.nextInt(totalWeight))
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) { override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
getModel(ctx.random).model.render(ctx, noDecorations) getModel(ctx.random).model.render(ctx, noDecorations)

View File

@@ -59,7 +59,7 @@ class SpriteSetDelegate(
@SubscribeEvent @SubscribeEvent
fun handlePreStitch(event: TextureStitchEvent.Pre) { fun handlePreStitch(event: TextureStitchEvent.Pre) {
if (event.map.textureLocation != Atlas.BLOCKS.resourceId) return if (event.map.location() != atlas.resourceId) return
spriteSet = null spriteSet = null
idList = (0 until 16) idList = (0 until 16)
.map(idFunc) .map(idFunc)

View File

@@ -2,6 +2,7 @@ package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.BetterFoliage import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.config.CACTUS_BLOCKS
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.model.HalfBakedSpecialWrapper import mods.betterfoliage.model.HalfBakedSpecialWrapper
import mods.betterfoliage.model.HalfBakedWrapperKey import mods.betterfoliage.model.HalfBakedWrapperKey
@@ -33,8 +34,6 @@ import net.minecraft.util.Direction.DOWN
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
object StandardCactusDiscovery : AbstractModelDiscovery() { object StandardCactusDiscovery : AbstractModelDiscovery() {
val CACTUS_BLOCKS = listOf(Blocks.CACTUS)
override fun processModel(ctx: ModelDiscoveryContext) { override fun processModel(ctx: ModelDiscoveryContext) {
val model = ctx.getUnbaked() val model = ctx.getUnbaked()
if (model is BlockModel && ctx.blockState.block in CACTUS_BLOCKS) { if (model is BlockModel && ctx.blockState.block in CACTUS_BLOCKS) {

View File

@@ -1,8 +1,12 @@
package mods.betterfoliage.render.block.vanilla package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.BetterFoliage import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.config.DIRT_BLOCKS
import mods.betterfoliage.config.SALTWATER_BIOMES
import mods.betterfoliage.config.isSnow
import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.model.HalfBakedSpecialWrapper import mods.betterfoliage.model.HalfBakedSpecialWrapper
import mods.betterfoliage.model.HalfBakedWrapperKey import mods.betterfoliage.model.HalfBakedWrapperKey
import mods.betterfoliage.model.SpecialRenderModel import mods.betterfoliage.model.SpecialRenderModel
@@ -12,7 +16,6 @@ import mods.betterfoliage.model.tuftModelSet
import mods.betterfoliage.model.tuftShapeSet import mods.betterfoliage.model.tuftShapeSet
import mods.betterfoliage.render.lighting.LightingPreferredFace import mods.betterfoliage.render.lighting.LightingPreferredFace
import mods.betterfoliage.render.pipeline.RenderCtxBase import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.render.pipeline.RenderCtxVanilla
import mods.betterfoliage.resource.discovery.AbstractModelDiscovery import mods.betterfoliage.resource.discovery.AbstractModelDiscovery
import mods.betterfoliage.resource.discovery.BakeWrapperManager import mods.betterfoliage.resource.discovery.BakeWrapperManager
import mods.betterfoliage.resource.discovery.ModelBakingContext import mods.betterfoliage.resource.discovery.ModelBakingContext
@@ -24,22 +27,18 @@ import mods.betterfoliage.util.LazyInvalidatable
import mods.betterfoliage.util.get import mods.betterfoliage.util.get
import mods.betterfoliage.util.offset import mods.betterfoliage.util.offset
import mods.betterfoliage.util.randomI import mods.betterfoliage.util.randomI
import net.minecraft.block.Blocks
import net.minecraft.block.material.Material import net.minecraft.block.material.Material
import net.minecraft.client.renderer.RenderType import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.RenderTypeLookup import net.minecraft.client.renderer.RenderTypeLookup
import net.minecraft.client.renderer.model.BlockModel import net.minecraft.client.renderer.model.BlockModel
import net.minecraft.util.Direction.UP import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
import net.minecraft.world.biome.Biome
object StandardDirtDiscovery : AbstractModelDiscovery() { object StandardDirtDiscovery : AbstractModelDiscovery() {
val DIRT_BLOCKS = listOf(Blocks.DIRT, Blocks.COARSE_DIRT, Blocks.PODZOL)
fun canRenderInLayer(layer: RenderType) = when { fun canRenderInLayer(layer: RenderType) = when {
!Config.enabled -> layer == RenderType.getSolid() !Config.enabled -> layer == RenderType.solid()
!Config.connectedGrass.enabled && !Config.algae.enabled && !Config.reed.enabled -> layer == RenderType.getSolid() !Config.connectedGrass.enabled && !Config.algae.enabled && !Config.reed.enabled -> layer == RenderType.solid()
else -> layer == RenderType.getCutoutMipped() else -> layer == RenderType.cutoutMipped()
} }
override fun processModel(ctx: ModelDiscoveryContext) { override fun processModel(ctx: ModelDiscoveryContext) {
@@ -64,10 +63,14 @@ class StandardDirtModel(
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) { override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
if (!Config.enabled || noDecorations) return super.render(ctx, noDecorations) if (!Config.enabled || noDecorations) return super.render(ctx, noDecorations)
val stateUp = ctx.offset(UP).state val stateUp = ctx.state(UP)
val isConnectedGrass = Config.connectedGrass.enabled && stateUp in BetterFoliage.blockTypes.grass val state2Up = ctx.state(Int3(0, 2, 0))
val isConnectedGrass = Config.connectedGrass.enabled &&
stateUp in BetterFoliage.blockTypes.grass &&
(Config.connectedGrass.snowEnabled || !state2Up.isSnow)
if (isConnectedGrass) { if (isConnectedGrass) {
(ctx.blockModelShapes.getModel(stateUp) as? SpecialRenderModel)?.let { grassModel -> (ctx.blockModelShapes.getBlockModel(stateUp) as? SpecialRenderModel)?.let { grassModel ->
ctx.renderMasquerade(UP.offset) { ctx.renderMasquerade(UP.offset) {
grassModel.render(ctx, true) grassModel.render(ctx, true)
} }
@@ -79,22 +82,24 @@ class StandardDirtModel(
super.render(ctx, false) super.render(ctx, false)
val isWater = stateUp.material == Material.WATER val isWater = stateUp.material == Material.WATER
val isDeepWater = isWater && ctx.offset(Int3(2 to UP)).state.material == Material.WATER val isDeepWater = isWater && state2Up.material == Material.WATER
val isShallowWater = isWater && ctx.offset(Int3(2 to UP)).state.isAir val isShallowWater = isWater && state2Up.isAir
val isSaltWater = isWater && ctx.biome?.category in SALTWATER_BIOMES val isSaltWater = isWater && ctx.biome?.biomeCategory in SALTWATER_BIOMES
if (Config.algae.enabled(ctx.random) && isDeepWater) { if (Config.algae.enabled(ctx.random) && isDeepWater) {
(ctx as? RenderCtxVanilla)?.vertexLighter = vanillaTuftLighting ctx.vertexLighter = vanillaTuftLighting
ShadersModIntegration.grass(ctx, Config.algae.shaderWind) {
ctx.renderQuads(algaeModels[ctx.random]) ctx.renderQuads(algaeModels[ctx.random])
}
} else if (Config.reed.enabled(ctx.random) && isShallowWater && !isSaltWater) { } else if (Config.reed.enabled(ctx.random) && isShallowWater && !isSaltWater) {
(ctx as? RenderCtxVanilla)?.vertexLighter = vanillaTuftLighting ctx.vertexLighter = vanillaTuftLighting
ShadersModIntegration.grass(ctx, Config.reed.shaderWind) {
ctx.renderQuads(reedModels[ctx.random]) ctx.renderQuads(reedModels[ctx.random])
} }
} }
}
companion object { companion object {
val SALTWATER_BIOMES = listOf(Biome.Category.BEACH, Biome.Category.OCEAN)
val algaeSprites by SpriteSetDelegate(Atlas.BLOCKS) { idx -> val algaeSprites by SpriteSetDelegate(Atlas.BLOCKS) { idx ->
ResourceLocation(BetterFoliageMod.MOD_ID, "blocks/better_algae_$idx") ResourceLocation(BetterFoliageMod.MOD_ID, "blocks/better_algae_$idx")
} }

View File

@@ -1,9 +1,10 @@
package mods.betterfoliage.render.block.vanilla package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.BetterFoliage import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.config.BlockConfig import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.config.isSnow
import mods.betterfoliage.integration.ShadersModIntegration import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.model.Color import mods.betterfoliage.model.Color
import mods.betterfoliage.model.HalfBakedSpecialWrapper import mods.betterfoliage.model.HalfBakedSpecialWrapper
@@ -28,7 +29,6 @@ import mods.betterfoliage.util.LazyMapInvalidatable
import mods.betterfoliage.util.averageColor import mods.betterfoliage.util.averageColor
import mods.betterfoliage.util.colorOverride import mods.betterfoliage.util.colorOverride
import mods.betterfoliage.util.get import mods.betterfoliage.util.get
import mods.betterfoliage.util.isSnow
import mods.betterfoliage.util.logColorOverride import mods.betterfoliage.util.logColorOverride
import mods.betterfoliage.util.randomI import mods.betterfoliage.util.randomI
import net.minecraft.util.Direction.DOWN import net.minecraft.util.Direction.DOWN
@@ -87,7 +87,7 @@ class StandardGrassModel(
super.render(ctx, noDecorations) super.render(ctx, noDecorations)
} }
if (Config.shortGrass.enabled(ctx.random) && (isAir || isSnowed)) { if (Config.shortGrass.enabled(ctx.random) && Config.shortGrass.grassEnabled && (isAir || isSnowed)) {
ctx.vertexLighter = tuftLighting ctx.vertexLighter = tuftLighting
ShadersModIntegration.grass(ctx, Config.shortGrass.shaderWind) { ShadersModIntegration.grass(ctx, Config.shortGrass.shaderWind) {
ctx.renderQuads(if (isSnowed) tuftSnowed[ctx.random] else tuftNormal[ctx.random]) ctx.renderQuads(if (isSnowed) tuftSnowed[ctx.random] else tuftNormal[ctx.random])

View File

@@ -1,9 +1,11 @@
package mods.betterfoliage.render.block.vanilla package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.BetterFoliage import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.config.BlockConfig import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.config.isSnow
import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.model.Color import mods.betterfoliage.model.Color
import mods.betterfoliage.model.HalfBakedSpecialWrapper import mods.betterfoliage.model.HalfBakedSpecialWrapper
import mods.betterfoliage.model.HalfBakedWrapperKey import mods.betterfoliage.model.HalfBakedWrapperKey
@@ -27,7 +29,6 @@ import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.LazyMapInvalidatable import mods.betterfoliage.util.LazyMapInvalidatable
import mods.betterfoliage.util.averageColor import mods.betterfoliage.util.averageColor
import mods.betterfoliage.util.colorOverride import mods.betterfoliage.util.colorOverride
import mods.betterfoliage.util.isSnow
import mods.betterfoliage.util.logColorOverride import mods.betterfoliage.util.logColorOverride
import net.minecraft.util.Direction.UP import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
@@ -72,6 +73,7 @@ class StandardLeafModel(
val leafSnowed by leafModelsSnowed.delegate(key) val leafSnowed by leafModelsSnowed.delegate(key)
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) { override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
ShadersModIntegration.leaves(ctx, true) {
super.render(ctx, noDecorations) super.render(ctx, noDecorations)
if (!Config.enabled || !Config.leaves.enabled || noDecorations) return if (!Config.enabled || !Config.leaves.enabled || noDecorations) return
@@ -80,6 +82,7 @@ class StandardLeafModel(
ctx.renderQuads(leafNormal[leafIdx]) ctx.renderQuads(leafNormal[leafIdx])
if (ctx.state(UP).isSnow) ctx.renderQuads(leafSnowed[leafIdx]) if (ctx.state(UP).isSnow) ctx.renderQuads(leafSnowed[leafIdx])
} }
}
companion object { companion object {
val leafSpritesSnowed by SpriteSetDelegate(Atlas.BLOCKS) { idx -> val leafSpritesSnowed by SpriteSetDelegate(Atlas.BLOCKS) { idx ->

View File

@@ -2,6 +2,7 @@ package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.config.LILYPAD_BLOCKS
import mods.betterfoliage.integration.ShadersModIntegration import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.model.HalfBakedSpecialWrapper import mods.betterfoliage.model.HalfBakedSpecialWrapper
import mods.betterfoliage.model.HalfBakedWrapperKey import mods.betterfoliage.model.HalfBakedWrapperKey
@@ -28,8 +29,6 @@ import net.minecraft.util.Direction.DOWN
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
object StandardLilypadDiscovery : AbstractModelDiscovery() { object StandardLilypadDiscovery : AbstractModelDiscovery() {
val LILYPAD_BLOCKS = listOf(Blocks.LILY_PAD)
override fun processModel(ctx: ModelDiscoveryContext) { override fun processModel(ctx: ModelDiscoveryContext) {
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in LILYPAD_BLOCKS) { if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in LILYPAD_BLOCKS) {
ctx.addReplacement(StandardLilypadKey) ctx.addReplacement(StandardLilypadKey)

View File

@@ -2,6 +2,7 @@ package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.config.MYCELIUM_BLOCKS
import mods.betterfoliage.model.HalfBakedSpecialWrapper import mods.betterfoliage.model.HalfBakedSpecialWrapper
import mods.betterfoliage.model.HalfBakedWrapperKey import mods.betterfoliage.model.HalfBakedWrapperKey
import mods.betterfoliage.model.SpecialRenderModel import mods.betterfoliage.model.SpecialRenderModel
@@ -27,12 +28,10 @@ import net.minecraft.util.Direction
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
object StandardMyceliumDiscovery : AbstractModelDiscovery() { object StandardMyceliumDiscovery : AbstractModelDiscovery() {
val MYCELIUM_BLOCKS = listOf(Blocks.MYCELIUM)
override fun processModel(ctx: ModelDiscoveryContext) { override fun processModel(ctx: ModelDiscoveryContext) {
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in MYCELIUM_BLOCKS) { if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in MYCELIUM_BLOCKS) {
ctx.addReplacement(StandardMyceliumKey) ctx.addReplacement(StandardMyceliumKey)
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutout()) RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutout())
} }
super.processModel(ctx) super.processModel(ctx)
} }
@@ -51,9 +50,8 @@ class StandardMyceliumModel(
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) { override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
super.render(ctx, noDecorations) super.render(ctx, noDecorations)
if (Config.shortGrass.enabled && if (Config.shortGrass.enabled(ctx.random) &&
Config.shortGrass.myceliumEnabled && Config.shortGrass.myceliumEnabled &&
Config.shortGrass.enabled(ctx.random) &&
ctx.state(Direction.UP).isAir(ctx.world, ctx.pos) ctx.state(Direction.UP).isAir(ctx.world, ctx.pos)
) { ) {
ctx.vertexLighter = tuftLighting ctx.vertexLighter = tuftLighting

View File

@@ -3,6 +3,7 @@ package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.BetterFoliage import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.config.NETHERRACK_BLOCKS
import mods.betterfoliage.model.HalfBakedSpecialWrapper import mods.betterfoliage.model.HalfBakedSpecialWrapper
import mods.betterfoliage.model.HalfBakedWrapperKey import mods.betterfoliage.model.HalfBakedWrapperKey
import mods.betterfoliage.model.SpecialRenderModel import mods.betterfoliage.model.SpecialRenderModel
@@ -30,12 +31,10 @@ import net.minecraft.util.Direction.DOWN
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
object StandardNetherrackDiscovery : AbstractModelDiscovery() { object StandardNetherrackDiscovery : AbstractModelDiscovery() {
val NETHERRACK_BLOCKS = listOf(Blocks.NETHERRACK)
fun canRenderInLayer(layer: RenderType) = when { fun canRenderInLayer(layer: RenderType) = when {
!Config.enabled -> layer == RenderType.getSolid() !Config.enabled -> layer == RenderType.solid()
!Config.netherrack.enabled -> layer == RenderType.getSolid() !Config.netherrack.enabled -> layer == RenderType.solid()
else -> layer == RenderType.getCutoutMipped() else -> layer == RenderType.cutoutMipped()
} }
override fun processModel(ctx: ModelDiscoveryContext) { override fun processModel(ctx: ModelDiscoveryContext) {

View File

@@ -1,9 +1,9 @@
package mods.betterfoliage.render.block.vanilla package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliage import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.config.ACCEPTED_ROUND_LOG_MATERIALS
import mods.betterfoliage.config.BlockConfig import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.resource.discovery.ModelTextureList
import mods.betterfoliage.model.HalfBakedWrapperKey import mods.betterfoliage.model.HalfBakedWrapperKey
import mods.betterfoliage.model.SpecialRenderModel import mods.betterfoliage.model.SpecialRenderModel
import mods.betterfoliage.render.column.ColumnBlockKey import mods.betterfoliage.render.column.ColumnBlockKey
@@ -16,11 +16,12 @@ import mods.betterfoliage.resource.discovery.ConfigurableModelDiscovery
import mods.betterfoliage.resource.discovery.ModelBakingContext import mods.betterfoliage.resource.discovery.ModelBakingContext
import mods.betterfoliage.resource.discovery.ModelBakingKey import mods.betterfoliage.resource.discovery.ModelBakingKey
import mods.betterfoliage.resource.discovery.ModelDiscoveryContext import mods.betterfoliage.resource.discovery.ModelDiscoveryContext
import mods.betterfoliage.resource.discovery.ModelTextureList
import mods.betterfoliage.util.Atlas import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.LazyMapInvalidatable import mods.betterfoliage.util.LazyMapInvalidatable
import mods.betterfoliage.util.tryDefault import mods.betterfoliage.util.tryDefault
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.LogBlock import net.minecraft.block.RotatedPillarBlock
import net.minecraft.util.Direction.Axis import net.minecraft.util.Direction.Axis
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
import org.apache.logging.log4j.Level.INFO import org.apache.logging.log4j.Level.INFO
@@ -43,13 +44,15 @@ object StandardRoundLogDiscovery : ConfigurableModelDiscovery() {
override fun processModel(ctx: ModelDiscoveryContext, textureMatch: List<ResourceLocation>) { override fun processModel(ctx: ModelDiscoveryContext, textureMatch: List<ResourceLocation>) {
val axis = getAxis(ctx.blockState) val axis = getAxis(ctx.blockState)
detailLogger.log(INFO, " axis $axis")
detailLogger.log(INFO, " axis $axis, material ${ctx.blockState.material}")
if (!Config.roundLogs.plantsOnly || ctx.blockState.material in ACCEPTED_ROUND_LOG_MATERIALS)
ctx.addReplacement(StandardRoundLogKey(axis, textureMatch[0], textureMatch[1])) ctx.addReplacement(StandardRoundLogKey(axis, textureMatch[0], textureMatch[1]))
} }
fun getAxis(state: BlockState): Axis? { fun getAxis(state: BlockState): Axis? {
val axis = tryDefault(null) { state.get(LogBlock.AXIS).toString() } ?: val axis = tryDefault(null) { state.getValue(RotatedPillarBlock.AXIS).toString() } ?:
state.values.entries.find { it.key.getName().toLowerCase() == "axis" }?.value?.toString() state.values.entries.find { it.key.name.toLowerCase() == "axis" }?.value?.toString()
return when (axis) { return when (axis) {
"x" -> Axis.X "x" -> Axis.X
"y" -> Axis.Y "y" -> Axis.Y

View File

@@ -1,8 +1,10 @@
package mods.betterfoliage.render.block.vanilla package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.BetterFoliage import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import mods.betterfoliage.config.SALTWATER_BIOMES
import mods.betterfoliage.config.SAND_BLOCKS
import mods.betterfoliage.model.HalfBakedSpecialWrapper import mods.betterfoliage.model.HalfBakedSpecialWrapper
import mods.betterfoliage.model.HalfBakedWrapperKey import mods.betterfoliage.model.HalfBakedWrapperKey
import mods.betterfoliage.model.Quad import mods.betterfoliage.model.Quad
@@ -13,7 +15,6 @@ import mods.betterfoliage.model.buildTufts
import mods.betterfoliage.model.transform import mods.betterfoliage.model.transform
import mods.betterfoliage.model.tuftModelSet import mods.betterfoliage.model.tuftModelSet
import mods.betterfoliage.model.tuftShapeSet import mods.betterfoliage.model.tuftShapeSet
import mods.betterfoliage.render.block.vanilla.StandardDirtModel.Companion.SALTWATER_BIOMES
import mods.betterfoliage.render.lighting.LightingPreferredFace import mods.betterfoliage.render.lighting.LightingPreferredFace
import mods.betterfoliage.render.pipeline.RenderCtxBase import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.resource.discovery.AbstractModelDiscovery import mods.betterfoliage.resource.discovery.AbstractModelDiscovery
@@ -29,7 +30,6 @@ import mods.betterfoliage.util.mapArray
import mods.betterfoliage.util.randomB import mods.betterfoliage.util.randomB
import mods.betterfoliage.util.randomD import mods.betterfoliage.util.randomD
import mods.betterfoliage.util.randomI import mods.betterfoliage.util.randomI
import net.minecraft.block.Blocks
import net.minecraft.block.material.Material import net.minecraft.block.material.Material
import net.minecraft.client.renderer.RenderType import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.RenderTypeLookup import net.minecraft.client.renderer.RenderTypeLookup
@@ -39,13 +39,11 @@ import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
object StandardSandDiscovery : AbstractModelDiscovery() { object StandardSandDiscovery : AbstractModelDiscovery() {
val SAND_BLOCKS = listOf(Blocks.SAND, Blocks.RED_SAND)
override fun processModel(ctx: ModelDiscoveryContext) { override fun processModel(ctx: ModelDiscoveryContext) {
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in SAND_BLOCKS) { if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in SAND_BLOCKS) {
BetterFoliage.blockTypes.dirt.add(ctx.blockState) BetterFoliage.blockTypes.dirt.add(ctx.blockState)
ctx.addReplacement(StandardSandKey) ctx.addReplacement(StandardSandKey)
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutoutMipped()) RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutoutMipped())
} }
super.processModel(ctx) super.processModel(ctx)
} }
@@ -63,7 +61,7 @@ class StandardSandModel(
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) { override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
super.render(ctx, noDecorations) super.render(ctx, noDecorations)
if (noDecorations || !Config.enabled || !Config.coral.enabled(ctx.random)) return if (noDecorations || !Config.enabled || !Config.coral.enabled(ctx.random)) return
if (ctx.biome?.category !in SALTWATER_BIOMES) return if (ctx.biome?.biomeCategory !in SALTWATER_BIOMES) return
allDirections.filter { ctx.random.nextInt(64) < Config.coral.chance }.forEach { face -> allDirections.filter { ctx.random.nextInt(64) < Config.coral.chance }.forEach { face ->
val isWater = ctx.state(face).material == Material.WATER val isWater = ctx.state(face).material == Material.WATER

View File

@@ -23,7 +23,7 @@ import net.minecraft.block.BlockState
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.Direction.Axis import net.minecraft.util.Direction.Axis
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader import net.minecraft.world.IBlockDisplayReader
/** Index of SOUTH-EAST quadrant. */ /** Index of SOUTH-EAST quadrant. */
const val SE = 0 const val SE = 0
@@ -83,13 +83,13 @@ abstract class ColumnRenderLayer : ChunkOverlayLayer<ColumnLayerData> {
val allNeighborOffsets = (-1..1).flatMap { offsetX -> (-1..1).flatMap { offsetY -> (-1..1).map { offsetZ -> Int3(offsetX, offsetY, offsetZ) }}} val allNeighborOffsets = (-1..1).flatMap { offsetX -> (-1..1).flatMap { offsetY -> (-1..1).map { offsetZ -> Int3(offsetX, offsetY, offsetZ) }}}
override fun onBlockUpdate(world: ILightReader, pos: BlockPos) { override fun onBlockUpdate(world: IBlockDisplayReader, pos: BlockPos) {
allNeighborOffsets.forEach { offset -> ChunkOverlayManager.clear(world.dimType, this, pos + offset) } allNeighborOffsets.forEach { offset -> ChunkOverlayManager.clear(world.dimType, this, pos + offset) }
} }
override fun calculate(ctx: BlockCtx): ColumnLayerData { override fun calculate(ctx: BlockCtx): ColumnLayerData {
// TODO detect round logs // TODO detect round logs
if (allDirections.all { dir -> ctx.offset(dir).let { it.isNormalCube } }) return ColumnLayerData.SkipRender if (allDirections.all { dir -> ctx.offset(dir).let { it.isFullBlock } }) return ColumnLayerData.SkipRender
val columnTextures = getColumnKey(ctx.state) ?: return ColumnLayerData.ResolveError val columnTextures = getColumnKey(ctx.state) ?: return ColumnLayerData.ResolveError
// if log axis is not defined and "Default to vertical" config option is not set, render normally // if log axis is not defined and "Default to vertical" config option is not set, render normally
@@ -185,7 +185,7 @@ abstract class ColumnRenderLayer : ChunkOverlayLayer<ColumnLayerData> {
val offsetRot = offset.rotate(rotation) val offsetRot = offset.rotate(rotation)
val key = getColumnKey(state(offsetRot)) val key = getColumnKey(state(offsetRot))
return if (key == null) { return if (key == null) {
if (offset(offsetRot).isNormalCube) SOLID else NONSOLID if (offset(offsetRot).isFullBlock) SOLID else NONSOLID
} else { } else {
(key.axis ?: if (Config.roundLogs.defaultY) Axis.Y else null)?.let { (key.axis ?: if (Config.roundLogs.defaultY) Axis.Y else null)?.let {
if (it == axis) PARALLEL else PERPENDICULAR if (it == axis) PARALLEL else PERPENDICULAR

View File

@@ -5,7 +5,7 @@ import net.minecraft.block.BlockState
import net.minecraft.client.renderer.BlockModelRenderer import net.minecraft.client.renderer.BlockModelRenderer
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader import net.minecraft.world.IBlockDisplayReader
data class LightingData( data class LightingData(
@JvmField var packedLight: Int = 0, @JvmField var packedLight: Int = 0,
@@ -23,13 +23,17 @@ data class LightingData(
} }
} }
// Vanilla has a very suspicious-looking offset here, which Indigo gets rid of and calls it a fix
// Naturally, we're going to believe Indigo, it's a hardcoded option for now
const val OCCLUSION_OFFSET_FIX = true
/** /**
* Replacement for [BlockModelRenderer.AmbientOcclusionFace] * Replacement for [BlockModelRenderer.AmbientOcclusionFace]
* This gets called on a LOT, so object instantiation is avoided. * This gets called on a LOT, so object instantiation is avoided.
* Not thread-safe, always use a [ThreadLocal] instance * Not thread-safe, always use a [ThreadLocal] instance
*/ */
class VanillaAoCalculator { class VanillaAoCalculator {
lateinit var world: ILightReader lateinit var world: IBlockDisplayReader
/** [blockPos] is used to get block-related information (i.e. tint, opacity, etc.) /** [blockPos] is used to get block-related information (i.e. tint, opacity, etc.)
* [lightPos] is used to get light-related information * [lightPos] is used to get light-related information
@@ -37,7 +41,7 @@ class VanillaAoCalculator {
lateinit var blockPos: BlockPos lateinit var blockPos: BlockPos
lateinit var lightPos: BlockPos lateinit var lightPos: BlockPos
private val probe = LightProbe(BlockModelRenderer.CACHE_COMBINED_LIGHT.get()) private val probe = LightProbe(BlockModelRenderer.CACHE.get())
val isValid = BooleanArray(6) val isValid = BooleanArray(6)
val aoData = Array(24) { LightingData() } val aoData = Array(24) { LightingData() }
@@ -70,13 +74,13 @@ class VanillaAoCalculator {
// Bit 0 of the bitset in vanilla calculations // Bit 0 of the bitset in vanilla calculations
// true if the block model is planar with the block boundary // true if the block model is planar with the block boundary
val isFullBlock = forceFull ?: world.getBlockState(blockPos).isCollisionShapeOpaque(world, blockPos) val isFullBlock = forceFull ?: world.getBlockState(blockPos).isCollisionShapeFullBlock(world, blockPos)
val lightOrigin = if (isFullBlock) lightPos.offset(lightFace) else lightPos val lightOrigin = if (isFullBlock) lightPos.relative(lightFace) else lightPos
// AO calculation for the face center // AO calculation for the face center
probe.position { setPos(lightOrigin) }.writeTo(centerAo) probe.position { set(lightOrigin) }.writeTo(centerAo)
if (!isFullBlock && !probe.position { move(lightFace) }.state.isOpaqueCube(world, probe.pos)) { if (!isFullBlock && !probe.position { move(lightFace) }.state.isSolidRender(world, probe.pos)) {
// if the neighboring block in the lightface direction is // if the neighboring block in the lightface direction is
// transparent (non-opaque), use its packed light instead of our own // transparent (non-opaque), use its packed light instead of our own
// (if our block is a full block, we are already using this value) // (if our block is a full block, we are already using this value)
@@ -86,10 +90,11 @@ class VanillaAoCalculator {
// AO calculation for the 4 sides // AO calculation for the 4 sides
sideHelper.sides.forEachIndexed { sideIdx, sideDir -> sideHelper.sides.forEachIndexed { sideIdx, sideDir ->
// record light data in the block 1 step to the side // record light data in the block 1 step to the side
probe.position { setPos(lightOrigin).move(sideDir) }.writeTo(sideAo[sideIdx]) probe.position { set(lightOrigin).move(sideDir) }.writeTo(sideAo[sideIdx])
// side is considered occluded if the block 1 step to that side and // side is considered occluded if the block 1 step to that side and
// 1 step forward (in the lightface direction) is not fully transparent // 1 step forward (in the lightface direction) is not fully transparent
isOccluded[sideIdx] = probe.position { move(lightFace) }.isNonTransparent if (!OCCLUSION_OFFSET_FIX) probe.position { move(lightFace) }
isOccluded[sideIdx] = probe.isNonTransparent
} }
// AO Calculation for the 4 corners // AO Calculation for the 4 corners
@@ -103,7 +108,7 @@ class VanillaAoCalculator {
else { else {
// lookup actual packed light from the cornering block in the world // lookup actual packed light from the cornering block in the world
probe.position { probe.position {
setPos(lightOrigin) set(lightOrigin)
.move(sideHelper.sides[sideIndices.first]) .move(sideHelper.sides[sideIndices.first])
.move(sideHelper.sides[sideIndices.second]) .move(sideHelper.sides[sideIndices.second])
}.writeTo(cornerAo[cornerIdx]) }.writeTo(cornerAo[cornerIdx])
@@ -129,9 +134,9 @@ class VanillaAoCalculator {
lateinit var state: BlockState lateinit var state: BlockState
val pos = BlockPos.Mutable() val pos = BlockPos.Mutable()
val packedLight: Int get() = cache.getPackedLight(state, world, pos) val packedLight: Int get() = cache.getLightColor(state, world, pos)
val colorMultiplier: Float get() = cache.getBrightness(state, world, pos) val colorMultiplier: Float get() = cache.getShadeBrightness(state, world, pos)
val isNonTransparent: Boolean get() = state.getOpacity(world, pos) > 0 val isNonTransparent: Boolean get() = state.getLightBlock(world, pos) > 0
fun writeTo(data: LightingData) { fun writeTo(data: LightingData) {
data.packedLight = packedLight data.packedLight = packedLight

View File

@@ -1,15 +1,15 @@
package mods.betterfoliage.render.lighting package mods.betterfoliage.render.lighting
import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.model.HalfBakedQuad import mods.betterfoliage.model.HalfBakedQuad
import mods.betterfoliage.util.Double3 import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.EPSILON_ONE import mods.betterfoliage.util.EPSILON_ONE
import mods.betterfoliage.util.EPSILON_ZERO import mods.betterfoliage.util.EPSILON_ZERO
import mods.betterfoliage.util.get
import mods.betterfoliage.util.minBy import mods.betterfoliage.util.minBy
import net.minecraft.client.renderer.color.BlockColors import net.minecraft.client.renderer.color.BlockColors
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.Direction.* import net.minecraft.util.Direction.*
import net.minecraft.util.Direction.Axis
import net.minecraftforge.client.model.pipeline.LightUtil
import kotlin.math.abs import kotlin.math.abs
class VanillaQuadLighting { class VanillaQuadLighting {
@@ -34,7 +34,7 @@ class VanillaQuadLighting {
} }
fun applyDiffuseLighting(face: Direction) { fun applyDiffuseLighting(face: Direction) {
val factor = LightUtil.diffuseLight(face) val factor = ShadersModIntegration.diffuseShades[face]
tint[0] *= factor; tint[1] *= factor; tint[2] *= factor tint[0] *= factor; tint[1] *= factor; tint[2] *= factor
} }
} }
@@ -69,7 +69,7 @@ object VanillaFullBlockLighting : VanillaVertexLighter() {
lighting.calc.fillLightData(face, true) lighting.calc.fillLightData(face, true)
lighting.updateWithCornerAo(quad) { nearestCornerOnFace(it, face) } lighting.updateWithCornerAo(quad) { nearestCornerOnFace(it, face) }
lighting.updateBlockTint(quad.baked.tintIndex) lighting.updateBlockTint(quad.baked.tintIndex)
if (quad.baked.shouldApplyDiffuseLighting()) lighting.applyDiffuseLighting(face) if (quad.baked.isShade) lighting.applyDiffuseLighting(face)
} }
} }

View File

@@ -1,127 +0,0 @@
package mods.betterfoliage.render.old
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.PI2
import net.minecraft.client.Minecraft
import net.minecraft.client.particle.IParticleRenderType
import net.minecraft.client.particle.SpriteTexturedParticle
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.world.World
import kotlin.math.cos
import kotlin.math.sin
abstract class AbstractEntityFX(world: World, x: Double, y: Double, z: Double) : SpriteTexturedParticle(world, x, y, z) {
companion object {
@JvmStatic val sin = Array(64) { idx -> sin(PI2 / 64.0 * idx) }
@JvmStatic val cos = Array(64) { idx -> cos(PI2 / 64.0 * idx) }
}
val billboardRot = Pair(Double3.zero, Double3.zero)
val currentPos = Double3.zero
val prevPos = Double3.zero
val velocity = Double3.zero
override fun tick() {
super.tick()
currentPos.setTo(posX, posY, posZ)
prevPos.setTo(prevPosX, prevPosY, prevPosZ)
velocity.setTo(motionX, motionY, motionZ)
update()
posX = currentPos.x; posY = currentPos.y; posZ = currentPos.z;
motionX = velocity.x; motionY = velocity.y; motionZ = velocity.z;
}
/** Render the particle. */
abstract fun render(worldRenderer: BufferBuilder, partialTickTime: Float)
/** Update particle on world tick. */
abstract fun update()
/** True if the particle is renderable. */
abstract val isValid: Boolean
/** Add the particle to the effect renderer if it is valid. */
fun addIfValid() { if (isValid) Minecraft.getInstance().particles.addEffect(this) }
// override fun renderParticle(buffer: BufferBuilder, entity: ActiveRenderInfo, partialTicks: Float, rotX: Float, rotZ: Float, rotYZ: Float, rotXY: Float, rotXZ: Float) {
// billboardRot.first.setTo(rotX + rotXY, rotZ, rotYZ + rotXZ)
// billboardRot.second.setTo(rotX - rotXY, -rotZ, rotYZ - rotXZ)
// render(buffer, partialTicks)
// }
/**
* Render a particle quad.
*
* @param[tessellator] the [Tessellator] instance to use
* @param[partialTickTime] partial tick time
* @param[currentPos] render position
* @param[prevPos] previous tick position for interpolation
* @param[size] particle size
* @param[rotation] viewpoint-dependent particle rotation (64 steps)
* @param[icon] particle texture
* @param[isMirrored] mirror particle texture along V-axis
* @param[alpha] aplha blending
*/
// fun renderParticleQuad(worldRenderer: BufferBuilder,
// partialTickTime: Float,
// currentPos: Double3 = this.currentPos,
// prevPos: Double3 = this.prevPos,
// size: Double = particleScale.toDouble(),
// rotation: Int = 0,
// icon: TextureAtlasSprite = sprite,
// isMirrored: Boolean = false,
// alpha: Float = this.particleAlpha) {
//
// val minU = (if (isMirrored) icon.minU else icon.maxU).toDouble()
// val maxU = (if (isMirrored) icon.maxU else icon.minU).toDouble()
// val minV = icon.minV.toDouble()
// val maxV = icon.maxV.toDouble()
//
// val center = currentPos.copy().sub(prevPos).mul(partialTickTime.toDouble()).add(prevPos).sub(interpPosX, interpPosY, interpPosZ)
// val v1 = if (rotation == 0) billboardRot.first * size else
// Double3.weight(billboardRot.first, cos[rotation and 63] * size, billboardRot.second, sin[rotation and 63] * size)
// val v2 = if (rotation == 0) billboardRot.second * size else
// Double3.weight(billboardRot.first, -sin[rotation and 63] * size, billboardRot.second, cos[rotation and 63] * size)
//
// val renderBrightness = this.getBrightnessForRender(partialTickTime)
// val brLow = renderBrightness shr 16 and 65535
// val brHigh = renderBrightness and 65535
//
// worldRenderer
// .pos(center.x - v1.x, center.y - v1.y, center.z - v1.z)
// .tex(maxU, maxV)
// .color(particleRed, particleGreen, particleBlue, alpha)
// .lightmap(brLow, brHigh)
// .endVertex()
//
// worldRenderer
// .pos(center.x - v2.x, center.y - v2.y, center.z - v2.z)
// .tex(maxU, minV)
// .color(particleRed, particleGreen, particleBlue, alpha)
// .lightmap(brLow, brHigh)
// .endVertex()
//
// worldRenderer
// .pos(center.x + v1.x, center.y + v1.y, center.z + v1.z)
// .tex(minU, minV)
// .color(particleRed, particleGreen, particleBlue, alpha)
// .lightmap(brLow, brHigh)
// .endVertex()
//
// worldRenderer
// .pos(center.x + v2.x, center.y + v2.y, center.z + v2.z)
// .tex(minU, maxV)
// .color(particleRed, particleGreen, particleBlue, alpha)
// .lightmap(brLow, brHigh)
// .endVertex()
// }
// override fun getFXLayer() = 1
override fun getRenderType(): IParticleRenderType = IParticleRenderType.PARTICLE_SHEET_TRANSLUCENT
fun setColor(color: Int) {
particleBlue = (color and 255) / 256.0f
particleGreen = ((color shr 8) and 255) / 256.0f
particleRed = ((color shr 16) and 255) / 256.0f
}
}

View File

@@ -5,12 +5,12 @@ import mods.betterfoliage.util.Double3
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.particle.SpriteTexturedParticle import net.minecraft.client.particle.SpriteTexturedParticle
import net.minecraft.client.renderer.ActiveRenderInfo import net.minecraft.client.renderer.ActiveRenderInfo
import net.minecraft.client.renderer.Vector3f
import net.minecraft.client.renderer.texture.TextureAtlasSprite import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.client.world.ClientWorld
import net.minecraft.util.math.MathHelper import net.minecraft.util.math.MathHelper
import net.minecraft.world.World import net.minecraft.util.math.vector.Vector3f
abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) : SpriteTexturedParticle(world, x, y, z) { abstract class AbstractParticle(world: ClientWorld, x: Double, y: Double, z: Double) : SpriteTexturedParticle(world, x, y, z) {
companion object { companion object {
// @JvmStatic val sin = Array(64) { idx -> Math.sin(PI2 / 64.0 * idx) } // @JvmStatic val sin = Array(64) { idx -> Math.sin(PI2 / 64.0 * idx) }
@@ -24,12 +24,12 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
override fun tick() { override fun tick() {
super.tick() super.tick()
currentPos.setTo(posX, posY, posZ) currentPos.setTo(x, y, z)
prevPos.setTo(prevPosX, prevPosY, prevPosZ) prevPos.setTo(xo, yo, zo)
velocity.setTo(motionX, motionY, motionZ) velocity.setTo(xd, yd, zd)
update() update()
posX = currentPos.x; posY = currentPos.y; posZ = currentPos.z; x = currentPos.x; y = currentPos.y; z = currentPos.z;
motionX = velocity.x; motionY = velocity.y; motionZ = velocity.z; xd = velocity.x; yd = velocity.y; zd = velocity.z;
} }
/** Update particle on world tick. */ /** Update particle on world tick. */
@@ -39,10 +39,10 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
abstract val isValid: Boolean abstract val isValid: Boolean
/** Add the particle to the effect renderer if it is valid. */ /** Add the particle to the effect renderer if it is valid. */
fun addIfValid() { if (isValid) Minecraft.getInstance().particles.addEffect(this) } fun addIfValid() { if (isValid) Minecraft.getInstance().particleEngine.add(this) }
override fun renderParticle(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) { override fun render(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
super.renderParticle(vertexBuilder, camera, tickDelta) super.render(vertexBuilder, camera, tickDelta)
} }
/** /**
@@ -63,39 +63,39 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
tickDelta: Float, tickDelta: Float,
currentPos: Double3 = this.currentPos, currentPos: Double3 = this.currentPos,
prevPos: Double3 = this.prevPos, prevPos: Double3 = this.prevPos,
size: Double = particleScale.toDouble(), size: Double = quadSize.toDouble(),
currentAngle: Float = this.particleAngle, currentAngle: Float = this.roll,
prevAngle: Float = this.prevParticleAngle, prevAngle: Float = this.oRoll,
sprite: TextureAtlasSprite = this.sprite, sprite: TextureAtlasSprite = this.sprite,
alpha: Float = this.particleAlpha) { alpha: Float = this.alpha) {
val center = Double3.lerp(tickDelta.toDouble(), prevPos, currentPos) val center = Double3.lerp(tickDelta.toDouble(), prevPos, currentPos)
val angle = MathHelper.lerp(tickDelta, prevAngle, currentAngle) val angle = MathHelper.lerp(tickDelta, prevAngle, currentAngle)
val rotation = camera.rotation.copy().apply { multiply(Vector3f.ZP.rotation(angle)) } val rotation = camera.rotation().copy().apply { mul(Vector3f.ZP.rotation(angle)) }
val lightmapCoord = getBrightnessForRender(tickDelta) val lightmapCoord = getLightColor(tickDelta)
val coords = arrayOf( val coords = arrayOf(
Double3(-1.0, -1.0, 0.0), Double3(-1.0, -1.0, 0.0),
Double3(-1.0, 1.0, 0.0), Double3(-1.0, 1.0, 0.0),
Double3(1.0, 1.0, 0.0), Double3(1.0, 1.0, 0.0),
Double3(1.0, -1.0, 0.0) Double3(1.0, -1.0, 0.0)
).map { it.rotate(rotation).mul(size).add(center).sub(camera.projectedView.x, camera.projectedView.y, camera.projectedView.z) } ).map { it.rotate(rotation).mul(size).add(center).sub(camera.position.x, camera.position.y, camera.position.z) }
fun renderVertex(vertex: Double3, u: Float, v: Float) = vertexConsumer fun renderVertex(vertex: Double3, u: Float, v: Float) = vertexConsumer
.pos(vertex.x, vertex.y, vertex.z).tex(u, v) .vertex(vertex.x, vertex.y, vertex.z).uv(u, v)
.color(particleRed, particleGreen, particleBlue, alpha).lightmap(lightmapCoord) .color(rCol, gCol, bCol, alpha).uv2(lightmapCoord)
.endVertex() .endVertex()
renderVertex(coords[0], sprite.maxU, sprite.maxV) renderVertex(coords[0], sprite.u1, sprite.v1)
renderVertex(coords[1], sprite.maxU, sprite.minV) renderVertex(coords[1], sprite.u1, sprite.v0)
renderVertex(coords[2], sprite.minU, sprite.minV) renderVertex(coords[2], sprite.u0, sprite.v0)
renderVertex(coords[3], sprite.minU, sprite.maxV) renderVertex(coords[3], sprite.u0, sprite.v1)
} }
fun setColor(color: Int) { fun setColor(color: Int) {
particleBlue = (color and 255) / 256.0f bCol = (color and 255) / 256.0f
particleGreen = ((color shr 8) and 255) / 256.0f gCol = ((color shr 8) and 255) / 256.0f
particleRed = ((color shr 16) and 255) / 256.0f rCol = ((color shr 16) and 255) / 256.0f
} }
} }

View File

@@ -8,22 +8,22 @@ import mods.betterfoliage.util.randomB
import mods.betterfoliage.util.randomD import mods.betterfoliage.util.randomD
import mods.betterfoliage.util.randomF import mods.betterfoliage.util.randomF
import mods.betterfoliage.util.randomI import mods.betterfoliage.util.randomI
import net.minecraft.client.Minecraft
import net.minecraft.client.particle.IParticleRenderType import net.minecraft.client.particle.IParticleRenderType
import net.minecraft.client.world.ClientWorld
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper import net.minecraft.util.math.MathHelper
import net.minecraft.world.World import net.minecraft.world.World
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.TickEvent import net.minecraftforge.event.TickEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.LogicalSide
import java.util.Random import java.util.Random
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.cos import kotlin.math.cos
import kotlin.math.sin import kotlin.math.sin
class FallingLeafParticle( class FallingLeafParticle(
world: World, pos: BlockPos, leaf: LeafParticleKey, blockColor: Int, random: Random world: ClientWorld, pos: BlockPos, leaf: LeafParticleKey, blockColor: Int, random: Random
) : AbstractParticle( ) : AbstractParticle(
world, pos.x.toDouble() + 0.5, pos.y.toDouble(), pos.z.toDouble() + 0.5 world, pos.x.toDouble() + 0.5, pos.y.toDouble(), pos.z.toDouble() + 0.5
) { ) {
@@ -37,13 +37,13 @@ class FallingLeafParticle(
var wasCollided = false var wasCollided = false
init { init {
particleAngle = random.randomF(max = PI2) roll = random.randomF(max = PI2)
prevParticleAngle = particleAngle - rotationSpeed oRoll = roll - rotationSpeed
maxAge = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0) lifetime = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
motionY = -Config.fallingLeaves.speed yd = -Config.fallingLeaves.speed
particleScale = Config.fallingLeaves.size.toFloat() * 0.1f quadSize = Config.fallingLeaves.size.toFloat() * 0.1f
setColor(leaf.overrideColor?.asInt ?: blockColor) setColor(leaf.overrideColor?.asInt ?: blockColor)
sprite = LeafParticleRegistry[leaf.leafType][randomI(max = 1024)] sprite = LeafParticleRegistry[leaf.leafType][randomI(max = 1024)]
} }
@@ -52,21 +52,21 @@ class FallingLeafParticle(
override fun update() { override fun update() {
if (rand.nextFloat() > 0.95f) rotationSpeed *= -1.0f if (random.nextFloat() > 0.95f) rotationSpeed *= -1.0f
if (age > maxAge - 20) particleAlpha = 0.05f * (maxAge - age) if (age > lifetime - 20) alpha = 0.05f * (lifetime - age)
if (onGround || wasCollided) { if (onGround || wasCollided) {
velocity.setTo(0.0, 0.0, 0.0) velocity.setTo(0.0, 0.0, 0.0)
if (!wasCollided) { if (!wasCollided) {
age = age.coerceAtLeast(maxAge - 20) age = age.coerceAtLeast(lifetime - 20)
wasCollided = true wasCollided = true
} }
} else { } else {
val cosRotation = cos(particleAngle).toDouble(); val sinRotation = sin(particleAngle).toDouble() val cosRotation = cos(roll).toDouble(); val sinRotation = sin(roll).toDouble()
velocity.setTo(cosRotation, 0.0, sinRotation).mul(Config.fallingLeaves.perturb) velocity.setTo(cosRotation, 0.0, sinRotation).mul(Config.fallingLeaves.perturb)
.add(LeafWindTracker.current).add(0.0, -1.0, 0.0).mul(Config.fallingLeaves.speed) .add(LeafWindTracker.current).add(0.0, -1.0, 0.0).mul(Config.fallingLeaves.speed)
prevParticleAngle = particleAngle oRoll = roll
particleAngle += rotationSpeed roll += rotationSpeed
} }
} }
@@ -84,7 +84,7 @@ object LeafWindTracker {
} }
fun changeWind(world: World) { fun changeWind(world: World) {
nextChange = world.worldInfo.gameTime + 120 + random.nextInt(80) nextChange = world.gameTime + 120 + random.nextInt(80)
val direction = PI2 * random.nextDouble() val direction = PI2 * random.nextDouble()
val speed = abs(random.nextGaussian()) * Config.fallingLeaves.windStrength + val speed = abs(random.nextGaussian()) * Config.fallingLeaves.windStrength +
(if (!world.isRaining) 0.0 else abs(random.nextGaussian()) * Config.fallingLeaves.stormStrength) (if (!world.isRaining) 0.0 else abs(random.nextGaussian()) * Config.fallingLeaves.stormStrength)
@@ -92,10 +92,10 @@ object LeafWindTracker {
} }
@SubscribeEvent @SubscribeEvent
fun handleWorldTick(event: TickEvent.ClientTickEvent) { fun handleWorldTick(event: TickEvent.WorldTickEvent) {
if (event.phase == TickEvent.Phase.START) Minecraft.getInstance().world?.let { world -> if (event.phase == TickEvent.Phase.START && event.side == LogicalSide.CLIENT) event.world.let { world ->
// change target wind speed // change target wind speed
if (world.worldInfo.dayTime >= nextChange) changeWind(world) if (world.dayTime >= nextChange) changeWind(world)
// change current wind speed // change current wind speed
val changeRate = if (world.isRaining) 0.015 else 0.005 val changeRate = if (world.isRaining) 0.015 else 0.005
@@ -107,6 +107,6 @@ object LeafWindTracker {
} }
} }
@SubscribeEvent // @SubscribeEvent
fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isRemote) changeWind(event.world.world) } // fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isClientSide) changeWind(event.world) }
} }

View File

@@ -41,7 +41,7 @@ object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
@SubscribeEvent @SubscribeEvent
fun handlePreStitch(event: TextureStitchEvent.Pre) { fun handlePreStitch(event: TextureStitchEvent.Pre) {
if (event.map.textureLocation == Atlas.PARTICLES.resourceId) { if (event.map.location() == Atlas.PARTICLES.resourceId) {
allTypes.forEach { leafType -> allTypes.forEach { leafType ->
val locations = (0 until 16).map { idx -> val locations = (0 until 16).map { idx ->
ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx") ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx")
@@ -55,7 +55,7 @@ object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
@SubscribeEvent @SubscribeEvent
fun handlePostStitch(event: TextureStitchEvent.Post) { fun handlePostStitch(event: TextureStitchEvent.Post) {
if (event.map.textureLocation == Atlas.PARTICLES.resourceId) { if (event.map.location() == Atlas.PARTICLES.resourceId) {
(typeMappings.mappings.map { it.type } + "default").distinct().forEach { leafType -> (typeMappings.mappings.map { it.type } + "default").distinct().forEach { leafType ->
val sprites = (0 until 16).map { idx -> val sprites = (0 until 16).map { idx ->
ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx") ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx")

View File

@@ -13,6 +13,7 @@ import mods.betterfoliage.util.randomD
import mods.betterfoliage.util.randomI import mods.betterfoliage.util.randomI
import net.minecraft.client.particle.IParticleRenderType import net.minecraft.client.particle.IParticleRenderType
import net.minecraft.client.renderer.ActiveRenderInfo import net.minecraft.client.renderer.ActiveRenderInfo
import net.minecraft.client.world.ClientWorld
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper import net.minecraft.util.math.MathHelper
@@ -23,7 +24,7 @@ import kotlin.math.cos
import kotlin.math.sin import kotlin.math.sin
class RisingSoulParticle( class RisingSoulParticle(
world: World, pos: BlockPos world: ClientWorld, pos: BlockPos
) : AbstractParticle( ) : AbstractParticle(
world, pos.x.toDouble() + 0.5, pos.y.toDouble() + 1.0, pos.z.toDouble() + 0.5 world, pos.x.toDouble() + 0.5, pos.y.toDouble() + 1.0, pos.z.toDouble() + 0.5
) { ) {
@@ -32,10 +33,10 @@ class RisingSoulParticle(
val initialPhase = randomD(max = PI2) val initialPhase = randomD(max = PI2)
init { init {
motionY = 0.1 yd = 0.1
particleGravity = 0.0f gravity = 0.0f
sprite = headIcons[randomI(max = 1024)] sprite = headIcons[randomI(max = 1024)]
maxAge = MathHelper.floor((0.6 + 0.4 * randomD()) * Config.risingSoul.lifetime * 20.0) lifetime = MathHelper.floor((0.6 + 0.4 * randomD()) * Config.risingSoul.lifetime * 20.0)
} }
override val isValid: Boolean get() = true override val isValid: Boolean get() = true
@@ -49,12 +50,12 @@ class RisingSoulParticle(
particleTrail.addFirst(currentPos.copy()) particleTrail.addFirst(currentPos.copy())
while (particleTrail.size > Config.risingSoul.trailLength) particleTrail.removeLast() while (particleTrail.size > Config.risingSoul.trailLength) particleTrail.removeLast()
if (!Config.enabled) setExpired() if (!Config.enabled) remove()
} }
override fun renderParticle(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) { override fun render(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
var alpha = Config.risingSoul.opacity.toFloat() var alpha = Config.risingSoul.opacity.toFloat()
if (age > maxAge - 40) alpha *= (maxAge - age) / 40.0f if (age > lifetime - 40) alpha *= (lifetime - age) / 40.0f
renderParticleQuad( renderParticleQuad(
vertexBuilder, camera, tickDelta, vertexBuilder, camera, tickDelta,

View File

@@ -3,18 +3,18 @@ package mods.betterfoliage.render.pipeline
import com.mojang.blaze3d.matrix.MatrixStack import com.mojang.blaze3d.matrix.MatrixStack
import mods.betterfoliage.chunk.BasicBlockCtx import mods.betterfoliage.chunk.BasicBlockCtx
import mods.betterfoliage.chunk.BlockCtx import mods.betterfoliage.chunk.BlockCtx
import mods.betterfoliage.model.HalfBakedQuad
import mods.betterfoliage.model.SpecialRenderModel import mods.betterfoliage.model.SpecialRenderModel
import mods.betterfoliage.render.lighting.VanillaFullBlockLighting import mods.betterfoliage.render.lighting.VanillaFullBlockLighting
import mods.betterfoliage.render.lighting.VanillaQuadLighting import mods.betterfoliage.render.lighting.VanillaQuadLighting
import mods.betterfoliage.render.lighting.VanillaVertexLighter import mods.betterfoliage.render.lighting.VanillaVertexLighter
import mods.betterfoliage.model.HalfBakedQuad
import mods.betterfoliage.util.Int3 import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.plus import mods.betterfoliage.util.plus
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader import net.minecraft.world.IBlockDisplayReader
import net.minecraftforge.client.model.data.IModelData import net.minecraftforge.client.model.data.IModelData
import java.util.Random import java.util.Random
@@ -25,7 +25,7 @@ import java.util.Random
* push-based partial rendering pipeline for [SpecialRenderModel] instances. * push-based partial rendering pipeline for [SpecialRenderModel] instances.
*/ */
abstract class RenderCtxBase( abstract class RenderCtxBase(
world: ILightReader, world: IBlockDisplayReader,
pos: BlockPos, pos: BlockPos,
val matrixStack: MatrixStack, val matrixStack: MatrixStack,
var checkSides: Boolean, var checkSides: Boolean,
@@ -36,14 +36,14 @@ abstract class RenderCtxBase(
abstract fun renderQuad(quad: HalfBakedQuad) abstract fun renderQuad(quad: HalfBakedQuad)
var hasRendered = false var hasRendered = false
val blockModelShapes = Minecraft.getInstance().blockRendererDispatcher.blockModelShapes val blockModelShapes = Minecraft.getInstance().blockRenderer.blockModelShaper
var vertexLighter: VanillaVertexLighter = VanillaFullBlockLighting var vertexLighter: VanillaVertexLighter = VanillaFullBlockLighting
protected val lightingData = RenderCtxBase.lightingData.get().apply { protected val lightingData = RenderCtxBase.lightingData.get().apply {
calc.reset(this@RenderCtxBase) calc.reset(this@RenderCtxBase)
blockColors = Minecraft.getInstance().blockColors blockColors = Minecraft.getInstance().blockColors
} }
inline fun Direction?.shouldRender() = this == null || !checkSides || Block.shouldSideBeRendered(state, world, pos, this) inline fun Direction?.shouldRender() = this == null || !checkSides || Block.shouldRenderFace(state, world, pos, this)
fun renderQuads(quads: Iterable<HalfBakedQuad>) { fun renderQuads(quads: Iterable<HalfBakedQuad>) {
quads.forEach { quad -> quads.forEach { quad ->

View File

@@ -1,20 +1,20 @@
package mods.betterfoliage.render.pipeline package mods.betterfoliage.render.pipeline
import com.mojang.blaze3d.matrix.MatrixStack import com.mojang.blaze3d.matrix.MatrixStack
import mods.betterfoliage.model.HalfBakedQuad
import mods.betterfoliage.model.SpecialRenderModel import mods.betterfoliage.model.SpecialRenderModel
import mods.betterfoliage.render.lighting.ForgeVertexLighter import mods.betterfoliage.render.lighting.ForgeVertexLighter
import mods.betterfoliage.render.lighting.ForgeVertexLighterAccess import mods.betterfoliage.render.lighting.ForgeVertexLighterAccess
import mods.betterfoliage.model.HalfBakedQuad
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.client.renderer.LightTexture import net.minecraft.client.renderer.LightTexture
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader import net.minecraft.world.IBlockDisplayReader
import net.minecraftforge.client.model.data.IModelData import net.minecraftforge.client.model.data.IModelData
import net.minecraftforge.client.model.pipeline.VertexLighterFlat import net.minecraftforge.client.model.pipeline.VertexLighterFlat
import java.util.Random import java.util.Random
class RenderCtxForge( class RenderCtxForge(
world: ILightReader, world: IBlockDisplayReader,
pos: BlockPos, pos: BlockPos,
val lighter: VertexLighterFlat, val lighter: VertexLighterFlat,
matrixStack: MatrixStack, matrixStack: MatrixStack,
@@ -33,8 +33,8 @@ class RenderCtxForge(
var vIdx = 0 var vIdx = 0
override fun updateVertexLightmap(normal: FloatArray, lightmap: FloatArray, x: Float, y: Float, z: Float) { override fun updateVertexLightmap(normal: FloatArray, lightmap: FloatArray, x: Float, y: Float, z: Float) {
lightingData.packedLight[vIdx].let { packedLight -> lightingData.packedLight[vIdx].let { packedLight ->
lightmap[0] = LightTexture.getLightBlock(packedLight) / 0xF.toFloat() lightmap[0] = LightTexture.block(packedLight) / 0xF.toFloat()
lightmap[1] = LightTexture.getLightSky(packedLight) / 0xF.toFloat() lightmap[1] = LightTexture.sky(packedLight) / 0xF.toFloat()
} }
} }
@@ -49,7 +49,7 @@ class RenderCtxForge(
@JvmStatic @JvmStatic
fun render( fun render(
lighter: VertexLighterFlat, lighter: VertexLighterFlat,
world: ILightReader, world: IBlockDisplayReader,
model: SpecialRenderModel, model: SpecialRenderModel,
state: BlockState, state: BlockState,
pos: BlockPos, pos: BlockPos,

View File

@@ -2,18 +2,18 @@ package mods.betterfoliage.render.pipeline
import com.mojang.blaze3d.matrix.MatrixStack import com.mojang.blaze3d.matrix.MatrixStack
import com.mojang.blaze3d.vertex.IVertexBuilder import com.mojang.blaze3d.vertex.IVertexBuilder
import mods.betterfoliage.model.SpecialRenderModel
import mods.betterfoliage.model.HalfBakedQuad import mods.betterfoliage.model.HalfBakedQuad
import mods.betterfoliage.model.SpecialRenderModel
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.client.renderer.BlockModelRenderer import net.minecraft.client.renderer.BlockModelRenderer
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader import net.minecraft.world.IBlockDisplayReader
import net.minecraftforge.client.model.data.IModelData import net.minecraftforge.client.model.data.IModelData
import java.util.Random import java.util.Random
class RenderCtxVanilla( class RenderCtxVanilla(
val renderer: BlockModelRenderer, val renderer: BlockModelRenderer,
world: ILightReader, world: IBlockDisplayReader,
pos: BlockPos, pos: BlockPos,
val buffer: IVertexBuilder, val buffer: IVertexBuilder,
val combinedOverlay: Int, val combinedOverlay: Int,
@@ -27,8 +27,8 @@ class RenderCtxVanilla(
override fun renderQuad(quad: HalfBakedQuad) { override fun renderQuad(quad: HalfBakedQuad) {
vertexLighter.updateLightmapAndColor(quad, lightingData) vertexLighter.updateLightmapAndColor(quad, lightingData)
buffer.addQuad( buffer.putBulkData(
matrixStack.last, quad.baked, matrixStack.last(), quad.baked,
lightingData.colorMultiplier, lightingData.colorMultiplier,
lightingData.tint[0], lightingData.tint[1], lightingData.tint[2], lightingData.tint[0], lightingData.tint[1], lightingData.tint[2],
lightingData.packedLight, combinedOverlay, true lightingData.packedLight, combinedOverlay, true
@@ -39,7 +39,7 @@ class RenderCtxVanilla(
@JvmStatic @JvmStatic
fun render( fun render(
renderer: BlockModelRenderer, renderer: BlockModelRenderer,
world: ILightReader, world: IBlockDisplayReader,
model: SpecialRenderModel, model: SpecialRenderModel,
state: BlockState, state: BlockState,
pos: BlockPos, pos: BlockPos,

View File

@@ -20,7 +20,7 @@ interface VeryEarlyReloadListener : IFutureReloadListener {
gameExecutor: Executor gameExecutor: Executor
): CompletableFuture<Void> { ): CompletableFuture<Void> {
onReloadStarted() onReloadStarted()
return stage.markCompleteAwaitingOthers(null) return stage.wait(null)
} }
fun onReloadStarted() {} fun onReloadStarted() {}

View File

@@ -8,8 +8,8 @@ import net.minecraft.block.BlockState
import net.minecraft.client.renderer.model.IBakedModel import net.minecraft.client.renderer.model.IBakedModel
import net.minecraft.client.renderer.model.IModelTransform import net.minecraft.client.renderer.model.IModelTransform
import net.minecraft.client.renderer.model.IUnbakedModel import net.minecraft.client.renderer.model.IUnbakedModel
import net.minecraft.client.renderer.model.Material
import net.minecraft.client.renderer.model.ModelBakery import net.minecraft.client.renderer.model.ModelBakery
import net.minecraft.client.renderer.model.RenderMaterial
import net.minecraft.client.renderer.texture.TextureAtlasSprite import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.ResourceLocation import net.minecraft.util.ResourceLocation
import net.minecraftforge.client.event.ModelBakeEvent import net.minecraftforge.client.event.ModelBakeEvent
@@ -30,7 +30,7 @@ data class ModelDefinitionsLoadedEvent(
interface ModelBakingKey { interface ModelBakingKey {
fun bake(ctx: ModelBakingContext): IBakedModel? = fun bake(ctx: ModelBakingContext): IBakedModel? =
ctx.getUnbaked().bakeModel(ctx.bakery, ctx.spriteGetter, ctx.transform, ctx.location) ctx.getUnbaked().bake(ctx.bakery, ctx.spriteGetter, ctx.transform, ctx.location)
} }
interface ModelDiscovery { interface ModelDiscovery {
@@ -49,7 +49,7 @@ data class ModelDiscoveryContext(
val replacements: MutableMap<ResourceLocation, ModelBakingKey>, val replacements: MutableMap<ResourceLocation, ModelBakingKey>,
val logger: Logger val logger: Logger
) { ) {
fun getUnbaked(location: ResourceLocation = modelLocation) = bakery.getUnbakedModel(location) fun getUnbaked(location: ResourceLocation = modelLocation) = bakery.getModel(location)
fun addReplacement(key: ModelBakingKey, addToStateKeys: Boolean = true) { fun addReplacement(key: ModelBakingKey, addToStateKeys: Boolean = true) {
replacements[modelLocation] = key replacements[modelLocation] = key
if (addToStateKeys) BetterFoliage.blockTypes.stateKeys[blockState] = key if (addToStateKeys) BetterFoliage.blockTypes.stateKeys[blockState] = key
@@ -59,12 +59,12 @@ data class ModelDiscoveryContext(
data class ModelBakingContext( data class ModelBakingContext(
val bakery: ModelBakery, val bakery: ModelBakery,
val spriteGetter: Function<Material, TextureAtlasSprite>, val spriteGetter: Function<RenderMaterial, TextureAtlasSprite>,
val location: ResourceLocation, val location: ResourceLocation,
val transform: IModelTransform, val transform: IModelTransform,
val logger: Logger val logger: Logger
) { ) {
fun getUnbaked() = bakery.getUnbakedModel(location) fun getUnbaked() = bakery.getModel(location)
fun getBaked() = bakery.getBakedModel(location, transform, spriteGetter) fun getBaked() = bakery.getBakedModel(location, transform, spriteGetter)
} }
@@ -94,7 +94,7 @@ object BakeWrapperManager : Invalidator, HasLogger() {
@SubscribeEvent @SubscribeEvent
fun handleStitch(event: TextureStitchEvent.Pre) { fun handleStitch(event: TextureStitchEvent.Pre) {
if (event.map.textureLocation == Atlas.BLOCKS.resourceId) { if (event.map.location() == Atlas.BLOCKS.resourceId) {
logger.log(INFO, "Adding ${sprites.size} sprites to block atlas") logger.log(INFO, "Adding ${sprites.size} sprites to block atlas")
sprites.forEach { event.addSprite(it) } sprites.forEach { event.addSprite(it) }
sprites.clear() sprites.clear()
@@ -109,7 +109,7 @@ object BakeWrapperManager : Invalidator, HasLogger() {
fun onBake( fun onBake(
unbaked: IUnbakedModel, unbaked: IUnbakedModel,
bakery: ModelBakery, bakery: ModelBakery,
spriteGetter: Function<Material, TextureAtlasSprite>, spriteGetter: Function<RenderMaterial, TextureAtlasSprite>,
transform: IModelTransform, transform: IModelTransform,
location: ResourceLocation location: ResourceLocation
): IBakedModel? { ): IBakedModel? {
@@ -124,6 +124,6 @@ object BakeWrapperManager : Invalidator, HasLogger() {
logger.log(WARN, "Error while baking $replacement", e) logger.log(WARN, "Error while baking $replacement", e)
} }
} }
return unbaked.bakeModel(bakery, spriteGetter, transform, location) return unbaked.bake(bakery, spriteGetter, transform, location)
} }
} }

View File

@@ -1,6 +1,5 @@
package mods.betterfoliage.resource.discovery package mods.betterfoliage.resource.discovery
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.util.HasLogger import mods.betterfoliage.util.HasLogger
import mods.betterfoliage.util.getJavaClass import mods.betterfoliage.util.getJavaClass
import mods.betterfoliage.util.getLines import mods.betterfoliage.util.getLines
@@ -45,8 +44,8 @@ class ConfigurableBlockMatcher(val location: ResourceLocation) : HasLogger(), IB
fun readDefaults() { fun readDefaults() {
blackList.clear() blackList.clear()
whiteList.clear() whiteList.clear()
resourceManager.getAllResources(location).forEach { resource -> resourceManager.getResources(location).forEach { resource ->
detailLogger.log(INFO, "Reading block class configuration $location from pack ${resource.packName}") detailLogger.log(INFO, "Reading block class configuration $location from pack ${resource.sourceName}")
resource.getLines().map{ it.trim() }.filter { !it.startsWith("//") && it.isNotEmpty() }.forEach { line -> resource.getLines().map{ it.trim() }.filter { !it.startsWith("//") && it.isNotEmpty() }.forEach { line ->
if (line.startsWith("-")) getJavaClass(line.substring(1))?.let { blackList.add(it) } if (line.startsWith("-")) getJavaClass(line.substring(1))?.let { blackList.add(it) }
else getJavaClass(line)?.let { whiteList.add(it) } else getJavaClass(line)?.let { whiteList.add(it) }
@@ -63,8 +62,8 @@ data class ModelTextureList(val modelLocation: ResourceLocation, val textureName
class ModelTextureListConfiguration(val location: ResourceLocation) : HasLogger() { class ModelTextureListConfiguration(val location: ResourceLocation) : HasLogger() {
val modelList = mutableListOf<ModelTextureList>() val modelList = mutableListOf<ModelTextureList>()
fun readDefaults() { fun readDefaults() {
resourceManager.getAllResources(location).forEach { resource -> resourceManager.getResources(location).forEach { resource ->
detailLogger.log(INFO, "Reading model/texture configuration $location from pack ${resource.packName}") detailLogger.log(INFO, "Reading model/texture configuration $location from pack ${resource.sourceName}")
resource.getLines().map{ it.trim() }.filter { !it.startsWith("//") && it.isNotEmpty() }.forEach { line -> resource.getLines().map{ it.trim() }.filter { !it.startsWith("//") && it.isNotEmpty() }.forEach { line ->
val elements = line.split(",") val elements = line.split(",")
modelList.add(ModelTextureList(ResourceLocation(elements.first()), elements.drop(1))) modelList.add(ModelTextureList(ResourceLocation(elements.first()), elements.drop(1)))

View File

@@ -18,9 +18,9 @@ abstract class AbstractModelDiscovery : HasLogger(), ModelDiscovery {
replacements: MutableMap<ResourceLocation, ModelBakingKey> replacements: MutableMap<ResourceLocation, ModelBakingKey>
) { ) {
ForgeRegistries.BLOCKS ForgeRegistries.BLOCKS
.flatMap { block -> block.stateContainer.validStates } .flatMap { block -> block.stateDefinition.possibleStates }
.forEach { state -> .forEach { state ->
val location = BlockModelShapes.getModelLocation(state) val location = BlockModelShapes.stateToModelLocation(state)
val ctx = ModelDiscoveryContext(bakery, state, location, sprites, replacements, detailLogger) val ctx = ModelDiscoveryContext(bakery, state, location, sprites, replacements, detailLogger)
try { try {
processModel(ctx) processModel(ctx)
@@ -38,7 +38,7 @@ abstract class AbstractModelDiscovery : HasLogger(), ModelDiscovery {
// per-location replacements need to be scoped to the variant list, as replacement models // per-location replacements need to be scoped to the variant list, as replacement models
// may need information from the BlockState which is not available at baking time // may need information from the BlockState which is not available at baking time
val scopedReplacements = mutableMapOf<ResourceLocation, ModelBakingKey>() val scopedReplacements = mutableMapOf<ResourceLocation, ModelBakingKey>()
model.variantList.forEach { variant -> model.variants.forEach { variant ->
processModel(ctx.copy(modelLocation = variant.modelLocation, replacements = scopedReplacements)) processModel(ctx.copy(modelLocation = variant.modelLocation, replacements = scopedReplacements))
} }
if (scopedReplacements.isNotEmpty()) { if (scopedReplacements.isNotEmpty()) {
@@ -66,20 +66,25 @@ abstract class ConfigurableModelDiscovery : AbstractModelDiscovery() {
detailLogger.log(Level.INFO, " model ${ctx.modelLocation}") detailLogger.log(Level.INFO, " model ${ctx.modelLocation}")
detailLogger.log(Level.INFO, " class ${ctx.blockState.block.javaClass.name} matches ${matchClass.name}") detailLogger.log(Level.INFO, " class ${ctx.blockState.block.javaClass.name} matches ${matchClass.name}")
modelTextures val ancestry = ctx.bakery.getAncestry(ctx.modelLocation)
.filter { matcher -> ctx.bakery.modelDerivesFrom(model, ctx.modelLocation, matcher.modelLocation) } val matches = modelTextures.filter { matcher ->
.forEach { match -> matcher.modelLocation in ancestry
}
matches.forEach { match ->
detailLogger.log(Level.INFO, " model $model matches ${match.modelLocation}") detailLogger.log(Level.INFO, " model $model matches ${match.modelLocation}")
val materials = match.textureNames.map { it to model.resolveTextureName(it) } val materials = match.textureNames.map { it to model.getMaterial(it) }
val texMapString = Joiner.on(", ").join(materials.map { "${it.first}=${it.second.textureLocation}" }) val texMapString = Joiner.on(", ").join(materials.map { "${it.first}=${it.second.texture()}" })
detailLogger.log(Level.INFO, " sprites [$texMapString]") detailLogger.log(Level.INFO, " sprites [$texMapString]")
if (materials.all { it.second.textureLocation != MissingTextureSprite.getLocation() }) { if (materials.all { it.second.texture() != MissingTextureSprite.getLocation() }) {
// found a valid model (all required textures exist) // found a valid model (all required textures exist)
processModel(ctx, materials.map { it.second.textureLocation }) processModel(ctx, materials.map { it.second.texture() })
} }
} }
if (matches.isEmpty()) {
detailLogger.log(Level.INFO, " no matches for model ${ctx.modelLocation}, inheritance chain ${ancestry.joinToString(" -> ")}")
}
} }
return super.processModel(ctx) return super.processModel(ctx)
} }
@@ -88,6 +93,12 @@ abstract class ConfigurableModelDiscovery : AbstractModelDiscovery() {
fun ModelBakery.modelDerivesFrom(model: BlockModel, location: ResourceLocation, target: ResourceLocation): Boolean = fun ModelBakery.modelDerivesFrom(model: BlockModel, location: ResourceLocation, target: ResourceLocation): Boolean =
if (location == target) true if (location == target) true
else model.parentLocation else model.parentLocation
?.let { getUnbakedModel(it) as? BlockModel } ?.let { getModel(it) as? BlockModel }
?.let { parent -> modelDerivesFrom(parent, model.parentLocation!!, target) } ?.let { parent -> modelDerivesFrom(parent, model.parentLocation!!, target) }
?: false ?: false
fun ModelBakery.getAncestry(location: ResourceLocation): List<ResourceLocation> {
val model = getModel(location) as? BlockModel ?: return listOf(location)
val parentAncestry = model.parentLocation?.let { getAncestry(it) } ?: emptyList()
return listOf(location) + parentAncestry
}

View File

@@ -20,7 +20,7 @@ class WeightedUnbakedKey(
if (unbaked !is VariantList) return super.bake(ctx) if (unbaked !is VariantList) return super.bake(ctx)
// bake all variants, replace as needed // bake all variants, replace as needed
val bakedModels = unbaked.variantList.mapNotNull { val bakedModels = unbaked.variants.mapNotNull {
val variantCtx = ctx.copy(location = it.modelLocation, transform = it) val variantCtx = ctx.copy(location = it.modelLocation, transform = it)
val replacement = replacements[it.modelLocation] val replacement = replacements[it.modelLocation]
val baked = replacement?.let { replacement -> val baked = replacement?.let { replacement ->
@@ -40,10 +40,10 @@ class WeightedUnbakedKey(
// let it through unchanged // let it through unchanged
if (bakedModels.isEmpty()) return super.bake(ctx) if (bakedModels.isEmpty()) return super.bake(ctx)
if (bakedModels.size < unbaked.variantList.size) { if (bakedModels.size < unbaked.variants.size) {
detailLogger.log( detailLogger.log(
WARN, WARN,
"Dropped ${unbaked.variantList.size - bakedModels.size} variants from model ${ctx.location}" "Dropped ${unbaked.variants.size - bakedModels.size} variants from model ${ctx.location}"
) )
} }
val weightedSpecials = bakedModels.map { (variant, model) -> val weightedSpecials = bakedModels.map { (variant, model) ->

View File

@@ -1,10 +1,8 @@
package mods.betterfoliage.resource.generated package mods.betterfoliage.resource.generated
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.util.Atlas import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.HasLogger import mods.betterfoliage.util.HasLogger
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.resources.ClientResourcePackInfo
import net.minecraft.resources.* import net.minecraft.resources.*
import net.minecraft.resources.ResourcePackType.CLIENT_RESOURCES import net.minecraft.resources.ResourcePackType.CLIENT_RESOURCES
import net.minecraft.resources.data.IMetadataSectionSerializer import net.minecraft.resources.data.IMetadataSectionSerializer
@@ -12,6 +10,7 @@ import net.minecraft.util.ResourceLocation
import net.minecraft.util.text.StringTextComponent import net.minecraft.util.text.StringTextComponent
import org.apache.logging.log4j.Level.INFO import org.apache.logging.log4j.Level.INFO
import java.util.* import java.util.*
import java.util.function.Consumer
import java.util.function.Predicate import java.util.function.Predicate
import java.util.function.Supplier import java.util.function.Supplier
@@ -25,10 +24,10 @@ class GeneratedTexturePack(
val nameSpace: String, val packName: String val nameSpace: String, val packName: String
) : HasLogger(), IResourcePack { ) : HasLogger(), IResourcePack {
override fun getName() = packName override fun getName() = packName
override fun getResourceNamespaces(type: ResourcePackType) = setOf(nameSpace) override fun getNamespaces(type: ResourcePackType) = setOf(nameSpace)
override fun <T : Any?> getMetadata(deserializer: IMetadataSectionSerializer<T>) = null override fun <T : Any?> getMetadataSection(deserializer: IMetadataSectionSerializer<T>) = null
override fun getRootResourceStream(id: String) = null override fun getRootResource(id: String) = null
override fun getAllResourceLocations(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<ResourceLocation>() override fun getResources(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<ResourceLocation>()
override fun close() {} override fun close() {}
@@ -49,21 +48,22 @@ class GeneratedTexturePack(
return id return id
} }
override fun getResourceStream(type: ResourcePackType, id: ResourceLocation) = override fun getResource(type: ResourcePackType, id: ResourceLocation) =
if (type != CLIENT_RESOURCES) null else resources[id]?.inputStream() if (type != CLIENT_RESOURCES) null else resources[id]?.inputStream()
override fun resourceExists(type: ResourcePackType, id: ResourceLocation) = override fun hasResource(type: ResourcePackType, id: ResourceLocation) =
type == CLIENT_RESOURCES && resources.containsKey(id) type == CLIENT_RESOURCES && resources.containsKey(id)
val finder = object : IPackFinder { val finder = object : IPackFinder {
val packInfo = ClientResourcePackInfo( val packInfo = ResourcePackInfo(
packName, true, Supplier { this@GeneratedTexturePack }, packName, true, Supplier { this@GeneratedTexturePack },
StringTextComponent(packName), StringTextComponent(packName),
StringTextComponent("Generated block textures resource pack"), StringTextComponent("Generated block textures resource pack"),
PackCompatibility.COMPATIBLE, ResourcePackInfo.Priority.TOP, true, null, true PackCompatibility.COMPATIBLE, ResourcePackInfo.Priority.TOP, true, IPackNameDecorator.DEFAULT, true
) )
override fun <T : ResourcePackInfo> addPackInfosToMap(nameToPackMap: MutableMap<String, T>, packInfoFactory: ResourcePackInfo.IFactory<T>) {
(nameToPackMap as MutableMap<String, ResourcePackInfo>).put(packName, packInfo) override fun loadPacks(p0: Consumer<ResourcePackInfo>, p1: ResourcePackInfo.IFactory) {
p0.accept(packInfo)
} }
} }
} }

View File

@@ -1,9 +0,0 @@
package mods.betterfoliage.util
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.block.material.Material
val BlockState.isSnow: Boolean get() = material.let { it == Material.SNOW }
val DIRT_BLOCKS = listOf(Blocks.DIRT, Blocks.COARSE_DIRT)

View File

@@ -1,12 +1,12 @@
package mods.betterfoliage.util package mods.betterfoliage.util
import net.minecraft.client.renderer.Quaternion
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.Direction.* import net.minecraft.util.Direction.*
import net.minecraft.util.Direction.Axis.* import net.minecraft.util.Direction.Axis.*
import net.minecraft.util.Direction.AxisDirection.NEGATIVE import net.minecraft.util.Direction.AxisDirection.NEGATIVE
import net.minecraft.util.Direction.AxisDirection.POSITIVE import net.minecraft.util.Direction.AxisDirection.POSITIVE
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.vector.Quaternion
val EPSILON_ZERO = 0.05 val EPSILON_ZERO = 0.05
val EPSILON_ONE = 0.95 val EPSILON_ONE = 0.95
@@ -55,15 +55,15 @@ val ROTATION_MATRIX: Array<IntArray> get() = arrayOf(
// Vectors // Vectors
// ================================ // ================================
operator fun Direction.times(scale: Double) = operator fun Direction.times(scale: Double) =
Double3(directionVec.x.toDouble() * scale, directionVec.y.toDouble() * scale, directionVec.z.toDouble() * scale) Double3(normal.x.toDouble() * scale, normal.y.toDouble() * scale, normal.z.toDouble() * scale)
val Direction.vec: Double3 get() = Double3(directionVec.x.toDouble(), directionVec.y.toDouble(), directionVec.z.toDouble()) val Direction.vec: Double3 get() = Double3(normal.x.toDouble(), normal.y.toDouble(), normal.z.toDouble())
operator fun BlockPos.plus(other: Int3) = BlockPos(x + other.x, y + other.y, z + other.z) operator fun BlockPos.plus(other: Int3) = BlockPos(x + other.x, y + other.y, z + other.z)
/** 3D vector of [Double]s. Offers both mutable operations, and immutable operations in operator notation. */ /** 3D vector of [Double]s. Offers both mutable operations, and immutable operations in operator notation. */
data class Double3(var x: Double, var y: Double, var z: Double) { data class Double3(var x: Double, var y: Double, var z: Double) {
constructor(x: Float, y: Float, z: Float) : this(x.toDouble(), y.toDouble(), z.toDouble()) constructor(x: Float, y: Float, z: Float) : this(x.toDouble(), y.toDouble(), z.toDouble())
constructor(dir: Direction) : this(dir.directionVec.x.toDouble(), dir.directionVec.y.toDouble(), dir.directionVec.z.toDouble()) constructor(dir: Direction) : this(dir.normal.x.toDouble(), dir.normal.y.toDouble(), dir.normal.z.toDouble())
companion object { companion object {
val zero: Double3 get() = Double3(0.0, 0.0, 0.0) val zero: Double3 get() = Double3(0.0, 0.0, 0.0)
fun weight(v1: Double3, weight1: Double, v2: Double3, weight2: Double) = fun weight(v1: Double3, weight1: Double, v2: Double3, weight2: Double) =
@@ -88,9 +88,9 @@ data class Double3(var x: Double, var y: Double, var z: Double) {
/** Rotate vector by the given [Quaternion] */ /** Rotate vector by the given [Quaternion] */
fun rotate(quat: Quaternion) = fun rotate(quat: Quaternion) =
quat.copy() quat.copy()
.apply { multiply(Quaternion(x, y, z, 0.0F)) } .apply { mul(Quaternion(x.toFloat(), y.toFloat(), z.toFloat(), 0.0F)) }
.apply { multiply(quat.copy().apply(Quaternion::conjugate)) } .apply { mul(quat.copy().apply(Quaternion::conj)) }
.let { Double3(it.x, it.y, it.z) } .let { Double3(it.i().toDouble(), it.j().toDouble(), it.k().toDouble()) }
// mutable operations // mutable operations
fun setTo(other: Double3): Double3 { x = other.x; y = other.y; z = other.z; return this } fun setTo(other: Double3): Double3 { x = other.x; y = other.y; z = other.z; return this }
@@ -120,11 +120,11 @@ data class Double3(var x: Double, var y: Double, var z: Double) {
/** 3D vector of [Int]s. Offers both mutable operations, and immutable operations in operator notation. */ /** 3D vector of [Int]s. Offers both mutable operations, and immutable operations in operator notation. */
data class Int3(var x: Int, var y: Int, var z: Int) { data class Int3(var x: Int, var y: Int, var z: Int) {
constructor(dir: Direction) : this(dir.directionVec.x, dir.directionVec.y, dir.directionVec.z) constructor(dir: Direction) : this(dir.normal.x, dir.normal.y, dir.normal.z)
constructor(offset: Pair<Int, Direction>) : this( constructor(offset: Pair<Int, Direction>) : this(
offset.first * offset.second.directionVec.x, offset.first * offset.second.normal.x,
offset.first * offset.second.directionVec.y, offset.first * offset.second.normal.y,
offset.first * offset.second.directionVec.z offset.first * offset.second.normal.z
) )
companion object { companion object {
val zero = Int3(0, 0, 0) val zero = Int3(0, 0, 0)
@@ -133,9 +133,9 @@ data class Int3(var x: Int, var y: Int, var z: Int) {
// immutable operations // immutable operations
operator fun plus(other: Int3) = Int3(x + other.x, y + other.y, z + other.z) operator fun plus(other: Int3) = Int3(x + other.x, y + other.y, z + other.z)
operator fun plus(other: Pair<Int, Direction>) = Int3( operator fun plus(other: Pair<Int, Direction>) = Int3(
x + other.first * other.second.directionVec.x, x + other.first * other.second.normal.x,
y + other.first * other.second.directionVec.y, y + other.first * other.second.normal.y,
z + other.first * other.second.directionVec.z z + other.first * other.second.normal.z
) )
operator fun unaryMinus() = Int3(-x, -y, -z) operator fun unaryMinus() = Int3(-x, -y, -z)
operator fun minus(other: Int3) = Int3(x - other.x, y - other.y, z - other.z) operator fun minus(other: Int3) = Int3(x - other.x, y - other.y, z - other.z)

View File

@@ -7,16 +7,19 @@ import net.minecraft.util.text.TextFormatting
import net.minecraft.util.text.TextFormatting.AQUA import net.minecraft.util.text.TextFormatting.AQUA
import net.minecraft.util.text.TextFormatting.GRAY import net.minecraft.util.text.TextFormatting.GRAY
fun stripTooltipDefaultText(tooltip: MutableList<String>) { //fun stripTooltipDefaultText(tooltip: MutableList<String>) {
var defaultRows = false // var defaultRows = false
val iter = tooltip.iterator() // val iter = tooltip.iterator()
while (iter.hasNext()) { // while (iter.hasNext()) {
if (iter.next().startsWith(AQUA.toString())) defaultRows = true // if (iter.next().startsWith(AQUA.toString())) defaultRows = true
if (defaultRows) iter.remove() // if (defaultRows) iter.remove()
} // }
} //}
//
//fun textComponent(msg: String, color: TextFormatting = GRAY): StringTextComponent {
// val style = Style().apply { this.color = color }
// return StringTextComponent(msg).apply { this.style = style }
//}
val styleGray = Style.EMPTY.applyFormats(GRAY)
fun textComponent(msg: String, color: TextFormatting = GRAY): StringTextComponent { fun String.asText() = StringTextComponent(this).setStyle(styleGray)
val style = Style().apply { this.color = color }
return StringTextComponent(msg).apply { this.style = style }
}

View File

@@ -1,8 +1,6 @@
package mods.betterfoliage.util package mods.betterfoliage.util
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.model.Material
import net.minecraft.client.renderer.texture.AtlasTexture
import net.minecraft.resources.IReloadableResourceManager import net.minecraft.resources.IReloadableResourceManager
import net.minecraft.resources.IResource import net.minecraft.resources.IResource
import net.minecraft.resources.IResourceManager import net.minecraft.resources.IResourceManager
@@ -19,11 +17,6 @@ operator fun ResourceLocation.plus(str: String) = ResourceLocation(namespace, pa
fun ResourceLocation.prependLocation(basePath: String) = fun ResourceLocation.prependLocation(basePath: String) =
ResourceLocation(namespace, basePath.stripEnd("/").let { "$it/$path" }) ResourceLocation(namespace, basePath.stripEnd("/").let { "$it/$path" })
val ResourceLocation.asBlockMaterial: Material get() = Material(
AtlasTexture.LOCATION_BLOCKS_TEXTURE,
this
)
/** Index operator to get a resource. */ /** Index operator to get a resource. */
operator fun IResourceManager.get(domain: String, path: String): IResource? = get(ResourceLocation(domain, path)) operator fun IResourceManager.get(domain: String, path: String): IResource? = get(ResourceLocation(domain, path))
/** Index operator to get a resource. */ /** Index operator to get a resource. */

View File

@@ -3,7 +3,6 @@ package mods.betterfoliage.util
import mods.betterfoliage.model.Color import mods.betterfoliage.model.Color
import mods.betterfoliage.model.HSB import mods.betterfoliage.model.HSB
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.model.Material
import net.minecraft.client.renderer.texture.AtlasTexture import net.minecraft.client.renderer.texture.AtlasTexture
import net.minecraft.client.renderer.texture.TextureAtlasSprite import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.resources.IResource import net.minecraft.resources.IResource
@@ -20,8 +19,8 @@ import kotlin.math.cos
import kotlin.math.sin import kotlin.math.sin
enum class Atlas(val resourceId: ResourceLocation) { enum class Atlas(val resourceId: ResourceLocation) {
BLOCKS(AtlasTexture.LOCATION_BLOCKS_TEXTURE), BLOCKS(AtlasTexture.LOCATION_BLOCKS),
PARTICLES(AtlasTexture.LOCATION_PARTICLES_TEXTURE); PARTICLES(AtlasTexture.LOCATION_PARTICLES);
/** Get the fully-qualified resource name for sprites belonging to this atlas */ /** Get the fully-qualified resource name for sprites belonging to this atlas */
fun file(resource: ResourceLocation) = ResourceLocation(resource.namespace, "textures/${resource.path}.png") fun file(resource: ResourceLocation) = ResourceLocation(resource.namespace, "textures/${resource.path}.png")
@@ -33,7 +32,7 @@ enum class Atlas(val resourceId: ResourceLocation) {
operator fun get(location: ResourceLocation) = atlas.getSprite(location) operator fun get(location: ResourceLocation) = atlas.getSprite(location)
} }
val Material.atlas: Atlas get() = Atlas.values().find { it.resourceId == atlasLocation } ?: Atlas.BLOCKS //val Spr.atlas: Atlas get() = Atlas.values().find { it.resourceId == atlasLocation } ?: Atlas.BLOCKS
inline operator fun AtlasTexture.get(res: ResourceLocation): TextureAtlasSprite? = this.getSprite(res) inline operator fun AtlasTexture.get(res: ResourceLocation): TextureAtlasSprite? = this.getSprite(res)
inline operator fun AtlasTexture.get(name: String): TextureAtlasSprite? = get(ResourceLocation(name)) inline operator fun AtlasTexture.get(name: String): TextureAtlasSprite? = get(ResourceLocation(name))

View File

@@ -1,14 +1,5 @@
#public net.minecraft.client.renderer.BlockModelRenderer$AmbientOcclusionFace
#public net.minecraft.client.renderer.BlockModelRenderer$AmbientOcclusionFace <init>
#public net.minecraft.client.renderer.BlockModelRenderer$AmbientOcclusionFace field_178206_b #vertexColorMultiplier
#public net.minecraft.client.renderer.BlockModelRenderer$AmbientOcclusionFace field_178207_c #vertexBrightness
#public net.minecraft.block.BlockState$Cache
public net.minecraft.client.renderer.chunk.ChunkRenderCache field_212408_i #world public net.minecraft.client.renderer.chunk.ChunkRenderCache field_212408_i #world
#public net.minecraft.client.renderer.texture.AtlasTexture$SheetData field_217808_d # sprites
public net.minecraft.client.renderer.BlockModelRenderer$Cache public net.minecraft.client.renderer.BlockModelRenderer$Cache
public net.minecraft.client.renderer.BlockModelRenderer field_210267_b public net.minecraft.client.renderer.BlockModelRenderer field_210267_b
public net.minecraft.client.renderer.BlockModelRenderer field_187499_a public net.minecraft.client.renderer.BlockModelRenderer field_187499_a

View File

@@ -1,7 +1,7 @@
modLoader="kotlinfml" modLoader="kotlinforforge"
loaderVersion="[1.4,)" loaderVersion="[1,)"
issueTrackerURL="https://github.com/octarine-noise/BetterFoliage/issues" issueTrackerURL="https://github.com/octarine-noise/BetterFoliage/issues"
license="MIT"
[[mods]] [[mods]]
modId="betterfoliage" modId="betterfoliage"
version="${version}" version="${version}"

View File

@@ -0,0 +1,177 @@
{
"key.betterfoliage.gui": "Open Settings",
"betterfoliage.title": "Better Foliage configuration",
"betterfoliage.global.enabled": "Enable Mod",
"betterfoliage.global.enabled.tooltip": "If set to false, BetterFoliage will not render anything",
"betterfoliage.nVidia": "nVidia GPU",
"betterfoliage.nVidia.tooltip": "Specify whether you have an nVidia GPU",
"betterfoliage.enabled": "Enable",
"betterfoliage.enabled.tooltip": "Is this feature enabled?",
"betterfoliage.hOffset": "Horizontal offset",
"betterfoliage.hOffset.tooltip": "The distance this element is shifted horizontally, in blocks",
"betterfoliage.vOffset": "Vertical offset",
"betterfoliage.vOffset.tooltip": "The distance this element is shifted vertically, in blocks",
"betterfoliage.size": "Size",
"betterfoliage.size.tooltip": "Size of this element",
"betterfoliage.heightMin": "Minimum height",
"betterfoliage.heightMin.tooltip": "Minimum height of element",
"betterfoliage.heightMax": "Maximum height",
"betterfoliage.heightMax.tooltip": "Maximum height of element",
"betterfoliage.population": "Population",
"betterfoliage.population.tooltip": "Chance (N in 64) that an eligible block will have this feature",
"betterfoliage.shaderWind": "Shader wind effects",
"betterfoliage.shaderWind.tooltip": "Apply wind effects from ShaderMod shaders to this element?",
"betterfoliage.distance": "Distance limit",
"betterfoliage.distance.tooltip": "Maximum distance from player at which to render this feature",
"betterfoliage.saturationThreshold": "Saturation threshold",
"betterfoliage.saturationThreshold.tooltip": "Color saturation cutoff between \"colorless\" blocks (using biome color) and \"colorful\" blocks (using their own specific color)",
"betterfoliage.rendererror": "§a[BetterFoliage]§f Error rendering block %s at position %s",
"betterfoliage.shaders": "Shader configuration",
"betterfoliage.shaders.tooltip": "Configure integration with shaders",
"betterfoliage.shaders.leavesId": "Leaves ID",
"betterfoliage.shaders.leavesId.tooltip": "Block ID reported to shader programs for all kinds of leaves. If your shader uses a §6block.properties§e file, you'll probably need to change this to match the shader's mappings.",
"betterfoliage.shaders.grassId": "Grass ID",
"betterfoliage.shaders.grassId.tooltip": "Block ID reported to shader programs for all grasses and crops. If your shader uses a §6block.properties§e file, you'll probably need to change this to match the shader's mappings.",
"betterfoliage.leaves": "Extra Leaves",
"betterfoliage.leaves.tooltip": "Extra round leaves on leaf blocks",
"betterfoliage.leaves.dense": "Dense mode",
"betterfoliage.leaves.dense.tooltip": "Dense mode has more round leaves",
"betterfoliage.leaves.snowEnabled": "Enable snow",
"betterfoliage.leaves.snowEnabled.tooltip": "Enable snow on extra leaves?",
"betterfoliage.leaves.hideInternal": "Hide internal leaves",
"betterfoliage.leaves.hideInternal.tooltip": "Skip rendering extra leaves if leaf block is completely surrounded by other leaves or solid blocks",
"betterfoliage.shortGrass": "Short Grass & Mycelium",
"betterfoliage.shortGrass.tooltip": "Tufts of grass/mycelium on top of appropriate blocks",
"betterfoliage.shortGrass.useGenerated": "Use generated texture for grass",
"betterfoliage.shortGrass.useGenerated.tooltip": "Generated texture is made by slicing the tallgrass texture from the active resource pack in half",
"betterfoliage.shortGrass.myceliumEnabled": "Enable Mycelium",
"betterfoliage.shortGrass.myceliumEnabled.tooltip": "Is this feature enabled for mycelium blocks?",
"betterfoliage.shortGrass.grassEnabled": "Enable Grass",
"betterfoliage.shortGrass.grassEnabled.tooltip": "Is this feature enabled for grass blocks?",
"betterfoliage.shortGrass.snowEnabled": "Enable under snow",
"betterfoliage.shortGrass.snowEnabled.tooltip": "Enable on snowed grass blocks?",
"betterfoliage.connectedGrass": "Connected grass textures",
"betterfoliage.connectedGrass.tooltip": "Connected grass textures",
"betterfoliage.connectedGrass.enabled": "Enable",
"betterfoliage.connectedGrass.enabled.tooltip": "If there is a grass block on top of a dirt block: draw grass top texture on all grass block sides,",
"betterfoliage.connectedGrass.snowEnabled": "Enable under snow",
"betterfoliage.connectedGrass.snowEnabled.tooltip": "Enable on snowed grass blocks?",
"betterfoliage.hangingGrass": "Hanging Grass",
"betterfoliage.hangingGrass.tooltip": "Grass tufts hanging down from the top edges of grass blocks",
"betterfoliage.hangingGrass.separation": "Separation",
"betterfoliage.hangingGrass.separation.tooltip": "How much the hanging grass stands out from the block",
"betterfoliage.cactus": "Better Cactus",
"betterfoliage.cactus.tooltip": "Enhance cactus with extra bits and smooth shading",
"betterfoliage.cactus.sizeVariation": "Size variation",
"betterfoliage.cactus.sizeVariation.tooltip": "Amount of random variation on cactus size",
"betterfoliage.lilypad": "Better Lilypad",
"betterfoliage.lilypad.tooltip": "Enhance lilypad with roots and occasional flowers",
"betterfoliage.lilypad.flowerChance": "Flower chance",
"betterfoliage.lilypad.flowerChance.tooltip": "Chance (N in 64) of a lilypad having a flower on it",
"betterfoliage.reed": "Reeds",
"betterfoliage.reed.tooltip": "Reeds on dirt blocks in shallow water",
"betterfoliage.reed.biomes": "Biome List",
"betterfoliage.reed.biomes.tooltip": "Configure which biomes reeds are allowed to appear in",
"betterfoliage.reed.biomes.tooltip.element": "Should reeds appear in the %s biome?",
"betterfoliage.algae": "Algae",
"betterfoliage.algae.tooltip": "Algae on dirt blocks in deep water",
"betterfoliage.algae.biomes": "Biome List",
"betterfoliage.algae.biomes.tooltip": "Configure which biomes algae is allowed to appear in",
"betterfoliage.algae.biomes.tooltip.element": "Should algae appear in the %s biome?",
"betterfoliage.coral": "Coral",
"betterfoliage.coral.tooltip": "Coral on sand blocks in deep water",
"betterfoliage.coral.size": "Coral size",
"betterfoliage.coral.size.tooltip": "Size of coral bits sticking out",
"betterfoliage.coral.crustSize": "Crust size",
"betterfoliage.coral.crustSize.tooltip": "Size of the flat coral part",
"betterfoliage.coral.chance": "Coral chance",
"betterfoliage.coral.chance.tooltip": "Chance (N in 64) of a specific face of the block to show coral",
"betterfoliage.coral.biomes": "Biome List",
"betterfoliage.coral.biomes.tooltip": "Configure which biomes coral is allowed to appear in",
"betterfoliage.coral.biomes.tooltip.element": "Should coral appear in the %s biome?",
"betterfoliage.coral.shallowWater": "Shallow water coral",
"betterfoliage.coral.shallowWater.tooltip": "Should coral appear in 1 block deep water?",
"betterfoliage.netherrack": "Netherrack Vines",
"betterfoliage.netherrack.tooltip": "Hanging Vines under netherrack",
"betterfoliage.fallingLeaves": "Falling leaves",
"betterfoliage.fallingLeaves.tooltip": "Falling leaf particle FX emitted from the bottom of leaf blocks",
"betterfoliage.fallingLeaves.speed": "Particle speed",
"betterfoliage.fallingLeaves.speed.tooltip": "Overall particle speed",
"betterfoliage.fallingLeaves.windStrength": "Wind strength",
"betterfoliage.fallingLeaves.windStrength.tooltip": "Magnitude of wind effects in good weather (spread of normal distribution centered on 0)",
"betterfoliage.fallingLeaves.stormStrength": "Storm strength",
"betterfoliage.fallingLeaves.stormStrength.tooltip": "Additional magnitude of wind effects in rainy weather (spread of normal distribution centered on 0)",
"betterfoliage.fallingLeaves.size": "Particle size",
"betterfoliage.fallingLeaves.chance": "Particle chance",
"betterfoliage.fallingLeaves.chance.tooltip": "Chance of each random render tick hitting a leaf block to spawn a particle",
"betterfoliage.fallingLeaves.perturb": "Perturbation",
"betterfoliage.fallingLeaves.perturb.tooltip": "Magnitude of perturbation effect. Adds a corkscrew-like motion to the particle synchronized to its rotation",
"betterfoliage.fallingLeaves.lifetime": "Maximum lifetime",
"betterfoliage.fallingLeaves.lifetime.tooltip": "Maximum lifetime of particle in seconds. Minimum lifetime is 60%% of this value",
"betterfoliage.fallingLeaves.opacityHack": "Opaque particles",
"betterfoliage.fallingLeaves.opacityHack.tooltip": "Stop transparent blocks obscuring particles even when particle is in front. WARNING: may cause glitches.",
"betterfoliage.risingSoul": "Rising souls",
"betterfoliage.risingSoul.tooltip": "Rising soul particle FX emitted from the top of soulsand blocks",
"betterfoliage.risingSoul.chance": "Particle chance",
"betterfoliage.risingSoul.chance.tooltip": "Chance of each random render tick hitting a soulsand block to spawn a particle",
"betterfoliage.risingSoul.speed": "Particle speed",
"betterfoliage.risingSoul.speed.tooltip": "Vertical speed of soul particles",
"betterfoliage.risingSoul.perturb": "Perturbation",
"betterfoliage.risingSoul.perturb.tooltip": "Magnitude of perturbation effect. Adds a corkscrew-like motion to the particle",
"betterfoliage.risingSoul.headSize": "Soul size",
"betterfoliage.risingSoul.headSize.tooltip": "Size of the soul particle",
"betterfoliage.risingSoul.trailSize": "Trail size",
"betterfoliage.risingSoul.trailSize.tooltip": "Initial size of the particle trail",
"betterfoliage.risingSoul.opacity": "Opacity",
"betterfoliage.risingSoul.opacity.tooltip": "Opacity of the particle effect",
"betterfoliage.risingSoul.sizeDecay": "Size decay",
"betterfoliage.risingSoul.sizeDecay.tooltip": "Trail particle size relative to its size in the previous tick",
"betterfoliage.risingSoul.opacityDecay": "Opacity decay",
"betterfoliage.risingSoul.opacityDecay.tooltip": "Trail particle opacity relative to its opacity in the previous tick",
"betterfoliage.risingSoul.lifetime": "Maximum lifetime",
"betterfoliage.risingSoul.lifetime.tooltip": "Maximum lifetime of particle effect in seconds. Minimum lifetime is 60%% of this value",
"betterfoliage.risingSoul.trailLength": "Trail length",
"betterfoliage.risingSoul.trailLength.tooltip": "Number of previous positions the particle remembers in ticks",
"betterfoliage.risingSoul.trailDensity": "Trail density",
"betterfoliage.risingSoul.trailDensity.tooltip": "Render every Nth previous position in the particle trail",
"betterfoliage.roundLogs": "Round Logs",
"betterfoliage.roundLogs.tooltip": "Round Logs",
"betterfoliage.roundLogs.connectSolids": "Connect to solid",
"betterfoliage.roundLogs.connectSolids.tooltip": "Connect round blocks to solid full blocks?",
"betterfoliage.roundLogs.connectPerpendicular": "Connect to perpendicular logs",
"betterfoliage.roundLogs.connectPerpendicular.tooltip": "Connect round logs to perpendicular logs along its axis?",
"betterfoliage.roundLogs.lenientConnect": "Lenient rounding",
"betterfoliage.roundLogs.lenientConnect.tooltip": "Connect parallel round logs in an L-shape too, not just 2x2",
"betterfoliage.roundLogs.connectGrass": "Connect Grass",
"betterfoliage.roundLogs.connectGrass.tooltip": "Render grass block under trees instead of dirt if there is grass nearby",
"betterfoliage.roundLogs.radiusSmall": "Chamfer radius",
"betterfoliage.roundLogs.radiusSmall.tooltip": "How much to chop off from the log corner",
"betterfoliage.roundLogs.radiusLarge": "Connected chamfer radius",
"betterfoliage.roundLogs.radiusLarge.tooltip": "How much to chop off from the outer corner of connected logs",
"betterfoliage.roundLogs.dimming": "Dimming",
"betterfoliage.roundLogs.dimming.tooltip": "Amount to darken obscured log faces",
"betterfoliage.roundLogs.zProtection": "Z-Protection",
"betterfoliage.roundLogs.zProtection.tooltip": "Amount to scale parallel log connection bits to stop Z-fighting (flickering). Try to set it as high as possible without having glitches.",
"betterfoliage.roundLogs.defaultY": "Default to vertical",
"betterfoliage.roundLogs.defaultY.tooltip": "If true, log blocks where the orientation cannot be determined will be rendered as vertical. Otherwise, they will be rendered as cube blocks.",
"betterfoliage.roundLogs.plantsOnly": "Plants only",
"betterfoliage.roundLogs.plantsOnly.tooltip": "If true, only blocks with plant materials (wood, grass) will be rounded. If false, all column blocks will be rounded, including stone columns."
}

View File

@@ -1,250 +0,0 @@
key.betterfoliage.gui=Open Settings
betterfoliage.global.enabled=Enable Mod
betterfoliage.global.enabled.tooltip=If set to false, BetterFoliage will not render anything
betterfoliage.global.nVidia=nVidia GPU
betterfoliage.global.nVidia.tooltip=Specify whether you have an nVidia GPU
betterfoliage.enabled=Enable
betterfoliage.enabled.tooltip=Is this feature enabled?
betterfoliage.hOffset=Horizontal offset
betterfoliage.hOffset.tooltip=The distance this element is shifted horizontally, in blocks
betterfoliage.vOffset=Vertical offset
betterfoliage.vOffset.tooltip=The distance this element is shifted vertically, in blocks
betterfoliage.size=Size
betterfoliage.size.tooltip=Size of this element
betterfoliage.heightMin=Minimum height
betterfoliage.heightMin.tooltip=Minimum height of element
betterfoliage.heightMax=Maximum height
betterfoliage.heightMax.tooltip=Maximum height of element
betterfoliage.population=Population
betterfoliage.population.tooltip=Chance (N in 64) that an eligible block will have this feature
betterfoliage.shaderWind=Shader wind effects
betterfoliage.shaderWind.tooltip=Apply wind effects from ShaderMod shaders to this element?
betterfoliage.distance=Distance limit
betterfoliage.distance.tooltip=Maximum distance from player at which to render this feature
betterfoliage.rendererror=§a[BetterFoliage]§f Error rendering block %s at position %s
betterfoliage.blocks=Block Types
betterfoliage.blocks.tooltip=Configure lists of block classes that will have specific features applied to them
betterfoliage.blocks.dirtWhitelist=Dirt Whitelist
betterfoliage.blocks.dirtBlacklist=Dirt Blacklist
betterfoliage.blocks.dirtWhitelist.arrayEntry=%d entries
betterfoliage.blocks.dirtBlacklist.arrayEntry=%d entries
betterfoliage.blocks.dirtWhitelist.tooltip=Blocks recognized as Dirt. Has an impact on Reeds, Algae, Connected Grass
betterfoliage.blocks.dirtBlacklist.tooltip=Blocks never accepted as Dirt. Has an impact on Reeds, Algae, Connected Grass
betterfoliage.blocks.grassClassesWhitelist=Grass Whitelist
betterfoliage.blocks.grassClassesBlacklist=Grass Blacklist
betterfoliage.blocks.grassClassesWhitelist.arrayEntry=%d entries
betterfoliage.blocks.grassClassesBlacklist.arrayEntry=%d entries
betterfoliage.blocks.grassModels=Grass Models
betterfoliage.blocks.grassModels.arrayEntry=%d entries
betterfoliage.blocks.grassWhitelist.tooltip=Blocks recognized as Grass. Has an impact on Short Grass, Connected Grass
betterfoliage.blocks.grassBlacklist.tooltip=Blocks never accepted as Grass. Has an impact on Short Grass, Connected Grass
betterfoliage.blocks.grassModels.tooltip=Models and textures recognized for grass blocks
betterfoliage.blocks.leavesClassesWhitelist=Leaves Whitelist
betterfoliage.blocks.leavesClassesBlacklist=Leaves Blacklist
betterfoliage.blocks.leavesClassesWhitelist.arrayEntry=%d entries
betterfoliage.blocks.leavesClassesBlacklist.arrayEntry=%d entries
betterfoliage.blocks.leavesModels=Leaves Models
betterfoliage.blocks.leavesModels.arrayEntry=%d entries
betterfoliage.blocks.leavesClassesWhitelist.tooltip=Blocks recognized as Leaves. Has an impact on Extra Leaves, Falling Leaves. Leaves will render with leaves block ID in shader programs
betterfoliage.blocks.leavesClassesBlacklist.tooltip=Blocks never accepted as Leaves. Has an impact on Extra Leaves, Falling Leaves. Leaves will render with leaves block ID in shader programs
betterfoliage.blocks.leavesModels.tooltip=Models and textures recognized for leaves blocks
betterfoliage.blocks.cropsWhitelist=Crop Whitelist
betterfoliage.blocks.cropsBlacklist=Crop Blacklist
betterfoliage.blocks.cropsWhitelist.arrayEntry=%d entries
betterfoliage.blocks.cropsBlacklist.arrayEntry=%d entries
betterfoliage.blocks.cropsWhitelist.tooltip=Blocks recognized as crops. Crops will render with tallgrass block ID in shader programs
betterfoliage.blocks.cropsBlacklist.tooltip=Blocks never accepted as crops. Crops will render with tallgrass block ID in shader programs
betterfoliage.blocks.logClassesWhitelist=Wood Log Whitelist
betterfoliage.blocks.logClassesBlacklist=Wood Log Blacklist
betterfoliage.blocks.logClassesWhitelist.arrayEntry=%d entries
betterfoliage.blocks.logClassesBlacklist.arrayEntry=%d entries
betterfoliage.blocks.logModels=Wood Log Models
betterfoliage.blocks.logModels.arrayEntry=%d entries
betterfoliage.blocks.logClassesWhitelist.tooltip=Blocks recognized as wooden logs. Has an impact on Rounded Logs
betterfoliage.blocks.logClassesBlacklist.tooltip=Blocks never accepted as wooden logs. Has an impact on Rounded Logs
betterfoliage.blocks.logModels.tooltip=Models and textures recognized for wood log blocks
betterfoliage.blocks.sandWhitelist=Sand Whitelist
betterfoliage.blocks.sandBlacklist=Sand Blacklist
betterfoliage.blocks.sandWhitelist.arrayEntry=%d entries
betterfoliage.blocks.sandBlacklist.arrayEntry=%d entries
betterfoliage.blocks.sandWhitelist.tooltip=Blocks recognized as Sand. Has an impact on Coral
betterfoliage.blocks.sandBlacklist.tooltip=Blocks never accepted Sand. Has an impact on Coral
betterfoliage.blocks.lilypadWhitelist=Lilypad Whitelist
betterfoliage.blocks.lilypadBlacklist=Lilypad Blacklist
betterfoliage.blocks.lilypadWhitelist.arrayEntry=%d entries
betterfoliage.blocks.lilypadBlacklist.arrayEntry=%d entries
betterfoliage.blocks.lilypadWhitelist.tooltip=Blocks recognized as Lilypad. Has an impact on Better Lilypad
betterfoliage.blocks.lilypadBlacklist.tooltip=Blocks never accepted Lilypad. Has an impact on Better Lilypad
betterfoliage.blocks.cactusWhitelist=Cactus Whitelist
betterfoliage.blocks.cactusBlacklist=Cactus Blacklist
betterfoliage.blocks.cactusWhitelist.arrayEntry=%d entries
betterfoliage.blocks.cactusBlacklist.arrayEntry=%d entries
betterfoliage.blocks.cactusWhitelist.tooltip=Blocks recognized as Cactus. Has an impact on Better Cactus
betterfoliage.blocks.cactusBlacklist.tooltip=Blocks never accepted Cactus. Has an impact on Better Cactus
betterfoliage.blocks.myceliumWhitelist=Mycelium Whitelist
betterfoliage.blocks.myceliumBlacklist=Mycelium Blacklist
betterfoliage.blocks.myceliumWhitelist.arrayEntry=%d entries
betterfoliage.blocks.myceliumBlacklist.arrayEntry=%d entries
betterfoliage.blocks.myceliumWhitelist.tooltip=Blocks recognized as Mycelium. Has an impact on Better Grass
betterfoliage.blocks.myceliumBlacklist.tooltip=Blocks never accepted Mycelium. Has an impact on Better Grass
betterfoliage.blocks.netherrackWhitelist=Netherrack Whitelist
betterfoliage.blocks.netherrackBlacklist=Netherrack Blacklist
betterfoliage.blocks.netherrackWhitelist.arrayEntry=%d entries
betterfoliage.blocks.netherrackBlacklist.arrayEntry=%d entries
betterfoliage.blocks.netherrackWhitelist.tooltip=Blocks recognized as Netherrack. Has an impact on Netherrack Vines
betterfoliage.blocks.netherrackBlacklist.tooltip=Blocks never accepted Netherrack. Has an impact on Netherrack Vines
betterfoliage.shaders=Shader configuration
betterfoliage.shaders.tooltip=Configure integration with shaders
betterfoliage.shaders.leavesId=Leaves ID
betterfoliage.shaders.leavesId.tooltip=Block ID reported to shader programs for all kinds of leaves. If your shader uses a §6block.properties§e file, you'll probably need to change this to match the shader's mappings.
betterfoliage.shaders.grassId=Grass ID
betterfoliage.shaders.grassId.tooltip=Block ID reported to shader programs for all grasses and crops. If your shader uses a §6block.properties§e file, you'll probably need to change this to match the shader's mappings.
betterfoliage.leaves=Extra Leaves
betterfoliage.leaves.tooltip=Extra round leaves on leaf blocks
betterfoliage.leaves.dense=Dense mode
betterfoliage.leaves.dense.tooltip=Dense mode has more round leaves
betterfoliage.leaves.snowEnabled=Enable snow
betterfoliage.leaves.snowEnabled.tooltip=Enable snow on extra leaves?
betterfoliage.leaves.hideInternal=Hide internal leaves
betterfoliage.leaves.hideInternal.tooltip=Skip rendering extra leaves if leaf block is completely surrounded by other leaves or solid blocks
betterfoliage.shortGrass=Short Grass & Mycelium
betterfoliage.shortGrass.tooltip=Tufts of grass/mycelium on top of appropriate blocks
betterfoliage.shortGrass.useGenerated=Use generated texture for grass
betterfoliage.shortGrass.useGenerated.tooltip=Generated texture is made by slicing the tallgrass texture from the active resource pack in half
betterfoliage.shortGrass.myceliumEnabled=Enable Mycelium
betterfoliage.shortGrass.myceliumEnabled.tooltip=Is this feature enabled for mycelium blocks?
betterfoliage.shortGrass.grassEnabled=Enable Grass
betterfoliage.shortGrass.grassEnabled.tooltip=Is this feature enabled for grass blocks?
betterfoliage.shortGrass.snowEnabled=Enable under snow
betterfoliage.shortGrass.snowEnabled.tooltip=Enable on snowed grass blocks?
betterfoliage.shortGrass.saturationThreshold=Saturation threshold
betterfoliage.shortGrass.saturationThreshold.tooltip=Color saturation cutoff between "colorless" blocks (using biome color) and "colorful" blocks (using their own specific color)
betterfoliage.hangingGrass=Hanging Grass
betterfoliage.hangingGrass.tooltip=Grass tufts hanging down from the top edges of grass blocks
betterfoliage.hangingGrass.separation=Separation
betterfoliage.hangingGrass.separation.tooltip=How much the hanging grass stands out from the block
betterfoliage.cactus=Better Cactus
betterfoliage.cactus.tooltip=Enhance cactus with extra bits and smooth shading
betterfoliage.cactus.sizeVariation=Size variation
betterfoliage.cactus.sizeVariation.tooltip=Amount of random variation on cactus size
betterfoliage.lilypad=Better Lilypad
betterfoliage.lilypad.tooltip=Enhance lilypad with roots and occasional flowers
betterfoliage.lilypad.flowerChance=Flower chance
betterfoliage.lilypad.flowerChance.tooltip=Chance (N in 64) of a lilypad having a flower on it
betterfoliage.reed=Reeds
betterfoliage.reed.tooltip=Reeds on dirt blocks in shallow water
betterfoliage.reed.biomes=Biome List
betterfoliage.reed.biomes.tooltip=Configure which biomes reeds are allowed to appear in
betterfoliage.reed.biomes.tooltip.element=Should reeds appear in the %s biome?
betterfoliage.algae=Algae
betterfoliage.algae.tooltip=Algae on dirt blocks in deep water
betterfoliage.algae.biomes=Biome List
betterfoliage.algae.biomes.tooltip=Configure which biomes algae is allowed to appear in
betterfoliage.algae.biomes.tooltip.element=Should algae appear in the %s biome?
betterfoliage.coral=Coral
betterfoliage.coral.tooltip=Coral on sand blocks in deep water
betterfoliage.coral.size=Coral size
betterfoliage.coral.size.tooltip=Size of coral bits sticking out
betterfoliage.coral.crustSize=Crust size
betterfoliage.coral.crustSize.tooltip=Size of the flat coral part
betterfoliage.coral.chance=Coral chance
betterfoliage.coral.chance.tooltip=Chance (N in 64) of a specific face of the block to show coral
betterfoliage.coral.biomes=Biome List
betterfoliage.coral.biomes.tooltip=Configure which biomes coral is allowed to appear in
betterfoliage.coral.biomes.tooltip.element=Should coral appear in the %s biome?
betterfoliage.coral.shallowWater=Shallow water coral
betterfoliage.coral.shallowWater.tooltip=Should coral appear in 1 block deep water?
betterfoliage.netherrack=Netherrack Vines
betterfoliage.netherrack.tooltip=Hanging Vines under netherrack
betterfoliage.fallingLeaves=Falling leaves
betterfoliage.fallingLeaves.tooltip=Falling leaf particle FX emitted from the bottom of leaf blocks
betterfoliage.fallingLeaves.speed=Particle speed
betterfoliage.fallingLeaves.speed.tooltip=Overall particle speed
betterfoliage.fallingLeaves.windStrength=Wind strength
betterfoliage.fallingLeaves.windStrength.tooltip=Magnitude of wind effects in good weather (spread of normal distribution centered on 0)
betterfoliage.fallingLeaves.stormStrength=Storm strength
betterfoliage.fallingLeaves.stormStrength.tooltip=Additional magnitude of wind effects in rainy weather (spread of normal distribution centered on 0)
betterfoliage.fallingLeaves.size=Particle size
betterfoliage.fallingLeaves.chance=Particle chance
betterfoliage.fallingLeaves.chance.tooltip=Chance of each random render tick hitting a leaf block to spawn a particle
betterfoliage.fallingLeaves.perturb=Perturbation
betterfoliage.fallingLeaves.perturb.tooltip=Magnitude of perturbation effect. Adds a corkscrew-like motion to the particle synchronized to its rotation
betterfoliage.fallingLeaves.lifetime=Maximum lifetime
betterfoliage.fallingLeaves.lifetime.tooltip=Maximum lifetime of particle in seconds. Minimum lifetime is 60%% of this value
betterfoliage.fallingLeaves.opacityHack=Opaque particles
betterfoliage.fallingLeaves.opacityHack.tooltip=Stop transparent blocks obscuring particles even when particle is in front. WARNING: may cause glitches.
betterfoliage.risingSoul=Rising souls
betterfoliage.risingSoul.tooltip=Rising soul particle FX emitted from the top of soulsand blocks
betterfoliage.risingSoul.chance=Particle chance
betterfoliage.risingSoul.chance.tooltip=Chance of each random render tick hitting a soulsand block to spawn a particle
betterfoliage.risingSoul.speed=Particle speed
betterfoliage.risingSoul.speed.tooltip=Vertical speed of soul particles
betterfoliage.risingSoul.perturb=Perturbation
betterfoliage.risingSoul.perturb.tooltip=Magnitude of perturbation effect. Adds a corkscrew-like motion to the particle
betterfoliage.risingSoul.headSize=Soul size
betterfoliage.risingSoul.headSize.tooltip=Size of the soul particle
betterfoliage.risingSoul.trailSize=Trail size
betterfoliage.risingSoul.trailSize.tooltip=Initial size of the particle trail
betterfoliage.risingSoul.opacity=Opacity
betterfoliage.risingSoul.opacity.tooltip=Opacity of the particle effect
betterfoliage.risingSoul.sizeDecay=Size decay
betterfoliage.risingSoul.sizeDecay.tooltip=Trail particle size relative to its size in the previous tick
betterfoliage.risingSoul.opacityDecay=Opacity decay
betterfoliage.risingSoul.opacityDecay.tooltip=Trail particle opacity relative to its opacity in the previous tick
betterfoliage.risingSoul.lifetime=Maximum lifetime
betterfoliage.risingSoul.lifetime.tooltip=Maximum lifetime of particle effect in seconds. Minimum lifetime is 60%% of this value
betterfoliage.risingSoul.trailLength=Trail length
betterfoliage.risingSoul.trailLength.tooltip=Number of previous positions the particle remembers in ticks
betterfoliage.risingSoul.trailDensity=Trail density
betterfoliage.risingSoul.trailDensity.tooltip=Render every Nth previous position in the particle trail
betterfoliage.connectedGrass=Connected grass textures
betterfoliage.connectedGrass.enabled=Enable
betterfoliage.connectedGrass.enabled.tooltip=If there is a grass block on top of a dirt block: draw grass top texture on all grass block sides,
betterfoliage.roundLogs=Round Logs
betterfoliage.roundLogs.tooltip=Connect round blocks to solid full blocks?
betterfoliage.roundLogs.connectSolids=Connect to solid
betterfoliage.roundLogs.connectSolids.tooltip=Connect round blocks to solid full blocks?
betterfoliage.roundLogs.connectPerpendicular=Connect to perpendicular logs
betterfoliage.roundLogs.connectPerpendicular.tooltip=Connect round logs to perpendicular logs along its axis?
betterfoliage.roundLogs.lenientConnect=Lenient rounding
betterfoliage.roundLogs.lenientConnect.tooltip=Connect parallel round logs in an L-shape too, not just 2x2
betterfoliage.roundLogs.connectGrass=Connect Grass
betterfoliage.roundLogs.connectGrass.tooltip=Render grass block under trees instead of dirt if there is grass nearby
betterfoliage.roundLogs.radiusSmall=Chamfer radius
betterfoliage.roundLogs.radiusSmall.tooltip=How much to chop off from the log corner
betterfoliage.roundLogs.radiusLarge=Connected chamfer radius
betterfoliage.roundLogs.radiusLarge.tooltip=How much to chop off from the outer corner of connected logs
betterfoliage.roundLogs.dimming=Dimming
betterfoliage.roundLogs.dimming.tooltip=Amount to darken obscured log faces
betterfoliage.roundLogs.zProtection=Z-Protection
betterfoliage.roundLogs.zProtection.tooltip=Amount to scale parallel log connection bits to stop Z-fighting (flickering). Try to set it as high as possible without having glitches.
betterfoliage.roundLogs.defaultY=Default to vertical
betterfoliage.roundLogs.defaultY.tooltip=If true, log blocks where the orientation cannot be determined will be rendered as vertical. Otherwise, they will be rendered as cube blocks.

View File

@@ -0,0 +1,155 @@
{
"key.betterfoliage.gui": "설정",
"betterfoliage.global.enabled": "모드 활성화",
"betterfoliage.global.enabled.tooltip": "비활성화 할 경우, 환경강화모드 렌더링이 보이지 않습니다.",
"betterfoliage.enabled": "활성화",
"betterfoliage.enabled.tooltip": "이 기능이 활성화 되어 있습니까?",
"betterfoliage.hOffset": "수평(가로) 상쇄시키다",
"betterfoliage.hOffset.tooltip": "이 성분이 블럭 수평으로 이동된다.",
"betterfoliage.vOffset": "수직(세로) 상쇄시키다",
"betterfoliage.vOffset.tooltip": "이 성분이 블럭 수직으로 이동된다.",
"betterfoliage.size": "사이즈(크기)",
"betterfoliage.size.tooltip": "사이즈(크기)의 최소",
"betterfoliage.heightMin": "최소한 높이",
"betterfoliage.heightMin.tooltip": "높이 최소한의 최소",
"betterfoliage.heightMax": "최대한 높이",
"betterfoliage.heightMax.tooltip": "높이 최대한의 최소",
"betterfoliage.population": "주민",
"betterfoliage.population.tooltip": "자격을 갖춘 블럭의 기능 확률(N 분의 64)",
"betterfoliage.shaderWind": "쉐이더 바람 효과",
"betterfoliage.shaderWind.tooltip": "바람효과를 쉐이더에 적용시키겠습니까?",
"betterfoliage.distance": "거리 제한",
"betterfoliage.distance.tooltip": "이 기능을 렌더링하는 플레이어의 최대거리",
"betterfoliage.saturationThreshold": "채도 임계값",
"betterfoliage.saturationThreshold.tooltip": "(특정 색상을 사용하여)\"무채색\"블록과 (바이옴 색을 사용하여)\"화려한\"블록 사이의 채도 차단",
"betterfoliage.leaves": "잎 추가",
"betterfoliage.leaves.tooltip": "둥글게 나뭇잎을 추가시켜줍니다.",
"betterfoliage.leaves.dense": "조밀한 모드",
"betterfoliage.leaves.dense.tooltip": "조밀한 모드는 둥근 나뭇잎을 더 추가시켜줍니다.",
"betterfoliage.shortGrass": "이쁜 잔디 & 균사체",
"betterfoliage.shortGrass.tooltip": "블록 상단에 잔디 / 균사체",
"betterfoliage.shortGrass.useGenerated": "잔디텍스쳐를 활성화 합니다.",
"betterfoliage.shortGrass.useGenerated.tooltip": "소스팩의 일부분에 활성화 되어있는 큰잔디 텍스쳐를 생성시킵니다.",
"betterfoliage.shortGrass.myceliumEnabled": "균사체 활성화",
"betterfoliage.shortGrass.myceliumEnabled.tooltip": "균사체 블록에 있는 기능을 활성화 시키겠습니까?",
"betterfoliage.shortGrass.grassEnabled": "잔디 활성화",
"betterfoliage.shortGrass.grassEnabled.tooltip": "잔디 블록에 있는 기능을 활성화 시키겠습니까?",
"betterfoliage.shortGrass.snowEnabled": "눈 활성화",
"betterfoliage.shortGrass.snowEnabled.tooltip": "잔디 블록위에 있는 눈을 활성화 시키겠습니까?",
"betterfoliage.hangingGrass": "매달려있는 잔디",
"betterfoliage.hangingGrass.tooltip": "잔디 블록 상단 가장자리에서 아래로 매달려 있는 잔디 다발",
"betterfoliage.hangingGrass.separation": "분리",
"betterfoliage.hangingGrass.separation.tooltip": "잔디블럭에 매달려있는 잔디의 양 ",
"betterfoliage.cactus": "선인장",
"betterfoliage.cactus.tooltip": "선인장의 비트 수와 부드러운 그림자를 추가",
"betterfoliage.cactus.sizeVariation": "사이즈 변화",
"betterfoliage.cactus.sizeVariation.tooltip": "선인장의 사이즈 크기를 무작위 변화 시킵니다.",
"betterfoliage.lilypad": "연꽃잎",
"betterfoliage.lilypad.tooltip": "연꽃의 뿌리와 약간의 꽃 추가",
"betterfoliage.lilypad.flowerChance": "꽃 확률",
"betterfoliage.lilypad.flowerChance.tooltip": "연꽃 위에 있는 꽃 확률(N 분의 64)",
"betterfoliage.reed": "갈대",
"betterfoliage.reed.tooltip": "물 속에서 흙블럭 위에 있는 갈대",
"betterfoliage.reed.biomes": "바이옴 리스트",
"betterfoliage.reed.biomes.tooltip": "갈대를 바이옴에 따라 표시",
"betterfoliage.reed.biomes.tooltip.element": "갈대를 %s 바이옴에 따라 나타내시겠습니까? ",
"betterfoliage.algae": "해조류",
"betterfoliage.algae.tooltip": "깊은 물 속 흙 블럭 위에 있는 해조류",
"betterfoliage.algae.biomes": "바이옴 리스트",
"betterfoliage.algae.biomes.tooltip": "해조류를 바이옴에 따라 표시",
"betterfoliage.algae.biomes.tooltip.element": "해조류를 %s 바이옴에 따라 나타내시겠습니까? ",
"betterfoliage.coral": "산호",
"betterfoliage.coral.tooltip": "깊은 물 속 모래 블럭 위에있는 산호",
"betterfoliage.coral.size": "산호 사이즈(크기)",
"betterfoliage.coral.size.tooltip": "산호 이미지만큼 적용",
"betterfoliage.coral.crustSize": "껍질 크기",
"betterfoliage.coral.crustSize.tooltip": "산호 부분의 크기 ",
"betterfoliage.coral.chance": "산호 확률",
"betterfoliage.coral.chance.tooltip": "산호를 특정블록에 표시하는 확률(N 분의 64)",
"betterfoliage.coral.biomes": "바이옴 리스트",
"betterfoliage.coral.biomes.tooltip": "산호를 바이옴에 따라 표시",
"betterfoliage.coral.biomes.tooltip.element": "산호를 %s 바이옴에 따라 나타내시겠습니까?",
"betterfoliage.coral.shallowWater": "얕은 물 산호",
"betterfoliage.coral.shallowWater.tooltip": "산호를 깊은 물에 표시하시겠습니까?",
"betterfoliage.netherrack": "네더랙 덩굴",
"betterfoliage.netherrack.tooltip": "네더랙에 매달려있는 덩굴",
"betterfoliage.fallingLeaves": "떨어지는 나뭇잎",
"betterfoliage.fallingLeaves.tooltip": "잎 블록에서 바닥으로 떨어지는 잎 파티클",
"betterfoliage.fallingLeaves.speed": "파티클 속도",
"betterfoliage.fallingLeaves.speed.tooltip": "전체 파티클 속도",
"betterfoliage.fallingLeaves.windStrength": "바람 세기",
"betterfoliage.fallingLeaves.windStrength.tooltip": "날씨 바람 추가효과 (0을 중심으로 정규분포의 확산)",
"betterfoliage.fallingLeaves.stormStrength": "폭풍 세기",
"betterfoliage.fallingLeaves.stormStrength.tooltip": "비 날씨에 바람 추가효과 (0을 중심으로 정규분포의 확산)",
"betterfoliage.fallingLeaves.size": "파티클 크기",
"betterfoliage.fallingLeaves.chance": "파티클 확률",
"betterfoliage.fallingLeaves.chance.tooltip": "잎 파티클 랜덤 확률 설정",
"betterfoliage.fallingLeaves.perturb": "움직임",
"betterfoliage.fallingLeaves.perturb.tooltip": "움직임 효과의 크기. 코르크 같은 움직임을 추가합니다.",
"betterfoliage.fallingLeaves.lifetime": "파티클 지속시간",
"betterfoliage.fallingLeaves.lifetime.tooltip": "최대 파티클 지속시간을 설정합니다. 최소 지속시간은 60%입니다.",
"betterfoliage.fallingLeaves.opacityHack": "불투명 파티클",
"betterfoliage.fallingLeaves.opacityHack.tooltip": "파티클이 앞에 있어도 파티클을 가리는 투명블럭을 없앱니다. 경고: 오류주의",
"betterfoliage.risingSoul": "소울 상승",
"betterfoliage.risingSoul.tooltip": "소울 블럭에서 올라오는 파티클",
"betterfoliage.risingSoul.chance": "파티클 수정",
"betterfoliage.risingSoul.chance.tooltip": "소울 파티클 랜덤 확률 설정",
"betterfoliage.risingSoul.speed": "파티클 속도",
"betterfoliage.risingSoul.speed.tooltip": "파티클 속도",
"betterfoliage.risingSoul.perturb": "움직임",
"betterfoliage.risingSoul.perturb.tooltip": "움직임 효과의 크기. 코르크 같은 움직임을 추가합니다.",
"betterfoliage.risingSoul.headSize": "소울 크기",
"betterfoliage.risingSoul.headSize.tooltip": "소울 파티클의 크기",
"betterfoliage.risingSoul.trailSize": "자취 사이즈",
"betterfoliage.risingSoul.trailSize.tooltip": "자취의 크기",
"betterfoliage.risingSoul.opacity": "불투명",
"betterfoliage.risingSoul.opacity.tooltip": "파티클의 불투명",
"betterfoliage.risingSoul.sizeDecay": "크기 감소",
"betterfoliage.risingSoul.sizeDecay.tooltip": "상대적인 자취 파티클 크기",
"betterfoliage.risingSoul.opacityDecay": "불투명 감소",
"betterfoliage.risingSoul.opacityDecay.tooltip": "상대적인 입자의 파티클 불투명도",
"betterfoliage.risingSoul.lifetime": "최대 지속시간",
"betterfoliage.risingSoul.lifetime.tooltip": "최대 파티클 지속시간을 설정합니다. 최소 지속시간은 60%입니다.",
"betterfoliage.risingSoul.trailLength": "자취의 세기",
"betterfoliage.risingSoul.trailLength.tooltip": "이전 파티클 틱으로 자취를 생성합니다.",
"betterfoliage.risingSoul.trailDensity": "자취의 밀도",
"betterfoliage.risingSoul.trailDensity.tooltip": "파티클 자취를 모두 렌더링 합니다.",
"betterfoliage.connectedGrass": "잔디 연결 텍스쳐",
"betterfoliage.connectedGrass.enabled": "활성화",
"betterfoliage.connectedGrass.enabled.tooltip": "잔디블록이 흙블록 위에 있을 경우 잔디블록 윗텍스쳐를 옆텍스쳐에 전부 씌웁니다.",
"betterfoliage.roundLogs": "둥근 나무",
"betterfoliage.roundLogs.tooltip": "둥근부분을 블럭과 연결.",
"betterfoliage.roundLogs.connectSolids": "블럭과 연결",
"betterfoliage.roundLogs.connectSolids.tooltip": "둥근부분을 블럭과 연결.",
"betterfoliage.roundLogs.connectPerpendicular": "나무 세로부분과 연결",
"betterfoliage.roundLogs.connectPerpendicular.tooltip": "나무 세로부분을 나무부분끼리 연결",
"betterfoliage.roundLogs.lenientConnect": "부드럽게 둥글게 연결",
"betterfoliage.roundLogs.lenientConnect.tooltip": "2x2사이즈처럼 나무 평형된 부분끼리 서로 연결합니다.",
"betterfoliage.roundLogs.connectGrass": "잔디 연결 텍스쳐",
"betterfoliage.roundLogs.connectGrass.tooltip": "잔디가 근처에 있을 경우 나무 아래 잔디 블록을 렌더링",
"betterfoliage.roundLogs.radiusSmall": "모서리 깎는 반지름",
"betterfoliage.roundLogs.radiusSmall.tooltip": "나무 모서리 깎는 정도",
"betterfoliage.roundLogs.radiusLarge": "모서리 깎는 부분 연결",
"betterfoliage.roundLogs.radiusLarge.tooltip": "나무 모서리 부분을 연결",
"betterfoliage.roundLogs.dimming": "조광",
"betterfoliage.roundLogs.dimming.tooltip": "나무 표면부분을 어둡게하는 양",
"betterfoliage.roundLogs.zProtection": "Z-Protection",
"betterfoliage.roundLogs.zProtection.tooltip": "Amount to scale parallel log connection bits to stop Z-fighting (flickering). Try to set it as high as possible without having glitches.",
"betterfoliage.roundLogs.defaultY": "수직선에대한 기본값",
"betterfoliage.roundLogs.defaultY.tooltip": "true 일경우, 나무 블럭이 수직선에대한 렌더링을 할수가 없습니다. 그렇지 아니하면, 네모난 블럭으로 렌더링 될것임니다."
}

View File

@@ -1,216 +0,0 @@
key.betterfoliage.gui=설정
betterfoliage.global.enabled=모드 활성화
betterfoliage.global.enabled.tooltip=비활성화 할 경우, 환경강화모드 렌더링이 보이지 않습니다.
betterfoliage.enabled=활성화
betterfoliage.enabled.tooltip=이 기능이 활성화 되어 있습니까?
betterfoliage.hOffset=수평(가로) 상쇄시키다
betterfoliage.hOffset.tooltip=이 성분이 블럭 수평으로 이동된다.
betterfoliage.vOffset=수직(세로) 상쇄시키다
betterfoliage.vOffset.tooltip=이 성분이 블럭 수직으로 이동된다.
betterfoliage.size=사이즈(크기)
betterfoliage.size.tooltip=사이즈(크기)의 최소
betterfoliage.heightMin=최소한 높이
betterfoliage.heightMin.tooltip=높이 최소한의 최소
betterfoliage.heightMax=최대한 높이
betterfoliage.heightMax.tooltip=높이 최대한의 최소
betterfoliage.population=주민
betterfoliage.population.tooltip=자격을 갖춘 블럭의 기능 확률(N 분의 64)
betterfoliage.shaderWind=쉐이더 바람 효과
betterfoliage.shaderWind.tooltip=바람효과를 쉐이더에 적용시키겠습니까?
betterfoliage.distance=거리 제한
betterfoliage.distance.tooltip=이 기능을 렌더링하는 플레이어의 최대거리
betterfoliage.blocks=블록 타입
betterfoliage.blocks.tooltip=세팅 된 것에 따라 블록이 바뀔 것입니다.
betterfoliage.blocks.dirtWhitelist=흙 허용목록
betterfoliage.blocks.dirtBlacklist=흙 차단목록
betterfoliage.blocks.dirtWhitelist.arrayEntry=%d entries
betterfoliage.blocks.dirtBlacklist.arrayEntry=%d entries
betterfoliage.blocks.grassWhitelist=잔디 허용목록
betterfoliage.blocks.grassBlacklist=잔디 차단목록
betterfoliage.blocks.grassWhitelist.arrayEntry=%d entries
betterfoliage.blocks.grassBlacklist.arrayEntry=%d entries
betterfoliage.blocks.leavesWhitelist=잎 허용목록
betterfoliage.blocks.leavesBlacklist=잎 차단목록
betterfoliage.blocks.leavesWhitelist.arrayEntry=%d entries
betterfoliage.blocks.leavesBlacklist.arrayEntry=%d entries
betterfoliage.blocks.cropsWhitelist=농작물 허용목록
betterfoliage.blocks.cropsBlacklist=농작물 차단목록
betterfoliage.blocks.cropsWhitelist.arrayEntry=%d entries
betterfoliage.blocks.cropsBlacklist.arrayEntry=%d entries
betterfoliage.blocks.logsWhitelist=나무 허용목록
betterfoliage.blocks.logsBlacklist=나무 차단목록
betterfoliage.blocks.logsWhitelist.arrayEntry=%d entries
betterfoliage.blocks.logsBlacklist.arrayEntry=%d entries
betterfoliage.blocks.sandWhitelist=모래 허용목록
betterfoliage.blocks.sandBlacklist=모래 차단목록
betterfoliage.blocks.sandWhitelist.arrayEntry=%d entries
betterfoliage.blocks.sandBlacklist.arrayEntry=%d entries
betterfoliage.blocks.lilypadWhitelist=연꽃 허용목록
betterfoliage.blocks.lilypadBlacklist=연꽃 차단목록
betterfoliage.blocks.lilypadWhitelist.arrayEntry=%d entries
betterfoliage.blocks.lilypadBlacklist.arrayEntry=%d entries
betterfoliage.blocks.cactusWhitelist=선인장 허용목록
betterfoliage.blocks.cactusBlacklist=선인장 차단목록
betterfoliage.blocks.cactusWhitelist.arrayEntry=%d entries
betterfoliage.blocks.cactusBlacklist.arrayEntry=%d entries
betterfoliage.blocks.dirtWhitelist.tooltip=흙으로 인식됩니다. 갈대, 조류, 잔디 텍스쳐 연결에 영향을 줍니다.
betterfoliage.blocks.dirtBlacklist.tooltip=흙으로 인식 되지 않습니다. 갈대, 조류, 잔디 텍스쳐 연결에 영향을 주지 않습니다.
betterfoliage.blocks.grassWhitelist.tooltip=잔디로 인식됩니다. 짧은 잔디, 잔디 텍스쳐 연결에 영향을 줍니다.
betterfoliage.blocks.grassBlacklist.tooltip=잔디로 인식 되지 않습니다. 짧은 잔디, 잔디 텍스쳐 연결에 영향을 주지 않습니다.
betterfoliage.blocks.leavesWhitelist.tooltip=잎으로 인식됩니다. 추가 잎, 떨어지는 잎에 영향을 줍니다.
betterfoliage.blocks.leavesBlacklist.tooltip=잎으로 인식 되지 않습니다. 추가 잎, 떨어지는 잎에 영향을 주지 않습니다.
betterfoliage.blocks.cropsWhitelist.tooltip=농작물로 인식됩니다. 농작물은 쉐이더 적용하면 큰잔디로 렌더링 됩니다.
betterfoliage.blocks.cropsBlacklist.tooltip=농작물로 인식 되지 않습니다. 농작물은 쉐이더 적용하면 큰잔디로 렌더링 되지 않습니다.
betterfoliage.blocks.logsWhitelist.tooltip=나무로 인식됩니다. 둥근 나무에 영향을 줍니다.
betterfoliage.blocks.logsBlacklist.tooltip=나무로 인식 되지 않습니다. 둥근 나무에 영향을 주지 않습니다.
betterfoliage.blocks.sandWhitelist.tooltip=모래로 인식됩니다. 산호에 영향을 줍니다
betterfoliage.blocks.sandBlacklist.tooltip=모래로 인식되지 않습니다. 산호에 영향을 주지 않습니다.
betterfoliage.blocks.lilypadWhitelist.tooltip=연꽃으로 인식됩니다. 보다 나은 연꽃에 영향을 줍니다.
betterfoliage.blocks.lilypadBlacklist.tooltip=연꽃으로 인식되지 않습니다. 보다 나은 연꽃에 영향을 주지 않습니다.
betterfoliage.blocks.cactusWhitelist.tooltip=선인장으로 인식됩니다. 보다 나은 선인장에 영향을 줍니다.
betterfoliage.blocks.cactusBlacklist.tooltip=선인장으로 인식되지 않습니다. 보다 나은 선인장에 영향을 주지 않습니다.
betterfoliage.leaves=잎 추가
betterfoliage.leaves.tooltip=둥글게 나뭇잎을 추가시켜줍니다.
betterfoliage.leaves.dense=조밀한 모드
betterfoliage.leaves.dense.tooltip=조밀한 모드는 둥근 나뭇잎을 더 추가시켜줍니다.
betterfoliage.shortGrass=이쁜 잔디 & 균사체
betterfoliage.shortGrass.tooltip=블록 상단에 잔디 / 균사체
betterfoliage.shortGrass.useGenerated=잔디텍스쳐를 활성화 합니다.
betterfoliage.shortGrass.useGenerated.tooltip=소스팩의 일부분에 활성화 되어있는 큰잔디 텍스쳐를 생성시킵니다.
betterfoliage.shortGrass.myceliumEnabled=균사체 활성화
betterfoliage.shortGrass.myceliumEnabled.tooltip=균사체 블록에 있는 기능을 활성화 시키겠습니까?
betterfoliage.shortGrass.grassEnabled=잔디 활성화
betterfoliage.shortGrass.grassEnabled.tooltip=잔디 블록에 있는 기능을 활성화 시키겠습니까?
betterfoliage.shortGrass.snowEnabled=눈 활성화
betterfoliage.shortGrass.snowEnabled.tooltip=잔디 블록위에 있는 눈을 활성화 시키겠습니까?
betterfoliage.shortGrass.saturationThreshold=채도 임계값
betterfoliage.shortGrass.saturationThreshold.tooltip=(특정 색상을 사용하여)"무채색"블록과 (바이옴 색을 사용하여)"화려한"블록 사이의 채도 차단
betterfoliage.hangingGrass=매달려있는 잔디
betterfoliage.hangingGrass.tooltip=잔디 블록 상단 가장자리에서 아래로 매달려 있는 잔디 다발
betterfoliage.hangingGrass.separation=분리
betterfoliage.hangingGrass.separation.tooltip=잔디블럭에 매달려있는 잔디의 양
betterfoliage.cactus=선인장
betterfoliage.cactus.tooltip=선인장의 비트 수와 부드러운 그림자를 추가
betterfoliage.cactus.sizeVariation=사이즈 변화
betterfoliage.cactus.sizeVariation.tooltip=선인장의 사이즈 크기를 무작위 변화 시킵니다.
betterfoliage.lilypad=연꽃잎
betterfoliage.lilypad.tooltip=연꽃의 뿌리와 약간의 꽃 추가
betterfoliage.lilypad.flowerChance=꽃 확률
betterfoliage.lilypad.flowerChance.tooltip=연꽃 위에 있는 꽃 확률(N 분의 64)
betterfoliage.reed=갈대
betterfoliage.reed.tooltip=물 속에서 흙블럭 위에 있는 갈대
betterfoliage.reed.biomes=바이옴 리스트
betterfoliage.reed.biomes.tooltip=갈대를 바이옴에 따라 표시
betterfoliage.reed.biomes.tooltip.element=갈대를 %s 바이옴에 따라 나타내시겠습니까?
betterfoliage.algae=해조류
betterfoliage.algae.tooltip=깊은 물 속 흙 블럭 위에 있는 해조류
betterfoliage.algae.biomes=바이옴 리스트
betterfoliage.algae.biomes.tooltip=해조류를 바이옴에 따라 표시
betterfoliage.algae.biomes.tooltip.element=해조류를 %s 바이옴에 따라 나타내시겠습니까?
betterfoliage.coral=산호
betterfoliage.coral.tooltip=깊은 물 속 모래 블럭 위에있는 산호
betterfoliage.coral.size=산호 사이즈(크기)
betterfoliage.coral.size.tooltip=산호 이미지만큼 적용
betterfoliage.coral.crustSize=껍질 크기
betterfoliage.coral.crustSize.tooltip=산호 부분의 크기
betterfoliage.coral.chance=산호 확률
betterfoliage.coral.chance.tooltip=산호를 특정블록에 표시하는 확률(N 분의 64)
betterfoliage.coral.biomes=바이옴 리스트
betterfoliage.coral.biomes.tooltip=산호를 바이옴에 따라 표시
betterfoliage.coral.biomes.tooltip.element=산호를 %s 바이옴에 따라 나타내시겠습니까?
betterfoliage.coral.shallowWater=얕은 물 산호
betterfoliage.coral.shallowWater.tooltip=산호를 깊은 물에 표시하시겠습니까?
betterfoliage.netherrack=네더랙 덩굴
betterfoliage.netherrack.tooltip=네더랙에 매달려있는 덩굴
betterfoliage.fallingLeaves=떨어지는 나뭇잎
betterfoliage.fallingLeaves.tooltip=잎 블록에서 바닥으로 떨어지는 잎 파티클
betterfoliage.fallingLeaves.speed=파티클 속도
betterfoliage.fallingLeaves.speed.tooltip=전체 파티클 속도
betterfoliage.fallingLeaves.windStrength=바람 세기
betterfoliage.fallingLeaves.windStrength.tooltip=날씨 바람 추가효과 (0을 중심으로 정규분포의 확산)
betterfoliage.fallingLeaves.stormStrength=폭풍 세기
betterfoliage.fallingLeaves.stormStrength.tooltip=비 날씨에 바람 추가효과 (0을 중심으로 정규분포의 확산)
betterfoliage.fallingLeaves.size=파티클 크기
betterfoliage.fallingLeaves.chance=파티클 확률
betterfoliage.fallingLeaves.chance.tooltip=잎 파티클 랜덤 확률 설정
betterfoliage.fallingLeaves.perturb=움직임
betterfoliage.fallingLeaves.perturb.tooltip=움직임 효과의 크기. 코르크 같은 움직임을 추가합니다.
betterfoliage.fallingLeaves.lifetime=파티클 지속시간
betterfoliage.fallingLeaves.lifetime.tooltip=최대 파티클 지속시간을 설정합니다. 최소 지속시간은 60%입니다.
betterfoliage.fallingLeaves.opacityHack=불투명 파티클
betterfoliage.fallingLeaves.opacityHack.tooltip=파티클이 앞에 있어도 파티클을 가리는 투명블럭을 없앱니다. 경고: 오류주의
betterfoliage.risingSoul=소울 상승
betterfoliage.risingSoul.tooltip=소울 블럭에서 올라오는 파티클
betterfoliage.risingSoul.chance=파티클 수정
betterfoliage.risingSoul.chance.tooltip=소울 파티클 랜덤 확률 설정
betterfoliage.risingSoul.speed=파티클 속도
betterfoliage.risingSoul.speed.tooltip=파티클 속도
betterfoliage.risingSoul.perturb=움직임
betterfoliage.risingSoul.perturb.tooltip=움직임 효과의 크기. 코르크 같은 움직임을 추가합니다.
betterfoliage.risingSoul.headSize=소울 크기
betterfoliage.risingSoul.headSize.tooltip=소울 파티클의 크기
betterfoliage.risingSoul.trailSize=자취 사이즈
betterfoliage.risingSoul.trailSize.tooltip=자취의 크기
betterfoliage.risingSoul.opacity=불투명
betterfoliage.risingSoul.opacity.tooltip=파티클의 불투명
betterfoliage.risingSoul.sizeDecay=크기 감소
betterfoliage.risingSoul.sizeDecay.tooltip=상대적인 자취 파티클 크기
betterfoliage.risingSoul.opacityDecay=불투명 감소
betterfoliage.risingSoul.opacityDecay.tooltip=상대적인 입자의 파티클 불투명도
betterfoliage.risingSoul.lifetime=최대 지속시간
betterfoliage.risingSoul.lifetime.tooltip=최대 파티클 지속시간을 설정합니다. 최소 지속시간은 60%입니다.
betterfoliage.risingSoul.trailLength=자취의 세기
betterfoliage.risingSoul.trailLength.tooltip=이전 파티클 틱으로 자취를 생성합니다.
betterfoliage.risingSoul.trailDensity=자취의 밀도
betterfoliage.risingSoul.trailDensity.tooltip=파티클 자취를 모두 렌더링 합니다.
betterfoliage.connectedGrass=잔디 연결 텍스쳐
betterfoliage.connectedGrass.enabled=활성화
betterfoliage.connectedGrass.enabled.tooltip=잔디블록이 흙블록 위에 있을 경우 잔디블록 윗텍스쳐를 옆텍스쳐에 전부 씌웁니다.
betterfoliage.roundLogs=둥근 나무
betterfoliage.roundLogs.tooltip=둥근부분을 블럭과 연결.
betterfoliage.roundLogs.connectSolids=블럭과 연결
betterfoliage.roundLogs.connectSolids.tooltip=둥근부분을 블럭과 연결.
betterfoliage.roundLogs.connectPerpendicular=나무 세로부분과 연결
betterfoliage.roundLogs.connectPerpendicular.tooltip=나무 세로부분을 나무부분끼리 연결
betterfoliage.roundLogs.lenientConnect=부드럽게 둥글게 연결
betterfoliage.roundLogs.lenientConnect.tooltip=2x2사이즈처럼 나무 평형된 부분끼리 서로 연결합니다.
betterfoliage.roundLogs.connectGrass=잔디 연결 텍스쳐
betterfoliage.roundLogs.connectGrass.tooltip=잔디가 근처에 있을 경우 나무 아래 잔디 블록을 렌더링
betterfoliage.roundLogs.radiusSmall=모서리 깎는 반지름
betterfoliage.roundLogs.radiusSmall.tooltip=나무 모서리 깎는 정도
betterfoliage.roundLogs.radiusLarge=모서리 깎는 부분 연결
betterfoliage.roundLogs.radiusLarge.tooltip=나무 모서리 부분을 연결
betterfoliage.roundLogs.dimming=조광
betterfoliage.roundLogs.dimming.tooltip=나무 표면부분을 어둡게하는 양
betterfoliage.roundLogs.zProtection=Z-Protection
betterfoliage.roundLogs.zProtection.tooltip=Amount to scale parallel log connection bits to stop Z-fighting (flickering). Try to set it as high as possible without having glitches.
betterfoliage.roundLogs.defaultY=수직선에대한 기본값
betterfoliage.roundLogs.defaultY.tooltip=true 일경우, 나무 블럭이 수직선에대한 렌더링을 할수가 없습니다. 그렇지 아니하면, 네모난 블럭으로 렌더링 될것임니다.
# Translate by IS_Jump for feedback mail acarus22@gmail.com

View File

@@ -0,0 +1,154 @@
{
"key.betterfoliage.gui": "Открыть настройки",
"betterfoliage.global.enabled": "Включить мод",
"betterfoliage.global.enabled.tooltip": "Если установлено на false, BetterFoliage не будет ничего рендерить",
"betterfoliage.enabled": "Включить",
"betterfoliage.enabled.tooltip": "Включена ли эта функция?",
"betterfoliage.hOffset": "Горизонтальное смещение",
"betterfoliage.hOffset.tooltip": "Дистанция горизонтального смещения этого элемента в блоках",
"betterfoliage.vOffset": "Вертикальное смещение",
"betterfoliage.vOffset.tooltip": "Дистанция вертикального смещения этого элемента в блоках",
"betterfoliage.size": "Размер",
"betterfoliage.size.tooltip": "Размер этого элемента",
"betterfoliage.heightMin": "Минимальная высота",
"betterfoliage.heightMin.tooltip": "Минимальная высота элемента",
"betterfoliage.heightMax": "Максимальная высота",
"betterfoliage.heightMax.tooltip": "Максимальная высота этого элемента",
"betterfoliage.population": "Популяция",
"betterfoliage.population.tooltip": "Шанс (N к 64), что блок будет иметь эту функцию",
"betterfoliage.shaderWind": "Шейдерные эффекты ветра",
"betterfoliage.shaderWind.tooltip": "Применить эффекты ветра с ShaderMod для этого элемента?",
"betterfoliage.distance": "Лимит дистанции",
"betterfoliage.distance.tooltip": "Максимальное расстояние от игрока для рендеринга этой функции",
"betterfoliage.saturationThreshold": "Порог насыщения",
"betterfoliage.saturationThreshold.tooltip": "Насыщенность цвета разделяется на: \"обесцвеченные\" блоки (используя цвет биома) и \"цветные\" блоки (используя их собственный цвет)",
"betterfoliage.leaves": "Улучшенная листва",
"betterfoliage.leaves.tooltip": "Дополнительное округление листьев на блоках листвы.",
"betterfoliage.leaves.dense": "Плотный режим",
"betterfoliage.leaves.dense.tooltip": "Плотный режим имеет более округлые листья.",
"betterfoliage.shortGrass": "Низкая трава и мицелий",
"betterfoliage.shortGrass.tooltip": "Пучки травы / мицелия на поверхности соответствующих блоков.",
"betterfoliage.shortGrass.useGenerated": "Использовать сгенерированные текстуры для травы.",
"betterfoliage.shortGrass.useGenerated.tooltip": "Сгенерированная текстура создается путём разрезания текстуры высокой травы с активного ресурс-пака пополам.",
"betterfoliage.shortGrass.myceliumEnabled": "Включить мицелий",
"betterfoliage.shortGrass.myceliumEnabled.tooltip": "Включить эту особенность для блоков мицелия?",
"betterfoliage.shortGrass.grassEnabled": "Включить траву",
"betterfoliage.shortGrass.grassEnabled.tooltip": "Включить эту особенность для блоков травы?",
"betterfoliage.shortGrass.snowEnabled": "Включить траву под снегом",
"betterfoliage.shortGrass.snowEnabled.tooltip": "Включить эту особенность для заснеженных блоков травы?",
"betterfoliage.hangingGrass": "Висячая трава",
"betterfoliage.hangingGrass.tooltip": "Пучки травы свисают вниз с верхних краев блока травы.",
"betterfoliage.hangingGrass.separation": "Разделение",
"betterfoliage.hangingGrass.separation.tooltip": "Как долго подвесная трава выделяется из блока?",
"betterfoliage.cactus": "Улучшенные кактусы",
"betterfoliage.cactus.tooltip": "Улучшить кактус с дополнительными частицами и плавными тенями.",
"betterfoliage.cactus.sizeVariation": "Вариации размера",
"betterfoliage.cactus.sizeVariation.tooltip": "Количество случайных изменений в размере кактусов.",
"betterfoliage.lilypad": "Улучшенные кувшинки",
"betterfoliage.lilypad.tooltip": "Добавить кувшинкам корни и цветы.",
"betterfoliage.lilypad.flowerChance": "Шанс появления цветов",
"betterfoliage.lilypad.flowerChance.tooltip": "Шанс (N к 64) появления цветка на кувшинке.",
"betterfoliage.reed": "Камыши",
"betterfoliage.reed.tooltip": "Мелководные камыши на блоках земли.",
"betterfoliage.reed.biomes": "Список биомов",
"betterfoliage.reed.biomes.tooltip": "Настройка биомов, в которых камышам разрешено появляться.",
"betterfoliage.reed.biomes.tooltip.element": "Должны ли камыши встречаться в %s биоме?",
"betterfoliage.algae": "Морские водоросли",
"betterfoliage.algae.tooltip": "Глубоководные водоросли на блоках земли.",
"betterfoliage.algae.biomes": "Список биомов",
"betterfoliage.algae.biomes.tooltip": "Настройка биомов, в которых водорослям разрешено появляться.",
"betterfoliage.algae.biomes.tooltip.element": "Должны ли водоросли встречаться в %s биоме?",
"betterfoliage.coral": "Кораллы",
"betterfoliage.coral.tooltip": "Кораллы на песчаных блоках в глубокой воде.",
"betterfoliage.coral.size": "Размер кораллов",
"betterfoliage.coral.size.tooltip": "Размер торчащих частичек кораллов.",
"betterfoliage.coral.crustSize": "Размер коры",
"betterfoliage.coral.crustSize.tooltip": "Размер плоской части кораллов.",
"betterfoliage.coral.chance": "Шанс кораллов",
"betterfoliage.coral.chance.tooltip": "Шанс (N in 64) появления кораллов на определенном блоке.",
"betterfoliage.coral.biomes": "Список биомов",
"betterfoliage.coral.biomes.tooltip": "Настройка биомов, в которых разрешено появляться кораллам.",
"betterfoliage.coral.biomes.tooltip.element": "Должны ли кораллы появляться в %s биоме?",
"betterfoliage.coral.shallowWater": "Мелководные кораллы",
"betterfoliage.coral.shallowWater.tooltip": "Должны ли появляться кораллы в воде, глубиной в 1 блок?",
"betterfoliage.netherrack": "Адская лоза",
"betterfoliage.netherrack.tooltip": "Висячая лоза под адским камнем",
"betterfoliage.fallingLeaves": "Падающие листья",
"betterfoliage.fallingLeaves.tooltip": "Падение FX частиц листвы исходящие из низа блоков листвы",
"betterfoliage.fallingLeaves.speed": "Скорость частиц",
"betterfoliage.fallingLeaves.speed.tooltip": "Общая скорость частиц",
"betterfoliage.fallingLeaves.windStrength": "Сила ветра",
"betterfoliage.fallingLeaves.windStrength.tooltip": "Величина воздействия ветра в хорошую погоду (распространение нормального распределения сосредоточено на 0)",
"betterfoliage.fallingLeaves.stormStrength": "Сила шторма",
"betterfoliage.fallingLeaves.stormStrength.tooltip": "Дополнительная величина воздействия ветра в ненастную погоду (распространение нормального распределения сосредоточено на 0)",
"betterfoliage.fallingLeaves.size": "Размер частиц",
"betterfoliage.fallingLeaves.chance": "Шанс частиц",
"betterfoliage.fallingLeaves.chance.tooltip": "Вероятность каждого случайного рендеринга в такт (1/20 секунды) опадения частицы блока листвы.",
"betterfoliage.fallingLeaves.perturb": "Возмущение",
"betterfoliage.fallingLeaves.perturb.tooltip": "Величина эффекта возмущений. Добавляет штопорообразное движение к частице синхронизированной с его вращением.",
"betterfoliage.fallingLeaves.lifetime": "Максимальное время жизни",
"betterfoliage.fallingLeaves.lifetime.tooltip": "Максимальное время жизни частиц. Минимальное время жизни - 60%% от этого значения.",
"betterfoliage.fallingLeaves.opacityHack": "Непрозрачные частицы",
"betterfoliage.fallingLeaves.opacityHack.tooltip": "Запретить прозрачным блокам затемнять частицы даже тогда, когда частицы впереди. ВНИМАНИЕ: может спровоцировать баги.",
"betterfoliage.risingSoul": "Адские духи",
"betterfoliage.risingSoul.tooltip": "Количество душ-частиц FX, испускаемых из верхней части блоков песка душ.",
"betterfoliage.risingSoul.chance": "Шанс частиц",
"betterfoliage.risingSoul.chance.tooltip": "Частота генерации частиц на песке душ.",
"betterfoliage.risingSoul.speed": "Скорость частиц",
"betterfoliage.risingSoul.speed.tooltip": "Вертикальная скорость движения частиц духов.",
"betterfoliage.risingSoul.perturb": "Возмущение",
"betterfoliage.risingSoul.perturb.tooltip": "Магнитуда эффекта возмущений. Добавляет штопороподобное движение частиц.",
"betterfoliage.risingSoul.headSize": "Размер духа",
"betterfoliage.risingSoul.headSize.tooltip": "Размер частицы духа",
"betterfoliage.risingSoul.trailSize": "Размер следов",
"betterfoliage.risingSoul.trailSize.tooltip": "Начальный размер следа частиц",
"betterfoliage.risingSoul.opacity": "Прозрачность",
"betterfoliage.risingSoul.opacity.tooltip": "Непрозрачность эффекта частиц",
"betterfoliage.risingSoul.sizeDecay": "Размер распада",
"betterfoliage.risingSoul.sizeDecay.tooltip": "Следующий размер частицы соответствует их же размеру в предыдущем такте (1/20 секунды).",
"betterfoliage.risingSoul.opacityDecay": "Непрозрачность распада",
"betterfoliage.risingSoul.opacityDecay.tooltip": "Следующий уровень прозрачности частицы соответствует их же уровню прозрачности в предыдущем такте (1/20 секунды).",
"betterfoliage.risingSoul.lifetime": "Максимальное время жизни",
"betterfoliage.risingSoul.lifetime.tooltip": "Максимальное время жизни эффекта частиц. Минимальное время жизни равно 60%% от этого числа.",
"betterfoliage.risingSoul.trailLength": "Длина следов",
"betterfoliage.risingSoul.trailLength.tooltip": "Количество предыдущих позиций, которые запомнила частица в тактах (1/20 секунды).",
"betterfoliage.risingSoul.trailDensity": "Плотность следов",
"betterfoliage.risingSoul.trailDensity.tooltip": "Рендер каждой предыдущий Nой позиции в следах частиц.",
"betterfoliage.connectedGrass": "Соединенные текстуры травы",
"betterfoliage.connectedGrass.enabled": "Включить",
"betterfoliage.connectedGrass.enabled.tooltip": "Если блок травы находится над блоком земли: прорисовать верхнюю текстуру травы на всех сторонах блока травы.",
"betterfoliage.roundLogs": "Цилиндрические брёвна",
"betterfoliage.roundLogs.tooltip": "Соединить круглые блоки в сплошные, полные блоки?",
"betterfoliage.roundLogs.connectSolids": "Соединение в крупные брёвна",
"betterfoliage.roundLogs.connectSolids.tooltip": "Соединить круглые блоки в сплошные, полные блоки?",
"betterfoliage.roundLogs.connectPerpendicular": "Соединение в перпендикулярные брёвна",
"betterfoliage.roundLogs.connectPerpendicular.tooltip": "Соединить круглые брёвна к перпендикулярным брёвнам относительно их оси?",
"betterfoliage.roundLogs.lenientConnect": "Мягкое округление",
"betterfoliage.roundLogs.lenientConnect.tooltip": "Соединение в параллельные круглые брёвна L-формы, не только 2х2.",
"betterfoliage.roundLogs.connectGrass": "Соединенная трава",
"betterfoliage.roundLogs.connectGrass.tooltip": "Заменяет землю под деревьями на траву, если она есть поблизости.",
"betterfoliage.roundLogs.radiusSmall": "Радиус фаски",
"betterfoliage.roundLogs.radiusSmall.tooltip": "Радиус обрезки углов от бревна.",
"betterfoliage.roundLogs.radiusLarge": "Радиус соединенной фаски",
"betterfoliage.roundLogs.radiusLarge.tooltip": "Радиус среза внешнего угла соединённых брёвен.",
"betterfoliage.roundLogs.dimming": "Затемнение",
"betterfoliage.roundLogs.dimming.tooltip": "Затемнить неясные длинные грани.",
"betterfoliage.roundLogs.zProtection": "Z-Защита",
"betterfoliage.roundLogs.zProtection.tooltip": "Для масштабирования параллельных битов соединения бревен, чтобы остановить Z-бой (мерцание). Попробуйте установить его как можно выше, для устранения мерцания."
}

View File

@@ -1,213 +0,0 @@
key.betterfoliage.gui=Открыть настройки
betterfoliage.global.enabled=Включить мод
betterfoliage.global.enabled.tooltip=Если установлено на false, BetterFoliage не будет ничего рендерить
betterfoliage.enabled=Включить
betterfoliage.enabled.tooltip=Включена ли эта функция?
betterfoliage.hOffset=Горизонтальное смещение
betterfoliage.hOffset.tooltip=Дистанция горизонтального смещения этого элемента в блоках
betterfoliage.vOffset=Вертикальное смещение
betterfoliage.vOffset.tooltip=Дистанция вертикального смещения этого элемента в блоках
betterfoliage.size=Размер
betterfoliage.size.tooltip=Размер этого элемента
betterfoliage.heightMin=Минимальная высота
betterfoliage.heightMin.tooltip=Минимальная высота элемента
betterfoliage.heightMax=Максимальная высота
betterfoliage.heightMax.tooltip=Максимальная высота этого элемента
betterfoliage.population=Популяция
betterfoliage.population.tooltip=Шанс (N к 64), что блок будет иметь эту функцию
betterfoliage.shaderWind=Шейдерные эффекты ветра
betterfoliage.shaderWind.tooltip=Применить эффекты ветра с ShaderMod для этого элемента?
betterfoliage.distance=Лимит дистанции
betterfoliage.distance.tooltip=Максимальное расстояние от игрока для рендеринга этой функции
betterfoliage.blocks=Типы блоков
betterfoliage.blocks.tooltip=Настройки списка классов блоков, которые будут иметь примененные к ним функции
betterfoliage.blocks.dirtWhitelist=Белый список земли
betterfoliage.blocks.dirtBlacklist=Черный список земли
betterfoliage.blocks.dirtWhitelist.arrayEntry=%d записей
betterfoliage.blocks.dirtBlacklist.arrayEntry=%d записей
betterfoliage.blocks.grassWhitelist=Белый список травы
betterfoliage.blocks.grassBlacklist=Черный список травы
betterfoliage.blocks.grassWhitelist.arrayEntry=%d записей
betterfoliage.blocks.grassBlacklist.arrayEntry=%d записей
betterfoliage.blocks.leavesWhitelist=Белый список листвы
betterfoliage.blocks.leavesBlacklist=Черный список листвы
betterfoliage.blocks.leavesWhitelist.arrayEntry=%d записей
betterfoliage.blocks.leavesBlacklist.arrayEntry=%d записей
betterfoliage.blocks.cropsWhitelist=Белый список урожая
betterfoliage.blocks.cropsBlacklist=Черный список урожая
betterfoliage.blocks.cropsWhitelist.arrayEntry=%d записей
betterfoliage.blocks.cropsBlacklist.arrayEntry=%d записей
betterfoliage.blocks.logsWhitelist=Белый список древесины
betterfoliage.blocks.logsBlacklist=Черный список древесины
betterfoliage.blocks.logsWhitelist.arrayEntry=%d записей
betterfoliage.blocks.logsBlacklist.arrayEntry=%d записей
betterfoliage.blocks.sandWhitelist=Белый список песка
betterfoliage.blocks.sandBlacklist=Черный список песка
betterfoliage.blocks.sandWhitelist.arrayEntry=%d записей
betterfoliage.blocks.sandBlacklist.arrayEntry=%d записей
betterfoliage.blocks.lilypadWhitelist=Белый список кувшинок
betterfoliage.blocks.lilypadBlacklist=Черный список кувшинок
betterfoliage.blocks.lilypadWhitelist.arrayEntry=%d записей
betterfoliage.blocks.lilypadBlacklist.arrayEntry=%d записей
betterfoliage.blocks.cactusWhitelist=Белый список кактусов
betterfoliage.blocks.cactusBlacklist=Черный список кактусов
betterfoliage.blocks.cactusWhitelist.arrayEntry=%d записей
betterfoliage.blocks.cactusBlacklist.arrayEntry=%d записей
betterfoliage.blocks.dirtWhitelist.tooltip=Блоки, которые будут восприниматься в качестве земли. Влияет на камыши, водоросли, соединенную траву.
betterfoliage.blocks.dirtBlacklist.tooltip=Блоки, которые не будут восприниматься в качестве земли. Влияет на камыши, водоросли, соединенную траву.
betterfoliage.blocks.grassWhitelist.tooltip=Блоки, которые будут восприниматься в качестве травы. Влияет на короткую и соединенную траву.
betterfoliage.blocks.grassBlacklist.tooltip=Блоки, которые не будут восприниматься в качестве травы. Влияет на короткую и соединенную траву.
betterfoliage.blocks.leavesWhitelist.tooltip=Блоки, которые будут восприниматься в качестве листвы. Влияет на дополнительную листву, падающую листву. Листва будут рендериться с ID листвы в шейдер-программах.
betterfoliage.blocks.leavesBlacklist.tooltip=Блоки, которые никогда не будут восприниматься как листва. Влияет на дополнительную листву, падающую листву. Листва будут рендериться с ID листвы в шейдер-программах.
betterfoliage.blocks.cropsWhitelist.tooltip=Блоки, которые будут восприниматься как культуры. Культуры будут рендериться с ID высокой травы в шейдер-программах.
betterfoliage.blocks.cropsBlacklist.tooltip= Блоки, которые никогда не будут восприниматься как культуры. Культуры будут рендериться с ID высокой травы в шейдер-программах.
betterfoliage.blocks.logsWhitelist.tooltip=Блоки, которые будут восприниматься в качестве деревянных брёвен. Влияет на цилиндрические брёвна.
betterfoliage.blocks.logsBlacklist.tooltip=Блоки, которые никогда не будут восприниматься в качестве деревянных брёвен. Влияет на цилиндрические брёвна.
betterfoliage.blocks.sandWhitelist.tooltip=Блоки, которые будут восприниматься в качестве песка. Влияет на кораллы.
betterfoliage.blocks.sandBlacklist.tooltip=Блоки, которые никогда не будут восприниматься в качестве песка. Влияет на кораллы.
betterfoliage.blocks.lilypadWhitelist.tooltip=Блоки, которые будут восприниматься в качестве кувшинок. Влияет на улучшенные кувшинки.
betterfoliage.blocks.lilypadBlacklist.tooltip=Блоки, которые никогда не будут восприниматься в качестве кувшинок. Влияет на улучшенные кувшинки.
betterfoliage.blocks.cactusWhitelist.tooltip=Блоки, которые будут восприниматься в качестве кактусов. Влияет на улучшенные кактусы.
betterfoliage.blocks.cactusBlacklist.tooltip=Блоки, которые никогда не будут восприниматься в качестве кувшинок. Влияет на улучшенные кактусы.
betterfoliage.leaves=Улучшенная листва
betterfoliage.leaves.tooltip=Дополнительное округление листьев на блоках листвы.
betterfoliage.leaves.dense=Плотный режим
betterfoliage.leaves.dense.tooltip=Плотный режим имеет более округлые листья.
betterfoliage.shortGrass=Низкая трава и мицелий
betterfoliage.shortGrass.tooltip=Пучки травы / мицелия на поверхности соответствующих блоков.
betterfoliage.shortGrass.useGenerated=Использовать сгенерированные текстуры для травы.
betterfoliage.shortGrass.useGenerated.tooltip=Сгенерированная текстура создается путём разрезания текстуры высокой травы с активного ресурс-пака пополам.
betterfoliage.shortGrass.myceliumEnabled=Включить мицелий
betterfoliage.shortGrass.myceliumEnabled.tooltip=Включить эту особенность для блоков мицелия?
betterfoliage.shortGrass.grassEnabled=Включить траву
betterfoliage.shortGrass.grassEnabled.tooltip=Включить эту особенность для блоков травы?
betterfoliage.shortGrass.snowEnabled=Включить траву под снегом
betterfoliage.shortGrass.snowEnabled.tooltip=Включить эту особенность для заснеженных блоков травы?
betterfoliage.shortGrass.saturationThreshold=Порог насыщения
betterfoliage.shortGrass.saturationThreshold.tooltip=Насыщенность цвета разделяется на: "обесцвеченные" блоки (используя цвет биома) и "цветные" блоки (используя их собственный цвет)
betterfoliage.hangingGrass=Висячая трава
betterfoliage.hangingGrass.tooltip=Пучки травы свисают вниз с верхних краев блока травы.
betterfoliage.hangingGrass.separation=Разделение
betterfoliage.hangingGrass.separation.tooltip=Как долго подвесная трава выделяется из блока?
betterfoliage.cactus=Улучшенные кактусы
betterfoliage.cactus.tooltip=Улучшить кактус с дополнительными частицами и плавными тенями.
betterfoliage.cactus.sizeVariation=Вариации размера
betterfoliage.cactus.sizeVariation.tooltip=Количество случайных изменений в размере кактусов.
betterfoliage.lilypad=Улучшенные кувшинки
betterfoliage.lilypad.tooltip=Добавить кувшинкам корни и цветы.
betterfoliage.lilypad.flowerChance=Шанс появления цветов
betterfoliage.lilypad.flowerChance.tooltip=Шанс (N к 64) появления цветка на кувшинке.
betterfoliage.reed=Камыши
betterfoliage.reed.tooltip=Мелководные камыши на блоках земли.
betterfoliage.reed.biomes=Список биомов
betterfoliage.reed.biomes.tooltip=Настройка биомов, в которых камышам разрешено появляться.
betterfoliage.reed.biomes.tooltip.element=Должны ли камыши встречаться в %s биоме?
betterfoliage.algae=Морские водоросли
betterfoliage.algae.tooltip=Глубоководные водоросли на блоках земли.
betterfoliage.algae.biomes=Список биомов
betterfoliage.algae.biomes.tooltip=Настройка биомов, в которых водорослям разрешено появляться.
betterfoliage.algae.biomes.tooltip.element=Должны ли водоросли встречаться в %s биоме?
betterfoliage.coral=Кораллы
betterfoliage.coral.tooltip=Кораллы на песчаных блоках в глубокой воде.
betterfoliage.coral.size=Размер кораллов
betterfoliage.coral.size.tooltip=Размер торчащих частичек кораллов.
betterfoliage.coral.crustSize=Размер коры
betterfoliage.coral.crustSize.tooltip=Размер плоской части кораллов.
betterfoliage.coral.chance=Шанс кораллов
betterfoliage.coral.chance.tooltip=Шанс (N in 64) появления кораллов на определенном блоке.
betterfoliage.coral.biomes=Список биомов
betterfoliage.coral.biomes.tooltip=Настройка биомов, в которых разрешено появляться кораллам.
betterfoliage.coral.biomes.tooltip.element=Должны ли кораллы появляться в %s биоме?
betterfoliage.coral.shallowWater=Мелководные кораллы
betterfoliage.coral.shallowWater.tooltip=Должны ли появляться кораллы в воде, глубиной в 1 блок?
betterfoliage.netherrack=Адская лоза
betterfoliage.netherrack.tooltip=Висячая лоза под адским камнем
betterfoliage.fallingLeaves=Падающие листья
betterfoliage.fallingLeaves.tooltip=Падение FX частиц листвы исходящие из низа блоков листвы
betterfoliage.fallingLeaves.speed=Скорость частиц
betterfoliage.fallingLeaves.speed.tooltip=Общая скорость частиц
betterfoliage.fallingLeaves.windStrength=Сила ветра
betterfoliage.fallingLeaves.windStrength.tooltip=Величина воздействия ветра в хорошую погоду (распространение нормального распределения сосредоточено на 0)
betterfoliage.fallingLeaves.stormStrength=Сила шторма
betterfoliage.fallingLeaves.stormStrength.tooltip=Дополнительная величина воздействия ветра в ненастную погоду (распространение нормального распределения сосредоточено на 0)
betterfoliage.fallingLeaves.size=Размер частиц
betterfoliage.fallingLeaves.chance=Шанс частиц
betterfoliage.fallingLeaves.chance.tooltip=Вероятность каждого случайного рендеринга в такт (1/20 секунды) опадения частицы блока листвы.
betterfoliage.fallingLeaves.perturb=Возмущение
betterfoliage.fallingLeaves.perturb.tooltip=Величина эффекта возмущений. Добавляет штопорообразное движение к частице синхронизированной с его вращением.
betterfoliage.fallingLeaves.lifetime=Максимальное время жизни
betterfoliage.fallingLeaves.lifetime.tooltip=Максимальное время жизни частиц. Минимальное время жизни - 60%% от этого значения.
betterfoliage.fallingLeaves.opacityHack=Непрозрачные частицы
betterfoliage.fallingLeaves.opacityHack.tooltip=Запретить прозрачным блокам затемнять частицы даже тогда, когда частицы впереди. ВНИМАНИЕ: может спровоцировать баги.
betterfoliage.risingSoul=Адские духи
betterfoliage.risingSoul.tooltip=Количество душ-частиц FX, испускаемых из верхней части блоков песка душ.
betterfoliage.risingSoul.chance=Шанс частиц
betterfoliage.risingSoul.chance.tooltip=Частота генерации частиц на песке душ.
betterfoliage.risingSoul.speed=Скорость частиц
betterfoliage.risingSoul.speed.tooltip=Вертикальная скорость движения частиц духов.
betterfoliage.risingSoul.perturb=Возмущение
betterfoliage.risingSoul.perturb.tooltip=Магнитуда эффекта возмущений. Добавляет штопороподобное движение частиц.
betterfoliage.risingSoul.headSize=Размер духа
betterfoliage.risingSoul.headSize.tooltip=Размер частицы духа
betterfoliage.risingSoul.trailSize=Размер следов
betterfoliage.risingSoul.trailSize.tooltip=Начальный размер следа частиц
betterfoliage.risingSoul.opacity=Прозрачность
betterfoliage.risingSoul.opacity.tooltip=Непрозрачность эффекта частиц
betterfoliage.risingSoul.sizeDecay=Размер распада
betterfoliage.risingSoul.sizeDecay.tooltip=Следующий размер частицы соответствует их же размеру в предыдущем такте (1/20 секунды).
betterfoliage.risingSoul.opacityDecay=Непрозрачность распада
betterfoliage.risingSoul.opacityDecay.tooltip=Следующий уровень прозрачности частицы соответствует их же уровню прозрачности в предыдущем такте (1/20 секунды).
betterfoliage.risingSoul.lifetime=Максимальное время жизни
betterfoliage.risingSoul.lifetime.tooltip=Максимальное время жизни эффекта частиц. Минимальное время жизни равно 60%% от этого числа.
betterfoliage.risingSoul.trailLength=Длина следов
betterfoliage.risingSoul.trailLength.tooltip=Количество предыдущих позиций, которые запомнила частица в тактах (1/20 секунды).
betterfoliage.risingSoul.trailDensity=Плотность следов
betterfoliage.risingSoul.trailDensity.tooltip=Рендер каждой предыдущий Nой позиции в следах частиц.
betterfoliage.connectedGrass=Соединенные текстуры травы
betterfoliage.connectedGrass.enabled=Включить
betterfoliage.connectedGrass.enabled.tooltip=Если блок травы находится над блоком земли: прорисовать верхнюю текстуру травы на всех сторонах блока травы.
betterfoliage.roundLogs=Цилиндрические брёвна
betterfoliage.roundLogs.tooltip=Соединить круглые блоки в сплошные, полные блоки?
betterfoliage.roundLogs.connectSolids=Соединение в крупные брёвна
betterfoliage.roundLogs.connectSolids.tooltip=Соединить круглые блоки в сплошные, полные блоки?
betterfoliage.roundLogs.connectPerpendicular=Соединение в перпендикулярные брёвна
betterfoliage.roundLogs.connectPerpendicular.tooltip=Соединить круглые брёвна к перпендикулярным брёвнам относительно их оси?
betterfoliage.roundLogs.lenientConnect=Мягкое округление
betterfoliage.roundLogs.lenientConnect.tooltip=Соединение в параллельные круглые брёвна L-формы, не только 2х2.
betterfoliage.roundLogs.connectGrass=Соединенная трава
betterfoliage.roundLogs.connectGrass.tooltip=Заменяет землю под деревьями на траву, если она есть поблизости.
betterfoliage.roundLogs.radiusSmall=Радиус фаски
betterfoliage.roundLogs.radiusSmall.tooltip=Радиус обрезки углов от бревна.
betterfoliage.roundLogs.radiusLarge=Радиус соединенной фаски
betterfoliage.roundLogs.radiusLarge.tooltip=Радиус среза внешнего угла соединённых брёвен.
betterfoliage.roundLogs.dimming=Затемнение
betterfoliage.roundLogs.dimming.tooltip=Затемнить неясные длинные грани.
betterfoliage.roundLogs.zProtection=Z-Защита
betterfoliage.roundLogs.zProtection.tooltip=Для масштабирования параллельных битов соединения бревен, чтобы остановить Z-бой (мерцание). Попробуйте установить его как можно выше, для устранения мерцания.

View File

@@ -0,0 +1,177 @@
{
"key.betterfoliage.gui": "打开BF设置",
"betterfoliage.global.enabled": "模组使用",
"betterfoliage.global.enabled.tooltip": "如果关闭,BetterFoliage不会呈现任何东西",
"betterfoliage.nVidia": "nVidia GPU",
"betterfoliage.nVidia.tooltip": "明确你是否有一个nVidia GPU",
"betterfoliage.enabled": "启用",
"betterfoliage.enabled.tooltip": "要启用这个功能吗?",
"betterfoliage.hOffset": "水平偏移",
"betterfoliage.hOffset.tooltip": "在方块中这个元素是横向距离移动的",
"betterfoliage.vOffset": "垂直偏移",
"betterfoliage.vOffset.tooltip": "在方块中这个元素是横向距离移动的",
"betterfoliage.size": "尺寸",
"betterfoliage.size.tooltip": "该元素的尺寸",
"betterfoliage.heightMin": "最小高度",
"betterfoliage.heightMin.tooltip": "最小元素的高度",
"betterfoliage.heightMax": "最大高度",
"betterfoliage.heightMax.tooltip": "最大元素的高度",
"betterfoliage.population": "物体密度",
"betterfoliage.population.tooltip": "生成的概率为64分之1",
"betterfoliage.shaderWind": "光影水反中的 风的影响",
"betterfoliage.shaderWind.tooltip": "能适用于光影水反中的\"风的影响\" 这一元素?",
"betterfoliage.distance": "距离限制",
"betterfoliage.distance.tooltip": "离游戏者的最大距离,在这个范围内呈现这个特征",
"betterfoliage.saturationThreshold": "饱和度阈值",
"betterfoliage.saturationThreshold.tooltip": "色彩饱和度将介于\"无色\"方块(使用生物群系的颜色)和\"有色\"方块(使用材质特定颜色)之间",
"betterfoliage.rendererror": "§a[BF更好的叶子]§f 错误:渲染方块 %s 此位置 %s",
"betterfoliage.shaders": "着色器配置",
"betterfoliage.shaders.tooltip": "Configure integration with shaders",
"betterfoliage.shaders.leavesId": "叶子 ID",
"betterfoliage.shaders.leavesId.tooltip": "方块 ID 将作为所有叶片都使用的相同ID提供给光影水反 如果你的光影水反文件使用了一个 §6block.properties§e 文件, 你可能需要修改这个以匹配光影水反的映射",
"betterfoliage.shaders.grassId": "草 ID",
"betterfoliage.shaders.grassId.tooltip": "方块 ID 将作为所有的草和作物都使用的相同ID提供给光影水反 如果你的光影水反文件使用了一个 §6block.properties§e 文件, 你可能需要修改这个以匹配光影水反的映射",
"betterfoliage.leaves": "额外的叶片",
"betterfoliage.leaves.tooltip": "叶方块上额外的密叶",
"betterfoliage.leaves.dense": "浓密模式",
"betterfoliage.leaves.dense.tooltip": "浓密的叶子会有更多额外的叶片",
"betterfoliage.leaves.snowEnabled": "启用雪覆盖叶片",
"betterfoliage.leaves.snowEnabled.tooltip": "是否启用被雪覆盖的额外叶片?",
"betterfoliage.leaves.hideInternal": "隐藏内部的叶片",
"betterfoliage.leaves.hideInternal.tooltip": "如果该叶方块完全被其他叶方块或者固体方块包围,将不渲染额外的叶片",
"betterfoliage.shortGrass": "短草和菌丝",
"betterfoliage.shortGrass.tooltip": "一簇小草或者一丛菌丝长在合适的方块的顶部",
"betterfoliage.shortGrass.useGenerated": "为草使用mod创建的材质",
"betterfoliage.shortGrass.useGenerated.tooltip": "mod创建的材质指的是将已选用的资源包中高草的材质切一半来用",
"betterfoliage.shortGrass.myceliumEnabled": "使用在菌丝上",
"betterfoliage.shortGrass.myceliumEnabled.tooltip": "将这个特性利用到菌丝中吗?",
"betterfoliage.shortGrass.grassEnabled": "使用在草方块上",
"betterfoliage.shortGrass.grassEnabled.tooltip": "将这个特性利用到草方块中吗?",
"betterfoliage.shortGrass.snowEnabled": "使用在雪地里",
"betterfoliage.shortGrass.snowEnabled.tooltip": "使用到被雪覆盖的草方块中去?",
"betterfoliage.shortGrass.saturationThreshold": "饱和度阈值",
"betterfoliage.shortGrass.saturationThreshold.tooltip": "色彩饱和度将介于\"无色\"方块(使用生物群系的颜色)和\"有色\"方块(使用材质特定颜色)之间",
"betterfoliage.connectedGrass": "草的纹理的连接",
"betterfoliage.connectedGrass.tooltip": "使得草方块侧面拥有像顶面的材质",
"betterfoliage.connectedGrass.enabled": "启用",
"betterfoliage.connectedGrass.enabled.tooltip": "如果泥土上有草方块:所有的草方块的侧面换成草方块顶部的材质,",
"betterfoliage.connectedGrass.snowEnabled": "使用在被雪覆盖的草方块上",
"betterfoliage.connectedGrass.snowEnabled.tooltip": "是否应用于被雪覆盖的草方块上?",
"betterfoliage.hangingGrass": "悬挂的草",
"betterfoliage.hangingGrass.tooltip": "草会在边缘的草方块上垂下来",
"betterfoliage.hangingGrass.separation": "垂下来的距离",
"betterfoliage.hangingGrass.separation.tooltip": "有多长的挂草会从草方块上垂下来",
"betterfoliage.cactus": "更好的仙人掌",
"betterfoliage.cactus.tooltip": "用额外的仙人掌刺和圆润的形状来提高仙人掌的真实性",
"betterfoliage.cactus.sizeVariation": "尺寸变化",
"betterfoliage.cactus.sizeVariation.tooltip": "仙人掌的尺寸随机变化的范围",
"betterfoliage.lilypad": "更好的莲叶与荷花",
"betterfoliage.lilypad.tooltip": "用莲叶的根和随机的莲花以提高莲叶的真实性",
"betterfoliage.lilypad.flowerChance": "花的生成概率",
"betterfoliage.lilypad.flowerChance.tooltip": "(64个莲叶中 N 个)莲叶具有花了",
"betterfoliage.reed": "芦苇",
"betterfoliage.reed.tooltip": "芦苇会生成在浅水中的泥土块上",
"betterfoliage.reed.biomes": "生物群系的列表",
"betterfoliage.reed.biomes.tooltip": "配置允许出现芦苇的生物群系",
"betterfoliage.reed.biomes.tooltip.element": "芦苇应该出现在%s生物群落?",
"betterfoliage.algae": "藻类",
"betterfoliage.algae.tooltip": "藻类会生成在深水中的泥土块上",
"betterfoliage.algae.biomes": "生物群系的列表",
"betterfoliage.algae.biomes.tooltip": "配置允许出现藻类的生物群系",
"betterfoliage.algae.biomes.tooltip.element": "藻类应该出现在%s生物群落?",
"betterfoliage.coral": "珊瑚",
"betterfoliage.coral.tooltip": "珊瑚会生成在深水中的沙块上",
"betterfoliage.coral.size": "珊瑚的大小",
"betterfoliage.coral.size.tooltip": "珊瑚伸出的部分的大小",
"betterfoliage.coral.crustSize": "外壳尺寸",
"betterfoliage.coral.crustSize.tooltip": "珊瑚的平的部分的尺寸",
"betterfoliage.coral.chance": "珊瑚的生成概率",
"betterfoliage.coral.chance.tooltip": "64个特殊表面的方块中有N个有机会出现珊瑚",
"betterfoliage.coral.biomes": "生物群落的列表",
"betterfoliage.coral.biomes.tooltip": "配置允许出现珊瑚的生物群系",
"betterfoliage.coral.biomes.tooltip.element": "珊瑚应该出现在%s生物群落?",
"betterfoliage.coral.shallowWater": "浅海珊瑚",
"betterfoliage.coral.shallowWater.tooltip": "珊瑚应该生成在深水1格?",
"betterfoliage.netherrack": "下界岩下面的藤蔓",
"betterfoliage.netherrack.tooltip": "下界岩下面将挂上藤蔓",
"betterfoliage.fallingLeaves": "落叶",
"betterfoliage.fallingLeaves.tooltip": "落叶粒子效果 FX 会从叶方块底部下落",
"betterfoliage.fallingLeaves.speed": "粒子速度",
"betterfoliage.fallingLeaves.speed.tooltip": "总体的粒子速度",
"betterfoliage.fallingLeaves.windStrength": "柔风的强度",
"betterfoliage.fallingLeaves.windStrength.tooltip": "在晴天中体现的风的效果(默认以0为中心散播)",
"betterfoliage.fallingLeaves.stormStrength": "风暴的强度",
"betterfoliage.fallingLeaves.stormStrength.tooltip": "附加在阴天里体现的风的效果(默认以0为中心散播)",
"betterfoliage.fallingLeaves.size": "粒子大小",
"betterfoliage.fallingLeaves.chance": "粒子生成机率",
"betterfoliage.fallingLeaves.chance.tooltip": "随机渲染刻激发叶方块生成粒子的概率",
"betterfoliage.fallingLeaves.perturb": "扰动",
"betterfoliage.fallingLeaves.perturb.tooltip": "扰动的大小.增加了一个与之旋转同步的螺旋状动量",
"betterfoliage.fallingLeaves.lifetime": "最长存在时间",
"betterfoliage.fallingLeaves.lifetime.tooltip": "粒子的最长存在时间,仅在几秒内,最短时间为这个值60%%",
"betterfoliage.fallingLeaves.opacityHack": "粒子不透明",
"betterfoliage.fallingLeaves.opacityHack.tooltip": "阻止透明方块隐藏粒子,即使粒子已经在前面了.警告:可能会导致错误",
"betterfoliage.risingSoul": "灵魂沙上飘起的魂灵",
"betterfoliage.risingSoul.tooltip": "灵魂沙的顶部飘出灵魂粒子 FX",
"betterfoliage.risingSoul.chance": "粒子的生成机率",
"betterfoliage.risingSoul.chance.tooltip": "随机渲染刻激发灵魂沙生成一个粒子的概率",
"betterfoliage.risingSoul.speed": "粒子速度",
"betterfoliage.risingSoul.speed.tooltip": "灵颗粒的垂直速度",
"betterfoliage.risingSoul.perturb": "扰动",
"betterfoliage.risingSoul.perturb.tooltip": "动的大小.增加了一个与之旋转同步的螺旋状动量",
"betterfoliage.risingSoul.headSize": "魂灵的大小",
"betterfoliage.risingSoul.headSize.tooltip": "灵魂粒子的大小",
"betterfoliage.risingSoul.trailSize": "魂灵轨迹的大小",
"betterfoliage.risingSoul.trailSize.tooltip": "灵魂粒子的轨迹的初始大小",
"betterfoliage.risingSoul.opacity": "不透明度",
"betterfoliage.risingSoul.opacity.tooltip": "粒子效果的不透明度",
"betterfoliage.risingSoul.sizeDecay": "大小的衰减",
"betterfoliage.risingSoul.sizeDecay.tooltip": "灵魂轨迹粒子大小与前一刻他的大小相关",
"betterfoliage.risingSoul.opacityDecay": "不透明度的衰减",
"betterfoliage.risingSoul.opacityDecay.tooltip": "灵魂轨迹粒子不透明度与前一刻他的不透明度相关",
"betterfoliage.risingSoul.lifetime": "最长存在时间",
"betterfoliage.risingSoul.lifetime.tooltip": "粒子的最长存在时间,仅在几秒内,最短时间为这个值60%%",
"betterfoliage.risingSoul.trailLength": "魂灵轨迹长度",
"betterfoliage.risingSoul.trailLength.tooltip": "在游戏刻内粒子记录的轨迹位置的数量",
"betterfoliage.risingSoul.trailDensity": "魂灵轨迹密集程度",
"betterfoliage.risingSoul.trailDensity.tooltip": "整条轨迹中渲染每第N个轨迹位置",
"betterfoliage.roundLogs": "圆木",
"betterfoliage.roundLogs.tooltip": "使木方块拥有八角形的横截面",
"betterfoliage.roundLogs.plantsOnly": "仅仅应用于植物性材料",
"betterfoliage.roundLogs.plantsOnly.tooltip": "是否仅仅应用于木质材料和干草堆,而不是所有圆柱方块?",
"betterfoliage.roundLogs.connectSolids": "连接到固体方块上",
"betterfoliage.roundLogs.connectSolids.tooltip": "要使圆木连接到完整的固体方块上吗?",
"betterfoliage.roundLogs.connectPerpendicular": "连接到垂直的圆木上",
"betterfoliage.roundLogs.connectPerpendicular.tooltip": "要使圆木根据它的角度连接到垂直圆木上吗?",
"betterfoliage.roundLogs.lenientConnect": "巨大的圆木",
"betterfoliage.roundLogs.lenientConnect.tooltip": "在L形中也连接成巨大的圆木, 不只是2x2形",
"betterfoliage.roundLogs.connectGrass": "连接到草方块上",
"betterfoliage.roundLogs.connectGrass.tooltip": "如果树木下的泥土附近有草方块,那么它也会被渲染成草方块",
"betterfoliage.roundLogs.radiusSmall": "圆木斜面的半径",
"betterfoliage.roundLogs.radiusSmall.tooltip": "从圆木的外角砍掉多大的部分",
"betterfoliage.roundLogs.radiusLarge": "连接圆木的斜面半径",
"betterfoliage.roundLogs.radiusLarge.tooltip": "从连接着的巨大圆木的外角砍掉多大的部分",
"betterfoliage.roundLogs.dimming": "调光变暗",
"betterfoliage.roundLogs.dimming.tooltip": "将圆木阴暗面变黑的程度",
"betterfoliage.roundLogs.zProtection": "Z-Protection [Z保护]",
"betterfoliage.roundLogs.zProtection.tooltip": "用多少倍放大平行圆木连接处的面 去停止 Z-fighting (闪烁)[斑驳,两个多边形共面所出现的效果].在没有发生故障的情况下,试着将这个值设置得尽可能的高[这是Z-fighting出现的原因:多个多面体的面重叠在一起,会一直闪烁]",
"betterfoliage.roundLogs.defaultY": "默认垂直",
"betterfoliage.roundLogs.defaultY.tooltip": "如果开启, 方向不确定的圆木将会渲染成垂直的.否则, 它们仅仅渲染为cube型方块."
}

View File

@@ -1,2 +1,2 @@
// Vanilla // Vanilla
net.minecraft.block.LogBlock net.minecraft.block.RotatedPillarBlock

View File

@@ -1,4 +1,4 @@
// Vanilla // Vanilla
block/column_side,side,end
block/cube_column,side,end block/cube_column,side,end
block/cube_column_horizontal,side,end
block/cube_all,all,all block/cube_all,all,all