Compare commits
4 Commits
1.15.2-For
...
1.16.5-For
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6219e9353d | ||
|
|
e3eb222d93 | ||
|
|
8f82fefbb7 | ||
|
|
8a303a1a29 |
@@ -1,26 +1,20 @@
|
||||
plugins {
|
||||
kotlin("jvm").version("1.3.61")
|
||||
id("net.minecraftforge.gradle").version("3.0.194")
|
||||
kotlin("jvm").version("1.4.20")
|
||||
id("net.minecraftforge.gradle").version("4.1.12")
|
||||
id("org.spongepowered.mixin").version("0.7-SNAPSHOT")
|
||||
}
|
||||
apply(plugin = "org.spongepowered.mixin")
|
||||
|
||||
repositories {
|
||||
maven("http://files.minecraftforge.net/maven")
|
||||
maven("https://files.minecraftforge.net/maven")
|
||||
maven("https://repo.spongepowered.org/maven")
|
||||
maven("https://minecraft.curseforge.com/api/maven")
|
||||
maven("https://maven.shedaniel.me/")
|
||||
maven("https://www.cursemaven.com")
|
||||
maven("https://thedarkcolour.github.io/KotlinForForge/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
"minecraft"("net.minecraftforge:forge:${properties["mcVersion"]}-${properties["forgeVersion"]}")
|
||||
|
||||
"api"(fg.deobf("curse.maven:clothconfig-348521:2938583"))
|
||||
|
||||
"implementation"(fg.deobf("curse.maven:biomesoplenty-220318:2988999"))
|
||||
"implementation"("kottle:Kottle:${properties["kottleVersion"]}")
|
||||
// "implementation"("org.spongepowered:mixin:0.8-SNAPSHOT")
|
||||
"implementation"("thedarkcolour:kotlinforforge:1.7.0")
|
||||
"implementation"("org.spongepowered:mixin:0.8-SNAPSHOT")
|
||||
}
|
||||
|
||||
configurations["annotationProcessor"].extendsFrom(configurations["implementation"])
|
||||
|
||||
@@ -4,11 +4,11 @@ org.gradle.daemon=false
|
||||
group = com.github.octarine-noise
|
||||
jarName = BetterFoliage-Forge
|
||||
|
||||
version = 2.6.1
|
||||
version = 2.6.2
|
||||
|
||||
mcVersion = 1.15.2
|
||||
forgeVersion = 31.2.44
|
||||
mappingsChannel = snapshot
|
||||
mappingsVersion = 20200514-1.15.1
|
||||
mcVersion = 1.16.5
|
||||
forgeVersion = 36.1.17
|
||||
mappingsChannel = official
|
||||
mappingsVersion = 1.16.5
|
||||
|
||||
kottleVersion = 1.4.0
|
||||
#kottleVersion = 1.4.0
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
53
gradlew
vendored
53
gradlew
vendored
@@ -1,5 +1,21 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
@@ -66,6 +82,7 @@ esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
@@ -109,10 +126,11 @@ if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
@@ -138,19 +156,19 @@ if $cygwin ; then
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@@ -159,14 +177,9 @@ save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
43
gradlew.bat
vendored
43
gradlew.bat
vendored
@@ -1,3 +1,19 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -35,7 +54,7 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
@@ -45,28 +64,14 @@ echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven("http://files.minecraftforge.net/maven")
|
||||
maven("https://files.minecraftforge.net/maven")
|
||||
maven("https://repo.spongepowered.org/maven")
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
*/
|
||||
@Mixin(Block.class)
|
||||
public class MixinBlock {
|
||||
private static final String shouldSideBeRendered = "Lnet/minecraft/block/Block;shouldSideBeRendered(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Z";
|
||||
private static final String shouldSideBeRendered = "Lnet/minecraft/block/Block;shouldRenderFace(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Z";
|
||||
private static final String getVoxelShape = "Lnet/minecraft/block/BlockState;func_215702_a(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Lnet/minecraft/util/math/shapes/VoxelShape;";
|
||||
private static final String getFaceOcclusionShape = "Lnet/minecraft/block/BlockState;getFaceOcclusionShape(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Lnet/minecraft/util/math/shapes/VoxelShape;";
|
||||
private static final String isOpaqueCube = "Lnet/minecraft/block/Block;isOpaqueCube(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)Z";
|
||||
|
||||
@@ -8,7 +8,7 @@ import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ILightReader;
|
||||
import net.minecraft.world.IBlockDisplayReader;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -19,12 +19,12 @@ import java.util.Random;
|
||||
@Mixin(BlockModelRenderer.class)
|
||||
public class MixinBlockModelRenderer {
|
||||
|
||||
private static final String renderModel = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModel(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String renderModelFlat = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModelFlat(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String renderModelSmooth = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModelSmooth(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String renderModel = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModel(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String renderModelFlat = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModelFlat(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String renderModelSmooth = "Lnet/minecraft/client/renderer/BlockModelRenderer;renderModelSmooth(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
|
||||
@Redirect(method = renderModel, at = @At(value = "INVOKE", target = renderModelSmooth), remap = false)
|
||||
public boolean onRenderModelSmooth(BlockModelRenderer renderer, ILightReader world, IBakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, IVertexBuilder buffer, boolean checkSides, Random random, long rand, int combinedOverlay, IModelData modelData) {
|
||||
public boolean onRenderModelSmooth(BlockModelRenderer renderer, IBlockDisplayReader world, IBakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, IVertexBuilder buffer, boolean checkSides, Random random, long rand, int combinedOverlay, IModelData modelData) {
|
||||
if (model instanceof SpecialRenderModel)
|
||||
return RenderCtxVanilla.render(renderer, world, (SpecialRenderModel) model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData, true);
|
||||
else
|
||||
@@ -32,7 +32,7 @@ public class MixinBlockModelRenderer {
|
||||
}
|
||||
|
||||
@Redirect(method = renderModel, at = @At(value = "INVOKE", target = renderModelFlat), remap = false)
|
||||
public boolean onRenderModelFlat(BlockModelRenderer renderer, ILightReader world, IBakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, IVertexBuilder buffer, boolean checkSides, Random random, long rand, int combinedOverlay, IModelData modelData) {
|
||||
public boolean onRenderModelFlat(BlockModelRenderer renderer, IBlockDisplayReader world, IBakedModel model, BlockState state, BlockPos pos, MatrixStack matrixStack, IVertexBuilder buffer, boolean checkSides, Random random, long rand, int combinedOverlay, IModelData modelData) {
|
||||
if (model instanceof SpecialRenderModel)
|
||||
return RenderCtxVanilla.render(renderer, world, (SpecialRenderModel) model, state, pos, matrixStack, buffer, checkSides, random, rand, combinedOverlay, modelData, false);
|
||||
else
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package mods.betterfoliage.mixin;
|
||||
|
||||
import mods.betterfoliage.Hooks;
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import org.spongepowered.asm.mixin.Debug;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Coerce;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
@@ -14,14 +17,15 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
*
|
||||
* Needed to avoid excessive darkening of Round Logs at the corners, now that they are not full blocks.
|
||||
*/
|
||||
@Mixin(BlockState.class)
|
||||
@Mixin(AbstractBlock.AbstractBlockState.class)
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public class MixinBlockState {
|
||||
private static final String callFrom = "Lnet/minecraft/block/BlockState;getAmbientOcclusionLightValue(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F";
|
||||
private static final String callTo = "Lnet/minecraft/block/Block;getAmbientOcclusionLightValue(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F";
|
||||
private static final String callFrom = "Lnet/minecraft/block/AbstractBlock$AbstractBlockState;getShadeBrightness(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F";
|
||||
// why is the INVOKEVIRTUAL target class Block in the bytecode, not AbstractBlock?
|
||||
private static final String callTo = "Lnet/minecraft/block/Block;getShadeBrightness(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F";
|
||||
|
||||
@Redirect(method = callFrom, at = @At(value = "INVOKE", target = callTo))
|
||||
float getAmbientOcclusionValue(Block block, BlockState state, IBlockReader reader, BlockPos pos) {
|
||||
return Hooks.getAmbientOcclusionLightValueOverride(block.getAmbientOcclusionLightValue(state, reader, pos), state);
|
||||
return Hooks.getAmbientOcclusionLightValueOverride(block.getShadeBrightness(state, reader, pos), state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,34 @@
|
||||
package mods.betterfoliage.mixin;
|
||||
|
||||
import mods.betterfoliage.Hooks;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@Mixin(ClientWorld.class)
|
||||
public class MixinClientWorld {
|
||||
|
||||
private static final String worldAnimateTick = "Lnet/minecraft/client/world/ClientWorld;animateTick(IIIILjava/util/Random;ZLnet/minecraft/util/math/BlockPos$Mutable;)V";
|
||||
private static final String worldAnimateTick = "Lnet/minecraft/client/world/ClientWorld;doAnimateTick(IIIILjava/util/Random;ZLnet/minecraft/util/math/BlockPos$Mutable;)V";
|
||||
private static final String blockAnimateTick = "Lnet/minecraft/block/Block;animateTick(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Ljava/util/Random;)V";
|
||||
|
||||
private static final String worldNotify = "Lnet/minecraft/client/world/ClientWorld;notifyBlockUpdate(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/BlockState;I)V";
|
||||
private static final String rendererNotify = "Lnet/minecraft/client/renderer/WorldRenderer;notifyBlockUpdate(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/BlockState;I)V";
|
||||
private static final String worldNotify = "Lnet/minecraft/client/world/ClientWorld;sendBlockUpdated(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/BlockState;I)V";
|
||||
private static final String rendererNotify = "Lnet/minecraft/client/renderer/WorldRenderer;blockChanged(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/BlockState;I)V";
|
||||
|
||||
/**
|
||||
* Inject a callback to call for every random display tick. Used for adding custom particle effects to blocks.
|
||||
*/
|
||||
@Redirect(method = worldAnimateTick, at = @At(value = "INVOKE", target = blockAnimateTick))
|
||||
void onAnimateTick(Block block, BlockState state, World world, BlockPos pos, Random random) {
|
||||
Hooks.onRandomDisplayTick(block, state, world, pos, random);
|
||||
block.animateTick(state, world, pos, random);
|
||||
@Inject(method = worldAnimateTick, at = @At(value = "INVOKE", target = blockAnimateTick))
|
||||
void onAnimateTick(int x, int y, int z, int range, Random random, boolean doBarrier, BlockPos.Mutable pos, CallbackInfo ci) {
|
||||
Hooks.onRandomDisplayTick((ClientWorld) (Object) this, pos, random);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,6 +38,6 @@ public class MixinClientWorld {
|
||||
@Redirect(method = worldNotify, at = @At(value = "INVOKE", target = rendererNotify))
|
||||
void onClientBlockChanged(WorldRenderer renderer, IBlockReader world, BlockPos pos, BlockState oldState, BlockState newState, int flags) {
|
||||
Hooks.onClientBlockChanged((ClientWorld) world, pos, oldState, newState, flags);
|
||||
renderer.notifyBlockUpdate(world, pos, oldState, newState, flags);
|
||||
renderer.blockChanged(world, pos, oldState, newState, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package mods.betterfoliage.mixin;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxForge;
|
||||
import mods.betterfoliage.model.SpecialRenderModel;
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxForge;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ILightReader;
|
||||
import net.minecraft.world.IBlockDisplayReader;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.pipeline.ForgeBlockModelRenderer;
|
||||
import net.minecraftforge.client.model.pipeline.VertexLighterFlat;
|
||||
@@ -19,14 +19,14 @@ import java.util.Random;
|
||||
@Mixin(ForgeBlockModelRenderer.class)
|
||||
public class MixinForgeBlockModelRenderer {
|
||||
|
||||
private static final String renderModelFlat = "renderModelFlat(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String renderModelSmooth = "renderModelSmooth(Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String render = "Lnet/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer;render(Lnet/minecraftforge/client/model/pipeline/VertexLighterFlat;Lnet/minecraft/world/ILightReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;ZLjava/util/Random;JLnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String renderModelFlat = "Lnet/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer;renderModelFlat(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String renderModelSmooth = "Lnet/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer;renderModelSmooth(Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;JILnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
private static final String render = "Lnet/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer;render(Lnet/minecraftforge/client/model/pipeline/VertexLighterFlat;Lnet/minecraft/world/IBlockDisplayReader;Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lcom/mojang/blaze3d/matrix/MatrixStack;ZLjava/util/Random;JLnet/minecraftforge/client/model/data/IModelData;)Z";
|
||||
|
||||
@Redirect(method = {renderModelFlat, renderModelSmooth}, at = @At(value = "INVOKE", target = render), remap = false)
|
||||
public boolean render(
|
||||
VertexLighterFlat lighter,
|
||||
ILightReader world,
|
||||
IBlockDisplayReader world,
|
||||
IBakedModel model,
|
||||
BlockState state,
|
||||
BlockPos pos,
|
||||
|
||||
@@ -20,13 +20,13 @@ abstract public class MixinModelBakery {
|
||||
|
||||
private static final String processLoading = "Lnet/minecraft/client/renderer/model/ModelBakery;processLoading(Lnet/minecraft/profiler/IProfiler;I)V";
|
||||
private static final String stitch = "Lnet/minecraft/client/renderer/texture/AtlasTexture;stitch(Lnet/minecraft/resources/IResourceManager;Ljava/util/stream/Stream;Lnet/minecraft/profiler/IProfiler;I)Lnet/minecraft/client/renderer/texture/AtlasTexture$SheetData;";
|
||||
private static final String profilerSection = "Lnet/minecraft/profiler/IProfiler;endStartSection(Ljava/lang/String;)V";
|
||||
private static final String profilerSection = "Lnet/minecraft/profiler/IProfiler;popPush(Ljava/lang/String;)V";
|
||||
private static final String getBakedModel = "Lnet/minecraft/client/renderer/model/ModelBakery;getBakedModel(Lnet/minecraft/util/ResourceLocation;Lnet/minecraft/client/renderer/model/IModelTransform;Ljava/util/function/Function;)Lnet/minecraft/client/renderer/model/IBakedModel;";
|
||||
private static final String bakeModel = "Lnet/minecraft/client/renderer/model/IUnbakedModel;bakeModel(Lnet/minecraft/client/renderer/model/ModelBakery;Ljava/util/function/Function;Lnet/minecraft/client/renderer/model/IModelTransform;Lnet/minecraft/util/ResourceLocation;)Lnet/minecraft/client/renderer/model/IBakedModel;";
|
||||
private static final String bakeModel = "Lnet/minecraft/client/renderer/model/IUnbakedModel;bake(Lnet/minecraft/client/renderer/model/ModelBakery;Ljava/util/function/Function;Lnet/minecraft/client/renderer/model/IModelTransform;Lnet/minecraft/util/ResourceLocation;)Lnet/minecraft/client/renderer/model/IBakedModel;";
|
||||
|
||||
@Inject(method = processLoading, at = @At(value = "INVOKE", target = profilerSection, ordinal = 4))
|
||||
void onBeforeTextures(IProfiler profiler, int maxMipmapLevel, CallbackInfo ci) {
|
||||
profiler.endStartSection("betterfoliage");
|
||||
profiler.popPush("betterfoliage");
|
||||
BetterFoliageMod.INSTANCE.getBus().post(new ModelDefinitionsLoadedEvent(ModelBakery.class.cast(this)));
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ abstract public class MixinModelBakery {
|
||||
IBakedModel onBakeModel(
|
||||
IUnbakedModel unbaked,
|
||||
ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter,
|
||||
Function<RenderMaterial, TextureAtlasSprite> spriteGetter,
|
||||
IModelTransform transform,
|
||||
ResourceLocation locationIn
|
||||
) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import mods.betterfoliage.resource.discovery.ModelDefinitionsLoadedEvent
|
||||
import mods.betterfoliage.resource.generated.GeneratedTexturePack
|
||||
import mods.betterfoliage.render.particle.LeafParticleRegistry
|
||||
import mods.betterfoliage.render.particle.RisingSoulParticle
|
||||
import mods.betterfoliage.util.resourceManager
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.resources.IReloadableResourceManager
|
||||
@@ -51,7 +52,7 @@ object BetterFoliage {
|
||||
// discoverers
|
||||
BetterFoliageMod.bus.register(BakeWrapperManager)
|
||||
BetterFoliageMod.bus.register(LeafParticleRegistry)
|
||||
(Minecraft.getInstance().resourceManager as IReloadableResourceManager).addReloadListener(LeafParticleRegistry)
|
||||
resourceManager.registerReloadListener(LeafParticleRegistry)
|
||||
|
||||
ChunkOverlayManager.layers.add(RoundLogOverlayLayer)
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package mods.betterfoliage
|
||||
|
||||
import mods.betterfoliage.config.BlockConfig
|
||||
import mods.betterfoliage.config.Config
|
||||
import net.alexwells.kottle.FMLKotlinModLoadingContext
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraftforge.fml.ModLoadingContext
|
||||
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.simple.SimpleLogger
|
||||
import org.apache.logging.log4j.util.PropertiesUtil
|
||||
import thedarkcolour.kotlinforforge.forge.MOD_BUS
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.util.Properties
|
||||
@@ -19,7 +19,7 @@ import java.util.Properties
|
||||
object BetterFoliageMod {
|
||||
const val MOD_ID = "betterfoliage"
|
||||
|
||||
val bus = FMLKotlinModLoadingContext.get().modEventBus
|
||||
val bus = MOD_BUS
|
||||
|
||||
val detailLogStream = PrintStream(File("logs/betterfoliage.log").apply {
|
||||
parentFile.mkdirs()
|
||||
@@ -33,7 +33,7 @@ object BetterFoliageMod {
|
||||
|
||||
init {
|
||||
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)
|
||||
BetterFoliage.init()
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ import net.minecraft.client.renderer.model.ModelBakery
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraftforge.client.model.pipeline.BlockInfo
|
||||
import net.minecraftforge.client.model.pipeline.VertexLighterFlat
|
||||
import java.util.*
|
||||
import java.util.Random
|
||||
|
||||
// Java
|
||||
val String = ClassRef<String>("java.lang.String")
|
||||
@@ -32,7 +32,7 @@ fun <K, V> mapRefMutable() = ClassRef<MutableMap<K, V>>("java.util.Map")
|
||||
|
||||
// Minecraft
|
||||
val IBlockReader = ClassRef<IBlockReader>("net.minecraft.world.IBlockReader")
|
||||
val ILightReader = ClassRef<ILightReader>("net.minecraft.world.ILightReader")
|
||||
val ILightReader = ClassRef<IBlockDisplayReader>("net.minecraft.world.IBlockDisplayReader")
|
||||
val BlockState = ClassRef<BlockState>("net.minecraft.block.BlockState")
|
||||
val BlockPos = ClassRef<BlockPos>("net.minecraft.util.math.BlockPos")
|
||||
val Block = ClassRef<Block>("net.minecraft.block.Block")
|
||||
|
||||
@@ -20,8 +20,8 @@ import net.minecraft.util.Direction.UP
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.shapes.VoxelShape
|
||||
import net.minecraft.util.math.shapes.VoxelShapes
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.World
|
||||
import java.util.Random
|
||||
|
||||
@@ -35,11 +35,12 @@ fun onClientBlockChanged(worldClient: ClientWorld, pos: BlockPos, oldState: Bloc
|
||||
ChunkOverlayManager.onBlockChange(worldClient, pos)
|
||||
}
|
||||
|
||||
fun onRandomDisplayTick(block: Block, state: BlockState, world: World, pos: BlockPos, random: Random) {
|
||||
fun onRandomDisplayTick(world: ClientWorld, pos: BlockPos, random: Random) {
|
||||
val state = world.getBlockState(pos)
|
||||
if (Config.enabled &&
|
||||
Config.risingSoul.enabled &&
|
||||
state.block == Blocks.SOUL_SAND &&
|
||||
world.isAirBlock(pos.offset(UP)) &&
|
||||
world.getBlockState(pos.relative(UP)).isAir &&
|
||||
Math.random() < Config.risingSoul.chance) {
|
||||
RisingSoulParticle(world, pos).addIfValid()
|
||||
}
|
||||
@@ -47,7 +48,7 @@ fun onRandomDisplayTick(block: Block, state: BlockState, world: World, pos: Bloc
|
||||
if (Config.enabled &&
|
||||
Config.fallingLeaves.enabled &&
|
||||
random.nextDouble() < Config.fallingLeaves.chance &&
|
||||
world.isAirBlock(pos.offset(DOWN))
|
||||
world.getBlockState(pos.relative(DOWN)).isAir
|
||||
) {
|
||||
(getActualRenderModel(world, pos, state, random) as? LeafBlockModel)?.let { leafModel ->
|
||||
val blockColor = Minecraft.getInstance().blockColors.getColor(state, world, pos, 0)
|
||||
@@ -63,13 +64,13 @@ fun getVoxelShapeOverride(state: BlockState, reader: IBlockReader, pos: BlockPos
|
||||
}
|
||||
|
||||
fun shouldForceSideRenderOF(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction) =
|
||||
world.getBlockState(pos.offset(face)).let { neighbor -> BetterFoliage.blockTypes.hasTyped<RoundLogKey>(neighbor) }
|
||||
world.getBlockState(pos.relative(face)).let { neighbor -> BetterFoliage.blockTypes.hasTyped<RoundLogKey>(neighbor) }
|
||||
|
||||
fun getActualRenderModel(world: ILightReader, pos: BlockPos, state: BlockState, random: Random): SpecialRenderModel? {
|
||||
val model = Minecraft.getInstance().blockRendererDispatcher.blockModelShapes.getModel(state) as? SpecialRenderModel
|
||||
fun getActualRenderModel(world: IBlockDisplayReader, pos: BlockPos, state: BlockState, random: Random): SpecialRenderModel? {
|
||||
val model = Minecraft.getInstance().blockRenderer.blockModelShaper.getBlockModel(state) as? SpecialRenderModel
|
||||
?: return null
|
||||
if (model is WeightedModelWrapper) {
|
||||
random.setSeed(state.getPositionRandom(pos))
|
||||
random.setSeed(state.getSeed(pos))
|
||||
return model.getModel(random).model
|
||||
}
|
||||
return model
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mods.betterfoliage.chunk
|
||||
|
||||
import mods.betterfoliage.util.Int3
|
||||
import mods.betterfoliage.util.allDirections
|
||||
import mods.betterfoliage.util.offset
|
||||
import mods.betterfoliage.util.plus
|
||||
import mods.betterfoliage.util.semiRandom
|
||||
@@ -10,7 +9,7 @@ import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderCache
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraft.world.IWorldReader
|
||||
import net.minecraft.world.biome.Biome
|
||||
import net.minecraft.world.level.ColorResolver
|
||||
@@ -20,7 +19,7 @@ import net.minecraft.world.level.ColorResolver
|
||||
* block-relative coordinates.
|
||||
*/
|
||||
interface BlockCtx {
|
||||
val world: ILightReader
|
||||
val world: IBlockDisplayReader
|
||||
val pos: BlockPos
|
||||
|
||||
fun offset(dir: Direction) = offset(dir.offset)
|
||||
@@ -35,13 +34,13 @@ interface BlockCtx {
|
||||
|
||||
val biome: Biome? get() =
|
||||
(world as? IWorldReader)?.getBiome(pos) ?:
|
||||
(world as? ChunkRenderCache)?.world?.getBiome(pos)
|
||||
(world as? ChunkRenderCache)?.level?.getBiome(pos)
|
||||
|
||||
val isNormalCube: Boolean get() = state.isNormalCube(world, pos)
|
||||
val isFullBlock: Boolean get() = state.isCollisionShapeFullBlock(world, pos)
|
||||
|
||||
fun isNeighborSolid(dir: Direction) = offset(dir).let { it.state.isSolidSide(it.world, it.pos, dir.opposite) }
|
||||
fun isNeighborSturdy(dir: Direction) = offset(dir).let { it.state.isFaceSturdy(it.world, it.pos, dir.opposite) }
|
||||
|
||||
fun shouldSideBeRendered(side: Direction) = Block.shouldSideBeRendered(state, world, pos, side)
|
||||
fun shouldSideBeRendered(side: Direction) = Block.shouldRenderFace(state, world, pos, side)
|
||||
|
||||
/** Get a semi-random value based on the block coordinate and the given seed. */
|
||||
fun semiRandom(seed: Int) = pos.semiRandom(seed)
|
||||
@@ -49,11 +48,11 @@ interface BlockCtx {
|
||||
/** Get an array of semi-random values based on the block coordinate. */
|
||||
fun semiRandomArray(num: Int): Array<Int> = Array(num) { semiRandom(it) }
|
||||
|
||||
fun color(resolver: ColorResolver) = world.getBlockColor(pos, resolver)
|
||||
fun color(resolver: ColorResolver) = world.getBlockTint(pos, resolver)
|
||||
}
|
||||
|
||||
class BasicBlockCtx(
|
||||
override val world: ILightReader,
|
||||
override val world: IBlockDisplayReader,
|
||||
override val pos: BlockPos
|
||||
) : BlockCtx {
|
||||
override val state: BlockState = world.getBlockState(pos)
|
||||
|
||||
@@ -1,32 +1,26 @@
|
||||
package mods.betterfoliage.chunk
|
||||
|
||||
import mods.octarinecore.ChunkCacheOF
|
||||
import mods.betterfoliage.util.get
|
||||
import mods.betterfoliage.util.isInstance
|
||||
import mods.octarinecore.ChunkCacheOF
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderCache
|
||||
import net.minecraft.client.world.ClientWorld
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.ChunkPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.DimensionType
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraft.world.IWorldReader
|
||||
import net.minecraft.world.dimension.DimensionType
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.event.world.ChunkEvent
|
||||
import net.minecraftforge.event.world.WorldEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import java.util.*
|
||||
import kotlin.collections.List
|
||||
import kotlin.collections.MutableMap
|
||||
import kotlin.collections.associateWith
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.mutableListOf
|
||||
import kotlin.collections.mutableMapOf
|
||||
import kotlin.collections.set
|
||||
|
||||
val ILightReader.dimType: DimensionType get() = when {
|
||||
this is IWorldReader -> dimension.type
|
||||
this is ChunkRenderCache -> world.dimension.type
|
||||
this.isInstance(ChunkCacheOF) -> this[ChunkCacheOF.chunkCache].world.dimension.type
|
||||
val IBlockDisplayReader.dimType: DimensionType get() = when {
|
||||
this is IWorldReader -> dimensionType()
|
||||
this is ChunkRenderCache -> level.dimensionType()
|
||||
this.isInstance(ChunkCacheOF) -> this[ChunkCacheOF.chunkCache].level.dimensionType()
|
||||
else -> throw IllegalArgumentException("DimensionType of world with class ${this::class.qualifiedName} cannot be determined!")
|
||||
}
|
||||
|
||||
@@ -35,7 +29,7 @@ val ILightReader.dimType: DimensionType get() = when {
|
||||
*/
|
||||
interface ChunkOverlayLayer<T> {
|
||||
fun calculate(ctx: BlockCtx): T
|
||||
fun onBlockUpdate(world: ILightReader, pos: BlockPos)
|
||||
fun onBlockUpdate(world: IBlockDisplayReader, pos: BlockPos)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -55,6 +55,7 @@ object Config : DelegatingConfig(BetterFoliageMod.MOD_ID, BetterFoliageMod.MOD_I
|
||||
|
||||
object roundLogs : ConfigCategory(){
|
||||
val enabled by featureEnable()
|
||||
val plantsOnly by boolean(true)
|
||||
val radiusSmall by double(max=0.5, default=0.25)
|
||||
val radiusLarge by double(max=0.5, default=0.44)
|
||||
val dimming by double(default = 0.7)
|
||||
|
||||
@@ -14,5 +14,7 @@ val MYCELIUM_BLOCKS = listOf(Blocks.MYCELIUM)
|
||||
|
||||
val SALTWATER_BIOMES = listOf(Biome.Category.BEACH, Biome.Category.OCEAN)
|
||||
|
||||
val SNOW_MATERIALS = listOf(Material.SNOW_BLOCK, Material.SNOW)
|
||||
val BlockState.isSnow: Boolean get() = material in SNOW_MATERIALS
|
||||
val SNOW_MATERIALS = listOf(Material.TOP_SNOW, Material.SNOW)
|
||||
val BlockState.isSnow: Boolean get() = material in SNOW_MATERIALS
|
||||
|
||||
val ACCEPTED_ROUND_LOG_MATERIALS = listOf(Material.WOOD, Material.GRASS)
|
||||
|
||||
@@ -34,7 +34,7 @@ object OptifineCustomColors {
|
||||
val fakeQuad = BakedQuad(IntArray(0), 1, UP, null, true)
|
||||
|
||||
fun getBlockColor(ctx: BlockCtx, resolver: ColorResolver): Int {
|
||||
val ofColor = if (isColorAvailable && Minecraft.getInstance().gameSettings.reflectField<Boolean>("ofCustomColors") == true) {
|
||||
val ofColor = if (isColorAvailable && Minecraft.getInstance().options.reflectField<Boolean>("ofCustomColors") == true) {
|
||||
renderEnv.reset(ctx.state, ctx.pos)
|
||||
CustomColors.getColorMultiplier.invokeStatic(fakeQuad, ctx.state, ctx.world, ctx.pos, renderEnv.wrapped) as? Int
|
||||
} else null
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package mods.betterfoliage.integration
|
||||
|
||||
import mods.betterfoliage.config.BlockConfig
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxBase
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxForge
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxVanilla
|
||||
import mods.betterfoliage.util.HasLogger
|
||||
import mods.betterfoliage.util.allAvailable
|
||||
@@ -14,7 +12,7 @@ import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.client.renderer.BufferBuilder
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import org.apache.logging.log4j.Level.INFO
|
||||
|
||||
/**
|
||||
@@ -23,14 +21,14 @@ import org.apache.logging.log4j.Level.INFO
|
||||
object ShadersModIntegration : HasLogger() {
|
||||
@JvmStatic val isAvailable = allAvailable(SVertexBuilder, SVertexBuilder.pushState, SVertexBuilder.popState, BlockAliases.getAliasBlockId)
|
||||
|
||||
val defaultLeaves = Blocks.OAK_LEAVES.defaultState
|
||||
val defaultGrass = Blocks.GRASS.defaultState
|
||||
val defaultLeaves = Blocks.OAK_LEAVES.defaultBlockState()
|
||||
val defaultGrass = Blocks.GRASS.defaultBlockState()
|
||||
|
||||
/**
|
||||
* Called from transformed ShadersMod code.
|
||||
* @see mods.betterfoliage.loader.BetterFoliageTransformer
|
||||
*/
|
||||
@JvmStatic fun getBlockStateOverride(state: BlockState, world: ILightReader, pos: BlockPos): BlockState {
|
||||
@JvmStatic fun getBlockStateOverride(state: BlockState, world: IBlockDisplayReader, pos: BlockPos): BlockState {
|
||||
// if (LeafRegistry[state, world, pos] != null) return defaultLeaves
|
||||
// if (BlockConfig.crops.matchesClass(state.block)) return defaultGrass
|
||||
return state
|
||||
|
||||
@@ -68,8 +68,8 @@ fun List<Quad>.bake(applyDiffuseLighting: Boolean) = map { quad ->
|
||||
)
|
||||
// don't fill lightmap UV coords
|
||||
element.usage == VertexFormatElement.Usage.UV && element.type == VertexFormatElement.Type.FLOAT -> builder.put(idx,
|
||||
quad.sprite.minU + (quad.sprite.maxU - quad.sprite.minU) * (vertex.uv.u + 0.5).toFloat(),
|
||||
quad.sprite.minV + (quad.sprite.maxV - quad.sprite.minV) * (vertex.uv.v + 0.5).toFloat(),
|
||||
quad.sprite.u0 + (quad.sprite.u1 - quad.sprite.u0) * (vertex.uv.u + 0.5).toFloat(),
|
||||
quad.sprite.v0 + (quad.sprite.v1 - quad.sprite.v0) * (vertex.uv.v + 0.5).toFloat(),
|
||||
0.0f, 1.0f
|
||||
)
|
||||
element.usage == VertexFormatElement.Usage.COLOR -> builder.put(idx,
|
||||
@@ -96,18 +96,18 @@ fun Array<List<Quad>>.bake(applyDiffuseLighting: Boolean) = mapArray { it.bake(a
|
||||
fun BakedQuad.unbake(): HalfBakedQuad {
|
||||
val size = DefaultVertexFormats.BLOCK.integerSize
|
||||
val verts = Array(4) { vIdx ->
|
||||
val x = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 0])
|
||||
val y = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 1])
|
||||
val z = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 2])
|
||||
val color = vertexData[vIdx * size + 3]
|
||||
val u = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 4])
|
||||
val v = java.lang.Float.intBitsToFloat(vertexData[vIdx * size + 5])
|
||||
val x = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 0])
|
||||
val y = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 1])
|
||||
val z = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 2])
|
||||
val color = vertices[vIdx * size + 3]
|
||||
val u = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 4])
|
||||
val v = java.lang.Float.intBitsToFloat(vertices[vIdx * size + 5])
|
||||
Vertex(Double3(x, y, z), UV(u.toDouble(), v.toDouble()), Color(color))
|
||||
}
|
||||
val unbaked = Quad(
|
||||
verts[0], verts[1], verts[2], verts[3],
|
||||
colorIndex = if (hasTintIndex()) tintIndex else -1,
|
||||
face = face
|
||||
colorIndex = if (isTinted) tintIndex else -1,
|
||||
face = direction
|
||||
)
|
||||
return HalfBakedQuad(unbaked, this)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
package mods.betterfoliage.model
|
||||
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxBase
|
||||
import mods.betterfoliage.util.HasLogger
|
||||
import net.minecraft.client.renderer.model.IBakedModel
|
||||
import net.minecraft.client.renderer.model.Material
|
||||
import net.minecraft.client.renderer.model.ModelBakery
|
||||
import net.minecraft.client.renderer.model.VariantList
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.util.WeightedRandom
|
||||
import org.apache.logging.log4j.Level.WARN
|
||||
import java.util.Random
|
||||
import java.util.function.Function
|
||||
|
||||
/**
|
||||
* Model that makes use of advanced rendering features.
|
||||
@@ -24,9 +16,9 @@ class WeightedModelWrapper(
|
||||
val models: List<WeightedModel>, baseModel: SpecialRenderModel
|
||||
): IBakedModel by baseModel, SpecialRenderModel {
|
||||
class WeightedModel(val model: SpecialRenderModel, weight: Int) : WeightedRandom.Item(weight)
|
||||
val totalWeight = models.sumBy { it.itemWeight }
|
||||
val totalWeight = models.sumBy { it.weight }
|
||||
|
||||
fun getModel(random: Random) = WeightedRandom.getRandomItem(models, random.nextInt(totalWeight))
|
||||
fun getModel(random: Random) = WeightedRandom.getWeightedItem(models, random.nextInt(totalWeight))
|
||||
|
||||
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
|
||||
getModel(ctx.random).model.render(ctx, noDecorations)
|
||||
|
||||
@@ -59,7 +59,7 @@ class SpriteSetDelegate(
|
||||
|
||||
@SubscribeEvent
|
||||
fun handlePreStitch(event: TextureStitchEvent.Pre) {
|
||||
if (event.map.textureLocation != Atlas.BLOCKS.resourceId) return
|
||||
if (event.map.location() != Atlas.BLOCKS.resourceId) return
|
||||
spriteSet = null
|
||||
idList = (0 until 16)
|
||||
.map(idFunc)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package mods.betterfoliage.render.block.vanilla
|
||||
|
||||
import mods.betterfoliage.BetterFoliageMod
|
||||
import mods.betterfoliage.BetterFoliage
|
||||
import mods.betterfoliage.BetterFoliageMod
|
||||
import mods.betterfoliage.config.Config
|
||||
import mods.betterfoliage.config.DIRT_BLOCKS
|
||||
import mods.betterfoliage.config.SALTWATER_BIOMES
|
||||
import mods.betterfoliage.config.isSnow
|
||||
import mods.betterfoliage.integration.ShadersModIntegration
|
||||
import mods.betterfoliage.model.HalfBakedSpecialWrapper
|
||||
import mods.betterfoliage.model.HalfBakedWrapperKey
|
||||
@@ -15,7 +16,6 @@ import mods.betterfoliage.model.tuftModelSet
|
||||
import mods.betterfoliage.model.tuftShapeSet
|
||||
import mods.betterfoliage.render.lighting.LightingPreferredFace
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxBase
|
||||
import mods.betterfoliage.render.pipeline.RenderCtxVanilla
|
||||
import mods.betterfoliage.resource.discovery.AbstractModelDiscovery
|
||||
import mods.betterfoliage.resource.discovery.BakeWrapperManager
|
||||
import mods.betterfoliage.resource.discovery.ModelBakingContext
|
||||
@@ -27,20 +27,18 @@ import mods.betterfoliage.util.LazyInvalidatable
|
||||
import mods.betterfoliage.util.get
|
||||
import mods.betterfoliage.util.offset
|
||||
import mods.betterfoliage.util.randomI
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.RenderTypeLookup
|
||||
import net.minecraft.client.renderer.model.BlockModel
|
||||
import net.minecraft.util.Direction.UP
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.world.biome.Biome
|
||||
|
||||
object StandardDirtDiscovery : AbstractModelDiscovery() {
|
||||
fun canRenderInLayer(layer: RenderType) = when {
|
||||
!Config.enabled -> layer == RenderType.getSolid()
|
||||
!Config.connectedGrass.enabled && !Config.algae.enabled && !Config.reed.enabled -> layer == RenderType.getSolid()
|
||||
else -> layer == RenderType.getCutoutMipped()
|
||||
!Config.enabled -> layer == RenderType.solid()
|
||||
!Config.connectedGrass.enabled && !Config.algae.enabled && !Config.reed.enabled -> layer == RenderType.solid()
|
||||
else -> layer == RenderType.cutoutMipped()
|
||||
}
|
||||
|
||||
override fun processModel(ctx: ModelDiscoveryContext) {
|
||||
@@ -67,9 +65,12 @@ class StandardDirtModel(
|
||||
|
||||
val stateUp = ctx.state(UP)
|
||||
val state2Up = ctx.state(Int3(0, 2, 0))
|
||||
val isConnectedGrass = Config.connectedGrass.enabled && stateUp in BetterFoliage.blockTypes.grass
|
||||
val isConnectedGrass = Config.connectedGrass.enabled &&
|
||||
stateUp in BetterFoliage.blockTypes.grass &&
|
||||
(Config.connectedGrass.snowEnabled || !state2Up.isSnow)
|
||||
|
||||
if (isConnectedGrass) {
|
||||
(ctx.blockModelShapes.getModel(stateUp) as? SpecialRenderModel)?.let { grassModel ->
|
||||
(ctx.blockModelShapes.getBlockModel(stateUp) as? SpecialRenderModel)?.let { grassModel ->
|
||||
ctx.renderMasquerade(UP.offset) {
|
||||
grassModel.render(ctx, true)
|
||||
}
|
||||
@@ -81,9 +82,9 @@ class StandardDirtModel(
|
||||
super.render(ctx, false)
|
||||
|
||||
val isWater = stateUp.material == Material.WATER
|
||||
val isDeepWater = isWater && ctx.offset(Int3(2 to UP)).state.material == Material.WATER
|
||||
val isShallowWater = isWater && ctx.offset(Int3(2 to UP)).state.isAir
|
||||
val isSaltWater = isWater && ctx.biome?.category in SALTWATER_BIOMES
|
||||
val isDeepWater = isWater && state2Up.material == Material.WATER
|
||||
val isShallowWater = isWater && state2Up.isAir
|
||||
val isSaltWater = isWater && ctx.biome?.biomeCategory in SALTWATER_BIOMES
|
||||
|
||||
if (Config.algae.enabled(ctx.random) && isDeepWater) {
|
||||
ctx.vertexLighter = vanillaTuftLighting
|
||||
|
||||
@@ -31,7 +31,7 @@ object StandardMyceliumDiscovery : AbstractModelDiscovery() {
|
||||
override fun processModel(ctx: ModelDiscoveryContext) {
|
||||
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in MYCELIUM_BLOCKS) {
|
||||
ctx.addReplacement(StandardMyceliumKey)
|
||||
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutout())
|
||||
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutout())
|
||||
}
|
||||
super.processModel(ctx)
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ import net.minecraft.util.ResourceLocation
|
||||
|
||||
object StandardNetherrackDiscovery : AbstractModelDiscovery() {
|
||||
fun canRenderInLayer(layer: RenderType) = when {
|
||||
!Config.enabled -> layer == RenderType.getSolid()
|
||||
!Config.netherrack.enabled -> layer == RenderType.getSolid()
|
||||
else -> layer == RenderType.getCutoutMipped()
|
||||
!Config.enabled -> layer == RenderType.solid()
|
||||
!Config.netherrack.enabled -> layer == RenderType.solid()
|
||||
else -> layer == RenderType.cutoutMipped()
|
||||
}
|
||||
|
||||
override fun processModel(ctx: ModelDiscoveryContext) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package mods.betterfoliage.render.block.vanilla
|
||||
|
||||
import mods.betterfoliage.BetterFoliage
|
||||
import mods.betterfoliage.config.ACCEPTED_ROUND_LOG_MATERIALS
|
||||
import mods.betterfoliage.config.BlockConfig
|
||||
import mods.betterfoliage.config.Config
|
||||
import mods.betterfoliage.resource.discovery.ModelTextureList
|
||||
import mods.betterfoliage.model.HalfBakedWrapperKey
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import mods.betterfoliage.render.column.ColumnBlockKey
|
||||
@@ -16,11 +16,12 @@ import mods.betterfoliage.resource.discovery.ConfigurableModelDiscovery
|
||||
import mods.betterfoliage.resource.discovery.ModelBakingContext
|
||||
import mods.betterfoliage.resource.discovery.ModelBakingKey
|
||||
import mods.betterfoliage.resource.discovery.ModelDiscoveryContext
|
||||
import mods.betterfoliage.resource.discovery.ModelTextureList
|
||||
import mods.betterfoliage.util.Atlas
|
||||
import mods.betterfoliage.util.LazyMapInvalidatable
|
||||
import mods.betterfoliage.util.tryDefault
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.LogBlock
|
||||
import net.minecraft.block.RotatedPillarBlock
|
||||
import net.minecraft.util.Direction.Axis
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import org.apache.logging.log4j.Level.INFO
|
||||
@@ -43,13 +44,15 @@ object StandardRoundLogDiscovery : ConfigurableModelDiscovery() {
|
||||
|
||||
override fun processModel(ctx: ModelDiscoveryContext, textureMatch: List<ResourceLocation>) {
|
||||
val axis = getAxis(ctx.blockState)
|
||||
detailLogger.log(INFO, " axis $axis")
|
||||
ctx.addReplacement(StandardRoundLogKey(axis, textureMatch[0], textureMatch[1]))
|
||||
|
||||
detailLogger.log(INFO, " axis $axis, material ${ctx.blockState.material}")
|
||||
if (!Config.roundLogs.plantsOnly || ctx.blockState.material in ACCEPTED_ROUND_LOG_MATERIALS)
|
||||
ctx.addReplacement(StandardRoundLogKey(axis, textureMatch[0], textureMatch[1]))
|
||||
}
|
||||
|
||||
fun getAxis(state: BlockState): Axis? {
|
||||
val axis = tryDefault(null) { state.get(LogBlock.AXIS).toString() } ?:
|
||||
state.values.entries.find { it.key.getName().toLowerCase() == "axis" }?.value?.toString()
|
||||
val axis = tryDefault(null) { state.getValue(RotatedPillarBlock.AXIS).toString() } ?:
|
||||
state.values.entries.find { it.key.name.toLowerCase() == "axis" }?.value?.toString()
|
||||
return when (axis) {
|
||||
"x" -> Axis.X
|
||||
"y" -> Axis.Y
|
||||
|
||||
@@ -43,7 +43,7 @@ object StandardSandDiscovery : AbstractModelDiscovery() {
|
||||
if (ctx.getUnbaked() is BlockModel && ctx.blockState.block in SAND_BLOCKS) {
|
||||
BetterFoliage.blockTypes.dirt.add(ctx.blockState)
|
||||
ctx.addReplacement(StandardSandKey)
|
||||
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.getCutoutMipped())
|
||||
RenderTypeLookup.setRenderLayer(ctx.blockState.block, RenderType.cutoutMipped())
|
||||
}
|
||||
super.processModel(ctx)
|
||||
}
|
||||
@@ -61,7 +61,7 @@ class StandardSandModel(
|
||||
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
|
||||
super.render(ctx, noDecorations)
|
||||
if (noDecorations || !Config.enabled || !Config.coral.enabled(ctx.random)) return
|
||||
if (ctx.biome?.category !in SALTWATER_BIOMES) return
|
||||
if (ctx.biome?.biomeCategory !in SALTWATER_BIOMES) return
|
||||
|
||||
allDirections.filter { ctx.random.nextInt(64) < Config.coral.chance }.forEach { face ->
|
||||
val isWater = ctx.state(face).material == Material.WATER
|
||||
|
||||
@@ -23,7 +23,7 @@ import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Direction.Axis
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
|
||||
/** Index of SOUTH-EAST quadrant. */
|
||||
const val SE = 0
|
||||
@@ -83,13 +83,13 @@ abstract class ColumnRenderLayer : ChunkOverlayLayer<ColumnLayerData> {
|
||||
|
||||
val allNeighborOffsets = (-1..1).flatMap { offsetX -> (-1..1).flatMap { offsetY -> (-1..1).map { offsetZ -> Int3(offsetX, offsetY, offsetZ) }}}
|
||||
|
||||
override fun onBlockUpdate(world: ILightReader, pos: BlockPos) {
|
||||
override fun onBlockUpdate(world: IBlockDisplayReader, pos: BlockPos) {
|
||||
allNeighborOffsets.forEach { offset -> ChunkOverlayManager.clear(world.dimType, this, pos + offset) }
|
||||
}
|
||||
|
||||
override fun calculate(ctx: BlockCtx): ColumnLayerData {
|
||||
// TODO detect round logs
|
||||
if (allDirections.all { dir -> ctx.offset(dir).let { it.isNormalCube } }) return ColumnLayerData.SkipRender
|
||||
if (allDirections.all { dir -> ctx.offset(dir).let { it.isFullBlock } }) return ColumnLayerData.SkipRender
|
||||
val columnTextures = getColumnKey(ctx.state) ?: return ColumnLayerData.ResolveError
|
||||
|
||||
// if log axis is not defined and "Default to vertical" config option is not set, render normally
|
||||
@@ -185,7 +185,7 @@ abstract class ColumnRenderLayer : ChunkOverlayLayer<ColumnLayerData> {
|
||||
val offsetRot = offset.rotate(rotation)
|
||||
val key = getColumnKey(state(offsetRot))
|
||||
return if (key == null) {
|
||||
if (offset(offsetRot).isNormalCube) SOLID else NONSOLID
|
||||
if (offset(offsetRot).isFullBlock) SOLID else NONSOLID
|
||||
} else {
|
||||
(key.axis ?: if (Config.roundLogs.defaultY) Axis.Y else null)?.let {
|
||||
if (it == axis) PARALLEL else PERPENDICULAR
|
||||
|
||||
@@ -5,7 +5,7 @@ import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.BlockModelRenderer
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
|
||||
data class LightingData(
|
||||
@JvmField var packedLight: Int = 0,
|
||||
@@ -29,7 +29,7 @@ data class LightingData(
|
||||
* Not thread-safe, always use a [ThreadLocal] instance
|
||||
*/
|
||||
class VanillaAoCalculator {
|
||||
lateinit var world: ILightReader
|
||||
lateinit var world: IBlockDisplayReader
|
||||
|
||||
/** [blockPos] is used to get block-related information (i.e. tint, opacity, etc.)
|
||||
* [lightPos] is used to get light-related information
|
||||
@@ -37,7 +37,7 @@ class VanillaAoCalculator {
|
||||
lateinit var blockPos: BlockPos
|
||||
lateinit var lightPos: BlockPos
|
||||
|
||||
private val probe = LightProbe(BlockModelRenderer.CACHE_COMBINED_LIGHT.get())
|
||||
private val probe = LightProbe(BlockModelRenderer.CACHE.get())
|
||||
|
||||
val isValid = BooleanArray(6)
|
||||
val aoData = Array(24) { LightingData() }
|
||||
@@ -70,13 +70,13 @@ class VanillaAoCalculator {
|
||||
|
||||
// Bit 0 of the bitset in vanilla calculations
|
||||
// true if the block model is planar with the block boundary
|
||||
val isFullBlock = forceFull ?: world.getBlockState(blockPos).isCollisionShapeOpaque(world, blockPos)
|
||||
val isFullBlock = forceFull ?: world.getBlockState(blockPos).isCollisionShapeFullBlock(world, blockPos)
|
||||
|
||||
val lightOrigin = if (isFullBlock) lightPos.offset(lightFace) else lightPos
|
||||
val lightOrigin = if (isFullBlock) lightPos.relative(lightFace) else lightPos
|
||||
|
||||
// AO calculation for the face center
|
||||
probe.position { setPos(lightOrigin) }.writeTo(centerAo)
|
||||
if (!isFullBlock && !probe.position { move(lightFace) }.state.isOpaqueCube(world, probe.pos)) {
|
||||
probe.position { set(lightOrigin) }.writeTo(centerAo)
|
||||
if (!isFullBlock && !probe.position { move(lightFace) }.state.isSolidRender(world, probe.pos)) {
|
||||
// if the neighboring block in the lightface direction is
|
||||
// transparent (non-opaque), use its packed light instead of our own
|
||||
// (if our block is a full block, we are already using this value)
|
||||
@@ -86,7 +86,7 @@ class VanillaAoCalculator {
|
||||
// AO calculation for the 4 sides
|
||||
sideHelper.sides.forEachIndexed { sideIdx, sideDir ->
|
||||
// record light data in the block 1 step to the side
|
||||
probe.position { setPos(lightOrigin).move(sideDir) }.writeTo(sideAo[sideIdx])
|
||||
probe.position { set(lightOrigin).move(sideDir) }.writeTo(sideAo[sideIdx])
|
||||
// side is considered occluded if the block 1 step to that side and
|
||||
// 1 step forward (in the lightface direction) is not fully transparent
|
||||
isOccluded[sideIdx] = probe.position { move(lightFace) }.isNonTransparent
|
||||
@@ -103,7 +103,7 @@ class VanillaAoCalculator {
|
||||
else {
|
||||
// lookup actual packed light from the cornering block in the world
|
||||
probe.position {
|
||||
setPos(lightOrigin)
|
||||
set(lightOrigin)
|
||||
.move(sideHelper.sides[sideIndices.first])
|
||||
.move(sideHelper.sides[sideIndices.second])
|
||||
}.writeTo(cornerAo[cornerIdx])
|
||||
@@ -129,9 +129,9 @@ class VanillaAoCalculator {
|
||||
lateinit var state: BlockState
|
||||
val pos = BlockPos.Mutable()
|
||||
|
||||
val packedLight: Int get() = cache.getPackedLight(state, world, pos)
|
||||
val colorMultiplier: Float get() = cache.getBrightness(state, world, pos)
|
||||
val isNonTransparent: Boolean get() = state.getOpacity(world, pos) > 0
|
||||
val packedLight: Int get() = cache.getLightColor(state, world, pos)
|
||||
val colorMultiplier: Float get() = cache.getShadeBrightness(state, world, pos)
|
||||
val isNonTransparent: Boolean get() = state.getLightBlock(world, pos) > 0
|
||||
|
||||
fun writeTo(data: LightingData) {
|
||||
data.packedLight = packedLight
|
||||
|
||||
@@ -69,7 +69,7 @@ object VanillaFullBlockLighting : VanillaVertexLighter() {
|
||||
lighting.calc.fillLightData(face, true)
|
||||
lighting.updateWithCornerAo(quad) { nearestCornerOnFace(it, face) }
|
||||
lighting.updateBlockTint(quad.baked.tintIndex)
|
||||
if (quad.baked.shouldApplyDiffuseLighting()) lighting.applyDiffuseLighting(face)
|
||||
if (quad.baked.isShade) lighting.applyDiffuseLighting(face)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ import mods.betterfoliage.util.Double3
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.particle.SpriteTexturedParticle
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo
|
||||
import net.minecraft.client.renderer.Vector3f
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.client.world.ClientWorld
|
||||
import net.minecraft.util.math.MathHelper
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.util.math.vector.Vector3f
|
||||
|
||||
abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) : SpriteTexturedParticle(world, x, y, z) {
|
||||
abstract class AbstractParticle(world: ClientWorld, x: Double, y: Double, z: Double) : SpriteTexturedParticle(world, x, y, z) {
|
||||
|
||||
companion object {
|
||||
// @JvmStatic val sin = Array(64) { idx -> Math.sin(PI2 / 64.0 * idx) }
|
||||
@@ -24,12 +24,12 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
currentPos.setTo(posX, posY, posZ)
|
||||
prevPos.setTo(prevPosX, prevPosY, prevPosZ)
|
||||
velocity.setTo(motionX, motionY, motionZ)
|
||||
currentPos.setTo(x, y, z)
|
||||
prevPos.setTo(xo, yo, zo)
|
||||
velocity.setTo(xd, yd, zd)
|
||||
update()
|
||||
posX = currentPos.x; posY = currentPos.y; posZ = currentPos.z;
|
||||
motionX = velocity.x; motionY = velocity.y; motionZ = velocity.z;
|
||||
x = currentPos.x; y = currentPos.y; z = currentPos.z;
|
||||
xd = velocity.x; yd = velocity.y; zd = velocity.z;
|
||||
}
|
||||
|
||||
/** Update particle on world tick. */
|
||||
@@ -39,10 +39,10 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
|
||||
abstract val isValid: Boolean
|
||||
|
||||
/** Add the particle to the effect renderer if it is valid. */
|
||||
fun addIfValid() { if (isValid) Minecraft.getInstance().particles.addEffect(this) }
|
||||
fun addIfValid() { if (isValid) Minecraft.getInstance().particleEngine.add(this) }
|
||||
|
||||
override fun renderParticle(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
|
||||
super.renderParticle(vertexBuilder, camera, tickDelta)
|
||||
override fun render(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
|
||||
super.render(vertexBuilder, camera, tickDelta)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,39 +63,39 @@ abstract class AbstractParticle(world: World, x: Double, y: Double, z: Double) :
|
||||
tickDelta: Float,
|
||||
currentPos: Double3 = this.currentPos,
|
||||
prevPos: Double3 = this.prevPos,
|
||||
size: Double = particleScale.toDouble(),
|
||||
currentAngle: Float = this.particleAngle,
|
||||
prevAngle: Float = this.prevParticleAngle,
|
||||
size: Double = quadSize.toDouble(),
|
||||
currentAngle: Float = this.roll,
|
||||
prevAngle: Float = this.oRoll,
|
||||
sprite: TextureAtlasSprite = this.sprite,
|
||||
alpha: Float = this.particleAlpha) {
|
||||
alpha: Float = this.alpha) {
|
||||
|
||||
val center = Double3.lerp(tickDelta.toDouble(), prevPos, currentPos)
|
||||
val angle = MathHelper.lerp(tickDelta, prevAngle, currentAngle)
|
||||
val rotation = camera.rotation.copy().apply { multiply(Vector3f.ZP.rotation(angle)) }
|
||||
val lightmapCoord = getBrightnessForRender(tickDelta)
|
||||
val rotation = camera.rotation().copy().apply { mul(Vector3f.ZP.rotation(angle)) }
|
||||
val lightmapCoord = getLightColor(tickDelta)
|
||||
|
||||
val coords = arrayOf(
|
||||
Double3(-1.0, -1.0, 0.0),
|
||||
Double3(-1.0, 1.0, 0.0),
|
||||
Double3(1.0, 1.0, 0.0),
|
||||
Double3(1.0, -1.0, 0.0)
|
||||
).map { it.rotate(rotation).mul(size).add(center).sub(camera.projectedView.x, camera.projectedView.y, camera.projectedView.z) }
|
||||
).map { it.rotate(rotation).mul(size).add(center).sub(camera.position.x, camera.position.y, camera.position.z) }
|
||||
|
||||
fun renderVertex(vertex: Double3, u: Float, v: Float) = vertexConsumer
|
||||
.pos(vertex.x, vertex.y, vertex.z).tex(u, v)
|
||||
.color(particleRed, particleGreen, particleBlue, alpha).lightmap(lightmapCoord)
|
||||
.vertex(vertex.x, vertex.y, vertex.z).uv(u, v)
|
||||
.color(rCol, gCol, bCol, alpha).uv2(lightmapCoord)
|
||||
.endVertex()
|
||||
|
||||
renderVertex(coords[0], sprite.maxU, sprite.maxV)
|
||||
renderVertex(coords[1], sprite.maxU, sprite.minV)
|
||||
renderVertex(coords[2], sprite.minU, sprite.minV)
|
||||
renderVertex(coords[3], sprite.minU, sprite.maxV)
|
||||
renderVertex(coords[0], sprite.u1, sprite.v1)
|
||||
renderVertex(coords[1], sprite.u1, sprite.v0)
|
||||
renderVertex(coords[2], sprite.u0, sprite.v0)
|
||||
renderVertex(coords[3], sprite.u0, sprite.v1)
|
||||
}
|
||||
|
||||
fun setColor(color: Int) {
|
||||
particleBlue = (color and 255) / 256.0f
|
||||
particleGreen = ((color shr 8) and 255) / 256.0f
|
||||
particleRed = ((color shr 16) and 255) / 256.0f
|
||||
bCol = (color and 255) / 256.0f
|
||||
gCol = ((color shr 8) and 255) / 256.0f
|
||||
rCol = ((color shr 16) and 255) / 256.0f
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,22 +8,22 @@ import mods.betterfoliage.util.randomB
|
||||
import mods.betterfoliage.util.randomD
|
||||
import mods.betterfoliage.util.randomF
|
||||
import mods.betterfoliage.util.randomI
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.particle.IParticleRenderType
|
||||
import net.minecraft.client.world.ClientWorld
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.MathHelper
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.event.TickEvent
|
||||
import net.minecraftforge.event.world.WorldEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.fml.LogicalSide
|
||||
import java.util.Random
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class FallingLeafParticle(
|
||||
world: World, pos: BlockPos, leaf: LeafParticleKey, blockColor: Int, random: Random
|
||||
world: ClientWorld, pos: BlockPos, leaf: LeafParticleKey, blockColor: Int, random: Random
|
||||
) : AbstractParticle(
|
||||
world, pos.x.toDouble() + 0.5, pos.y.toDouble(), pos.z.toDouble() + 0.5
|
||||
) {
|
||||
@@ -37,13 +37,13 @@ class FallingLeafParticle(
|
||||
var wasCollided = false
|
||||
|
||||
init {
|
||||
particleAngle = random.randomF(max = PI2)
|
||||
prevParticleAngle = particleAngle - rotationSpeed
|
||||
roll = random.randomF(max = PI2)
|
||||
oRoll = roll - rotationSpeed
|
||||
|
||||
maxAge = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
|
||||
motionY = -Config.fallingLeaves.speed
|
||||
lifetime = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
|
||||
yd = -Config.fallingLeaves.speed
|
||||
|
||||
particleScale = Config.fallingLeaves.size.toFloat() * 0.1f
|
||||
quadSize = Config.fallingLeaves.size.toFloat() * 0.1f
|
||||
setColor(leaf.overrideColor?.asInt ?: blockColor)
|
||||
sprite = LeafParticleRegistry[leaf.leafType][randomI(max = 1024)]
|
||||
}
|
||||
@@ -52,21 +52,21 @@ class FallingLeafParticle(
|
||||
|
||||
|
||||
override fun update() {
|
||||
if (rand.nextFloat() > 0.95f) rotationSpeed *= -1.0f
|
||||
if (age > maxAge - 20) particleAlpha = 0.05f * (maxAge - age)
|
||||
if (random.nextFloat() > 0.95f) rotationSpeed *= -1.0f
|
||||
if (age > lifetime - 20) alpha = 0.05f * (lifetime - age)
|
||||
|
||||
if (onGround || wasCollided) {
|
||||
velocity.setTo(0.0, 0.0, 0.0)
|
||||
if (!wasCollided) {
|
||||
age = age.coerceAtLeast(maxAge - 20)
|
||||
age = age.coerceAtLeast(lifetime - 20)
|
||||
wasCollided = true
|
||||
}
|
||||
} else {
|
||||
val cosRotation = cos(particleAngle).toDouble(); val sinRotation = sin(particleAngle).toDouble()
|
||||
val cosRotation = cos(roll).toDouble(); val sinRotation = sin(roll).toDouble()
|
||||
velocity.setTo(cosRotation, 0.0, sinRotation).mul(Config.fallingLeaves.perturb)
|
||||
.add(LeafWindTracker.current).add(0.0, -1.0, 0.0).mul(Config.fallingLeaves.speed)
|
||||
prevParticleAngle = particleAngle
|
||||
particleAngle += rotationSpeed
|
||||
oRoll = roll
|
||||
roll += rotationSpeed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ object LeafWindTracker {
|
||||
}
|
||||
|
||||
fun changeWind(world: World) {
|
||||
nextChange = world.worldInfo.gameTime + 120 + random.nextInt(80)
|
||||
nextChange = world.gameTime + 120 + random.nextInt(80)
|
||||
val direction = PI2 * random.nextDouble()
|
||||
val speed = abs(random.nextGaussian()) * Config.fallingLeaves.windStrength +
|
||||
(if (!world.isRaining) 0.0 else abs(random.nextGaussian()) * Config.fallingLeaves.stormStrength)
|
||||
@@ -92,10 +92,10 @@ object LeafWindTracker {
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun handleWorldTick(event: TickEvent.ClientTickEvent) {
|
||||
if (event.phase == TickEvent.Phase.START) Minecraft.getInstance().world?.let { world ->
|
||||
fun handleWorldTick(event: TickEvent.WorldTickEvent) {
|
||||
if (event.phase == TickEvent.Phase.START && event.side == LogicalSide.CLIENT) event.world.let { world ->
|
||||
// change target wind speed
|
||||
if (world.worldInfo.dayTime >= nextChange) changeWind(world)
|
||||
if (world.dayTime >= nextChange) changeWind(world)
|
||||
|
||||
// change current wind speed
|
||||
val changeRate = if (world.isRaining) 0.015 else 0.005
|
||||
@@ -107,6 +107,6 @@ object LeafWindTracker {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isRemote) changeWind(event.world.world) }
|
||||
// @SubscribeEvent
|
||||
// fun handleWorldLoad(event: WorldEvent.Load) { if (event.world.isClientSide) changeWind(event.world) }
|
||||
}
|
||||
@@ -41,7 +41,7 @@ object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
|
||||
|
||||
@SubscribeEvent
|
||||
fun handlePreStitch(event: TextureStitchEvent.Pre) {
|
||||
if (event.map.textureLocation == Atlas.PARTICLES.resourceId) {
|
||||
if (event.map.location() == Atlas.PARTICLES.resourceId) {
|
||||
allTypes.forEach { leafType ->
|
||||
val locations = (0 until 16).map { idx ->
|
||||
ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx")
|
||||
@@ -55,7 +55,7 @@ object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {
|
||||
|
||||
@SubscribeEvent
|
||||
fun handlePostStitch(event: TextureStitchEvent.Post) {
|
||||
if (event.map.textureLocation == Atlas.PARTICLES.resourceId) {
|
||||
if (event.map.location() == Atlas.PARTICLES.resourceId) {
|
||||
(typeMappings.mappings.map { it.type } + "default").distinct().forEach { leafType ->
|
||||
val sprites = (0 until 16).map { idx ->
|
||||
ResourceLocation(BetterFoliageMod.MOD_ID, "particle/falling_leaf_${leafType}_$idx")
|
||||
|
||||
@@ -13,6 +13,7 @@ import mods.betterfoliage.util.randomD
|
||||
import mods.betterfoliage.util.randomI
|
||||
import net.minecraft.client.particle.IParticleRenderType
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo
|
||||
import net.minecraft.client.world.ClientWorld
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.MathHelper
|
||||
@@ -23,7 +24,7 @@ import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class RisingSoulParticle(
|
||||
world: World, pos: BlockPos
|
||||
world: ClientWorld, pos: BlockPos
|
||||
) : AbstractParticle(
|
||||
world, pos.x.toDouble() + 0.5, pos.y.toDouble() + 1.0, pos.z.toDouble() + 0.5
|
||||
) {
|
||||
@@ -32,10 +33,10 @@ class RisingSoulParticle(
|
||||
val initialPhase = randomD(max = PI2)
|
||||
|
||||
init {
|
||||
motionY = 0.1
|
||||
particleGravity = 0.0f
|
||||
yd = 0.1
|
||||
gravity = 0.0f
|
||||
sprite = headIcons[randomI(max = 1024)]
|
||||
maxAge = MathHelper.floor((0.6 + 0.4 * randomD()) * Config.risingSoul.lifetime * 20.0)
|
||||
lifetime = MathHelper.floor((0.6 + 0.4 * randomD()) * Config.risingSoul.lifetime * 20.0)
|
||||
}
|
||||
|
||||
override val isValid: Boolean get() = true
|
||||
@@ -49,12 +50,12 @@ class RisingSoulParticle(
|
||||
particleTrail.addFirst(currentPos.copy())
|
||||
while (particleTrail.size > Config.risingSoul.trailLength) particleTrail.removeLast()
|
||||
|
||||
if (!Config.enabled) setExpired()
|
||||
if (!Config.enabled) remove()
|
||||
}
|
||||
|
||||
override fun renderParticle(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
|
||||
override fun render(vertexBuilder: IVertexBuilder, camera: ActiveRenderInfo, tickDelta: Float) {
|
||||
var alpha = Config.risingSoul.opacity.toFloat()
|
||||
if (age > maxAge - 40) alpha *= (maxAge - age) / 40.0f
|
||||
if (age > lifetime - 40) alpha *= (lifetime - age) / 40.0f
|
||||
|
||||
renderParticleQuad(
|
||||
vertexBuilder, camera, tickDelta,
|
||||
|
||||
@@ -3,18 +3,18 @@ package mods.betterfoliage.render.pipeline
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import mods.betterfoliage.chunk.BasicBlockCtx
|
||||
import mods.betterfoliage.chunk.BlockCtx
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import mods.betterfoliage.render.lighting.VanillaFullBlockLighting
|
||||
import mods.betterfoliage.render.lighting.VanillaQuadLighting
|
||||
import mods.betterfoliage.render.lighting.VanillaVertexLighter
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import mods.betterfoliage.util.Int3
|
||||
import mods.betterfoliage.util.plus
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraftforge.client.model.data.IModelData
|
||||
import java.util.Random
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.Random
|
||||
* push-based partial rendering pipeline for [SpecialRenderModel] instances.
|
||||
*/
|
||||
abstract class RenderCtxBase(
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
pos: BlockPos,
|
||||
val matrixStack: MatrixStack,
|
||||
var checkSides: Boolean,
|
||||
@@ -36,14 +36,14 @@ abstract class RenderCtxBase(
|
||||
abstract fun renderQuad(quad: HalfBakedQuad)
|
||||
|
||||
var hasRendered = false
|
||||
val blockModelShapes = Minecraft.getInstance().blockRendererDispatcher.blockModelShapes
|
||||
val blockModelShapes = Minecraft.getInstance().blockRenderer.blockModelShaper
|
||||
var vertexLighter: VanillaVertexLighter = VanillaFullBlockLighting
|
||||
protected val lightingData = RenderCtxBase.lightingData.get().apply {
|
||||
calc.reset(this@RenderCtxBase)
|
||||
blockColors = Minecraft.getInstance().blockColors
|
||||
}
|
||||
|
||||
inline fun Direction?.shouldRender() = this == null || !checkSides || Block.shouldSideBeRendered(state, world, pos, this)
|
||||
inline fun Direction?.shouldRender() = this == null || !checkSides || Block.shouldRenderFace(state, world, pos, this)
|
||||
|
||||
fun renderQuads(quads: Iterable<HalfBakedQuad>) {
|
||||
quads.forEach { quad ->
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package mods.betterfoliage.render.pipeline
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import mods.betterfoliage.render.lighting.ForgeVertexLighter
|
||||
import mods.betterfoliage.render.lighting.ForgeVertexLighterAccess
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.LightTexture
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraftforge.client.model.data.IModelData
|
||||
import net.minecraftforge.client.model.pipeline.VertexLighterFlat
|
||||
import java.util.Random
|
||||
|
||||
class RenderCtxForge(
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
pos: BlockPos,
|
||||
val lighter: VertexLighterFlat,
|
||||
matrixStack: MatrixStack,
|
||||
@@ -33,8 +33,8 @@ class RenderCtxForge(
|
||||
var vIdx = 0
|
||||
override fun updateVertexLightmap(normal: FloatArray, lightmap: FloatArray, x: Float, y: Float, z: Float) {
|
||||
lightingData.packedLight[vIdx].let { packedLight ->
|
||||
lightmap[0] = LightTexture.getLightBlock(packedLight) / 0xF.toFloat()
|
||||
lightmap[1] = LightTexture.getLightSky(packedLight) / 0xF.toFloat()
|
||||
lightmap[0] = LightTexture.block(packedLight) / 0xF.toFloat()
|
||||
lightmap[1] = LightTexture.sky(packedLight) / 0xF.toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class RenderCtxForge(
|
||||
@JvmStatic
|
||||
fun render(
|
||||
lighter: VertexLighterFlat,
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
model: SpecialRenderModel,
|
||||
state: BlockState,
|
||||
pos: BlockPos,
|
||||
|
||||
@@ -2,18 +2,18 @@ package mods.betterfoliage.render.pipeline
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import mods.betterfoliage.model.HalfBakedQuad
|
||||
import mods.betterfoliage.model.SpecialRenderModel
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.BlockModelRenderer
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.ILightReader
|
||||
import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraftforge.client.model.data.IModelData
|
||||
import java.util.Random
|
||||
|
||||
class RenderCtxVanilla(
|
||||
val renderer: BlockModelRenderer,
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
pos: BlockPos,
|
||||
val buffer: IVertexBuilder,
|
||||
val combinedOverlay: Int,
|
||||
@@ -27,8 +27,8 @@ class RenderCtxVanilla(
|
||||
|
||||
override fun renderQuad(quad: HalfBakedQuad) {
|
||||
vertexLighter.updateLightmapAndColor(quad, lightingData)
|
||||
buffer.addQuad(
|
||||
matrixStack.last, quad.baked,
|
||||
buffer.putBulkData(
|
||||
matrixStack.last(), quad.baked,
|
||||
lightingData.colorMultiplier,
|
||||
lightingData.tint[0], lightingData.tint[1], lightingData.tint[2],
|
||||
lightingData.packedLight, combinedOverlay, true
|
||||
@@ -39,7 +39,7 @@ class RenderCtxVanilla(
|
||||
@JvmStatic
|
||||
fun render(
|
||||
renderer: BlockModelRenderer,
|
||||
world: ILightReader,
|
||||
world: IBlockDisplayReader,
|
||||
model: SpecialRenderModel,
|
||||
state: BlockState,
|
||||
pos: BlockPos,
|
||||
|
||||
@@ -20,7 +20,7 @@ interface VeryEarlyReloadListener : IFutureReloadListener {
|
||||
gameExecutor: Executor
|
||||
): CompletableFuture<Void> {
|
||||
onReloadStarted()
|
||||
return stage.markCompleteAwaitingOthers(null)
|
||||
return stage.wait(null)
|
||||
}
|
||||
|
||||
fun onReloadStarted() {}
|
||||
|
||||
@@ -8,8 +8,8 @@ import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.model.IBakedModel
|
||||
import net.minecraft.client.renderer.model.IModelTransform
|
||||
import net.minecraft.client.renderer.model.IUnbakedModel
|
||||
import net.minecraft.client.renderer.model.Material
|
||||
import net.minecraft.client.renderer.model.ModelBakery
|
||||
import net.minecraft.client.renderer.model.RenderMaterial
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraftforge.client.event.ModelBakeEvent
|
||||
@@ -30,7 +30,7 @@ data class ModelDefinitionsLoadedEvent(
|
||||
|
||||
interface ModelBakingKey {
|
||||
fun bake(ctx: ModelBakingContext): IBakedModel? =
|
||||
ctx.getUnbaked().bakeModel(ctx.bakery, ctx.spriteGetter, ctx.transform, ctx.location)
|
||||
ctx.getUnbaked().bake(ctx.bakery, ctx.spriteGetter, ctx.transform, ctx.location)
|
||||
}
|
||||
|
||||
interface ModelDiscovery {
|
||||
@@ -49,7 +49,7 @@ data class ModelDiscoveryContext(
|
||||
val replacements: MutableMap<ResourceLocation, ModelBakingKey>,
|
||||
val logger: Logger
|
||||
) {
|
||||
fun getUnbaked(location: ResourceLocation = modelLocation) = bakery.getUnbakedModel(location)
|
||||
fun getUnbaked(location: ResourceLocation = modelLocation) = bakery.getModel(location)
|
||||
fun addReplacement(key: ModelBakingKey, addToStateKeys: Boolean = true) {
|
||||
replacements[modelLocation] = key
|
||||
if (addToStateKeys) BetterFoliage.blockTypes.stateKeys[blockState] = key
|
||||
@@ -59,12 +59,12 @@ data class ModelDiscoveryContext(
|
||||
|
||||
data class ModelBakingContext(
|
||||
val bakery: ModelBakery,
|
||||
val spriteGetter: Function<Material, TextureAtlasSprite>,
|
||||
val spriteGetter: Function<RenderMaterial, TextureAtlasSprite>,
|
||||
val location: ResourceLocation,
|
||||
val transform: IModelTransform,
|
||||
val logger: Logger
|
||||
) {
|
||||
fun getUnbaked() = bakery.getUnbakedModel(location)
|
||||
fun getUnbaked() = bakery.getModel(location)
|
||||
fun getBaked() = bakery.getBakedModel(location, transform, spriteGetter)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ object BakeWrapperManager : Invalidator, HasLogger() {
|
||||
|
||||
@SubscribeEvent
|
||||
fun handleStitch(event: TextureStitchEvent.Pre) {
|
||||
if (event.map.textureLocation == Atlas.BLOCKS.resourceId) {
|
||||
if (event.map.location() == Atlas.BLOCKS.resourceId) {
|
||||
logger.log(INFO, "Adding ${sprites.size} sprites to block atlas")
|
||||
sprites.forEach { event.addSprite(it) }
|
||||
sprites.clear()
|
||||
@@ -109,7 +109,7 @@ object BakeWrapperManager : Invalidator, HasLogger() {
|
||||
fun onBake(
|
||||
unbaked: IUnbakedModel,
|
||||
bakery: ModelBakery,
|
||||
spriteGetter: Function<Material, TextureAtlasSprite>,
|
||||
spriteGetter: Function<RenderMaterial, TextureAtlasSprite>,
|
||||
transform: IModelTransform,
|
||||
location: ResourceLocation
|
||||
): IBakedModel? {
|
||||
@@ -124,6 +124,6 @@ object BakeWrapperManager : Invalidator, HasLogger() {
|
||||
logger.log(WARN, "Error while baking $replacement", e)
|
||||
}
|
||||
}
|
||||
return unbaked.bakeModel(bakery, spriteGetter, transform, location)
|
||||
return unbaked.bake(bakery, spriteGetter, transform, location)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package mods.betterfoliage.resource.discovery
|
||||
|
||||
import mods.betterfoliage.BetterFoliageMod
|
||||
import mods.betterfoliage.util.HasLogger
|
||||
import mods.betterfoliage.util.getJavaClass
|
||||
import mods.betterfoliage.util.getLines
|
||||
@@ -45,8 +44,8 @@ class ConfigurableBlockMatcher(val location: ResourceLocation) : HasLogger(), IB
|
||||
fun readDefaults() {
|
||||
blackList.clear()
|
||||
whiteList.clear()
|
||||
resourceManager.getAllResources(location).forEach { resource ->
|
||||
detailLogger.log(INFO, "Reading block class configuration $location from pack ${resource.packName}")
|
||||
resourceManager.getResources(location).forEach { resource ->
|
||||
detailLogger.log(INFO, "Reading block class configuration $location from pack ${resource.sourceName}")
|
||||
resource.getLines().map{ it.trim() }.filter { !it.startsWith("//") && it.isNotEmpty() }.forEach { line ->
|
||||
if (line.startsWith("-")) getJavaClass(line.substring(1))?.let { blackList.add(it) }
|
||||
else getJavaClass(line)?.let { whiteList.add(it) }
|
||||
@@ -63,8 +62,8 @@ data class ModelTextureList(val modelLocation: ResourceLocation, val textureName
|
||||
class ModelTextureListConfiguration(val location: ResourceLocation) : HasLogger() {
|
||||
val modelList = mutableListOf<ModelTextureList>()
|
||||
fun readDefaults() {
|
||||
resourceManager.getAllResources(location).forEach { resource ->
|
||||
detailLogger.log(INFO, "Reading model/texture configuration $location from pack ${resource.packName}")
|
||||
resourceManager.getResources(location).forEach { resource ->
|
||||
detailLogger.log(INFO, "Reading model/texture configuration $location from pack ${resource.sourceName}")
|
||||
resource.getLines().map{ it.trim() }.filter { !it.startsWith("//") && it.isNotEmpty() }.forEach { line ->
|
||||
val elements = line.split(",")
|
||||
modelList.add(ModelTextureList(ResourceLocation(elements.first()), elements.drop(1)))
|
||||
|
||||
@@ -18,9 +18,9 @@ abstract class AbstractModelDiscovery : HasLogger(), ModelDiscovery {
|
||||
replacements: MutableMap<ResourceLocation, ModelBakingKey>
|
||||
) {
|
||||
ForgeRegistries.BLOCKS
|
||||
.flatMap { block -> block.stateContainer.validStates }
|
||||
.flatMap { block -> block.stateDefinition.possibleStates }
|
||||
.forEach { state ->
|
||||
val location = BlockModelShapes.getModelLocation(state)
|
||||
val location = BlockModelShapes.stateToModelLocation(state)
|
||||
val ctx = ModelDiscoveryContext(bakery, state, location, sprites, replacements, detailLogger)
|
||||
try {
|
||||
processModel(ctx)
|
||||
@@ -38,7 +38,7 @@ abstract class AbstractModelDiscovery : HasLogger(), ModelDiscovery {
|
||||
// per-location replacements need to be scoped to the variant list, as replacement models
|
||||
// may need information from the BlockState which is not available at baking time
|
||||
val scopedReplacements = mutableMapOf<ResourceLocation, ModelBakingKey>()
|
||||
model.variantList.forEach { variant ->
|
||||
model.variants.forEach { variant ->
|
||||
processModel(ctx.copy(modelLocation = variant.modelLocation, replacements = scopedReplacements))
|
||||
}
|
||||
if (scopedReplacements.isNotEmpty()) {
|
||||
@@ -73,15 +73,18 @@ abstract class ConfigurableModelDiscovery : AbstractModelDiscovery() {
|
||||
matches.forEach { match ->
|
||||
detailLogger.log(Level.INFO, " model $model matches ${match.modelLocation}")
|
||||
|
||||
val materials = match.textureNames.map { it to model.resolveTextureName(it) }
|
||||
val texMapString = Joiner.on(", ").join(materials.map { "${it.first}=${it.second.textureLocation}" })
|
||||
detailLogger.log(Level.INFO, " sprites [$texMapString]")
|
||||
val materials = match.textureNames.map { it to model.getMaterial(it) }
|
||||
val texMapString = Joiner.on(", ").join(materials.map { "${it.first}=${it.second.texture()}" })
|
||||
detailLogger.log(Level.INFO, " sprites [$texMapString]")
|
||||
|
||||
if (materials.all { it.second.textureLocation != MissingTextureSprite.getLocation() }) {
|
||||
// found a valid model (all required textures exist)
|
||||
processModel(ctx, materials.map { it.second.textureLocation })
|
||||
}
|
||||
if (materials.all { it.second.texture() != MissingTextureSprite.getLocation() }) {
|
||||
// found a valid model (all required textures exist)
|
||||
processModel(ctx, materials.map { it.second.texture() })
|
||||
}
|
||||
}
|
||||
if (matches.isEmpty()) {
|
||||
detailLogger.log(Level.INFO, " no matches for model ${ctx.modelLocation}, inheritance chain ${ancestry.joinToString(" -> ")}")
|
||||
}
|
||||
}
|
||||
return super.processModel(ctx)
|
||||
}
|
||||
@@ -90,12 +93,12 @@ abstract class ConfigurableModelDiscovery : AbstractModelDiscovery() {
|
||||
fun ModelBakery.modelDerivesFrom(model: BlockModel, location: ResourceLocation, target: ResourceLocation): Boolean =
|
||||
if (location == target) true
|
||||
else model.parentLocation
|
||||
?.let { getUnbakedModel(it) as? BlockModel }
|
||||
?.let { getModel(it) as? BlockModel }
|
||||
?.let { parent -> modelDerivesFrom(parent, model.parentLocation!!, target) }
|
||||
?: false
|
||||
|
||||
fun ModelBakery.getAncestry(location: ResourceLocation): List<ResourceLocation> {
|
||||
val model = getUnbakedModel(location) as? BlockModel ?: return listOf(location)
|
||||
val model = getModel(location) as? BlockModel ?: return listOf(location)
|
||||
val parentAncestry = model.parentLocation?.let { getAncestry(it) } ?: emptyList()
|
||||
return listOf(location) + parentAncestry
|
||||
}
|
||||
@@ -20,7 +20,7 @@ class WeightedUnbakedKey(
|
||||
if (unbaked !is VariantList) return super.bake(ctx)
|
||||
|
||||
// bake all variants, replace as needed
|
||||
val bakedModels = unbaked.variantList.mapNotNull {
|
||||
val bakedModels = unbaked.variants.mapNotNull {
|
||||
val variantCtx = ctx.copy(location = it.modelLocation, transform = it)
|
||||
val replacement = replacements[it.modelLocation]
|
||||
val baked = replacement?.let { replacement ->
|
||||
@@ -40,10 +40,10 @@ class WeightedUnbakedKey(
|
||||
// let it through unchanged
|
||||
if (bakedModels.isEmpty()) return super.bake(ctx)
|
||||
|
||||
if (bakedModels.size < unbaked.variantList.size) {
|
||||
if (bakedModels.size < unbaked.variants.size) {
|
||||
detailLogger.log(
|
||||
WARN,
|
||||
"Dropped ${unbaked.variantList.size - bakedModels.size} variants from model ${ctx.location}"
|
||||
"Dropped ${unbaked.variants.size - bakedModels.size} variants from model ${ctx.location}"
|
||||
)
|
||||
}
|
||||
val weightedSpecials = bakedModels.map { (variant, model) ->
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package mods.betterfoliage.resource.generated
|
||||
|
||||
import mods.betterfoliage.BetterFoliageMod
|
||||
import mods.betterfoliage.util.Atlas
|
||||
import mods.betterfoliage.util.HasLogger
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.resources.ClientResourcePackInfo
|
||||
import net.minecraft.resources.*
|
||||
import net.minecraft.resources.ResourcePackType.CLIENT_RESOURCES
|
||||
import net.minecraft.resources.data.IMetadataSectionSerializer
|
||||
@@ -12,6 +10,7 @@ import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.util.text.StringTextComponent
|
||||
import org.apache.logging.log4j.Level.INFO
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
import java.util.function.Predicate
|
||||
import java.util.function.Supplier
|
||||
|
||||
@@ -25,10 +24,10 @@ class GeneratedTexturePack(
|
||||
val nameSpace: String, val packName: String
|
||||
) : HasLogger(), IResourcePack {
|
||||
override fun getName() = packName
|
||||
override fun getResourceNamespaces(type: ResourcePackType) = setOf(nameSpace)
|
||||
override fun <T : Any?> getMetadata(deserializer: IMetadataSectionSerializer<T>) = null
|
||||
override fun getRootResourceStream(id: String) = null
|
||||
override fun getAllResourceLocations(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<ResourceLocation>()
|
||||
override fun getNamespaces(type: ResourcePackType) = setOf(nameSpace)
|
||||
override fun <T : Any?> getMetadataSection(deserializer: IMetadataSectionSerializer<T>) = null
|
||||
override fun getRootResource(id: String) = null
|
||||
override fun getResources(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<ResourceLocation>()
|
||||
|
||||
override fun close() {}
|
||||
|
||||
@@ -49,21 +48,22 @@ class GeneratedTexturePack(
|
||||
return id
|
||||
}
|
||||
|
||||
override fun getResourceStream(type: ResourcePackType, id: ResourceLocation) =
|
||||
override fun getResource(type: ResourcePackType, id: ResourceLocation) =
|
||||
if (type != CLIENT_RESOURCES) null else resources[id]?.inputStream()
|
||||
|
||||
override fun resourceExists(type: ResourcePackType, id: ResourceLocation) =
|
||||
override fun hasResource(type: ResourcePackType, id: ResourceLocation) =
|
||||
type == CLIENT_RESOURCES && resources.containsKey(id)
|
||||
|
||||
val finder = object : IPackFinder {
|
||||
val packInfo = ClientResourcePackInfo(
|
||||
val packInfo = ResourcePackInfo(
|
||||
packName, true, Supplier { this@GeneratedTexturePack },
|
||||
StringTextComponent(packName),
|
||||
StringTextComponent("Generated block textures resource pack"),
|
||||
PackCompatibility.COMPATIBLE, ResourcePackInfo.Priority.TOP, true, null, true
|
||||
)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -1,12 +1,12 @@
|
||||
package mods.betterfoliage.util
|
||||
|
||||
import net.minecraft.client.renderer.Quaternion
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Direction.*
|
||||
import net.minecraft.util.Direction.Axis.*
|
||||
import net.minecraft.util.Direction.AxisDirection.NEGATIVE
|
||||
import net.minecraft.util.Direction.AxisDirection.POSITIVE
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.vector.Quaternion
|
||||
|
||||
val EPSILON_ZERO = 0.05
|
||||
val EPSILON_ONE = 0.95
|
||||
@@ -55,15 +55,15 @@ val ROTATION_MATRIX: Array<IntArray> get() = arrayOf(
|
||||
// Vectors
|
||||
// ================================
|
||||
operator fun Direction.times(scale: Double) =
|
||||
Double3(directionVec.x.toDouble() * scale, directionVec.y.toDouble() * scale, directionVec.z.toDouble() * scale)
|
||||
val Direction.vec: Double3 get() = Double3(directionVec.x.toDouble(), directionVec.y.toDouble(), directionVec.z.toDouble())
|
||||
Double3(normal.x.toDouble() * scale, normal.y.toDouble() * scale, normal.z.toDouble() * scale)
|
||||
val Direction.vec: Double3 get() = Double3(normal.x.toDouble(), normal.y.toDouble(), normal.z.toDouble())
|
||||
|
||||
operator fun BlockPos.plus(other: Int3) = BlockPos(x + other.x, y + other.y, z + other.z)
|
||||
|
||||
/** 3D vector of [Double]s. Offers both mutable operations, and immutable operations in operator notation. */
|
||||
data class Double3(var x: Double, var y: Double, var z: Double) {
|
||||
constructor(x: Float, y: Float, z: Float) : this(x.toDouble(), y.toDouble(), z.toDouble())
|
||||
constructor(dir: Direction) : this(dir.directionVec.x.toDouble(), dir.directionVec.y.toDouble(), dir.directionVec.z.toDouble())
|
||||
constructor(dir: Direction) : this(dir.normal.x.toDouble(), dir.normal.y.toDouble(), dir.normal.z.toDouble())
|
||||
companion object {
|
||||
val zero: Double3 get() = Double3(0.0, 0.0, 0.0)
|
||||
fun weight(v1: Double3, weight1: Double, v2: Double3, weight2: Double) =
|
||||
@@ -88,9 +88,9 @@ data class Double3(var x: Double, var y: Double, var z: Double) {
|
||||
/** Rotate vector by the given [Quaternion] */
|
||||
fun rotate(quat: Quaternion) =
|
||||
quat.copy()
|
||||
.apply { multiply(Quaternion(x, y, z, 0.0F)) }
|
||||
.apply { multiply(quat.copy().apply(Quaternion::conjugate)) }
|
||||
.let { Double3(it.x, it.y, it.z) }
|
||||
.apply { mul(Quaternion(x.toFloat(), y.toFloat(), z.toFloat(), 0.0F)) }
|
||||
.apply { mul(quat.copy().apply(Quaternion::conj)) }
|
||||
.let { Double3(it.i().toDouble(), it.j().toDouble(), it.k().toDouble()) }
|
||||
|
||||
// mutable operations
|
||||
fun setTo(other: Double3): Double3 { x = other.x; y = other.y; z = other.z; return this }
|
||||
@@ -120,11 +120,11 @@ data class Double3(var x: Double, var y: Double, var z: Double) {
|
||||
|
||||
/** 3D vector of [Int]s. Offers both mutable operations, and immutable operations in operator notation. */
|
||||
data class Int3(var x: Int, var y: Int, var z: Int) {
|
||||
constructor(dir: Direction) : this(dir.directionVec.x, dir.directionVec.y, dir.directionVec.z)
|
||||
constructor(dir: Direction) : this(dir.normal.x, dir.normal.y, dir.normal.z)
|
||||
constructor(offset: Pair<Int, Direction>) : this(
|
||||
offset.first * offset.second.directionVec.x,
|
||||
offset.first * offset.second.directionVec.y,
|
||||
offset.first * offset.second.directionVec.z
|
||||
offset.first * offset.second.normal.x,
|
||||
offset.first * offset.second.normal.y,
|
||||
offset.first * offset.second.normal.z
|
||||
)
|
||||
companion object {
|
||||
val zero = Int3(0, 0, 0)
|
||||
@@ -133,9 +133,9 @@ data class Int3(var x: Int, var y: Int, var z: Int) {
|
||||
// immutable operations
|
||||
operator fun plus(other: Int3) = Int3(x + other.x, y + other.y, z + other.z)
|
||||
operator fun plus(other: Pair<Int, Direction>) = Int3(
|
||||
x + other.first * other.second.directionVec.x,
|
||||
y + other.first * other.second.directionVec.y,
|
||||
z + other.first * other.second.directionVec.z
|
||||
x + other.first * other.second.normal.x,
|
||||
y + other.first * other.second.normal.y,
|
||||
z + other.first * other.second.normal.z
|
||||
)
|
||||
operator fun unaryMinus() = Int3(-x, -y, -z)
|
||||
operator fun minus(other: Int3) = Int3(x - other.x, y - other.y, z - other.z)
|
||||
|
||||
@@ -7,16 +7,16 @@ import net.minecraft.util.text.TextFormatting
|
||||
import net.minecraft.util.text.TextFormatting.AQUA
|
||||
import net.minecraft.util.text.TextFormatting.GRAY
|
||||
|
||||
fun stripTooltipDefaultText(tooltip: MutableList<String>) {
|
||||
var defaultRows = false
|
||||
val iter = tooltip.iterator()
|
||||
while (iter.hasNext()) {
|
||||
if (iter.next().startsWith(AQUA.toString())) defaultRows = true
|
||||
if (defaultRows) iter.remove()
|
||||
}
|
||||
}
|
||||
|
||||
fun textComponent(msg: String, color: TextFormatting = GRAY): StringTextComponent {
|
||||
val style = Style().apply { this.color = color }
|
||||
return StringTextComponent(msg).apply { this.style = style }
|
||||
}
|
||||
//fun stripTooltipDefaultText(tooltip: MutableList<String>) {
|
||||
// var defaultRows = false
|
||||
// val iter = tooltip.iterator()
|
||||
// while (iter.hasNext()) {
|
||||
// if (iter.next().startsWith(AQUA.toString())) defaultRows = true
|
||||
// if (defaultRows) iter.remove()
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//fun textComponent(msg: String, color: TextFormatting = GRAY): StringTextComponent {
|
||||
// val style = Style().apply { this.color = color }
|
||||
// return StringTextComponent(msg).apply { this.style = style }
|
||||
//}
|
||||
@@ -1,8 +1,6 @@
|
||||
package mods.betterfoliage.util
|
||||
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.model.Material
|
||||
import net.minecraft.client.renderer.texture.AtlasTexture
|
||||
import net.minecraft.resources.IReloadableResourceManager
|
||||
import net.minecraft.resources.IResource
|
||||
import net.minecraft.resources.IResourceManager
|
||||
@@ -19,11 +17,6 @@ operator fun ResourceLocation.plus(str: String) = ResourceLocation(namespace, pa
|
||||
fun ResourceLocation.prependLocation(basePath: String) =
|
||||
ResourceLocation(namespace, basePath.stripEnd("/").let { "$it/$path" })
|
||||
|
||||
val ResourceLocation.asBlockMaterial: Material get() = Material(
|
||||
AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
this
|
||||
)
|
||||
|
||||
/** Index operator to get a resource. */
|
||||
operator fun IResourceManager.get(domain: String, path: String): IResource? = get(ResourceLocation(domain, path))
|
||||
/** Index operator to get a resource. */
|
||||
|
||||
@@ -3,7 +3,6 @@ package mods.betterfoliage.util
|
||||
import mods.betterfoliage.model.Color
|
||||
import mods.betterfoliage.model.HSB
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.model.Material
|
||||
import net.minecraft.client.renderer.texture.AtlasTexture
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.resources.IResource
|
||||
@@ -20,8 +19,8 @@ import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
enum class Atlas(val resourceId: ResourceLocation) {
|
||||
BLOCKS(AtlasTexture.LOCATION_BLOCKS_TEXTURE),
|
||||
PARTICLES(AtlasTexture.LOCATION_PARTICLES_TEXTURE);
|
||||
BLOCKS(AtlasTexture.LOCATION_BLOCKS),
|
||||
PARTICLES(AtlasTexture.LOCATION_PARTICLES);
|
||||
|
||||
/** Get the fully-qualified resource name for sprites belonging to this atlas */
|
||||
fun file(resource: ResourceLocation) = ResourceLocation(resource.namespace, "textures/${resource.path}.png")
|
||||
@@ -33,7 +32,7 @@ enum class Atlas(val resourceId: ResourceLocation) {
|
||||
operator fun get(location: ResourceLocation) = atlas.getSprite(location)
|
||||
}
|
||||
|
||||
val Material.atlas: Atlas get() = Atlas.values().find { it.resourceId == atlasLocation } ?: Atlas.BLOCKS
|
||||
//val Spr.atlas: Atlas get() = Atlas.values().find { it.resourceId == atlasLocation } ?: Atlas.BLOCKS
|
||||
|
||||
inline operator fun AtlasTexture.get(res: ResourceLocation): TextureAtlasSprite? = this.getSprite(res)
|
||||
inline operator fun AtlasTexture.get(name: String): TextureAtlasSprite? = get(ResourceLocation(name))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
modLoader="kotlinfml"
|
||||
loaderVersion="[1.4,)"
|
||||
modLoader="kotlinforforge"
|
||||
loaderVersion="[1,)"
|
||||
issueTrackerURL="https://github.com/octarine-noise/BetterFoliage/issues"
|
||||
|
||||
license="MIT"
|
||||
[[mods]]
|
||||
modId="betterfoliage"
|
||||
version="${version}"
|
||||
|
||||
@@ -230,6 +230,8 @@ betterfoliage.connectedGrass.enabled.tooltip=If there is a grass block on top of
|
||||
|
||||
betterfoliage.roundLogs=Round Logs
|
||||
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.tooltip=Connect round blocks to solid full blocks?
|
||||
betterfoliage.roundLogs.connectPerpendicular=Connect to perpendicular logs
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// Vanilla
|
||||
net.minecraft.block.LogBlock
|
||||
net.minecraft.block.RotatedPillarBlock
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Vanilla
|
||||
block/column_side,side,end
|
||||
block/cube_column,side,end
|
||||
block/cube_column_horizontal,side,end
|
||||
block/cube_all,all,all
|
||||
|
||||
Reference in New Issue
Block a user