Compare commits

..

4 Commits

Author SHA1 Message Date
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
57 changed files with 378 additions and 412 deletions

View File

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

View File

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

Binary file not shown.

View File

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

53
gradlew vendored
View File

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

43
gradlew.bat vendored
View File

@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS= set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,7 +2,6 @@ package mods.betterfoliage
import mods.betterfoliage.config.BlockConfig import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config import mods.betterfoliage.config.Config
import net.alexwells.kottle.FMLKotlinModLoadingContext
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraftforge.fml.ModLoadingContext import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.Mod
@@ -11,6 +10,7 @@ import org.apache.logging.log4j.Level
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.simple.SimpleLogger import org.apache.logging.log4j.simple.SimpleLogger
import org.apache.logging.log4j.util.PropertiesUtil import org.apache.logging.log4j.util.PropertiesUtil
import thedarkcolour.kotlinforforge.forge.MOD_BUS
import java.io.File import java.io.File
import java.io.PrintStream import java.io.PrintStream
import java.util.Properties import java.util.Properties
@@ -19,7 +19,7 @@ import java.util.Properties
object BetterFoliageMod { object BetterFoliageMod {
const val MOD_ID = "betterfoliage" const val MOD_ID = "betterfoliage"
val bus = FMLKotlinModLoadingContext.get().modEventBus val bus = MOD_BUS
val detailLogStream = PrintStream(File("logs/betterfoliage.log").apply { val detailLogStream = PrintStream(File("logs/betterfoliage.log").apply {
parentFile.mkdirs() parentFile.mkdirs()
@@ -33,7 +33,7 @@ object BetterFoliageMod {
init { init {
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.build()) ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.build())
Minecraft.getInstance().resourcePackList.addPackFinder(BetterFoliage.generatedPack.finder) Minecraft.getInstance().resourcePackRepository.addPackFinder(BetterFoliage.generatedPack.finder)
bus.register(BlockConfig) bus.register(BlockConfig)
BetterFoliage.init() BetterFoliage.init()
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -55,6 +55,7 @@ object Config : DelegatingConfig(BetterFoliageMod.MOD_ID, BetterFoliageMod.MOD_I
object roundLogs : ConfigCategory(){ object roundLogs : ConfigCategory(){
val enabled by featureEnable() val enabled by featureEnable()
val plantsOnly by boolean(true)
val radiusSmall by double(max=0.5, default=0.25) val radiusSmall by double(max=0.5, default=0.25)
val radiusLarge by double(max=0.5, default=0.44) val radiusLarge by double(max=0.5, default=0.44)
val dimming by double(default = 0.7) val dimming by double(default = 0.7)

View File

@@ -14,5 +14,7 @@ val MYCELIUM_BLOCKS = listOf(Blocks.MYCELIUM)
val SALTWATER_BIOMES = listOf(Biome.Category.BEACH, Biome.Category.OCEAN) val SALTWATER_BIOMES = listOf(Biome.Category.BEACH, Biome.Category.OCEAN)
val SNOW_MATERIALS = listOf(Material.SNOW_BLOCK, Material.SNOW) val SNOW_MATERIALS = listOf(Material.TOP_SNOW, Material.SNOW)
val BlockState.isSnow: Boolean get() = material in SNOW_MATERIALS val BlockState.isSnow: Boolean get() = material in SNOW_MATERIALS
val ACCEPTED_ROUND_LOG_MATERIALS = listOf(Material.WOOD, Material.GRASS)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,7 +31,7 @@ object StandardMyceliumDiscovery : AbstractModelDiscovery() {
override fun processModel(ctx: ModelDiscoveryContext) { override fun processModel(ctx: ModelDiscoveryContext) {
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in MYCELIUM_BLOCKS) { if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in MYCELIUM_BLOCKS) {
ctx.addReplacement(StandardMyceliumKey) ctx.addReplacement(StandardMyceliumKey)
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutout()) RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutout())
} }
super.processModel(ctx) super.processModel(ctx)
} }

View File

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

View File

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

View File

@@ -43,7 +43,7 @@ object StandardSandDiscovery : AbstractModelDiscovery() {
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in SAND_BLOCKS) { if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in SAND_BLOCKS) {
BetterFoliage.blockTypes.dirt.add(ctx.blockState) BetterFoliage.blockTypes.dirt.add(ctx.blockState)
ctx.addReplacement(StandardSandKey) ctx.addReplacement(StandardSandKey)
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutoutMipped()) RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutoutMipped())
} }
super.processModel(ctx) super.processModel(ctx)
} }
@@ -61,7 +61,7 @@ class StandardSandModel(
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) { override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
super.render(ctx, noDecorations) super.render(ctx, noDecorations)
if (noDecorations || !Config.enabled || !Config.coral.enabled(ctx.random)) return if (noDecorations || !Config.enabled || !Config.coral.enabled(ctx.random)) return
if (ctx.biome?.category !in SALTWATER_BIOMES) return if (ctx.biome?.biomeCategory !in SALTWATER_BIOMES) return
allDirections.filter { ctx.random.nextInt(64) < Config.coral.chance }.forEach { face -> allDirections.filter { ctx.random.nextInt(64) < Config.coral.chance }.forEach { face ->
val isWater = ctx.state(face).material == Material.WATER val isWater = ctx.state(face).material == Material.WATER

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,10 +1,8 @@
package mods.betterfoliage.resource.generated package mods.betterfoliage.resource.generated
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.util.Atlas import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.HasLogger import mods.betterfoliage.util.HasLogger
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.resources.ClientResourcePackInfo
import net.minecraft.resources.* import net.minecraft.resources.*
import net.minecraft.resources.ResourcePackType.CLIENT_RESOURCES import net.minecraft.resources.ResourcePackType.CLIENT_RESOURCES
import net.minecraft.resources.data.IMetadataSectionSerializer import net.minecraft.resources.data.IMetadataSectionSerializer
@@ -12,6 +10,7 @@ import net.minecraft.util.ResourceLocation
import net.minecraft.util.text.StringTextComponent import net.minecraft.util.text.StringTextComponent
import org.apache.logging.log4j.Level.INFO import org.apache.logging.log4j.Level.INFO
import java.util.* import java.util.*
import java.util.function.Consumer
import java.util.function.Predicate import java.util.function.Predicate
import java.util.function.Supplier import java.util.function.Supplier
@@ -25,10 +24,10 @@ class GeneratedTexturePack(
val nameSpace: String, val packName: String val nameSpace: String, val packName: String
) : HasLogger(), IResourcePack { ) : HasLogger(), IResourcePack {
override fun getName() = packName override fun getName() = packName
override fun getResourceNamespaces(type: ResourcePackType) = setOf(nameSpace) override fun getNamespaces(type: ResourcePackType) = setOf(nameSpace)
override fun <T : Any?> getMetadata(deserializer: IMetadataSectionSerializer<T>) = null override fun <T : Any?> getMetadataSection(deserializer: IMetadataSectionSerializer<T>) = null
override fun getRootResourceStream(id: String) = null override fun getRootResource(id: String) = null
override fun getAllResourceLocations(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<ResourceLocation>() override fun getResources(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<ResourceLocation>()
override fun close() {} override fun close() {}
@@ -49,21 +48,22 @@ class GeneratedTexturePack(
return id return id
} }
override fun getResourceStream(type: ResourcePackType, id: ResourceLocation) = override fun getResource(type: ResourcePackType, id: ResourceLocation) =
if (type != CLIENT_RESOURCES) null else resources[id]?.inputStream() if (type != CLIENT_RESOURCES) null else resources[id]?.inputStream()
override fun resourceExists(type: ResourcePackType, id: ResourceLocation) = override fun hasResource(type: ResourcePackType, id: ResourceLocation) =
type == CLIENT_RESOURCES && resources.containsKey(id) type == CLIENT_RESOURCES && resources.containsKey(id)
val finder = object : IPackFinder { val finder = object : IPackFinder {
val packInfo = ClientResourcePackInfo( val packInfo = ResourcePackInfo(
packName, true, Supplier { this@GeneratedTexturePack }, packName, true, Supplier { this@GeneratedTexturePack },
StringTextComponent(packName), StringTextComponent(packName),
StringTextComponent("Generated block textures resource pack"), StringTextComponent("Generated block textures resource pack"),
PackCompatibility.COMPATIBLE, ResourcePackInfo.Priority.TOP, true, null, true PackCompatibility.COMPATIBLE, ResourcePackInfo.Priority.TOP, true, null, 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 package mods.betterfoliage.util
import net.minecraft.client.renderer.Quaternion
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.Direction.* import net.minecraft.util.Direction.*
import net.minecraft.util.Direction.Axis.* import net.minecraft.util.Direction.Axis.*
import net.minecraft.util.Direction.AxisDirection.NEGATIVE import net.minecraft.util.Direction.AxisDirection.NEGATIVE
import net.minecraft.util.Direction.AxisDirection.POSITIVE import net.minecraft.util.Direction.AxisDirection.POSITIVE
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.vector.Quaternion
val EPSILON_ZERO = 0.05 val EPSILON_ZERO = 0.05
val EPSILON_ONE = 0.95 val EPSILON_ONE = 0.95
@@ -55,15 +55,15 @@ val ROTATION_MATRIX: Array<IntArray> get() = arrayOf(
// Vectors // Vectors
// ================================ // ================================
operator fun Direction.times(scale: Double) = operator fun Direction.times(scale: Double) =
Double3(directionVec.x.toDouble() * scale, directionVec.y.toDouble() * scale, directionVec.z.toDouble() * scale) Double3(normal.x.toDouble() * scale, normal.y.toDouble() * scale, normal.z.toDouble() * scale)
val Direction.vec: Double3 get() = Double3(directionVec.x.toDouble(), directionVec.y.toDouble(), directionVec.z.toDouble()) val Direction.vec: Double3 get() = Double3(normal.x.toDouble(), normal.y.toDouble(), normal.z.toDouble())
operator fun BlockPos.plus(other: Int3) = BlockPos(x + other.x, y + other.y, z + other.z) operator fun BlockPos.plus(other: Int3) = BlockPos(x + other.x, y + other.y, z + other.z)
/** 3D vector of [Double]s. Offers both mutable operations, and immutable operations in operator notation. */ /** 3D vector of [Double]s. Offers both mutable operations, and immutable operations in operator notation. */
data class Double3(var x: Double, var y: Double, var z: Double) { data class Double3(var x: Double, var y: Double, var z: Double) {
constructor(x: Float, y: Float, z: Float) : this(x.toDouble(), y.toDouble(), z.toDouble()) constructor(x: Float, y: Float, z: Float) : this(x.toDouble(), y.toDouble(), z.toDouble())
constructor(dir: Direction) : this(dir.directionVec.x.toDouble(), dir.directionVec.y.toDouble(), dir.directionVec.z.toDouble()) constructor(dir: Direction) : this(dir.normal.x.toDouble(), dir.normal.y.toDouble(), dir.normal.z.toDouble())
companion object { companion object {
val zero: Double3 get() = Double3(0.0, 0.0, 0.0) val zero: Double3 get() = Double3(0.0, 0.0, 0.0)
fun weight(v1: Double3, weight1: Double, v2: Double3, weight2: Double) = fun weight(v1: Double3, weight1: Double, v2: Double3, weight2: Double) =
@@ -88,9 +88,9 @@ data class Double3(var x: Double, var y: Double, var z: Double) {
/** Rotate vector by the given [Quaternion] */ /** Rotate vector by the given [Quaternion] */
fun rotate(quat: Quaternion) = fun rotate(quat: Quaternion) =
quat.copy() quat.copy()
.apply { multiply(Quaternion(x, y, z, 0.0F)) } .apply { mul(Quaternion(x.toFloat(), y.toFloat(), z.toFloat(), 0.0F)) }
.apply { multiply(quat.copy().apply(Quaternion::conjugate)) } .apply { mul(quat.copy().apply(Quaternion::conj)) }
.let { Double3(it.x, it.y, it.z) } .let { Double3(it.i().toDouble(), it.j().toDouble(), it.k().toDouble()) }
// mutable operations // mutable operations
fun setTo(other: Double3): Double3 { x = other.x; y = other.y; z = other.z; return this } fun setTo(other: Double3): Double3 { x = other.x; y = other.y; z = other.z; return this }
@@ -120,11 +120,11 @@ data class Double3(var x: Double, var y: Double, var z: Double) {
/** 3D vector of [Int]s. Offers both mutable operations, and immutable operations in operator notation. */ /** 3D vector of [Int]s. Offers both mutable operations, and immutable operations in operator notation. */
data class Int3(var x: Int, var y: Int, var z: Int) { data class Int3(var x: Int, var y: Int, var z: Int) {
constructor(dir: Direction) : this(dir.directionVec.x, dir.directionVec.y, dir.directionVec.z) constructor(dir: Direction) : this(dir.normal.x, dir.normal.y, dir.normal.z)
constructor(offset: Pair<Int, Direction>) : this( constructor(offset: Pair<Int, Direction>) : this(
offset.first * offset.second.directionVec.x, offset.first * offset.second.normal.x,
offset.first * offset.second.directionVec.y, offset.first * offset.second.normal.y,
offset.first * offset.second.directionVec.z offset.first * offset.second.normal.z
) )
companion object { companion object {
val zero = Int3(0, 0, 0) val zero = Int3(0, 0, 0)
@@ -133,9 +133,9 @@ data class Int3(var x: Int, var y: Int, var z: Int) {
// immutable operations // immutable operations
operator fun plus(other: Int3) = Int3(x + other.x, y + other.y, z + other.z) operator fun plus(other: Int3) = Int3(x + other.x, y + other.y, z + other.z)
operator fun plus(other: Pair<Int, Direction>) = Int3( operator fun plus(other: Pair<Int, Direction>) = Int3(
x + other.first * other.second.directionVec.x, x + other.first * other.second.normal.x,
y + other.first * other.second.directionVec.y, y + other.first * other.second.normal.y,
z + other.first * other.second.directionVec.z z + other.first * other.second.normal.z
) )
operator fun unaryMinus() = Int3(-x, -y, -z) operator fun unaryMinus() = Int3(-x, -y, -z)
operator fun minus(other: Int3) = Int3(x - other.x, y - other.y, z - other.z) operator fun minus(other: Int3) = Int3(x - other.x, y - other.y, z - other.z)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -230,6 +230,8 @@ betterfoliage.connectedGrass.enabled.tooltip=If there is a grass block on top of
betterfoliage.roundLogs=Round Logs betterfoliage.roundLogs=Round Logs
betterfoliage.roundLogs.tooltip=Connect round blocks to solid full blocks? betterfoliage.roundLogs.tooltip=Connect round blocks to solid full blocks?
betterfoliage.roundLogs.plantsOnly=Plant materials only
betterfoliage.roundLogs.plantsOnly.tooltip=Only apply to wood and hay, not all column blocks?
betterfoliage.roundLogs.connectSolids=Connect to solid betterfoliage.roundLogs.connectSolids=Connect to solid
betterfoliage.roundLogs.connectSolids.tooltip=Connect round blocks to solid full blocks? betterfoliage.roundLogs.connectSolids.tooltip=Connect round blocks to solid full blocks?
betterfoliage.roundLogs.connectPerpendicular=Connect to perpendicular logs betterfoliage.roundLogs.connectPerpendicular=Connect to perpendicular logs

View File

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

View File

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