Compare commits

...

27 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
49d4f8aa31 remove some Fabric aliases 2021-04-30 12:28:34 +02:00
67 changed files with 1444 additions and 1300 deletions

View File

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

View File

@@ -4,11 +4,11 @@ org.gradle.daemon=false
group = com.github.octarine-noise
jarName = BetterFoliage-Forge
version = 2.6.1
version = 2.6.5
mcVersion = 1.15.2
forgeVersion = 31.2.44
mappingsChannel = snapshot
mappingsVersion = 20200514-1.15.1
mcVersion = 1.16.5
forgeVersion = 36.1.17
mappingsChannel = official
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
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
zipStorePath=wrapper/dists

53
gradlew vendored
View File

@@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -109,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@@ -138,19 +156,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -159,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

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
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

View File

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

View File

@@ -21,7 +21,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
*/
@Mixin(Block.class)
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 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";

View File

@@ -8,7 +8,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraftforge.client.model.data.IModelData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -19,12 +19,12 @@ import java.util.Random;
@Mixin(BlockModelRenderer.class)
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 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 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 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/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/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)
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)
return RenderCtxVanilla.render(renderer, world, (SpecialRenderModel) model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData, true);
else
@@ -32,10 +32,10 @@ public class MixinBlockModelRenderer {
}
@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)
return RenderCtxVanilla.render(renderer, world, (SpecialRenderModel) model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData, false);
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;
import mods.betterfoliage.Hooks;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import org.spongepowered.asm.mixin.Debug;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Coerce;
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.
*/
@Mixin(BlockState.class)
@Mixin(AbstractBlock.AbstractBlockState.class)
@SuppressWarnings({"deprecation"})
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 callTo = "Lnet/minecraft/block/Block;getAmbientOcclusionLightValue(Lnet/minecraft/block/BlockState;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";
// 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))
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;
import mods.betterfoliage.Hooks;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@Mixin(ClientWorld.class)
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 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 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 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;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.
*/
@Redirect(method = worldAnimateTick, at = @At(value = "INVOKE", target = blockAnimateTick))
void onAnimateTick(Block block, BlockState state, World world, BlockPos pos, Random random) {
Hooks.onRandomDisplayTick(block, state, world, pos, random);
block.animateTick(state, world, pos, random);
@Inject(method = worldAnimateTick, at = @At(value = "INVOKE", target = blockAnimateTick))
void onAnimateTick(int x, int y, int z, int range, Random random, boolean doBarrier, BlockPos.Mutable pos, CallbackInfo ci) {
Hooks.onRandomDisplayTick((ClientWorld) (Object) this, pos, random);
}
/**
@@ -39,6 +38,6 @@ public class MixinClientWorld {
@Redirect(method = worldNotify, at = @At(value = "INVOKE", target = rendererNotify))
void onClientBlockChanged(WorldRenderer renderer, IBlockReader world, BlockPos pos, BlockState oldState, BlockState newState, int 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;
import com.mojang.blaze3d.matrix.MatrixStack;
import mods.betterfoliage.render.pipeline.RenderCtxForge;
import mods.betterfoliage.model.SpecialRenderModel;
import mods.betterfoliage.render.pipeline.RenderCtxForge;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.model.IBakedModel;
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.pipeline.ForgeBlockModelRenderer;
import net.minecraftforge.client.model.pipeline.VertexLighterFlat;
@@ -19,14 +19,14 @@ import java.util.Random;
@Mixin(ForgeBlockModelRenderer.class)
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 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 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 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 = "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/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)
public boolean render(
VertexLighterFlat lighter,
ILightReader world,
IBlockDisplayReader world,
IBakedModel model,
BlockState state,
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 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 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))
void onBeforeTextures(IProfiler profiler, int maxMipmapLevel, CallbackInfo ci) {
profiler.endStartSection("betterfoliage");
profiler.popPush("betterfoliage");
BetterFoliageMod.INSTANCE.getBus().post(new ModelDefinitionsLoadedEvent(ModelBakery.class.cast(this)));
}
@@ -34,7 +34,7 @@ abstract public class MixinModelBakery {
IBakedModel onBakeModel(
IUnbakedModel unbaked,
ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter,
Function<RenderMaterial, TextureAtlasSprite> spriteGetter,
IModelTransform transform,
ResourceLocation locationIn
) {

View File

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

View File

@@ -1,25 +1,37 @@
package mods.betterfoliage
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import net.alexwells.kottle.FMLKotlinModLoadingContext
import mods.betterfoliage.config.MainConfig
import mods.betterfoliage.util.tryDefault
import mods.betterfoliage.config.clothGuiRoot
import mods.betterfoliage.config.forgeSpecRoot
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.common.Mod
import net.minecraftforge.fml.config.ModConfig
import org.apache.commons.lang3.tuple.Pair
import org.apache.logging.log4j.Level
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.simple.SimpleLogger
import org.apache.logging.log4j.util.PropertiesUtil
import thedarkcolour.kotlinforforge.forge.MOD_BUS
import java.io.File
import java.io.PrintStream
import java.util.Properties
import java.util.function.BiFunction
import java.util.function.BiPredicate
import java.util.function.Supplier
@Mod(BetterFoliageMod.MOD_ID)
object BetterFoliageMod {
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 {
parentFile.mkdirs()
@@ -32,8 +44,34 @@ object BetterFoliageMod {
)
init {
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.build())
Minecraft.getInstance().resourcePackList.addPackFinder(BetterFoliage.generatedPack.finder)
val ctx = ModLoadingContext.get()
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)
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.util.ResourceLocation
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockDisplayReader
import net.minecraft.world.IBlockReader
import net.minecraft.world.ILightReader
import net.minecraftforge.client.model.pipeline.BlockInfo
import net.minecraftforge.client.model.pipeline.VertexLighterFlat
import java.util.*
import java.util.Random
typealias Sprite = TextureAtlasSprite
// Java
val String = ClassRef<String>("java.lang.String")
@@ -32,7 +34,7 @@ fun <K, V> mapRefMutable() = ClassRef<MutableMap<K, V>>("java.util.Map")
// Minecraft
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 BlockPos = ClassRef<BlockPos>("net.minecraft.util.math.BlockPos")
val Block = ClassRef<Block>("net.minecraft.block.Block")
@@ -77,6 +79,13 @@ object CustomColors : ClassRef<Any>("net.optifine.CustomColors") {
}
// 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") {
val pushState = MethodRef(this, "pushEntity", void, long)
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.shapes.VoxelShape
import net.minecraft.util.math.shapes.VoxelShapes
import net.minecraft.world.IBlockDisplayReader
import net.minecraft.world.IBlockReader
import net.minecraft.world.ILightReader
import net.minecraft.world.World
import java.util.Random
@@ -35,11 +35,12 @@ fun onClientBlockChanged(worldClient: ClientWorld, pos: BlockPos, oldState: Bloc
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 &&
Config.risingSoul.enabled &&
state.block == Blocks.SOUL_SAND &&
world.isAirBlock(pos.offset(UP)) &&
world.getBlockState(pos.relative(UP)).isAir &&
Math.random() < Config.risingSoul.chance) {
RisingSoulParticle(world, pos).addIfValid()
}
@@ -47,7 +48,7 @@ fun onRandomDisplayTick(block: Block, state: BlockState, world: World, pos: Bloc
if (Config.enabled &&
Config.fallingLeaves.enabled &&
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 ->
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) =
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? {
val model = Minecraft.getInstance().blockRendererDispatcher.blockModelShapes.getModel(state) as? SpecialRenderModel
fun getActualRenderModel(world: IBlockDisplayReader, pos: BlockPos, state: BlockState, random: Random): SpecialRenderModel? {
val model = Minecraft.getInstance().blockRenderer.blockModelShaper.getBlockModel(state) as? SpecialRenderModel
?: return null
if (model is WeightedModelWrapper) {
random.setSeed(state.getPositionRandom(pos))
random.setSeed(state.getSeed(pos))
return model.getModel(random).model
}
return model

View File

@@ -1,7 +1,6 @@
package mods.betterfoliage.chunk
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.allDirections
import mods.betterfoliage.util.offset
import mods.betterfoliage.util.plus
import mods.betterfoliage.util.semiRandom
@@ -10,7 +9,7 @@ import net.minecraft.block.BlockState
import net.minecraft.client.renderer.chunk.ChunkRenderCache
import net.minecraft.util.Direction
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.biome.Biome
import net.minecraft.world.level.ColorResolver
@@ -20,7 +19,7 @@ import net.minecraft.world.level.ColorResolver
* block-relative coordinates.
*/
interface BlockCtx {
val world: ILightReader
val world: IBlockDisplayReader
val pos: BlockPos
fun offset(dir: Direction) = offset(dir.offset)
@@ -35,13 +34,13 @@ interface BlockCtx {
val biome: Biome? get() =
(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. */
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. */
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(
override val world: ILightReader,
override val world: IBlockDisplayReader,
override val pos: BlockPos
) : BlockCtx {
override val state: BlockState = world.getBlockState(pos)

View File

@@ -1,32 +1,26 @@
package mods.betterfoliage.chunk
import mods.octarinecore.ChunkCacheOF
import mods.betterfoliage.util.get
import mods.betterfoliage.util.isInstance
import mods.octarinecore.ChunkCacheOF
import net.minecraft.client.renderer.chunk.ChunkRenderCache
import net.minecraft.client.world.ClientWorld
import net.minecraft.util.math.BlockPos
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.dimension.DimensionType
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.world.ChunkEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
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
val ILightReader.dimType: DimensionType get() = when {
this is IWorldReader -> dimension.type
this is ChunkRenderCache -> world.dimension.type
this.isInstance(ChunkCacheOF) -> this[ChunkCacheOF.chunkCache].world.dimension.type
val IBlockDisplayReader.dimType: DimensionType get() = when {
this is IWorldReader -> dimensionType()
this is ChunkRenderCache -> level.dimensionType()
this.isInstance(ChunkCacheOF) -> this[ChunkCacheOF.chunkCache].level.dimensionType()
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> {
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.minecraftforge.eventbus.api.SubscribeEvent
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 {
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

@@ -14,5 +14,7 @@ val MYCELIUM_BLOCKS = listOf(Blocks.MYCELIUM)
val SALTWATER_BIOMES = listOf(Biome.Category.BEACH, Biome.Category.OCEAN)
val SNOW_MATERIALS = listOf(Material.SNOW_BLOCK, Material.SNOW)
val BlockState.isSnow: Boolean get() = material in SNOW_MATERIALS
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)
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)
CustomColors.getColorMultiplier.invokeStatic(fakeQuad, ctx.state, ctx.world, ctx.pos, renderEnv.wrapped) as? Int
} else null

View File

@@ -1,48 +1,75 @@
package mods.betterfoliage.integration
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.render.pipeline.RenderCtxForge
import mods.betterfoliage.render.pipeline.RenderCtxVanilla
import mods.betterfoliage.resource.discovery.BakeWrapperManager
import mods.betterfoliage.util.HasLogger
import mods.betterfoliage.util.allAvailable
import mods.betterfoliage.util.get
import mods.betterfoliage.util.mapArray
import mods.octarinecore.*
import net.minecraft.block.BlockRenderType
import net.minecraft.block.BlockRenderType.MODEL
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
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.world.ILightReader
import net.minecraft.world.IBlockDisplayReader
import net.minecraftforge.client.model.pipeline.LightUtil
import org.apache.logging.log4j.Level.INFO
/**
* Integration for ShadersMod.
*/
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
val defaultGrass = Blocks.GRASS.defaultState
@JvmStatic val defaultLeaves = Blocks.OAK_LEAVES.defaultBlockState()
@JvmStatic val defaultGrass = Blocks.GRASS.defaultBlockState()
@JvmStatic var diffuseShades = Direction.values().mapArray { LightUtil.diffuseLight(it) }
/**
* Called from transformed ShadersMod code.
* @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 (BlockConfig.crops.matchesClass(state.block)) return defaultGrass
return state
}
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. */
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 sVertexBuilder = buffer[BufferBuilder_sVertexBuilder]
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
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.minV + (quad.sprite.maxV - quad.sprite.minV) * (vertex.uv.v + 0.5).toFloat(),
quad.sprite.u0 + (quad.sprite.u1 - quad.sprite.u0) * (vertex.uv.u + 0.5).toFloat(),
quad.sprite.v0 + (quad.sprite.v1 - quad.sprite.v0) * (vertex.uv.v + 0.5).toFloat(),
0.0f, 1.0f
)
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 {
val size = DefaultVertexFormats.BLOCK.integerSize
val verts = Array(4) { vIdx ->
val x = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 0])
val y = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 1])
val z = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 2])
val color = vertexData[vIdx * size + 3]
val u = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 4])
val v = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 5])
val x = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 0]) - 0.5f
val y = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 1]) - 0.5f
val z = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 2]) - 0.5f
val color = vertices[vIdx * size + 3]
val u = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 4])
val v = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 5])
Vertex(Double3(x, y, z), UV(u.toDouble(), v.toDouble()), Color(color))
}
val unbaked = Quad(
verts[0], verts[1], verts[2], verts[3],
colorIndex = if (hasTintIndex()) tintIndex else -1,
face = face
colorIndex = if (isTinted) tintIndex else -1,
face = direction
)
return HalfBakedQuad(unbaked, this)
}

View File

@@ -1,17 +1,9 @@
package mods.betterfoliage.model
import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.util.HasLogger
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 org.apache.logging.log4j.Level.WARN
import java.util.Random
import java.util.function.Function
/**
* Model that makes use of advanced rendering features.
@@ -24,9 +16,9 @@ class WeightedModelWrapper(
val models: List<WeightedModel>, baseModel: SpecialRenderModel
): IBakedModel by baseModel, SpecialRenderModel {
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) {
getModel(ctx.random).model.render(ctx, noDecorations)

View File

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

View File

@@ -1,10 +1,11 @@
package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
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.HalfBakedWrapperKey
@@ -15,7 +16,6 @@ import mods.betterfoliage.model.tuftModelSet
import mods.betterfoliage.model.tuftShapeSet
import mods.betterfoliage.render.lighting.LightingPreferredFace
import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.render.pipeline.RenderCtxVanilla
import mods.betterfoliage.resource.discovery.AbstractModelDiscovery
import mods.betterfoliage.resource.discovery.BakeWrapperManager
import mods.betterfoliage.resource.discovery.ModelBakingContext
@@ -27,20 +27,18 @@ import mods.betterfoliage.util.LazyInvalidatable
import mods.betterfoliage.util.get
import mods.betterfoliage.util.offset
import mods.betterfoliage.util.randomI
import net.minecraft.block.Blocks
import net.minecraft.block.material.Material
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.RenderTypeLookup
import net.minecraft.client.renderer.model.BlockModel
import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation
import net.minecraft.world.biome.Biome
object StandardDirtDiscovery : AbstractModelDiscovery() {
fun canRenderInLayer(layer: RenderType) = when {
!Config.enabled -> layer == RenderType.getSolid()
!Config.connectedGrass.enabled && !Config.algae.enabled && !Config.reed.enabled -> layer == RenderType.getSolid()
else -> layer == RenderType.getCutoutMipped()
!Config.enabled -> layer == RenderType.solid()
!Config.connectedGrass.enabled && !Config.algae.enabled && !Config.reed.enabled -> layer == RenderType.solid()
else -> layer == RenderType.cutoutMipped()
}
override fun processModel(ctx: ModelDiscoveryContext) {
@@ -67,9 +65,12 @@ class StandardDirtModel(
val stateUp = ctx.state(UP)
val state2Up = ctx.state(Int3(0, 2, 0))
val isConnectedGrass = Config.connectedGrass.enabled && stateUp in BetterFoliage.blockTypes.grass
val isConnectedGrass = Config.connectedGrass.enabled &&
stateUp in BetterFoliage.blockTypes.grass &&
(Config.connectedGrass.snowEnabled || !state2Up.isSnow)
if (isConnectedGrass) {
(ctx.blockModelShapes.getModel(stateUp) as? SpecialRenderModel)?.let { grassModel ->
(ctx.blockModelShapes.getBlockModel(stateUp) as? SpecialRenderModel)?.let { grassModel ->
ctx.renderMasquerade(UP.offset) {
grassModel.render(ctx, true)
}
@@ -81,9 +82,9 @@ class StandardDirtModel(
super.render(ctx, false)
val isWater = stateUp.material == Material.WATER
val isDeepWater = isWater && ctx.offset(Int3(2 to UP)).state.material == Material.WATER
val isShallowWater = isWater && ctx.offset(Int3(2 to UP)).state.isAir
val isSaltWater = isWater && ctx.biome?.category in SALTWATER_BIOMES
val isDeepWater = isWater && state2Up.material == Material.WATER
val isShallowWater = isWater && state2Up.isAir
val isSaltWater = isWater && ctx.biome?.biomeCategory in SALTWATER_BIOMES
if (Config.algae.enabled(ctx.random) && isDeepWater) {
ctx.vertexLighter = vanillaTuftLighting

View File

@@ -87,7 +87,7 @@ class StandardGrassModel(
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
ShadersModIntegration.grass(ctx, Config.shortGrass.shaderWind) {
ctx.renderQuads(if (isSnowed) tuftSnowed[ctx.random] else tuftNormal[ctx.random])

View File

@@ -31,7 +31,7 @@ object StandardMyceliumDiscovery : AbstractModelDiscovery() {
override fun processModel(ctx: ModelDiscoveryContext) {
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in MYCELIUM_BLOCKS) {
ctx.addReplacement(StandardMyceliumKey)
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutout())
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutout())
}
super.processModel(ctx)
}
@@ -50,9 +50,8 @@ class StandardMyceliumModel(
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
super.render(ctx, noDecorations)
if (Config.shortGrass.enabled &&
if (Config.shortGrass.enabled(ctx.random) &&
Config.shortGrass.myceliumEnabled &&
Config.shortGrass.enabled(ctx.random) &&
ctx.state(Direction.UP).isAir(ctx.world, ctx.pos)
) {
ctx.vertexLighter = tuftLighting

View File

@@ -32,9 +32,9 @@ import net.minecraft.util.ResourceLocation
object StandardNetherrackDiscovery : AbstractModelDiscovery() {
fun canRenderInLayer(layer: RenderType) = when {
!Config.enabled -> layer == RenderType.getSolid()
!Config.netherrack.enabled -> layer == RenderType.getSolid()
else -> layer == RenderType.getCutoutMipped()
!Config.enabled -> layer == RenderType.solid()
!Config.netherrack.enabled -> layer == RenderType.solid()
else -> layer == RenderType.cutoutMipped()
}
override fun processModel(ctx: ModelDiscoveryContext) {

View File

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

View File

@@ -43,7 +43,7 @@ object StandardSandDiscovery : AbstractModelDiscovery() {
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in SAND_BLOCKS) {
BetterFoliage.blockTypes.dirt.add(ctx.blockState)
ctx.addReplacement(StandardSandKey)
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutoutMipped())
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutoutMipped())
}
super.processModel(ctx)
}
@@ -61,7 +61,7 @@ class StandardSandModel(
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
super.render(ctx, noDecorations)
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 ->
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.Axis
import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader
import net.minecraft.world.IBlockDisplayReader
/** Index of SOUTH-EAST quadrant. */
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) }}}
override fun onBlockUpdate(world: ILightReader, pos: BlockPos) {
override fun onBlockUpdate(world: IBlockDisplayReader, pos: BlockPos) {
allNeighborOffsets.forEach { offset -> ChunkOverlayManager.clear(world.dimType, this, pos + offset) }
}
override fun calculate(ctx: BlockCtx): ColumnLayerData {
// 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
// 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 key = getColumnKey(state(offsetRot))
return if (key == null) {
if (offset(offsetRot).isNormalCube) SOLID else NONSOLID
if (offset(offsetRot).isFullBlock) SOLID else NONSOLID
} else {
(key.axis ?: if (Config.roundLogs.defaultY) Axis.Y else null)?.let {
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.util.Direction
import net.minecraft.util.math.BlockPos
import net.minecraft.world.ILightReader
import net.minecraft.world.IBlockDisplayReader
data class LightingData(
@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]
* This gets called on a LOT, so object instantiation is avoided.
* Not thread-safe, always use a [ThreadLocal] instance
*/
class VanillaAoCalculator {
lateinit var world: ILightReader
lateinit var world: IBlockDisplayReader
/** [blockPos] is used to get block-related information (i.e. tint, opacity, etc.)
* [lightPos] is used to get light-related information
@@ -37,7 +41,7 @@ class VanillaAoCalculator {
lateinit var blockPos: 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 aoData = Array(24) { LightingData() }
@@ -70,13 +74,13 @@ class VanillaAoCalculator {
// Bit 0 of the bitset in vanilla calculations
// 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
probe.position { setPos(lightOrigin) }.writeTo(centerAo)
if (!isFullBlock && !probe.position { move(lightFace) }.state.isOpaqueCube(world, probe.pos)) {
probe.position { set(lightOrigin) }.writeTo(centerAo)
if (!isFullBlock && !probe.position { move(lightFace) }.state.isSolidRender(world, probe.pos)) {
// if the neighboring block in the lightface direction is
// transparent (non-opaque), use its packed light instead of our own
// (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
sideHelper.sides.forEachIndexed { sideIdx, sideDir ->
// 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
// 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
@@ -103,7 +108,7 @@ class VanillaAoCalculator {
else {
// lookup actual packed light from the cornering block in the world
probe.position {
setPos(lightOrigin)
set(lightOrigin)
.move(sideHelper.sides[sideIndices.first])
.move(sideHelper.sides[sideIndices.second])
}.writeTo(cornerAo[cornerIdx])
@@ -129,9 +134,9 @@ class VanillaAoCalculator {
lateinit var state: BlockState
val pos = BlockPos.Mutable()
val packedLight: Int get() = cache.getPackedLight(state, world, pos)
val colorMultiplier: Float get() = cache.getBrightness(state, world, pos)
val isNonTransparent: Boolean get() = state.getOpacity(world, pos) > 0
val packedLight: Int get() = cache.getLightColor(state, world, pos)
val colorMultiplier: Float get() = cache.getShadeBrightness(state, world, pos)
val isNonTransparent: Boolean get() = state.getLightBlock(world, pos) > 0
fun writeTo(data: LightingData) {
data.packedLight = packedLight

View File

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

View File

@@ -5,12 +5,12 @@ import mods.betterfoliage.util.Double3
import net.minecraft.client.Minecraft
import net.minecraft.client.particle.SpriteTexturedParticle
import net.minecraft.client.renderer.ActiveRenderInfo
import net.minecraft.client.renderer.Vector3f
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.client.world.ClientWorld
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 {
// @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() {
super.tick()
currentPos.setTo(posX, posY, posZ)
prevPos.setTo(prevPosX, prevPosY, prevPosZ)
velocity.setTo(motionX, motionY, motionZ)
currentPos.setTo(x, y, z)
prevPos.setTo(xo, yo, zo)
velocity.setTo(xd, yd, zd)
update()
posX = currentPos.x; posY = currentPos.y; posZ = currentPos.z;
motionX = velocity.x; motionY = velocity.y; motionZ = velocity.z;
x = currentPos.x; y = currentPos.y; z = currentPos.z;
xd = velocity.x; yd = velocity.y; zd = velocity.z;
}
/** Update particle on world tick. */
@@ -39,10 +39,10 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
abstract val isValid: Boolean
/** 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) {
super.renderParticle(vertexBuilder, camera, tickDelta)
override fun render(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
super.render(vertexBuilder, camera, tickDelta)
}
/**
@@ -63,39 +63,39 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
tickDelta: Float,
currentPos: Double3 = this.currentPos,
prevPos: Double3 = this.prevPos,
size: Double = particleScale.toDouble(),
currentAngle: Float = this.particleAngle,
prevAngle: Float = this.prevParticleAngle,
size: Double = quadSize.toDouble(),
currentAngle: Float = this.roll,
prevAngle: Float = this.oRoll,
sprite: TextureAtlasSprite = this.sprite,
alpha: Float = this.particleAlpha) {
alpha: Float = this.alpha) {
val center = Double3.lerp(tickDelta.toDouble(), prevPos, currentPos)
val angle = MathHelper.lerp(tickDelta, prevAngle, currentAngle)
val rotation = camera.rotation.copy().apply { multiply(Vector3f.ZP.rotation(angle)) }
val lightmapCoord = getBrightnessForRender(tickDelta)
val rotation = camera.rotation().copy().apply { mul(Vector3f.ZP.rotation(angle)) }
val lightmapCoord = getLightColor(tickDelta)
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)
).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
.pos(vertex.x, vertex.y, vertex.z).tex(u, v)
.color(particleRed, particleGreen, particleBlue, alpha).lightmap(lightmapCoord)
.vertex(vertex.x, vertex.y, vertex.z).uv(u, v)
.color(rCol, gCol, bCol, alpha).uv2(lightmapCoord)
.endVertex()
renderVertex(coords[0], sprite.maxU, sprite.maxV)
renderVertex(coords[1], sprite.maxU, sprite.minV)
renderVertex(coords[2], sprite.minU, sprite.minV)
renderVertex(coords[3], sprite.minU, sprite.maxV)
renderVertex(coords[0], sprite.u1, sprite.v1)
renderVertex(coords[1], sprite.u1, sprite.v0)
renderVertex(coords[2], sprite.u0, sprite.v0)
renderVertex(coords[3], sprite.u0, sprite.v1)
}
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
bCol = (color and 255) / 256.0f
gCol = ((color shr 8) 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.randomF
import mods.betterfoliage.util.randomI
import net.minecraft.client.Minecraft
import net.minecraft.client.particle.IParticleRenderType
import net.minecraft.client.world.ClientWorld
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper
import net.minecraft.world.World
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.TickEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.LogicalSide
import java.util.Random
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.sin
class FallingLeafParticle(
world: World, pos: BlockPos, leaf: LeafParticleKey, blockColor: Int, random: Random
world: ClientWorld, pos: BlockPos, leaf: LeafParticleKey, blockColor: Int, random: Random
) : AbstractParticle(
world, pos.x.toDouble() + 0.5, pos.y.toDouble(), pos.z.toDouble() + 0.5
) {
@@ -37,13 +37,13 @@ class FallingLeafParticle(
var wasCollided = false
init {
particleAngle = random.randomF(max = PI2)
prevParticleAngle = particleAngle - rotationSpeed
roll = random.randomF(max = PI2)
oRoll = roll - rotationSpeed
maxAge = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
motionY = -Config.fallingLeaves.speed
lifetime = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
yd = -Config.fallingLeaves.speed
particleScale = Config.fallingLeaves.size.toFloat() * 0.1f
quadSize = Config.fallingLeaves.size.toFloat() * 0.1f
setColor(leaf.overrideColor?.asInt ?: blockColor)
sprite = LeafParticleRegistry[leaf.leafType][randomI(max = 1024)]
}
@@ -52,21 +52,21 @@ class FallingLeafParticle(
override fun update() {
if (rand.nextFloat() > 0.95f) rotationSpeed *= -1.0f
if (age > maxAge - 20) particleAlpha = 0.05f * (maxAge - age)
if (random.nextFloat() > 0.95f) rotationSpeed *= -1.0f
if (age > lifetime - 20) alpha = 0.05f * (lifetime - age)
if (onGround || wasCollided) {
velocity.setTo(0.0, 0.0, 0.0)
if (!wasCollided) {
age = age.coerceAtLeast(maxAge - 20)
age = age.coerceAtLeast(lifetime - 20)
wasCollided = true
}
} 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)
.add(LeafWindTracker.current).add(0.0, -1.0, 0.0).mul(Config.fallingLeaves.speed)
prevParticleAngle = particleAngle
particleAngle += rotationSpeed
oRoll = roll
roll += rotationSpeed
}
}
@@ -84,7 +84,7 @@ object LeafWindTracker {
}
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 speed = abs(random.nextGaussian()) * Config.fallingLeaves.windStrength +
(if (!world.isRaining) 0.0 else abs(random.nextGaussian()) * Config.fallingLeaves.stormStrength)
@@ -92,10 +92,10 @@ object LeafWindTracker {
}
@SubscribeEvent
fun handleWorldTick(event: TickEvent.ClientTickEvent) {
if (event.phase == TickEvent.Phase.START) Minecraft.getInstance().world?.let { world ->
fun handleWorldTick(event: TickEvent.WorldTickEvent) {
if (event.phase == TickEvent.Phase.START && event.side == LogicalSide.CLIENT) event.world.let { world ->
// change target wind speed
if (world.worldInfo.dayTime >= nextChange) changeWind(world)
if (world.dayTime >= nextChange) changeWind(world)
// change current wind speed
val changeRate = if (world.isRaining) 0.015 else 0.005
@@ -107,6 +107,6 @@ object LeafWindTracker {
}
}
@SubscribeEvent
fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isRemote) changeWind(event.world.world) }
// @SubscribeEvent
// fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isClientSide) changeWind(event.world) }
}

View File

@@ -41,7 +41,7 @@ object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
@SubscribeEvent
fun handlePreStitch(event: TextureStitchEvent.Pre) {
if (event.map.textureLocation == Atlas.PARTICLES.resourceId) {
if (event.map.location() == Atlas.PARTICLES.resourceId) {
allTypes.forEach { leafType ->
val locations = (0 until 16).map { idx ->
ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx")
@@ -55,7 +55,7 @@ object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
@SubscribeEvent
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 ->
val sprites = (0 until 16).map { 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 net.minecraft.client.particle.IParticleRenderType
import net.minecraft.client.renderer.ActiveRenderInfo
import net.minecraft.client.world.ClientWorld
import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper
@@ -23,7 +24,7 @@ import kotlin.math.cos
import kotlin.math.sin
class RisingSoulParticle(
world: World, pos: BlockPos
world: ClientWorld, pos: BlockPos
) : AbstractParticle(
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)
init {
motionY = 0.1
particleGravity = 0.0f
yd = 0.1
gravity = 0.0f
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
@@ -49,12 +50,12 @@ class RisingSoulParticle(
particleTrail.addFirst(currentPos.copy())
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()
if (age > maxAge - 40) alpha *= (maxAge - age) / 40.0f
if (age > lifetime - 40) alpha *= (lifetime - age) / 40.0f
renderParticleQuad(
vertexBuilder, camera, tickDelta,

View File

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

View File

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

View File

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

View File

@@ -20,7 +20,7 @@ interface VeryEarlyReloadListener : IFutureReloadListener {
gameExecutor: Executor
): CompletableFuture<Void> {
onReloadStarted()
return stage.markCompleteAwaitingOthers(null)
return stage.wait(null)
}
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.IModelTransform
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.RenderMaterial
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.ResourceLocation
import net.minecraftforge.client.event.ModelBakeEvent
@@ -30,7 +30,7 @@ data class ModelDefinitionsLoadedEvent(
interface ModelBakingKey {
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 {
@@ -49,7 +49,7 @@ data class ModelDiscoveryContext(
val replacements: MutableMap<ResourceLocation, ModelBakingKey>,
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) {
replacements[modelLocation] = key
if (addToStateKeys) BetterFoliage.blockTypes.stateKeys[blockState] = key
@@ -59,12 +59,12 @@ data class ModelDiscoveryContext(
data class ModelBakingContext(
val bakery: ModelBakery,
val spriteGetter: Function<Material, TextureAtlasSprite>,
val spriteGetter: Function<RenderMaterial, TextureAtlasSprite>,
val location: ResourceLocation,
val transform: IModelTransform,
val logger: Logger
) {
fun getUnbaked() = bakery.getUnbakedModel(location)
fun getUnbaked() = bakery.getModel(location)
fun getBaked() = bakery.getBakedModel(location, transform, spriteGetter)
}
@@ -94,7 +94,7 @@ object BakeWrapperManager : Invalidator, HasLogger() {
@SubscribeEvent
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")
sprites.forEach { event.addSprite(it) }
sprites.clear()
@@ -109,7 +109,7 @@ object BakeWrapperManager : Invalidator, HasLogger() {
fun onBake(
unbaked: IUnbakedModel,
bakery: ModelBakery,
spriteGetter: Function<Material, TextureAtlasSprite>,
spriteGetter: Function<RenderMaterial, TextureAtlasSprite>,
transform: IModelTransform,
location: ResourceLocation
): IBakedModel? {
@@ -124,6 +124,6 @@ object BakeWrapperManager : Invalidator, HasLogger() {
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
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.util.HasLogger
import mods.betterfoliage.util.getJavaClass
import mods.betterfoliage.util.getLines
@@ -45,8 +44,8 @@ class ConfigurableBlockMatcher(val location: ResourceLocation) : HasLogger(), IB
fun readDefaults() {
blackList.clear()
whiteList.clear()
resourceManager.getAllResources(location).forEach { resource ->
detailLogger.log(INFO, "Reading block class configuration $location from pack ${resource.packName}")
resourceManager.getResources(location).forEach { resource ->
detailLogger.log(INFO, "Reading block class configuration $location from pack ${resource.sourceName}")
resource.getLines().map{ it.trim() }.filter { !it.startsWith("//") && it.isNotEmpty() }.forEach { line ->
if (line.startsWith("-")) getJavaClass(line.substring(1))?.let { blackList.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() {
val modelList = mutableListOf<ModelTextureList>()
fun readDefaults() {
resourceManager.getAllResources(location).forEach { resource ->
detailLogger.log(INFO, "Reading model/texture configuration $location from pack ${resource.packName}")
resourceManager.getResources(location).forEach { resource ->
detailLogger.log(INFO, "Reading model/texture configuration $location from pack ${resource.sourceName}")
resource.getLines().map{ it.trim() }.filter { !it.startsWith("//") && it.isNotEmpty() }.forEach { line ->
val elements = line.split(",")
modelList.add(ModelTextureList(ResourceLocation(elements.first()), elements.drop(1)))

View File

@@ -18,9 +18,9 @@ abstract class AbstractModelDiscovery : HasLogger(), ModelDiscovery {
replacements: MutableMap<ResourceLocation, ModelBakingKey>
) {
ForgeRegistries.BLOCKS
.flatMap { block -> block.stateContainer.validStates }
.flatMap { block -> block.stateDefinition.possibleStates }
.forEach { state ->
val location = BlockModelShapes.getModelLocation(state)
val location = BlockModelShapes.stateToModelLocation(state)
val ctx = ModelDiscoveryContext(bakery, state, location, sprites, replacements, detailLogger)
try {
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
// may need information from the BlockState which is not available at baking time
val scopedReplacements = mutableMapOf<ResourceLocation, ModelBakingKey>()
model.variantList.forEach { variant ->
model.variants.forEach { variant ->
processModel(ctx.copy(modelLocation = variant.modelLocation, replacements = scopedReplacements))
}
if (scopedReplacements.isNotEmpty()) {
@@ -73,15 +73,18 @@ abstract class ConfigurableModelDiscovery : AbstractModelDiscovery() {
matches.forEach { match ->
detailLogger.log(Level.INFO, " model $model matches ${match.modelLocation}")
val materials = match.textureNames.map { it to model.resolveTextureName(it) }
val texMapString = Joiner.on(", ").join(materials.map { "${it.first}=${it.second.textureLocation}" })
detailLogger.log(Level.INFO, " sprites [$texMapString]")
val materials = match.textureNames.map { it to model.getMaterial(it) }
val texMapString = Joiner.on(", ").join(materials.map { "${it.first}=${it.second.texture()}" })
detailLogger.log(Level.INFO, " sprites [$texMapString]")
if (materials.all { it.second.textureLocation != MissingTextureSprite.getLocation() }) {
// found a valid model (all required textures exist)
processModel(ctx, materials.map { it.second.textureLocation })
}
if (materials.all { it.second.texture() != MissingTextureSprite.getLocation() }) {
// found a valid model (all required textures exist)
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)
}
@@ -90,12 +93,12 @@ abstract class ConfigurableModelDiscovery : AbstractModelDiscovery() {
fun ModelBakery.modelDerivesFrom(model: BlockModel, location: ResourceLocation, target: ResourceLocation): Boolean =
if (location == target) true
else model.parentLocation
?.let { getUnbakedModel(it) as? BlockModel }
?.let { getModel(it) as? BlockModel }
?.let { parent -> modelDerivesFrom(parent, model.parentLocation!!, target) }
?: false
fun ModelBakery.getAncestry(location: ResourceLocation): List<ResourceLocation> {
val model = getUnbakedModel(location) as? BlockModel ?: return listOf(location)
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)
// 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 replacement = replacements[it.modelLocation]
val baked = replacement?.let { replacement ->
@@ -40,10 +40,10 @@ class WeightedUnbakedKey(
// let it through unchanged
if (bakedModels.isEmpty()) return super.bake(ctx)
if (bakedModels.size < unbaked.variantList.size) {
if (bakedModels.size < unbaked.variants.size) {
detailLogger.log(
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) ->

View File

@@ -1,10 +1,8 @@
package mods.betterfoliage.resource.generated
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.HasLogger
import net.minecraft.client.Minecraft
import net.minecraft.client.resources.ClientResourcePackInfo
import net.minecraft.resources.*
import net.minecraft.resources.ResourcePackType.CLIENT_RESOURCES
import net.minecraft.resources.data.IMetadataSectionSerializer
@@ -12,6 +10,7 @@ import net.minecraft.util.ResourceLocation
import net.minecraft.util.text.StringTextComponent
import org.apache.logging.log4j.Level.INFO
import java.util.*
import java.util.function.Consumer
import java.util.function.Predicate
import java.util.function.Supplier
@@ -25,10 +24,10 @@ class GeneratedTexturePack(
val nameSpace: String, val packName: String
) : HasLogger(), IResourcePack {
override fun getName() = packName
override fun getResourceNamespaces(type: ResourcePackType) = setOf(nameSpace)
override fun <T : Any?> getMetadata(deserializer: IMetadataSectionSerializer<T>) = null
override fun getRootResourceStream(id: String) = null
override fun getAllResourceLocations(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<ResourceLocation>()
override fun getNamespaces(type: ResourcePackType) = setOf(nameSpace)
override fun <T : Any?> getMetadataSection(deserializer: IMetadataSectionSerializer<T>) = null
override fun getRootResource(id: String) = null
override fun getResources(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<ResourceLocation>()
override fun close() {}
@@ -49,21 +48,22 @@ class GeneratedTexturePack(
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()
override fun resourceExists(type: ResourcePackType, id: ResourceLocation) =
override fun hasResource(type: ResourcePackType, id: ResourceLocation) =
type == CLIENT_RESOURCES && resources.containsKey(id)
val finder = object : IPackFinder {
val packInfo = ClientResourcePackInfo(
val packInfo = ResourcePackInfo(
packName, true, Supplier { this@GeneratedTexturePack },
StringTextComponent(packName),
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 DIRT_BLOCKS = listOf(Blocks.DIRT, Blocks.COARSE_DIRT)

View File

@@ -1,12 +1,12 @@
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.Axis.*
import net.minecraft.util.Direction.AxisDirection.NEGATIVE
import net.minecraft.util.Direction.AxisDirection.POSITIVE
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.vector.Quaternion
val EPSILON_ZERO = 0.05
val EPSILON_ONE = 0.95
@@ -55,15 +55,15 @@ val ROTATION_MATRIX: Array<IntArray> get() = arrayOf(
// Vectors
// ================================
operator fun Direction.times(scale: Double) =
Double3(directionVec.x.toDouble() * scale, directionVec.y.toDouble() * scale, directionVec.z.toDouble() * scale)
val Direction.vec: Double3 get() = Double3(directionVec.x.toDouble(), directionVec.y.toDouble(), directionVec.z.toDouble())
Double3(normal.x.toDouble() * scale, normal.y.toDouble() * scale, normal.z.toDouble() * scale)
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)
/** 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) {
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 {
val zero: Double3 get() = Double3(0.0, 0.0, 0.0)
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] */
fun rotate(quat: Quaternion) =
quat.copy()
.apply { multiply(Quaternion(x, y, z, 0.0F)) }
.apply { multiply(quat.copy().apply(Quaternion::conjugate)) }
.let { Double3(it.x, it.y, it.z) }
.apply { mul(Quaternion(x.toFloat(), y.toFloat(), z.toFloat(), 0.0F)) }
.apply { mul(quat.copy().apply(Quaternion::conj)) }
.let { Double3(it.i().toDouble(), it.j().toDouble(), it.k().toDouble()) }
// mutable operations
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. */
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(
offset.first * offset.second.directionVec.x,
offset.first * offset.second.directionVec.y,
offset.first * offset.second.directionVec.z
offset.first * offset.second.normal.x,
offset.first * offset.second.normal.y,
offset.first * offset.second.normal.z
)
companion object {
val zero = Int3(0, 0, 0)
@@ -133,9 +133,9 @@ data class Int3(var x: Int, var y: Int, var z: Int) {
// immutable operations
operator fun plus(other: Int3) = Int3(x + other.x, y + other.y, z + other.z)
operator fun plus(other: Pair<Int, Direction>) = Int3(
x + other.first * other.second.directionVec.x,
y + other.first * other.second.directionVec.y,
z + other.first * other.second.directionVec.z
x + other.first * other.second.normal.x,
y + other.first * other.second.normal.y,
z + other.first * other.second.normal.z
)
operator fun unaryMinus() = Int3(-x, -y, -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.GRAY
fun stripTooltipDefaultText(tooltip: MutableList<String>) {
var defaultRows = false
val iter = tooltip.iterator()
while (iter.hasNext()) {
if (iter.next().startsWith(AQUA.toString())) defaultRows = true
if (defaultRows) iter.remove()
}
}
//fun stripTooltipDefaultText(tooltip: MutableList<String>) {
// var defaultRows = false
// val iter = tooltip.iterator()
// while (iter.hasNext()) {
// if (iter.next().startsWith(AQUA.toString())) defaultRows = true
// 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 {
val style = Style().apply { this.color = color }
return StringTextComponent(msg).apply { this.style = style }
}
fun String.asText() = StringTextComponent(this).setStyle(styleGray)

View File

@@ -1,8 +1,6 @@
package mods.betterfoliage.util
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.IResource
import net.minecraft.resources.IResourceManager
@@ -19,11 +17,6 @@ operator fun ResourceLocation.plus(str: String) = ResourceLocation(namespace, pa
fun ResourceLocation.prependLocation(basePath: String) =
ResourceLocation(namespace, basePath.stripEnd("/").let { "$it/$path" })
val ResourceLocation.asBlockMaterial: Material get() = Material(
AtlasTexture.LOCATION_BLOCKS_TEXTURE,
this
)
/** Index operator to get a resource. */
operator fun IResourceManager.get(domain: String, path: String): IResource? = get(ResourceLocation(domain, path))
/** 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.HSB
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.TextureAtlasSprite
import net.minecraft.resources.IResource
@@ -20,8 +19,8 @@ import kotlin.math.cos
import kotlin.math.sin
enum class Atlas(val resourceId: ResourceLocation) {
BLOCKS(AtlasTexture.LOCATION_BLOCKS_TEXTURE),
PARTICLES(AtlasTexture.LOCATION_PARTICLES_TEXTURE);
BLOCKS(AtlasTexture.LOCATION_BLOCKS),
PARTICLES(AtlasTexture.LOCATION_PARTICLES);
/** Get the fully-qualified resource name for sprites belonging to this atlas */
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)
}
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(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.texture.AtlasTexture$SheetData field_217808_d # sprites
public net.minecraft.client.renderer.BlockModelRenderer$Cache
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"
loaderVersion="[1.4,)"
modLoader="kotlinforforge"
loaderVersion="[1,)"
issueTrackerURL="https://github.com/octarine-noise/BetterFoliage/issues"
license="MIT"
[[mods]]
modId="betterfoliage"
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
net.minecraft.block.LogBlock
net.minecraft.block.RotatedPillarBlock

View File

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