[WIP] start 1.15 port

reorganize packages to match Fabric version
use util classes from Fabric version
This commit is contained in:
octarine-noise
2021-05-01 13:52:21 +02:00
parent 9566ae8341
commit 09ccb83e8b
81 changed files with 1220 additions and 1011 deletions

View File

@@ -1,6 +1,6 @@
plugins {
kotlin("jvm").version("1.3.61")
id("net.minecraftforge.gradle").version("3.0.157")
id("net.minecraftforge.gradle").version("3.0.194")
id("org.spongepowered.mixin").version("0.7-SNAPSHOT")
}
apply(plugin = "org.spongepowered.mixin")

View File

@@ -6,9 +6,9 @@ jarName = BetterFoliage-Forge
version = 2.5.1
mcVersion = 1.14.4
forgeVersion = 28.2.0
mcVersion = 1.15.2
forgeVersion = 31.2.0
mappingsChannel = snapshot
mappingsVersion = 20190719-1.14.3
mappingsVersion = 20200514-1.15.1
kottleVersion = 1.4.0

View File

@@ -1,6 +1,6 @@
package mods.betterfoliage.mixin;
import mods.betterfoliage.client.Hooks;
import mods.betterfoliage.Hooks;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
@@ -21,8 +21,9 @@ import org.spongepowered.asm.mixin.injection.Redirect;
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 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;";
@Redirect(method = shouldSideBeRendered, at = @At(value = "INVOKE", target = getVoxelShape, ordinal = 1))
@Redirect(method = shouldSideBeRendered, at = @At(value = "INVOKE", target = getFaceOcclusionShape, ordinal = 1))
private static VoxelShape getVoxelShapeOverride(BlockState state, IBlockReader reader, BlockPos pos, Direction dir) {
return Hooks.getVoxelShapeOverride(state, reader, pos, dir);
}

View File

@@ -1,6 +1,6 @@
package mods.betterfoliage.mixin;
import mods.betterfoliage.client.Hooks;
import mods.betterfoliage.Hooks;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
@@ -15,13 +15,13 @@ 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)
@SuppressWarnings({"UnnecessaryQualifiedMemberReference", "deprecation"})
@SuppressWarnings({"deprecation"})
public class MixinBlockState {
private static final String callFrom = "Lnet/minecraft/block/BlockState;func_215703_d(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F";
private static final String callTo = "Lnet/minecraft/block/Block;func_220080_a(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)F";
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";
@Redirect(method = callFrom, at = @At(value = "INVOKE", target = callTo))
float getAmbientOcclusionValue(Block block, BlockState state, IBlockReader reader, BlockPos pos) {
return Hooks.getAmbientOcclusionLightValueOverride(block.func_220080_a(state, reader, pos), state);
return Hooks.getAmbientOcclusionLightValueOverride(block.getAmbientOcclusionLightValue(state, reader, pos), state);
}
}

View File

@@ -1,12 +1,12 @@
package mods.betterfoliage.mixin;
import mods.betterfoliage.client.Hooks;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import mods.betterfoliage.Hooks;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.chunk.ChunkRender;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IEnviromentBlockReader;
import net.minecraft.world.ILightReader;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.client.model.data.IModelData;
import org.spongepowered.asm.mixin.Mixin;
@@ -15,14 +15,13 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.Random;
@Mixin(ChunkRender.class)
@Mixin(targets = {"net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$ChunkRender$RebuildTask"})
public class MixinChunkRender {
private static final String rebuildChunk = "rebuildChunk(FFFLnet/minecraft/client/renderer/chunk/ChunkRenderTask;)V";
private static final String renderBlock = "Lnet/minecraft/client/renderer/BlockRendererDispatcher;renderBlock(Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/IEnviromentBlockReader;Lnet/minecraft/client/renderer/BufferBuilder;Ljava/util/Random;Lnet/minecraftforge/client/model/data/IModelData;)Z";
@Redirect(method = rebuildChunk, at = @At(value = "INVOKE", target = renderBlock))
public boolean renderBlock(BlockRendererDispatcher dispatcher, BlockState state, BlockPos pos, IEnviromentBlockReader reader, BufferBuilder buffer, Random random, IModelData modelData) {
return Hooks.renderWorldBlock(dispatcher, state, pos, reader, buffer, random, modelData, MinecraftForgeClient.getRenderLayer());
private static final String compile = "Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$ChunkRender$RebuildTask;compile(FFFLnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$CompiledChunk;Lnet/minecraft/client/renderer/RegionRenderCacheBuilder;)Ljava/util/Set;";
private static final String renderModel = "Lnet/minecraft/client/renderer/BlockRendererDispatcher;renderModel(Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/ILightReader;Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;ZLjava/util/Random;Lnet/minecraftforge/client/model/data/IModelData;)Z";
@Redirect(method = compile, at = @At(value = "INVOKE", target = renderModel))
public boolean renderModel(BlockRendererDispatcher dispatcher, BlockState state, BlockPos pos, ILightReader reader, MatrixStack matrixStack, IVertexBuilder vertexBuilder, boolean checkSides, Random random, IModelData modelData) {
return Hooks.renderWorldBlock(dispatcher, state, pos, reader, matrixStack, vertexBuilder, checkSides, random, modelData, MinecraftForgeClient.getRenderLayer());
}
}

View File

@@ -1,21 +1,20 @@
package mods.betterfoliage.mixin;
import mods.betterfoliage.client.Hooks;
import mods.betterfoliage.Hooks;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.chunk.ChunkRender;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.client.renderer.RenderType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ChunkRender.class)
@Mixin(targets = {"net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$ChunkRender$RebuildTask"})
public class MixinChunkRenderVanilla {
private static final String rebuildChunk = "rebuildChunk(FFFLnet/minecraft/client/renderer/chunk/ChunkRenderTask;)V";
private static final String canRenderInLayer = "Lnet/minecraft/block/BlockState;canRenderInLayer(Lnet/minecraft/util/BlockRenderLayer;)Z";
private static final String compile = "Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$ChunkRender$RebuildTask;compile(FFFLnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$CompiledChunk;Lnet/minecraft/client/renderer/RegionRenderCacheBuilder;)Ljava/util/Set;";
private static final String canRenderInLayer = "Lnet/minecraft/client/renderer/RenderTypeLookup;canRenderInLayer(Lnet/minecraft/block/BlockState;Lnet/minecraft/client/renderer/RenderType;)Z";
@Redirect(method = rebuildChunk, at = @At(value = "INVOKE", target = canRenderInLayer))
boolean canRenderInLayer(BlockState state, BlockRenderLayer layer) {
@Redirect(method = compile, at = @At(value = "INVOKE", target = canRenderInLayer))
boolean canRenderInLayer(BlockState state, RenderType layer) {
return Hooks.canRenderInLayerOverride(state, layer);
}
}

View File

@@ -1,6 +1,6 @@
package mods.betterfoliage.mixin;
import mods.betterfoliage.client.Hooks;
import mods.betterfoliage.Hooks;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.WorldRenderer;
@@ -17,7 +17,7 @@ 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$MutableBlockPos;)V";
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 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";
@@ -34,7 +34,7 @@ public class MixinClientWorld {
/**
* Inject callback to get notified of client-side blockstate changes.
* Used to invalidate caches in the {@link mods.betterfoliage.client.chunk.ChunkOverlayManager}
* Used to invalidate caches in the {@link mods.betterfoliage.chunk.ChunkOverlayManager}
*/
@Redirect(method = worldNotify, at = @At(value = "INVOKE", target = rendererNotify))
void onClientBlockChanged(WorldRenderer renderer, IBlockReader world, BlockPos pos, BlockState oldState, BlockState newState, int flags) {

View File

@@ -1,29 +1,43 @@
package mods.betterfoliage.mixin;
import com.google.common.collect.Maps;
import mods.betterfoliage.BetterFoliage;
import net.minecraft.client.renderer.model.IUnbakedModel;
import net.minecraft.client.renderer.model.ModelBakery;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.profiler.IProfiler;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Mixin(ModelBakery.class)
abstract public class MixinModelBakery {
private static final String processLoading = "processLoading(Lnet/minecraft/profiler/IProfiler;)V";
private static final String stitch = "Lnet/minecraft/client/renderer/texture/AtlasTexture;stitch(Lnet/minecraft/resources/IResourceManager;Ljava/lang/Iterable;Lnet/minecraft/profiler/IProfiler;)Lnet/minecraft/client/renderer/texture/AtlasTexture$SheetData;";
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";
@Redirect(method = processLoading, at = @At(value = "INVOKE", target = stitch))
AtlasTexture.SheetData onStitchModelTextures(AtlasTexture atlas, IResourceManager manager, Iterable<ResourceLocation> idList, IProfiler profiler) {
return BetterFoliage.INSTANCE.getBlockSprites().finish(
atlas.stitch(
manager,
BetterFoliage.INSTANCE.getBlockSprites().prepare(this, manager, idList, profiler),
profiler
), profiler
);
AtlasTexture.SheetData onStitchModelTextures(AtlasTexture atlas, IResourceManager manager, Stream<ResourceLocation> idStream, IProfiler profiler, int maxMipmapLevel) {
Set<ResourceLocation> idSetIn = idStream.collect(Collectors.toSet());
Set<ResourceLocation> idSetOut = BetterFoliage.INSTANCE.getBlockSprites().prepare(this, manager, idSetIn, profiler);
AtlasTexture.SheetData sheetData = atlas.stitch(manager, idSetOut.stream(), profiler, maxMipmapLevel);
return BetterFoliage.INSTANCE.getBlockSprites().finish(sheetData, profiler);
}
@Inject(method = processLoading, at = @At(value = "INVOKE", target = profilerSection, ordinal = 4))
void onBeforeTextures(IProfiler profiler, int maxMipmapLevel, CallbackInfo ci) {
profiler.endStartSection("betterfoliage");
}
}

View File

@@ -1,6 +1,6 @@
package mods.betterfoliage.mixin;
import mods.betterfoliage.client.Hooks;
import mods.betterfoliage.Hooks;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@@ -14,10 +14,10 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(BlockUtils.class)
public class MixinOptifineBlockUtils {
private static final String shouldSideBeRenderedCached = "shouldSideBeRenderedCached(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;Lnet/optifine/render/RenderEnv;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;)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;";
@SuppressWarnings("UnresolvedMixinReference")
@Redirect(method = shouldSideBeRenderedCached, at = @At(value = "INVOKE", target = getVoxelShape, ordinal = 1))
@Redirect(method = shouldSideBeRenderedCached, at = @At(value = "INVOKE", target = getFaceOcclusionShape, ordinal = 1))
private static VoxelShape getVoxelShapeOverride(BlockState state, IBlockReader reader, BlockPos pos, Direction dir) {
return Hooks.getVoxelShapeOverride(state, reader, pos, dir);
}

View File

@@ -1,24 +1,23 @@
package mods.betterfoliage.mixin;
import mods.betterfoliage.client.Hooks;
import mods.betterfoliage.Hooks;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.chunk.ChunkRender;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.client.renderer.RenderType;
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;
import org.spongepowered.asm.mixin.injection.Slice;
@Mixin(ChunkRender.class)
@Mixin(targets = {"net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$ChunkRender$RebuildTask"})
public class MixinOptifineChunkRender {
private static final String rebuildChunk = "rebuildChunk(FFFLnet/minecraft/client/renderer/chunk/ChunkRenderTask;)V";
private static final String compile = "Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$ChunkRender$RebuildTask;compile(FFFLnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$CompiledChunk;Lnet/minecraft/client/renderer/RegionRenderCacheBuilder;)Ljava/util/Set;";
private static final String invokeReflector = "Lnet/optifine/reflect/Reflector;callBoolean(Ljava/lang/Object;Lnet/optifine/reflect/ReflectorMethod;[Ljava/lang/Object;)Z";
private static final String forgeBlockCanRender = "Lnet/minecraft/client/renderer/chunk/ChunkRender;FORGE_BLOCK_CAN_RENDER_IN_LAYER:Z";
@Redirect(
method = rebuildChunk,
method = compile,
at = @At(value = "INVOKE", target = invokeReflector),
slice = @Slice(
from = @At(value = "FIELD", target = forgeBlockCanRender)
@@ -26,6 +25,6 @@ public class MixinOptifineChunkRender {
)
@SuppressWarnings("UnresolvedMixinReference")
boolean canRenderInLayer(Object state, @Coerce Object reflector, Object[] layer) {
return Hooks.canRenderInLayerOverride((BlockState) state, (BlockRenderLayer) layer[0]);
return Hooks.canRenderInLayerOverride((BlockState) state, (RenderType) layer[0]);
}
}

View File

@@ -11,23 +11,23 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Mixin(ParticleManager.class)
public class MixinParticleManager {
private static final String reload = "reload(Lnet/minecraft/resources/IFutureReloadListener$IStage;Lnet/minecraft/resources/IResourceManager;Lnet/minecraft/profiler/IProfiler;Lnet/minecraft/profiler/IProfiler;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;";
private static final String stitch = "Lnet/minecraft/client/renderer/texture/AtlasTexture;stitch(Lnet/minecraft/resources/IResourceManager;Ljava/lang/Iterable;Lnet/minecraft/profiler/IProfiler;)Lnet/minecraft/client/renderer/texture/AtlasTexture$SheetData;";
private static final String stitch = "Lnet/minecraft/client/renderer/texture/AtlasTexture;stitch(Lnet/minecraft/resources/IResourceManager;Ljava/util/stream/Stream;Lnet/minecraft/profiler/IProfiler;I)Lnet/minecraft/client/renderer/texture/AtlasTexture$SheetData;";
// ewww :S
@SuppressWarnings("UnresolvedMixinReference")
@Redirect(method = "*", at = @At(value = "INVOKE", target = stitch))
AtlasTexture.SheetData onStitchModelTextures(AtlasTexture atlas, IResourceManager manager, Iterable<ResourceLocation> idList, IProfiler profiler) {
return BetterFoliage.INSTANCE.getParticleSprites().finish(
atlas.stitch(
manager,
BetterFoliage.INSTANCE.getParticleSprites().prepare(this, manager, idList, profiler),
profiler
), profiler
);
AtlasTexture.SheetData onStitchModelTextures(AtlasTexture atlas, IResourceManager manager, Stream<ResourceLocation> idStream, IProfiler profiler, int maxMipmapLevel) {
Set<ResourceLocation> idSetIn = idStream.collect(Collectors.toSet());
Set<ResourceLocation> idSetOut = BetterFoliage.INSTANCE.getParticleSprites().prepare(this, manager, idSetIn, profiler);
AtlasTexture.SheetData sheetData = atlas.stitch(manager, idSetOut.stream(), profiler, maxMipmapLevel);
return BetterFoliage.INSTANCE.getParticleSprites().finish(sheetData, profiler);
}
}

View File

@@ -1,11 +1,11 @@
package mods.betterfoliage.mixin;
import mods.betterfoliage.client.integration.ShadersModIntegration;
import mods.betterfoliage.integration.ShadersModIntegration;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IEnviromentBlockReader;
import net.minecraft.world.ILightReader;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@@ -18,7 +18,7 @@ public class MixinShadersBlockModelRenderer {
@SuppressWarnings("UnresolvedMixinReference")
@ModifyArg(method = renderModel, at = @At(value = "INVOKE", target = pushEntity), remap = false)
BlockState overrideBlockState(BlockState state, BlockPos pos, IEnviromentBlockReader world, BufferBuilder buffer) {
BlockState overrideBlockState(BlockState state, BlockPos pos, ILightReader world, BufferBuilder buffer) {
return ShadersModIntegration.getBlockStateOverride(state, world, pos);
}
}

View File

@@ -1,12 +1,9 @@
package mods.betterfoliage
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.render.RisingSoulTextures
import mods.octarinecore.client.gui.textComponent
import mods.betterfoliage.util.textComponent
import mods.octarinecore.client.resource.AsnycSpriteProviderManager
import mods.octarinecore.client.resource.AsyncSpriteProvider
import mods.octarinecore.client.resource.Atlas
import mods.octarinecore.client.resource.GeneratedBlockTexturePack
import mods.betterfoliage.resource.generated.GeneratedBlockTexturePack
import mods.betterfoliage.util.Atlas
import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
import net.minecraft.client.particle.ParticleManager

View File

@@ -1,24 +1,12 @@
package mods.betterfoliage
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.config.Config
import mods.octarinecore.client.resource.AsnycSpriteProviderManager
import mods.octarinecore.client.resource.GeneratedBlockTexturePack
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import net.alexwells.kottle.FMLKotlinModLoadingContext
import net.minecraft.client.Minecraft
import net.minecraft.client.particle.ParticleManager
import net.minecraft.client.renderer.model.ModelBakery
import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.common.Mod
import net.minecraftforge.fml.config.ModConfig
import org.apache.logging.log4j.Level.DEBUG
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.simple.SimpleLogger
import org.apache.logging.log4j.util.PropertiesUtil
import java.io.File
import java.io.PrintStream
import java.util.*
@Mod(BetterFoliageMod.MOD_ID)
object BetterFoliageMod {

View File

@@ -1,30 +1,36 @@
package mods.betterfoliage.client
package mods.betterfoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.chunk.ChunkOverlayManager
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.integration.*
import mods.betterfoliage.client.render.*
import mods.betterfoliage.client.texture.AsyncGrassDiscovery
import mods.betterfoliage.client.texture.AsyncLeafDiscovery
import mods.betterfoliage.client.texture.LeafParticleRegistry
import mods.octarinecore.client.gui.textComponent
import mods.octarinecore.client.render.RenderDecorator
import mods.octarinecore.client.resource.IConfigChangeListener
import mods.betterfoliage.chunk.ChunkOverlayManager
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.integration.*
import mods.betterfoliage.render.*
import mods.betterfoliage.render.block.vanillaold.AsyncCactusDiscovery
import mods.betterfoliage.render.block.vanillaold.AsyncLogDiscovery
import mods.betterfoliage.render.block.vanillaold.RenderAlgae
import mods.betterfoliage.render.block.vanillaold.RenderCactus
import mods.betterfoliage.render.block.vanillaold.RenderConnectedGrass
import mods.betterfoliage.render.block.vanillaold.RenderConnectedGrassLog
import mods.betterfoliage.render.block.vanillaold.RenderCoral
import mods.betterfoliage.render.block.vanillaold.RenderGrass
import mods.betterfoliage.render.block.vanillaold.RenderLeaves
import mods.betterfoliage.render.block.vanillaold.RenderLilypad
import mods.betterfoliage.render.block.vanillaold.RenderLog
import mods.betterfoliage.render.block.vanillaold.RenderMycelium
import mods.betterfoliage.render.block.vanillaold.RenderNetherrack
import mods.betterfoliage.render.block.vanillaold.RenderReeds
import mods.betterfoliage.texture.AsyncGrassDiscovery
import mods.betterfoliage.texture.AsyncLeafDiscovery
import mods.betterfoliage.texture.LeafParticleRegistry
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.resource.IConfigChangeListener
import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
import net.minecraft.util.math.BlockPos
import net.minecraft.util.text.TextFormatting
import net.minecraft.util.text.TranslationTextComponent
import net.minecraftforge.registries.ForgeRegistries
import org.apache.logging.log4j.Level
/**
* Object responsible for initializing (and holding a reference to) all the infrastructure of the mod
* except for the call hooks.
*/
object Client {
var renderers= emptyList<RenderDecorator>()
var renderers = emptyList<RenderDecorator>()
var configListeners = emptyList<IConfigChangeListener>()
val suppressRenderErrors = mutableSetOf<BlockState>()

View File

@@ -1,9 +1,9 @@
package mods.octarinecore
import mods.octarinecore.metaprog.ClassRef
import mods.octarinecore.metaprog.ClassRef.Companion.void
import mods.octarinecore.metaprog.FieldRef
import mods.octarinecore.metaprog.MethodRef
import mods.betterfoliage.util.ClassRef
import mods.betterfoliage.util.ClassRef.Companion.void
import mods.betterfoliage.util.FieldRef
import mods.betterfoliage.util.MethodRef
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.client.renderer.BlockRendererDispatcher
@@ -11,11 +11,10 @@ import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.client.renderer.chunk.ChunkRenderCache
import net.minecraft.client.renderer.model.BakedQuad
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.BlockRenderLayer
import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
import net.minecraft.world.IEnviromentBlockReader
import net.minecraft.world.ILightReader
import java.util.*
// Java
@@ -26,10 +25,9 @@ val Random = ClassRef<Random>("java.util.Random")
// Minecraft
val IBlockReader = ClassRef<IBlockReader>("net.minecraft.world.IBlockReader")
val IEnvironmentBlockReader = ClassRef<IEnviromentBlockReader>("net.minecraft.world.IEnviromentBlockReader")
val ILightReader = ClassRef<ILightReader>("net.minecraft.world.ILightReader")
val BlockState = ClassRef<BlockState>("net.minecraft.block.BlockState")
val BlockPos = ClassRef<BlockPos>("net.minecraft.util.math.BlockPos")
val BlockRenderLayer = ClassRef<BlockRenderLayer>("net.minecraft.util.BlockRenderLayer")
val Block = ClassRef<Block>("net.minecraft.block.Block")
val TextureAtlasSprite = ClassRef<TextureAtlasSprite>("net.minecraft.client.renderer.texture.TextureAtlasSprite")
@@ -55,7 +53,7 @@ object RenderEnv : ClassRef<Any>("net.optifine.render.RenderEnv") {
// Optifine custom colors
val IColorizer = ClassRef<Any>("net.optifine.CustomColors\$IColorizer")
object CustomColors : ClassRef<Any>("net.optifine.CustomColors") {
val getColorMultiplier = MethodRef(this, "getColorMultiplier", int, BakedQuad, BlockState, IEnvironmentBlockReader, BlockPos, RenderEnv)
val getColorMultiplier = MethodRef(this, "getColorMultiplier", int, BakedQuad, BlockState, ILightReader, BlockPos, RenderEnv)
}
// Optifine shaders

View File

@@ -1,33 +1,42 @@
@file:JvmName("Hooks")
package mods.betterfoliage.client
package mods.betterfoliage
import mods.betterfoliage.client.chunk.ChunkOverlayManager
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.render.*
import mods.octarinecore.ThreadLocalDelegate
import mods.octarinecore.client.render.*
import mods.octarinecore.client.render.lighting.DefaultLightingCtx
import mods.octarinecore.common.plus
import com.mojang.blaze3d.matrix.MatrixStack
import com.mojang.blaze3d.vertex.IVertexBuilder
import mods.betterfoliage.chunk.ChunkOverlayManager
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.EntityFallingLeavesFX
import mods.betterfoliage.render.EntityRisingSoulFX
import mods.betterfoliage.render.block.vanillaold.LogRegistry
import mods.betterfoliage.render.canRenderInLayer
import mods.betterfoliage.render.down1
import mods.betterfoliage.render.isCutout
import mods.betterfoliage.render.up1
import mods.betterfoliage.render.old.BasicBlockCtx
import mods.betterfoliage.render.old.CachedBlockCtx
import mods.betterfoliage.render.old.NonNullWorld
import mods.betterfoliage.render.old.RenderCtx
import mods.betterfoliage.render.lighting.DefaultLightingCtx
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.util.ThreadLocalDelegate
import mods.betterfoliage.util.plus
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.BlockRendererDispatcher
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.world.ClientWorld
import net.minecraft.util.BlockRenderLayer
import net.minecraft.util.BlockRenderLayer.CUTOUT
import net.minecraft.util.BlockRenderLayer.CUTOUT_MIPPED
import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.shapes.VoxelShape
import net.minecraft.util.math.shapes.VoxelShapes
import net.minecraft.world.IBlockReader
import net.minecraft.world.IEnviromentBlockReader
import net.minecraft.world.ILightReader
import net.minecraft.world.World
import net.minecraftforge.client.model.data.IModelData
import java.util.*
import java.util.Random
fun getAmbientOcclusionLightValueOverride(original: Float, state: BlockState): Float {
if (Config.enabled && Config.roundLogs.enabled && BlockConfig.logBlocks.matchesClass(state.block)) return Config.roundLogs.dimming.toFloat();
@@ -62,27 +71,34 @@ fun onRandomDisplayTick(block: Block, state: BlockState, world: World, pos: Bloc
fun getVoxelShapeOverride(state: BlockState, reader: IBlockReader, pos: BlockPos, dir: Direction): VoxelShape {
if (LogRegistry[state, reader, pos] != null) return VoxelShapes.empty()
return state.func_215702_a(reader, pos, dir)
return state.getFaceOcclusionShape(reader, pos, dir)
}
val lightingCtx by ThreadLocalDelegate { DefaultLightingCtx(BasicBlockCtx(NonNullWorld, BlockPos.ZERO)) }
fun renderWorldBlock(dispatcher: BlockRendererDispatcher,
state: BlockState,
pos: BlockPos,
reader: IEnviromentBlockReader,
buffer: BufferBuilder,
reader: ILightReader,
matrixStack: MatrixStack,
buffer: IVertexBuilder,
checkSides: Boolean,
random: Random,
modelData: IModelData,
layer: BlockRenderLayer
layer: RenderType
): Boolean {
// build context
val blockCtx = CachedBlockCtx(reader, pos)
val renderCtx = RenderCtx(dispatcher, buffer, layer, random, modelData)
val renderCtx = RenderCtx(dispatcher, buffer, matrixStack, layer, checkSides, random, modelData)
lightingCtx.reset(blockCtx)
val combinedCtx = CombinedContext(blockCtx, renderCtx, lightingCtx)
combinedCtx.render()
return combinedCtx.hasRendered
// loop render decorators
val doBaseRender = state.canRenderInLayer(layer) || (layer == targetCutoutLayer && state.canRenderInLayer(otherCutoutLayer))
val doBaseRender = state.canRenderInLayer(layer) || (layer == targetCutoutLayer && state.canRenderInLayer(
otherCutoutLayer
))
Client.renderers.forEach { renderer ->
if (renderer.isEligible(combinedCtx)) {
// render on the block's default layer
@@ -103,10 +119,10 @@ fun renderWorldBlock(dispatcher: BlockRendererDispatcher,
return combinedCtx.hasRendered
}
fun canRenderInLayerOverride(state: BlockState, layer: BlockRenderLayer) = state.canRenderInLayer(layer) || layer == targetCutoutLayer
fun canRenderInLayerOverride(state: BlockState, layer: RenderType) = state.canRenderInLayer(layer) || layer == targetCutoutLayer
fun canRenderInLayerOverrideOptifine(state: BlockState, optifineReflector: Any?, layerArray: Array<Any>) =
canRenderInLayerOverride(state, layerArray[0] as BlockRenderLayer)
canRenderInLayerOverride(state, layerArray[0] as RenderType)
val targetCutoutLayer: BlockRenderLayer get() = if (Minecraft.getInstance().gameSettings.mipmapLevels > 0) CUTOUT_MIPPED else CUTOUT
val otherCutoutLayer: BlockRenderLayer get() = if (Minecraft.getInstance().gameSettings.mipmapLevels > 0) CUTOUT else CUTOUT_MIPPED
val targetCutoutLayer: RenderType get() = if (Minecraft.getInstance().gameSettings.mipmapLevels > 0) RenderType.getCutoutMipped() else RenderType.getCutout()
val otherCutoutLayer: RenderType get() = if (Minecraft.getInstance().gameSettings.mipmapLevels > 0) RenderType.getCutout() else RenderType.getCutoutMipped()

View File

@@ -1,14 +1,14 @@
package mods.betterfoliage.client.chunk
package mods.betterfoliage.chunk
import mods.octarinecore.ChunkCacheOF
import mods.octarinecore.client.render.BlockCtx
import mods.octarinecore.metaprog.get
import mods.octarinecore.metaprog.isInstance
import mods.betterfoliage.render.old.BlockCtx
import mods.betterfoliage.util.get
import mods.betterfoliage.util.isInstance
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.IEnviromentBlockReader
import net.minecraft.world.ILightReader
import net.minecraft.world.IWorldReader
import net.minecraft.world.dimension.DimensionType
import net.minecraftforge.common.MinecraftForge
@@ -24,7 +24,7 @@ import kotlin.collections.mutableListOf
import kotlin.collections.mutableMapOf
import kotlin.collections.set
val IEnviromentBlockReader.dimType: DimensionType get() = when {
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
@@ -36,7 +36,7 @@ val IEnviromentBlockReader.dimType: DimensionType get() = when {
*/
interface ChunkOverlayLayer<T> {
fun calculate(ctx: BlockCtx): T
fun onBlockUpdate(world: IEnviromentBlockReader, pos: BlockPos)
fun onBlockUpdate(world: ILightReader, pos: BlockPos)
}
/**

View File

@@ -1,9 +1,7 @@
package mods.betterfoliage.client.config
package mods.betterfoliage.config
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.integration.ShadersModIntegration
import mods.octarinecore.common.config.*
import net.minecraft.util.ResourceLocation
import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.config.ModConfig

View File

@@ -1,9 +1,9 @@
@file:JvmName("DelegatingConfigKt")
package mods.octarinecore.common.config
package mods.betterfoliage.config
import mods.octarinecore.metaprog.reflectDelegates
import mods.octarinecore.metaprog.reflectNestedObjects
import mods.betterfoliage.util.reflectDelegates
import mods.betterfoliage.util.reflectNestedObjects
import net.minecraftforge.common.ForgeConfigSpec
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

View File

@@ -1,8 +1,8 @@
package mods.octarinecore.common.config
package mods.betterfoliage.config
import mods.octarinecore.client.resource.getLines
import mods.octarinecore.client.resource.resourceManager
import mods.octarinecore.metaprog.getJavaClass
import mods.betterfoliage.util.getLines
import mods.betterfoliage.util.resourceManager
import mods.betterfoliage.util.getJavaClass
import net.minecraft.block.Block
import net.minecraft.util.ResourceLocation
import org.apache.logging.log4j.Logger

View File

@@ -1,20 +1,27 @@
package mods.betterfoliage.client.integration
package mods.betterfoliage.integration
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.render.AsyncLogDiscovery
import mods.betterfoliage.client.render.column.ColumnTextureInfo
import mods.betterfoliage.client.render.column.SimpleColumnInfo
import mods.betterfoliage.client.resource.Identifier
import mods.betterfoliage.client.texture.LeafInfo
import mods.betterfoliage.client.texture.defaultRegisterLeaf
import mods.octarinecore.HasLogger
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.render.block.vanillaold.AsyncLogDiscovery
import mods.betterfoliage.render.column.ColumnTextureInfo
import mods.betterfoliage.render.column.SimpleColumnInfo
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.resource.discovery.ModelDiscovery
import mods.betterfoliage.resource.discovery.ModelDiscoveryContext
import mods.betterfoliage.resource.discovery.ModelRenderRegistry
import mods.betterfoliage.texture.LeafInfo
import mods.betterfoliage.texture.defaultRegisterLeaf
import mods.betterfoliage.util.ClassRef
import mods.octarinecore.Map
import mods.octarinecore.ResourceLocation
import mods.octarinecore.String
import mods.octarinecore.client.resource.*
import mods.octarinecore.metaprog.*
import mods.octarinecore.metaprog.ClassRef.Companion.boolean
import mods.betterfoliage.util.ClassRef.Companion.boolean
import mods.betterfoliage.util.FieldRef
import mods.betterfoliage.util.HasLogger
import mods.betterfoliage.util.MethodRef
import mods.betterfoliage.util.allAvailable
import mods.betterfoliage.util.get
import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.model.ModelBakery

View File

@@ -1,14 +1,14 @@
package mods.betterfoliage.client.integration
package mods.betterfoliage.integration
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.util.ThreadLocalDelegate
import mods.octarinecore.*
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.metaprog.allAvailable
import mods.octarinecore.metaprog.reflectField
import mods.betterfoliage.util.allAvailable
import mods.betterfoliage.util.reflectField
import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.model.BakedQuad
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
import net.minecraft.util.Direction.UP
import net.minecraft.util.math.BlockPos
import org.apache.logging.log4j.Level
@@ -26,7 +26,7 @@ object OptifineCustomColors {
}
val renderEnv by ThreadLocalDelegate { OptifineRenderEnv() }
val fakeQuad = BakedQuad(IntArray(0), 1, UP, null, true, DefaultVertexFormats.BLOCK)
val fakeQuad = BakedQuad(IntArray(0), 1, UP, null, true)
fun getBlockColor(ctx: CombinedContext): Int {
val ofColor = if (isColorAvailable && Minecraft.getInstance().gameSettings.reflectField<Boolean>("ofCustomColors") == true) {

View File

@@ -1,23 +1,25 @@
package mods.betterfoliage.client.integration
package mods.betterfoliage.integration
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.client.render.LogRegistry
import mods.betterfoliage.client.render.column.ColumnTextureInfo
import mods.betterfoliage.client.render.column.SimpleColumnInfo
import mods.betterfoliage.client.resource.Sprite
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.Quad
import mods.octarinecore.client.render.lighting.QuadIconResolver
import mods.betterfoliage.render.column.ColumnTextureInfo
import mods.betterfoliage.render.column.SimpleColumnInfo
import mods.betterfoliage.resource.Sprite
import mods.betterfoliage.render.old.Quad
import mods.betterfoliage.render.lighting.QuadIconResolver
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.resource.discovery.ModelDiscovery
import mods.betterfoliage.resource.discovery.ModelDiscoveryContext
import mods.betterfoliage.resource.discovery.derivesFrom
import mods.octarinecore.client.resource.*
import mods.octarinecore.common.rotate
import mods.octarinecore.metaprog.ClassRef
import mods.octarinecore.metaprog.allAvailable
import mods.betterfoliage.util.rotate
import mods.betterfoliage.util.ClassRef
import mods.betterfoliage.util.allAvailable
import net.minecraft.client.renderer.model.BlockModel
import net.minecraft.client.renderer.texture.MissingTextureSprite
import net.minecraft.util.Direction
import net.minecraft.util.Direction.*
import net.minecraft.util.ResourceLocation
import net.minecraftforge.fml.ModList
import org.apache.logging.log4j.Level
import java.util.concurrent.CompletableFuture
@@ -86,8 +88,8 @@ object IC2LogDiscovery : ModelDiscovery<ColumnTextureInfo>() {
"plain_z" -> Axis.Z
else -> null
}
val textureNames = listOf("end", "side").map { blockLoc.first.resolveTextureName(it) }
if (textureNames.any { it == "missingno" }) return null
val textureNames = listOf("end", "side").map { blockLoc.first.resolveTextureName(it).textureLocation }
if (textureNames.any { it == MissingTextureSprite.getLocation() }) return null
log("IC2LogSupport: block state ${ctx.state.toString()}")
log("IC2LogSupport: axis=$axis, end=${textureNames[0]}, side=${textureNames[1]}")
val endSprite = atlas.sprite(textureNames[0])
@@ -105,9 +107,9 @@ object IC2LogDiscovery : ModelDiscovery<ColumnTextureInfo>() {
"dry_east", "wet_east" -> EAST
else -> null
}
val textureNames = listOf("up", "down", "north", "south").map { blockLoc.first.resolveTextureName(it) }
if (textureNames.any { it == "missingno" }) return null
log("IC2LogSupport: block state ${ctx.state.toString()}")
val textureNames = listOf("up", "down", "north", "south").map { blockLoc.first.resolveTextureName(it).textureLocation }
if (textureNames.any { it == MissingTextureSprite.getLocation() }) return null
log("IC2LogSupport: block state ${ctx.state}")
log("IC2LogSupport: spotDir=$spotDir, up=${textureNames[0]}, down=${textureNames[1]}, side=${textureNames[2]}, spot=${textureNames[3]}")
val upSprite = atlas.sprite(textureNames[0])
val downSprite = atlas.sprite(textureNames[1])

View File

@@ -1,18 +1,18 @@
package mods.betterfoliage.client.integration
package mods.betterfoliage.integration
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.texture.LeafRegistry
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.texture.LeafRegistry
import mods.octarinecore.*
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.metaprog.allAvailable
import mods.octarinecore.metaprog.get
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.util.allAvailable
import mods.betterfoliage.util.get
import net.minecraft.block.BlockRenderType
import net.minecraft.block.BlockRenderType.MODEL
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IEnviromentBlockReader
import net.minecraft.world.ILightReader
import org.apache.logging.log4j.Level.INFO
/**
@@ -29,7 +29,7 @@ object ShadersModIntegration {
* Called from transformed ShadersMod code.
* @see mods.betterfoliage.loader.BetterFoliageTransformer
*/
@JvmStatic fun getBlockStateOverride(state: BlockState, world: IEnviromentBlockReader, pos: BlockPos): BlockState {
@JvmStatic fun getBlockStateOverride(state: BlockState, world: ILightReader, pos: BlockPos): BlockState {
if (LeafRegistry[state, world, pos] != null) return defaultLeaves
if (BlockConfig.crops.matchesClass(state.block)) return defaultGrass
return state

View File

@@ -1,14 +1,14 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.texture.LeafParticleRegistry
import mods.betterfoliage.client.texture.LeafRegistry
import mods.octarinecore.PI2
import mods.octarinecore.client.render.AbstractEntityFX
import mods.octarinecore.client.render.lighting.HSB
import mods.octarinecore.common.Double3
import mods.octarinecore.minmax
import mods.octarinecore.random
import mods.betterfoliage.config.Config
import mods.betterfoliage.texture.LeafParticleRegistry
import mods.betterfoliage.texture.LeafRegistry
import mods.betterfoliage.render.old.AbstractEntityFX
import mods.betterfoliage.render.lighting.HSB
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.PI2
import mods.betterfoliage.util.minmax
import mods.betterfoliage.util.randomD
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.util.math.BlockPos
@@ -18,7 +18,6 @@ import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.TickEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import org.lwjgl.opengl.GL11
import java.util.*
import kotlin.math.abs
import kotlin.math.cos
@@ -42,7 +41,7 @@ class EntityFallingLeavesFX(
var wasCollided = false
init {
maxAge = MathHelper.floor(random(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
maxAge = MathHelper.floor(randomD(0.6, 1.0) * Config.fallingLeaves.lifetime * 20.0)
motionY = -Config.fallingLeaves.speed
particleScale = Config.fallingLeaves.size.toFloat() * 0.1f
@@ -68,7 +67,7 @@ class EntityFallingLeavesFX(
if (onGround || wasCollided) {
velocity.setTo(0.0, 0.0, 0.0)
if (!wasCollided) {
age = Math.max(age, maxAge - 20)
age = age.coerceAtLeast(maxAge - 20)
wasCollided = true
}
} else {
@@ -80,8 +79,8 @@ class EntityFallingLeavesFX(
}
override fun render(worldRenderer: BufferBuilder, partialTickTime: Float) {
if (Config.fallingLeaves.opacityHack) GL11.glDepthMask(true)
renderParticleQuad(worldRenderer, partialTickTime, rotation = particleRot, isMirrored = isMirrored)
// if (Config.fallingLeaves.opacityHack) GL11.glDepthMask(true)
// renderParticleQuad(worldRenderer, partialTickTime, rotation = particleRot, isMirrored = isMirrored)
}
fun calculateParticleColor(textureAvgColor: Int, blockColor: Int) {

View File

@@ -1,21 +1,17 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.render.AbstractEntityFX
import mods.octarinecore.client.resource.Atlas
import mods.octarinecore.client.resource.ResourceHandler
import mods.octarinecore.common.Double3
import mods.octarinecore.forEachPairIndexed
import mods.betterfoliage.config.Config
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.render.old.AbstractEntityFX
import mods.betterfoliage.resource.ResourceHandler
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.Double3
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper
import net.minecraft.world.World
import org.apache.logging.log4j.Level.DEBUG
import java.util.*
class EntityRisingSoulFX(world: World, pos: BlockPos) :
@@ -44,26 +40,26 @@ AbstractEntityFX(world, pos.x.toDouble() + 0.5, pos.y.toDouble() + 1.0, pos.z.to
}
override fun render(worldRenderer: BufferBuilder, partialTickTime: Float) {
var alpha = Config.risingSoul.opacity.toFloat()
if (age > maxAge - 40) alpha *= (maxAge - age) / 40.0f
renderParticleQuad(worldRenderer, partialTickTime,
size = Config.risingSoul.headSize * 0.25,
alpha = alpha
)
var scale = Config.risingSoul.trailSize * 0.25
particleTrail.forEachPairIndexed { idx, current, previous ->
scale *= Config.risingSoul.sizeDecay
alpha *= Config.risingSoul.opacityDecay.toFloat()
if (idx % Config.risingSoul.trailDensity == 0) renderParticleQuad(worldRenderer, partialTickTime,
currentPos = current,
prevPos = previous,
size = scale,
alpha = alpha,
icon = RisingSoulTextures.trackIcon
)
}
// var alpha = Config.risingSoul.opacity.toFloat()
// if (age > maxAge - 40) alpha *= (maxAge - age) / 40.0f
//
// renderParticleQuad(worldRenderer, partialTickTime,
// size = Config.risingSoul.headSize * 0.25,
// alpha = alpha
// )
//
// var scale = Config.risingSoul.trailSize * 0.25
// particleTrail.forEachPairIndexed { idx, current, previous ->
// scale *= Config.risingSoul.sizeDecay
// alpha *= Config.risingSoul.opacityDecay.toFloat()
// if (idx % Config.risingSoul.trailDensity == 0) renderParticleQuad(worldRenderer, partialTickTime,
// currentPos = current,
// prevPos = previous,
// size = scale,
// alpha = alpha,
// icon = RisingSoulTextures.trackIcon
// )
// }
}
}

View File

@@ -1,11 +1,22 @@
@file:JvmName("ModelColumn")
package mods.betterfoliage.client.render
package mods.betterfoliage.render
import mods.betterfoliage.client.config.Config
import mods.octarinecore.client.render.*
import mods.octarinecore.client.render.lighting.*
import mods.octarinecore.common.Double3
import mods.octarinecore.exchange
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.lighting.CornerSingleFallback
import mods.betterfoliage.render.lighting.EdgeInterpolateFallback
import mods.betterfoliage.render.lighting.FaceCenter
import mods.betterfoliage.render.lighting.FaceFlat
import mods.betterfoliage.render.lighting.cornerAo
import mods.betterfoliage.render.lighting.cornerFlat
import mods.betterfoliage.render.lighting.cornerInterpolate
import mods.betterfoliage.render.lighting.faceOrientedAuto
import mods.betterfoliage.render.lighting.faceOrientedInterpolate
import mods.betterfoliage.render.old.Model
import mods.betterfoliage.render.old.Quad
import mods.betterfoliage.render.old.UV
import mods.betterfoliage.render.old.Vertex
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.exchange
import net.minecraft.util.Direction.*
/** Weight of the same-side AO values on the outer edges of the 45deg chamfered column faces. */
@@ -37,7 +48,8 @@ fun Model.columnSide(radius: Double, yBottom: Double, yTop: Double, transform: (
verticalRectangle(x1 = 0.5 - halfRadius, z1 = 0.5 - halfRadius, x2 = 0.5, z2 = 0.5 - radius, yBottom = yBottom, yTop = yTop)
.clampUV(maxU = radius - 0.5)
.setAoShader(
faceOrientedAuto(overrideFace = EAST, corner = cornerInterpolate(Axis.Y, chamferAffinity, Config.roundLogs.dimming.toFloat())))
faceOrientedAuto(overrideFace = EAST, corner = cornerInterpolate(Axis.Y, chamferAffinity, Config.roundLogs.dimming.toFloat()))
)
.setAoShader(
faceOrientedAuto(overrideFace = EAST, corner = cornerInterpolate(Axis.Y, 0.5f, Config.roundLogs.dimming.toFloat())),
predicate = { v, vi -> vi == 0 || vi == 3}
@@ -79,7 +91,7 @@ fun Model.columnSideSquare(yBottom: Double, yTop: Double, transform: (Quad) -> Q
* @param[radius] the chamfer radius
* @param[transform] transformation to apply to the model
*/
fun Model.columnLid(radius: Double, transform: (Quad)->Quad = { it }) {
fun Model.columnLid(radius: Double, transform: (Quad)-> Quad = { it }) {
val v1 = Vertex(Double3(0.0, 0.5, 0.0), UV(0.0, 0.0))
val v2 = Vertex(Double3(0.0, 0.5, 0.5), UV(0.0, 0.5))
val v3 = Vertex(Double3(0.5 - radius, 0.5, 0.5), UV(0.5 - radius, 0.5))

View File

@@ -1,19 +1,27 @@
@file:JvmName("Utils")
package mods.betterfoliage.client.render
import mods.octarinecore.PI2
import mods.octarinecore.client.render.Model
import mods.octarinecore.client.render.lighting.PostProcessLambda
import mods.octarinecore.client.render.Quad
import mods.octarinecore.common.Double3
import mods.octarinecore.common.Int3
import mods.octarinecore.common.Rotation
import mods.octarinecore.common.times
package mods.betterfoliage.render
import mods.betterfoliage.render.lighting.PostProcessLambda
import mods.betterfoliage.render.old.Model
import mods.betterfoliage.render.old.Quad
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.PI2
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.util.times
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.block.material.Material
import net.minecraft.util.BlockRenderLayer
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.RenderTypeLookup
import net.minecraft.util.Direction
import net.minecraft.util.Direction.*
import net.minecraft.util.Direction.DOWN
import net.minecraft.util.Direction.EAST
import net.minecraft.util.Direction.NORTH
import net.minecraft.util.Direction.SOUTH
import net.minecraft.util.Direction.UP
import net.minecraft.util.Direction.WEST
import kotlin.math.cos
import kotlin.math.sin
@@ -30,10 +38,13 @@ val greywash: PostProcessLambda = { _, _, _, _, _ -> setGrey(1.0f) }
val BlockState.isSnow: Boolean get() = material.let { it == Material.SNOW }
fun Quad.toCross(rotAxis: Direction, trans: (Quad)->Quad) =
val DIRT_BLOCKS = listOf(Blocks.DIRT, Blocks.COARSE_DIRT)
fun Quad.toCross(rotAxis: Direction, trans: (Quad) -> Quad) =
(0..3).map { rotIdx ->
trans(rotate(Rotation.rot90[rotAxis.ordinal] * rotIdx).mirrorUV(rotIdx > 1, false))
}
fun Quad.toCross(rotAxis: Direction) = toCross(rotAxis) { it }
fun xzDisk(modelIdx: Int) = (PI2 * modelIdx / 64.0).let { Double3(cos(it), 0.0, sin(it)) }
@@ -47,7 +58,7 @@ val rotationFromUp = arrayOf(
Rotation.rot90[NORTH.ordinal]
)
fun Model.mix(first: Model, second: Model, predicate: (Int)->Boolean) {
fun Model.mix(first: Model, second: Model, predicate: (Int) -> Boolean) {
first.quads.forEachIndexed { qi, quad ->
val otherQuad = second.quads[qi]
Quad(
@@ -59,7 +70,9 @@ fun Model.mix(first: Model, second: Model, predicate: (Int)->Boolean) {
}
}
val BlockRenderLayer.isCutout: Boolean get() = (this == BlockRenderLayer.CUTOUT) || (this == BlockRenderLayer.CUTOUT_MIPPED)
val RenderType.isCutout: Boolean get() = (this == RenderType.getCutout()) || (this == RenderType.getCutoutMipped())
fun BlockState.canRenderInLayer(layer: BlockRenderLayer) = this.block.canRenderInLayer(this, layer)
fun BlockState.canRenderInCutout() = this.block.canRenderInLayer(this, BlockRenderLayer.CUTOUT) || this.block.canRenderInLayer(this, BlockRenderLayer.CUTOUT_MIPPED)
fun BlockState.canRenderInLayer(layer: RenderType) = RenderTypeLookup.canRenderInLayer(this, layer)
fun BlockState.canRenderInCutout() =
RenderTypeLookup.canRenderInLayer(this, RenderType.getCutout()) ||
RenderTypeLookup.canRenderInLayer(this, RenderType.getCutoutMipped())

View File

@@ -1,17 +1,16 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.integration.ShadersModIntegration
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.RenderDecorator
import mods.betterfoliage.config.Config
import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.render.DIRT_BLOCKS
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.up1
import mods.betterfoliage.render.up2
import mods.betterfoliage.render.old.RenderDecorator
import net.minecraft.block.material.Material
import net.minecraft.tags.BlockTags
import net.minecraft.util.ResourceLocation
import net.minecraft.world.biome.Biome
import org.apache.logging.log4j.Level.DEBUG
class RenderAlgae : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bus) {
@@ -24,9 +23,10 @@ class RenderAlgae : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bu
Config.enabled && Config.algae.enabled &&
ctx.state(up2).material == Material.WATER &&
ctx.state(up1).material == Material.WATER &&
BlockTags.DIRT_LIKE.contains(ctx.state.block) &&
ctx.biome.category.let { it == Biome.Category.OCEAN || it == Biome.Category.BEACH || it == Biome.Category.RIVER } &&
noise[ctx.pos] < Config.algae.population
DIRT_BLOCKS.contains(ctx.state.block) &&
ctx.biome?.category
.let { it == Biome.Category.OCEAN || it == Biome.Category.BEACH || it == Biome.Category.RIVER } &&
noise[ctx.pos] < Config.algae.population
override fun render(ctx: CombinedContext) {
ctx.render()

View File

@@ -1,29 +1,36 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.render.column.ColumnTextureInfo
import mods.betterfoliage.client.render.column.SimpleColumnInfo
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.render.*
import mods.octarinecore.client.render.lighting.*
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.column.ColumnTextureInfo
import mods.betterfoliage.render.column.SimpleColumnInfo
import mods.betterfoliage.render.lighting.cornerAo
import mods.betterfoliage.render.lighting.cornerAoMaxGreen
import mods.betterfoliage.render.lighting.edgeOrientedAuto
import mods.betterfoliage.render.lighting.faceOrientedAuto
import mods.betterfoliage.render.toCross
import mods.betterfoliage.render.xzDisk
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.resource.discovery.ConfigurableModelDiscovery
import mods.octarinecore.client.resource.*
import mods.octarinecore.common.Rotation
import mods.octarinecore.common.config.ModelTextureList
import mods.octarinecore.common.config.SimpleBlockMatcher
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.config.ModelTextureList
import mods.betterfoliage.config.SimpleBlockMatcher
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.old.Vertex
import net.minecraft.block.BlockState
import net.minecraft.block.CactusBlock
import net.minecraft.util.Direction.*
import org.apache.logging.log4j.Level.DEBUG
import java.util.concurrent.CompletableFuture
object AsyncCactusDiscovery : ConfigurableModelDiscovery<ColumnTextureInfo>() {
override val logger = BetterFoliage.logDetail
override val matchClasses = SimpleBlockMatcher(CactusBlock::class.java)
override val modelTextures = listOf(ModelTextureList("block/cactus", "top", "bottom", "side"))
override fun processModel(state: BlockState, textures: List<String>, atlas: AtlasFuture): CompletableFuture<ColumnTextureInfo>? {
val sprites = textures.map { atlas.sprite(Identifier(it)) }
override fun processModel(state: BlockState, textures: List<Identifier>, atlas: AtlasFuture): CompletableFuture<ColumnTextureInfo>? {
val sprites = textures.map { atlas.sprite(it) }
return atlas.mapAfter {
SimpleColumnInfo(
Axis.Y,

View File

@@ -1,19 +1,22 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.texture.GrassRegistry
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.RenderDecorator
import mods.octarinecore.common.Int3
import mods.octarinecore.common.horizontalDirections
import mods.octarinecore.common.offset
import net.minecraft.tags.BlockTags
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.DIRT_BLOCKS
import mods.betterfoliage.render.isSnow
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.up1
import mods.betterfoliage.render.up2
import mods.betterfoliage.texture.GrassRegistry
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.horizontalDirections
import mods.betterfoliage.util.offset
class RenderConnectedGrass : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bus) {
override fun isEligible(ctx: CombinedContext) =
Config.enabled && Config.connectedGrass.enabled &&
BlockTags.DIRT_LIKE.contains(ctx.state.block) &&
DIRT_BLOCKS.contains(ctx.state.block) &&
GrassRegistry[ctx, up1] != null &&
(Config.connectedGrass.snowEnabled || !ctx.state(up2).isSnow)
@@ -31,7 +34,7 @@ class RenderConnectedGrassLog : RenderDecorator(BetterFoliageMod.MOD_ID, BetterF
override fun isEligible(ctx: CombinedContext) =
Config.enabled && Config.roundLogs.enabled && Config.roundLogs.connectGrass &&
BlockTags.DIRT_LIKE.contains(ctx.state.block) &&
DIRT_BLOCKS.contains(ctx.state.block) &&
LogRegistry[ctx, up1] != null
override fun render(ctx: CombinedContext) {

View File

@@ -1,21 +1,25 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.config.Config
import mods.octarinecore.client.render.*
import mods.octarinecore.client.render.lighting.*
import mods.octarinecore.common.allDirections
import mods.octarinecore.random
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.lighting.cornerAo
import mods.betterfoliage.render.lighting.cornerFlat
import mods.betterfoliage.render.lighting.faceOrientedAuto
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.rotationFromUp
import mods.betterfoliage.render.toCross
import mods.betterfoliage.render.up1
import mods.betterfoliage.render.up2
import mods.betterfoliage.render.xzDisk
import mods.betterfoliage.util.allDirections
import mods.betterfoliage.util.randomD
import net.minecraft.block.material.Material
import net.minecraft.tags.BlockTags
import net.minecraft.util.Direction.Axis
import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation
import net.minecraft.world.biome.Biome
import org.apache.logging.log4j.Level.DEBUG
class RenderCoral : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bus) {
@@ -28,7 +32,7 @@ class RenderCoral : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bu
.scale(Config.coral.size).move(0.5 to UP)
.toCross(UP) { it.move(xzDisk(modelIdx) * Config.coral.hOffset) }.addAll()
val separation = random(0.01, Config.coral.vOffset)
val separation = randomD(0.01, Config.coral.vOffset)
horizontalRectangle(x1 = -0.5, x2 = 0.5, z1 = -0.5, z2 = 0.5, y = 0.0)
.scale(Config.coral.crustSize).move(0.5 + separation to UP).add()
@@ -43,8 +47,9 @@ class RenderCoral : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bu
(ctx.state(up2).material == Material.WATER || Config.coral.shallowWater) &&
ctx.state(up1).material == Material.WATER &&
BlockTags.SAND.contains(ctx.state.block) &&
ctx.biome.category.let { it == Biome.Category.OCEAN || it == Biome.Category.BEACH } &&
noise[ctx.pos] < Config.coral.population
ctx.biome?.category
.let { it == Biome.Category.OCEAN || it == Biome.Category.BEACH } &&
noise[ctx.pos] < Config.coral.population
override fun render(ctx: CombinedContext) {
val baseRender = ctx.render()

View File

@@ -1,34 +1,37 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.integration.OptifineCustomColors
import mods.betterfoliage.client.integration.ShadersModIntegration
import mods.betterfoliage.client.resource.Identifier
import mods.betterfoliage.client.texture.GeneratedGrass
import mods.betterfoliage.client.texture.GrassRegistry
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.Model
import mods.octarinecore.client.render.RenderDecorator
import mods.octarinecore.client.render.fullCube
import mods.octarinecore.client.render.lighting.cornerAo
import mods.octarinecore.client.render.lighting.cornerFlat
import mods.octarinecore.client.render.lighting.faceOrientedAuto
import mods.octarinecore.common.Double3
import mods.octarinecore.common.allDirections
import mods.octarinecore.random
import net.minecraft.tags.BlockTags
import mods.betterfoliage.config.Config
import mods.betterfoliage.integration.OptifineCustomColors
import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.render.DIRT_BLOCKS
import mods.betterfoliage.render.down1
import mods.betterfoliage.render.isSnow
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.resource.generated.GeneratedGrass
import mods.betterfoliage.texture.GrassRegistry
import mods.betterfoliage.render.old.Model
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.old.fullCube
import mods.betterfoliage.render.lighting.cornerAo
import mods.betterfoliage.render.lighting.cornerFlat
import mods.betterfoliage.render.lighting.faceOrientedAuto
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.snowOffset
import mods.betterfoliage.render.toCross
import mods.betterfoliage.render.xzDisk
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.allDirections
import mods.betterfoliage.util.randomD
import net.minecraft.util.Direction.*
import org.apache.logging.log4j.Level.DEBUG
class RenderGrass : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bus) {
companion object {
@JvmStatic fun grassTopQuads(heightMin: Double, heightMax: Double): Model.(Int)->Unit = { modelIdx ->
verticalRectangle(x1 = -0.5, z1 = 0.5, x2 = 0.5, z2 = -0.5, yBottom = 0.5,
yTop = 0.5 + random(heightMin, heightMax)
yTop = 0.5 + randomD(heightMin, heightMax)
)
.setAoShader(faceOrientedAuto(overrideFace = UP, corner = cornerAo(Axis.Y)))
.setFlatShader(faceOrientedAuto(overrideFace = UP, corner = cornerFlat))
@@ -53,7 +56,7 @@ class RenderGrass : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bu
override val onlyOnCutout get() = true
override fun render(ctx: CombinedContext) {
val isConnected = BlockTags.DIRT_LIKE.contains(ctx.state(DOWN).block) || GrassRegistry[ctx, down1] != null
val isConnected = DIRT_BLOCKS.contains(ctx.state(DOWN).block) || GrassRegistry[ctx, down1] != null
val isSnowed = ctx.state(UP).isSnow
val connectedGrass = isConnected && Config.connectedGrass.enabled && (!isSnowed || Config.connectedGrass.snowEnabled)

View File

@@ -1,22 +1,27 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.integration.OptifineCustomColors
import mods.betterfoliage.client.integration.ShadersModIntegration
import mods.betterfoliage.client.resource.Identifier
import mods.betterfoliage.client.texture.LeafRegistry
import mods.octarinecore.PI2
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.RenderDecorator
import mods.octarinecore.client.render.lighting.FlatOffset
import mods.octarinecore.client.render.lighting.cornerAoMaxGreen
import mods.octarinecore.client.render.lighting.edgeOrientedAuto
import mods.octarinecore.common.Double3
import mods.octarinecore.common.Int3
import mods.octarinecore.common.allDirections
import mods.octarinecore.common.vec
import mods.octarinecore.random
import mods.betterfoliage.config.Config
import mods.betterfoliage.integration.OptifineCustomColors
import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.render.denseLeavesRot
import mods.betterfoliage.render.isSnow
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.texture.LeafRegistry
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.lighting.FlatOffset
import mods.betterfoliage.render.lighting.cornerAoMaxGreen
import mods.betterfoliage.render.lighting.edgeOrientedAuto
import mods.betterfoliage.render.normalLeavesRot
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.toCross
import mods.betterfoliage.render.whitewash
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.PI2
import mods.betterfoliage.util.allDirections
import mods.betterfoliage.util.randomD
import mods.betterfoliage.util.vec
import net.minecraft.util.Direction.UP
import java.lang.Math.cos
import java.lang.Math.sin
@@ -35,7 +40,7 @@ class RenderLeaves : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.b
val perturbs = vectorSet(64) { idx ->
val angle = PI2 * idx / 64.0
Double3(cos(angle), 0.0, sin(angle)) * Config.leaves.hOffset +
UP.vec * random(-1.0, 1.0) * Config.leaves.vOffset
UP.vec * randomD(-1.0, 1.0) * Config.leaves.vOffset
}
override fun isEligible(ctx: CombinedContext) =

View File

@@ -1,19 +1,18 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.integration.ShadersModIntegration
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.RenderDecorator
import mods.octarinecore.client.render.lighting.FlatOffsetNoColor
import mods.octarinecore.common.Int3
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.lighting.FlatOffsetNoColor
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.toCross
import mods.betterfoliage.render.xzDisk
import mods.betterfoliage.util.Int3
import net.minecraft.util.Direction.DOWN
import net.minecraft.util.Direction.UP
import org.apache.logging.log4j.Level.DEBUG
class RenderLilypad : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bus) {

View File

@@ -1,20 +1,23 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.chunk.ChunkOverlayManager
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.render.column.AbstractRenderColumn
import mods.betterfoliage.client.render.column.ColumnRenderLayer
import mods.betterfoliage.client.render.column.ColumnTextureInfo
import mods.betterfoliage.client.render.column.SimpleColumnInfo
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.render.CombinedContext
import mods.betterfoliage.chunk.ChunkOverlayManager
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.column.AbstractRenderColumn
import mods.betterfoliage.render.column.ColumnRenderLayer
import mods.betterfoliage.render.column.ColumnTextureInfo
import mods.betterfoliage.render.column.SimpleColumnInfo
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.resource.discovery.ConfigurableModelDiscovery
import mods.betterfoliage.resource.discovery.ModelRenderRegistry
import mods.betterfoliage.resource.discovery.ModelRenderRegistryRoot
import mods.octarinecore.client.resource.*
import mods.octarinecore.common.config.ConfigurableBlockMatcher
import mods.octarinecore.common.config.ModelTextureList
import mods.octarinecore.tryDefault
import mods.betterfoliage.config.ConfigurableBlockMatcher
import mods.betterfoliage.config.ModelTextureList
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.util.tryDefault
import net.minecraft.block.BlockState
import net.minecraft.block.LogBlock
import net.minecraft.util.Direction.Axis
@@ -54,10 +57,10 @@ object AsyncLogDiscovery : ConfigurableModelDiscovery<ColumnTextureInfo>() {
override val matchClasses: ConfigurableBlockMatcher get() = BlockConfig.logBlocks
override val modelTextures: List<ModelTextureList> get() = BlockConfig.logModels.modelList
override fun processModel(state: BlockState, textures: List<String>, atlas: AtlasFuture): CompletableFuture<ColumnTextureInfo> {
override fun processModel(state: BlockState, textures: List<Identifier>, atlas: AtlasFuture): CompletableFuture<ColumnTextureInfo> {
val axis = getAxis(state)
logger.log(Level.DEBUG, "$logName: axis $axis")
val spriteList = textures.map { atlas.sprite(Identifier(it)) }
val spriteList = textures.map { atlas.sprite(it) }
return atlas.mapAfter {
SimpleColumnInfo(
axis,

View File

@@ -1,22 +1,25 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.RenderDecorator
import mods.octarinecore.client.render.noPost
import mods.octarinecore.common.Double3
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.isSnow
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.old.noPost
import mods.betterfoliage.render.snowOffset
import mods.betterfoliage.render.whitewash
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.util.Double3
import net.minecraft.util.Direction.UP
import org.apache.logging.log4j.Level.DEBUG
class RenderMycelium : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bus) {
val myceliumIcon = spriteSet { idx -> Identifier(BetterFoliageMod.MOD_ID, "blocks/better_mycel_$idx") }
val myceliumModel = modelSet(64) { idx -> RenderGrass.grassTopQuads(Config.shortGrass.heightMin, Config.shortGrass.heightMax)(idx) }
val myceliumModel = modelSet(64) { idx -> RenderGrass.grassTopQuads(
Config.shortGrass.heightMin,
Config.shortGrass.heightMax
)(idx) }
override fun isEligible(ctx: CombinedContext): Boolean {
if (!Config.enabled || !Config.shortGrass.myceliumEnabled) return false

View File

@@ -1,25 +1,26 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.render.*
import mods.octarinecore.client.render.lighting.*
import mods.octarinecore.random
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.lighting.cornerAo
import mods.betterfoliage.render.lighting.cornerFlat
import mods.betterfoliage.render.lighting.faceOrientedAuto
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.toCross
import mods.betterfoliage.render.xzDisk
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.util.randomD
import net.minecraft.block.Blocks
import net.minecraft.util.Direction.Axis
import net.minecraft.util.Direction.*
import org.apache.logging.log4j.Level.DEBUG
class RenderNetherrack : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bus) {
val netherrackIcon = spriteSet { idx -> Identifier(BetterFoliageMod.MOD_ID, "blocks/better_netherrack_$idx") }
val netherrackModel = modelSet(64) { modelIdx ->
verticalRectangle(x1 = -0.5, z1 = 0.5, x2 = 0.5, z2 = -0.5, yTop = -0.5,
yBottom = -0.5 - random(Config.netherrack.heightMin, Config.netherrack.heightMax))
yBottom = -0.5 - randomD(Config.netherrack.heightMin, Config.netherrack.heightMax))
.setAoShader(faceOrientedAuto(overrideFace = DOWN, corner = cornerAo(Axis.Y)))
.setFlatShader(faceOrientedAuto(overrideFace = DOWN, corner = cornerFlat))
.toCross(UP) { it.move(xzDisk(modelIdx) * Config.shortGrass.hOffset) }.addAll()

View File

@@ -1,20 +1,22 @@
package mods.betterfoliage.client.render
package mods.betterfoliage.render.block.vanillaold
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.integration.ShadersModIntegration
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.RenderDecorator
import mods.octarinecore.client.render.lighting.FlatOffsetNoColor
import mods.octarinecore.client.resource.CenteredSprite
import mods.octarinecore.random
import mods.betterfoliage.config.Config
import mods.betterfoliage.integration.ShadersModIntegration
import mods.betterfoliage.render.DIRT_BLOCKS
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.lighting.FlatOffsetNoColor
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.toCross
import mods.betterfoliage.render.up1
import mods.betterfoliage.render.up2
import mods.betterfoliage.render.xzDisk
import mods.betterfoliage.resource.generated.CenteredSprite
import mods.betterfoliage.util.randomD
import net.minecraft.block.material.Material
import net.minecraft.tags.BlockTags
import net.minecraft.util.Direction.UP
import org.apache.logging.log4j.Level.DEBUG
class RenderReeds : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bus) {
@@ -24,7 +26,7 @@ class RenderReeds : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bu
register = { CenteredSprite(it).register(BetterFoliage.asyncPack) }
)
val reedModels = modelSet(64) { modelIdx ->
val height = random(Config.reed.heightMin, Config.reed.heightMax)
val height = randomD(Config.reed.heightMin, Config.reed.heightMax)
val waterline = 0.875f
val vCutLine = 0.5 - waterline / height
listOf(
@@ -45,9 +47,10 @@ class RenderReeds : RenderDecorator(BetterFoliageMod.MOD_ID, BetterFoliageMod.bu
Config.enabled && Config.reed.enabled &&
ctx.state(up2).material == Material.AIR &&
ctx.state(UP).material == Material.WATER &&
BlockTags.DIRT_LIKE.contains(ctx.state.block) &&
ctx.biome.let { it.downfall > Config.reed.minBiomeRainfall && it.defaultTemperature >= Config.reed.minBiomeTemp } &&
noise[ctx.pos] < Config.reed.population
DIRT_BLOCKS.contains(ctx.state.block) &&
ctx.biome
?.let { it.downfall > Config.reed.minBiomeRainfall && it.defaultTemperature >= Config.reed.minBiomeTemp } ?: false &&
noise[ctx.pos] < Config.reed.population
override val onlyOnCutout get() = false

View File

@@ -1,20 +1,19 @@
package mods.betterfoliage.client.render.column
package mods.betterfoliage.render.column
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.client.Client
import mods.betterfoliage.client.chunk.ChunkOverlayManager
import mods.betterfoliage.client.integration.ShadersModIntegration.renderAs
import mods.betterfoliage.client.render.*
import mods.betterfoliage.client.render.column.ColumnLayerData.SpecialRender.BlockType.*
import mods.betterfoliage.client.render.column.ColumnLayerData.SpecialRender.QuadrantType
import mods.betterfoliage.client.render.column.ColumnLayerData.SpecialRender.QuadrantType.*
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.Model
import mods.octarinecore.client.render.RenderDecorator
import mods.octarinecore.client.render.noPost
import mods.octarinecore.common.Rotation
import mods.octarinecore.common.face
import mods.octarinecore.common.rot
import mods.betterfoliage.chunk.ChunkOverlayManager
import mods.betterfoliage.integration.ShadersModIntegration.renderAs
import mods.betterfoliage.render.*
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.BlockType.*
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType.*
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.old.Model
import mods.betterfoliage.render.old.RenderDecorator
import mods.betterfoliage.render.old.noPost
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.util.face
import mods.betterfoliage.util.rot
import net.minecraft.block.BlockRenderType.MODEL
import net.minecraft.util.Direction.*
import net.minecraftforge.eventbus.api.IEventBus

View File

@@ -1,22 +1,25 @@
package mods.betterfoliage.client.render.column
package mods.betterfoliage.render.column
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.client.chunk.ChunkOverlayLayer
import mods.betterfoliage.client.chunk.ChunkOverlayManager
import mods.betterfoliage.client.chunk.dimType
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.render.column.ColumnLayerData.SpecialRender.BlockType.*
import mods.betterfoliage.client.render.column.ColumnLayerData.SpecialRender.QuadrantType
import mods.betterfoliage.client.render.column.ColumnLayerData.SpecialRender.QuadrantType.*
import mods.betterfoliage.client.render.rotationFromUp
import mods.octarinecore.client.render.BlockCtx
import mods.octarinecore.client.resource.ModelRenderRegistry
import mods.octarinecore.common.*
import mods.betterfoliage.chunk.ChunkOverlayLayer
import mods.betterfoliage.chunk.ChunkOverlayManager
import mods.betterfoliage.chunk.dimType
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.BlockType.*
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType
import mods.betterfoliage.render.column.ColumnLayerData.SpecialRender.QuadrantType.*
import mods.betterfoliage.render.rotationFromUp
import mods.betterfoliage.render.old.BlockCtx
import mods.betterfoliage.resource.discovery.ModelRenderRegistry
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.util.allDirections
import mods.betterfoliage.util.face
import mods.betterfoliage.util.plus
import net.minecraft.block.BlockState
import net.minecraft.util.Direction.Axis
import net.minecraft.util.Direction.AxisDirection
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IEnviromentBlockReader
import net.minecraft.world.ILightReader
/** Index of SOUTH-EAST quadrant. */
const val SE = 0
@@ -68,7 +71,7 @@ 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: IEnviromentBlockReader, pos: BlockPos) {
override fun onBlockUpdate(world: ILightReader, pos: BlockPos) {
allNeighborOffsets.forEach { offset -> ChunkOverlayManager.clear(world.dimType, this, pos + offset) }
}

View File

@@ -1,7 +1,7 @@
package mods.betterfoliage.client.render.column
package mods.betterfoliage.render.column
import mods.octarinecore.client.render.lighting.QuadIconResolver
import mods.octarinecore.common.rotate
import mods.betterfoliage.render.lighting.QuadIconResolver
import mods.betterfoliage.util.rotate
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.Direction.*

View File

@@ -1,7 +1,18 @@
package mods.octarinecore.client.render.lighting
package mods.betterfoliage.render.lighting
import mods.octarinecore.client.render.*
import mods.octarinecore.common.*
import mods.betterfoliage.render.old.Quad
import mods.betterfoliage.render.old.Vertex
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.util.axes
import mods.betterfoliage.util.boxEdges
import mods.betterfoliage.util.boxFaces
import mods.betterfoliage.util.face
import mods.betterfoliage.util.get
import mods.betterfoliage.util.nearestAngle
import mods.betterfoliage.util.nearestPosition
import mods.betterfoliage.util.perpendiculars
import mods.betterfoliage.util.vec
import net.minecraft.util.Direction
import net.minecraft.util.Direction.*
import java.lang.Math.min
@@ -124,7 +135,8 @@ fun faceOrientedAuto(overrideFace: Direction? = null,
* @param[corner] ModelLighter instantiation lambda
*/
fun edgeOrientedAuto(overrideEdge: Pair<Direction, Direction>? = null,
corner: CornerShaderFactory) =
corner: CornerShaderFactory
) =
fun(quad: Quad, vertex: Vertex): ModelLighter {
val edgeDir = overrideEdge ?: nearestAngle(quad.normal, boxEdges) { it.first.vec + it.second.vec }.first
val nearestFace = nearestPosition(vertex.xyz, edgeDir.toList()) { it.vec }.first

View File

@@ -1,11 +1,18 @@
package mods.octarinecore.client.render.lighting
package mods.betterfoliage.render.lighting
import mods.octarinecore.client.render.BlockCtx
import mods.octarinecore.common.*
import mods.betterfoliage.render.old.BlockCtx
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.util.allDirections
import mods.betterfoliage.util.boxFaces
import mods.betterfoliage.util.get
import mods.betterfoliage.util.offset
import mods.betterfoliage.util.plus
import mods.betterfoliage.util.rotate
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.BlockModelRenderer
import net.minecraft.client.renderer.WorldRenderer
import net.minecraft.util.Direction
import net.minecraft.world.IEnviromentBlockReader
import java.util.*
val Direction.aoMultiplier: Float get() = when(this) {
@@ -26,7 +33,7 @@ interface LightingCtx {
fun color(face: Direction) = color(face.offset)
fun brightness(offset: Int3) = offset.rotate(modelRotation).let {
blockContext.state(it).getPackedLightmapCoords(blockContext.world, blockContext.pos + it)
WorldRenderer.getCombinedLight(blockContext.world, blockContext.pos + it)
}
fun color(offset: Int3) = blockContext.offset(offset.rotate(modelRotation)).let { Minecraft.getInstance().blockColors.getColor(it.state, it.world, it.pos, 0) }
@@ -94,7 +101,7 @@ class FaceLightData(val face: Direction) {
fun update(blockCtx: BlockCtx, multiplier: Float) {
val quadBounds = FloatArray(12)
val flags = BitSet(3).apply { set(0) }
delegate.updateVertexBrightness(blockCtx.world, blockCtx.state, blockCtx.pos, face, quadBounds, flags)
// delegate.updateVertexBrightness(blockCtx.world, blockCtx.state, blockCtx.pos, face, quadBounds, flags)
vanillaOrdered.forEachIndexed { idx, corner -> corner.set(delegate.vertexBrightness[idx], delegate.vertexColorMultiplier[idx] * multiplier) }
isValid = true
}

View File

@@ -1,6 +1,13 @@
package mods.octarinecore.client.render.lighting
package mods.betterfoliage.render.lighting
import mods.octarinecore.common.*
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.util.axes
import mods.betterfoliage.util.boxFaces
import mods.betterfoliage.util.face
import mods.betterfoliage.util.get
import mods.betterfoliage.util.offset
import mods.betterfoliage.util.rotate
import net.minecraft.util.Direction
@@ -34,7 +41,8 @@ object NoLighting : ModelLighter {
override fun rotate(rot: Rotation) = this
}
class CornerSingleFallback(val face: Direction, val dir1: Direction, val dir2: Direction, val fallbackDir: Direction, val fallbackDimming: Float = defaultCornerDimming) : ModelLighter {
class CornerSingleFallback(val face: Direction, val dir1: Direction, val dir2: Direction, val fallbackDir: Direction, val fallbackDimming: Float = defaultCornerDimming) :
ModelLighter {
val offset = Int3(fallbackDir)
override fun shade(context: LightingCtx, vertex: RenderVertex) {
val shading = context.lighting(face, dir1, dir2)
@@ -72,7 +80,8 @@ class CornerTri(val face: Direction, val dir1: Direction, val dir2: Direction,
override fun rotate(rot: Rotation) = CornerTri(face.rotate(rot), dir1.rotate(rot), dir2.rotate(rot), func)
}
class EdgeInterpolateFallback(val face: Direction, val edgeDir: Direction, val pos: Double, val fallbackDimming: Float = defaultEdgeDimming): ModelLighter {
class EdgeInterpolateFallback(val face: Direction, val edgeDir: Direction, val pos: Double, val fallbackDimming: Float = defaultEdgeDimming):
ModelLighter {
val offset = Int3(edgeDir)
val edgeAxis = axes.find { it != face.axis && it != edgeDir.axis }!!
val weightN = (0.5 - pos).toFloat()
@@ -92,7 +101,8 @@ class EdgeInterpolateFallback(val face: Direction, val edgeDir: Direction, val p
}
class CornerInterpolateDimming(val face1: Direction, val face2: Direction, val edgeDir: Direction,
val weight: Float, val dimming: Float, val fallbackDimming: Float = defaultCornerDimming) : ModelLighter {
val weight: Float, val dimming: Float, val fallbackDimming: Float = defaultCornerDimming
) : ModelLighter {
val offset = Int3(edgeDir)
override fun shade(context: LightingCtx, vertex: RenderVertex) {
var shading1 = context.lighting(face1, edgeDir, face2)

View File

@@ -0,0 +1,3 @@
@file:JvmName("PixelFormat")
package mods.betterfoliage.render.lighting

View File

@@ -1,10 +1,10 @@
package mods.octarinecore.client.render.lighting
package mods.betterfoliage.render.lighting
import mods.octarinecore.client.render.CombinedContext
import mods.octarinecore.client.render.Quad
import mods.octarinecore.client.render.Vertex
import mods.octarinecore.common.Double3
import mods.octarinecore.common.Rotation
import mods.betterfoliage.render.old.CombinedContext
import mods.betterfoliage.render.old.Quad
import mods.betterfoliage.render.old.Vertex
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.Rotation
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.Direction.*
import java.awt.Color

View File

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

View File

@@ -1,17 +1,20 @@
package mods.octarinecore.client.render
package mods.betterfoliage.render.old
import mods.octarinecore.common.*
import mods.octarinecore.semiRandom
import com.mojang.blaze3d.matrix.MatrixStack
import com.mojang.blaze3d.vertex.IVertexBuilder
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
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.client.renderer.BlockRendererDispatcher
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.util.BlockRenderLayer
import net.minecraft.client.renderer.RenderType
import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
import net.minecraft.world.IEnviromentBlockReader
import net.minecraft.world.World
import net.minecraft.world.ILightReader
import net.minecraft.world.IWorldReader
import net.minecraft.world.biome.Biome
import net.minecraftforge.client.model.data.IModelData
import java.util.*
@@ -21,7 +24,7 @@ import java.util.*
* block-relative coordinates.
*/
interface BlockCtx {
val world: IEnviromentBlockReader
val world: ILightReader
val pos: BlockPos
fun offset(dir: Direction) = offset(dir.offset)
@@ -31,21 +34,21 @@ interface BlockCtx {
fun state(dir: Direction) = world.getBlockState(pos + dir.offset)
fun state(offset: Int3) = world.getBlockState(pos + offset)
val biome: Biome get() = world.getBiome(pos)
val biome: Biome? get() = (world as? IWorldReader)?.getBiome(pos)
val isNormalCube: Boolean get() = state.isNormalCube(world, pos)
fun shouldSideBeRendered(side: Direction) = Block.shouldSideBeRendered(state, world, pos, side)
/** Get a semi-random value based on the block coordinate and the given seed. */
fun semiRandom(seed: Int) = semiRandom(pos.x, pos.y, pos.z, seed)
fun semiRandom(seed: Int) = pos.semiRandom(seed)
/** Get an array of semi-random values based on the block coordinate. */
fun semiRandomArray(num: Int): Array<Int> = Array(num) { semiRandom(it) }
}
open class BasicBlockCtx(
override val world: IEnviromentBlockReader,
override val world: ILightReader,
override val pos: BlockPos
) : BlockCtx {
override var state: BlockState = world.getBlockState(pos)
@@ -54,20 +57,24 @@ open class BasicBlockCtx(
fun cache() = CachedBlockCtx(world, pos)
}
open class CachedBlockCtx(world: IEnviromentBlockReader, pos: BlockPos) : BasicBlockCtx(world, pos) {
open class CachedBlockCtx(world: ILightReader, pos: BlockPos) : BasicBlockCtx(world, pos) {
var neighbors = Array<BlockState>(6) { world.getBlockState(pos + allDirections[it].offset) }
override var biome: Biome = world.getBiome(pos)
override var biome: Biome? = super.biome
override fun state(dir: Direction) = neighbors[dir.ordinal]
}
data class RenderCtx(
val dispatcher: BlockRendererDispatcher,
val renderBuffer: BufferBuilder,
val layer: BlockRenderLayer,
val renderBuffer: IVertexBuilder,
val matrixStack: MatrixStack,
val layer: RenderType,
val checkSides: Boolean,
val random: Random,
val modelData: IModelData
) {
fun render(worldBlock: BlockCtx) = dispatcher.renderBlock(worldBlock.state, worldBlock.pos, worldBlock.world, renderBuffer, random, modelData)
fun render(worldBlock: BlockCtx) =
// dispatcher.renderBlock(worldBlock.state, worldBlock.pos, worldBlock.world, renderBuffer, random, modelData)
dispatcher.renderModel(worldBlock.state, worldBlock.pos, worldBlock.world, matrixStack, renderBuffer, checkSides, random, modelData)
}

View File

@@ -1,23 +1,27 @@
package mods.octarinecore.client.render
package mods.betterfoliage.render.old
import mods.betterfoliage.client.render.canRenderInCutout
import mods.betterfoliage.client.render.isCutout
import mods.octarinecore.BufferBuilder
import mods.betterfoliage.render.canRenderInCutout
import mods.betterfoliage.render.isCutout
import mods.betterfoliage.render.lighting.DefaultLightingCtx
import mods.betterfoliage.render.lighting.LightingCtx
import mods.betterfoliage.render.lighting.PostProcessLambda
import mods.betterfoliage.render.lighting.QuadIconResolver
import mods.betterfoliage.render.lighting.RenderVertex
import mods.octarinecore.BufferBuilder_setSprite
import mods.octarinecore.client.render.lighting.*
import mods.octarinecore.common.Double3
import mods.octarinecore.common.Int3
import mods.octarinecore.common.Rotation
import mods.octarinecore.common.plus
import mods.octarinecore.metaprog.get
import mods.octarinecore.metaprog.set
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.util.plus
import net.minecraft.block.Blocks
import net.minecraft.client.renderer.RenderTypeLookup
import net.minecraft.client.renderer.Vector3f
import net.minecraft.client.renderer.Vector4f
import net.minecraft.fluid.Fluids
import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IEnviromentBlockReader
import net.minecraft.world.ILightReader
import net.minecraft.world.LightType
import net.minecraft.world.biome.Biomes
import net.minecraft.world.level.ColorResolver
class CombinedContext(
val blockCtx: BlockCtx, val renderCtx: RenderCtx, val lightingCtx: DefaultLightingCtx
@@ -26,7 +30,7 @@ class CombinedContext(
var hasRendered = false
fun render(force: Boolean = false) = renderCtx.let {
if (force || state.canRenderInLayer(it.layer) || (state.canRenderInCutout() && it.layer.isCutout)) {
if (force || RenderTypeLookup.canRenderInLayer(state, it.layer) || (state.canRenderInCutout() && it.layer.isCutout)) {
it.render(blockCtx)
hasRendered = true
}
@@ -42,7 +46,7 @@ class CombinedContext(
val isCutout = renderCtx.layer.isCutout
/** Get the centerpoint of the block being rendered. */
val blockCenter: Double3 get() = Double3(pos.x + 0.5, pos.y + 0.5, pos.z + 0.5)
val blockCenter: Double3 get() = Double3((pos.x and 15) + 0.5, (pos.y and 15) + 0.5, (pos.z and 15) + 0.5)
/** Holds final vertex data before it goes to the [Tessellator]. */
val temp = RenderVertex()
@@ -56,9 +60,13 @@ class CombinedContext(
icon: QuadIconResolver,
postProcess: PostProcessLambda = noPost
) {
val cameraTransform = renderCtx.matrixStack.last
lightingCtx.modelRotation = rotation
model.quads.forEachIndexed { quadIdx, quad ->
if (quadFilter(quadIdx, quad)) {
val normal = quad.normal.let { Vector3f(it.x.toFloat(), it.y.toFloat(), it.z.toFloat()) }
normal.transform(cameraTransform.normal)
val drawIcon = icon(this, quadIdx, quad)
if (drawIcon != null) {
// let OptiFine know the texture we're using, so it can
@@ -66,7 +74,10 @@ class CombinedContext(
BufferBuilder_setSprite.invoke(renderCtx.renderBuffer, drawIcon)
quad.verts.forEachIndexed { vertIdx, vert ->
temp.init(vert).rotate(lightingCtx.modelRotation).translate(translation)
temp.init(vert).rotate(lightingCtx.modelRotation)
.translate(translation)
val vertex = temp.let { Vector4f(it.x.toFloat(), it.y.toFloat(), it.z.toFloat(), 0.0F) }
.apply { transform(cameraTransform.matrix) }
val shader = if (lightingCtx.aoEnabled && !forceFlat) vert.aoShader else vert.flatShader
shader.shade(lightingCtx, temp)
temp.postProcess(this, quadIdx, quad, vertIdx, vert)
@@ -74,9 +85,12 @@ class CombinedContext(
renderCtx.renderBuffer
.pos(temp.x, temp.y, temp.z)
// .pos(vertex.x.toDouble(), vertex.y.toDouble(), vertex.z.toDouble())
.color(temp.red, temp.green, temp.blue, 1.0f)
.tex(temp.u, temp.v)
.tex(temp.u.toFloat(), temp.v.toFloat())
.lightmap(temp.brightness shr 16 and 65535, temp.brightness and 65535)
.normal(quad.normal.x.toFloat(), quad.normal.y.toFloat(), quad.normal.z.toFloat())
// .normal(normal.x, normal.y, normal.z)
.endVertex()
}
}
@@ -92,10 +106,11 @@ val topOnly: (Direction) -> Boolean = { it == Direction.UP }
/** Perform no post-processing */
val noPost: PostProcessLambda = { _, _, _, _, _ -> }
object NonNullWorld : IEnviromentBlockReader {
object NonNullWorld : ILightReader {
override fun getBlockState(pos: BlockPos) = Blocks.AIR.defaultState
override fun getLightFor(type: LightType, pos: BlockPos) = 0
override fun getFluidState(pos: BlockPos) = Fluids.EMPTY.defaultState
override fun getTileEntity(pos: BlockPos) = null
override fun getBiome(pos: BlockPos) = Biomes.THE_VOID
override fun getLightManager() = null
override fun getBlockColor(p0: BlockPos, p1: ColorResolver) = 0
}

View File

@@ -1,9 +1,20 @@
package mods.octarinecore.client.render
package mods.betterfoliage.render.old
import mods.octarinecore.client.render.lighting.*
import mods.octarinecore.common.*
import mods.octarinecore.minmax
import mods.octarinecore.replace
import mods.betterfoliage.render.lighting.ModelLighter
import mods.betterfoliage.render.lighting.NoLighting
import mods.betterfoliage.render.lighting.ShaderFactory
import mods.betterfoliage.render.lighting.cornerAo
import mods.betterfoliage.render.lighting.cornerFlat
import mods.betterfoliage.render.lighting.faceOrientedAuto
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.Rotation
import mods.betterfoliage.util.allDirections
import mods.betterfoliage.util.boxFaces
import mods.betterfoliage.util.get
import mods.betterfoliage.util.minmax
import mods.betterfoliage.util.replace
import mods.betterfoliage.util.times
import mods.betterfoliage.util.vec
import net.minecraft.util.Direction
import java.lang.Math.max
import java.lang.Math.min
@@ -47,15 +58,16 @@ data class UV(val u: Double, val v: Double) {
data class Vertex(val xyz: Double3 = Double3(0.0, 0.0, 0.0),
val uv: UV = UV(0.0, 0.0),
val aoShader: ModelLighter = NoLighting,
val flatShader: ModelLighter = NoLighting)
val flatShader: ModelLighter = NoLighting
)
/**
* Model quad
*/
data class Quad(val v1: Vertex, val v2: Vertex, val v3: Vertex, val v4: Vertex) {
val verts = arrayOf(v1, v2, v3, v4)
inline fun transformV(trans: (Vertex)->Vertex): Quad = transformVI { vertex, idx -> trans(vertex) }
inline fun transformVI(trans: (Vertex, Int)->Vertex): Quad =
inline fun transformV(trans: (Vertex)-> Vertex): Quad = transformVI { vertex, idx -> trans(vertex) }
inline fun transformVI(trans: (Vertex, Int)-> Vertex): Quad =
Quad(trans(v1, 0), trans(v2, 1), trans(v3, 2), trans(v4, 3))
val normal: Double3 get() = (v2.xyz - v1.xyz).cross(v4.xyz - v1.xyz).normalize
@@ -103,8 +115,8 @@ class Model() {
fun Quad.add() = quads.add(this)
fun Iterable<Quad>.addAll() = forEach { quads.add(it) }
fun transformQ(trans: (Quad)->Quad) = quads.replace(trans)
fun transformV(trans: (Vertex)->Vertex) = quads.replace{ it.transformV(trans) }
fun transformQ(trans: (Quad)-> Quad) = quads.replace(trans)
fun transformV(trans: (Vertex)-> Vertex) = quads.replace{ it.transformV(trans) }
fun verticalRectangle(x1: Double, z1: Double, x2: Double, z2: Double, yBottom: Double, yTop: Double) = Quad(
Vertex(Double3(x1, yBottom, z1), UV.bottomLeft),

View File

@@ -1,11 +1,8 @@
package mods.octarinecore.client.render
package mods.betterfoliage.render.old
import mods.octarinecore.common.Int3
import mods.octarinecore.common.plus
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
import net.minecraft.world.IEnviromentBlockReader
import net.minecraft.world.LightType
import net.minecraft.world.ILightReader
/**
* Delegating [IBlockAccess] that fakes a _modified_ location to return values from a _target_ location.
@@ -23,16 +20,12 @@ open class OffsetBlockReader(open val original: IBlockReader, val modded: BlockP
}
@Suppress("NOTHING_TO_INLINE", "NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS", "HasPlatformType")
class OffsetEnvBlockReader(val original: IEnviromentBlockReader, val modded: BlockPos, val target: BlockPos) : IEnviromentBlockReader by original {
inline fun actualPos(pos: BlockPos) = if (pos != null && pos.x == modded.x && pos.y == modded.y && pos.z == modded.z) target else pos
class OffsetEnvBlockReader(val original: ILightReader, val modded: BlockPos, val target: BlockPos) : ILightReader by original {
inline fun actualPos(pos: BlockPos) = if (pos.x == modded.x && pos.y == modded.y && pos.z == modded.z) target else pos
override fun getBlockState(pos: BlockPos) = original.getBlockState(actualPos(pos))
override fun getTileEntity(pos: BlockPos) = original.getTileEntity(actualPos(pos))
override fun getFluidState(pos: BlockPos) = original.getFluidState(actualPos(pos))
override fun getLightFor(type: LightType, pos: BlockPos) = original.getLightFor(type, actualPos(pos))
override fun getCombinedLight(pos: BlockPos, light: Int) = original.getCombinedLight(actualPos(pos), light)
override fun getBiome(pos: BlockPos) = original.getBiome(actualPos(pos))
}
/**

View File

@@ -0,0 +1,23 @@
@file:JvmName("RendererHolder")
package mods.betterfoliage.render.old
import mods.betterfoliage.resource.ResourceHandler
import net.minecraft.block.BlockState
import net.minecraftforge.eventbus.api.IEventBus
abstract class RenderDecorator(modId: String, modBus: IEventBus) : ResourceHandler(modId, modBus) {
open val renderOnCutout: Boolean get() = true
open val onlyOnCutout: Boolean get() = false
// ============================
// Custom rendering
// ============================
abstract fun isEligible(ctx: CombinedContext): Boolean
abstract fun render(ctx: CombinedContext)
}
data class BlockData(val state: BlockState, val color: Int, val brightness: Int)

View File

@@ -1,4 +1,4 @@
package mods.betterfoliage.client.resource
package mods.betterfoliage.resource
import net.minecraft.client.renderer.model.ModelResourceLocation
import net.minecraft.client.renderer.texture.TextureAtlasSprite

View File

@@ -1,21 +1,20 @@
package mods.octarinecore.client.resource
package mods.betterfoliage.resource
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.client.resource.Identifier
import mods.betterfoliage.client.resource.Sprite
import mods.octarinecore.client.render.Model
import mods.octarinecore.common.Double3
import mods.octarinecore.common.Int3
import mods.octarinecore.common.completedVoid
import mods.octarinecore.common.sink
import mods.octarinecore.stripEnd
import mods.octarinecore.stripStart
import mods.betterfoliage.render.old.Model
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.Int3
import mods.betterfoliage.util.completedVoid
import mods.betterfoliage.util.sink
import mods.octarinecore.client.resource.AsyncSpriteProvider
import mods.octarinecore.client.resource.AtlasFuture
import mods.octarinecore.client.resource.StitchPhases
import net.minecraft.resources.IResourceManager
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper
import net.minecraft.world.IWorld
import net.minecraft.world.gen.SimplexNoiseGenerator
import net.minecraftforge.client.event.TextureStitchEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.eventbus.api.SubscribeEvent
@@ -25,15 +24,6 @@ import java.util.concurrent.CompletableFuture
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
enum class Atlas(val basePath: String) {
BLOCKS("textures"),
PARTICLES("textures/particle");
fun wrap(resource: Identifier) = Identifier(resource.namespace, "$basePath/${resource.path}.png")
fun unwrap(resource: Identifier) = resource.stripStart("$basePath/").stripEnd(".png")
fun matches(event: TextureStitchEvent) = event.map.basePath == basePath
}
// ============================
// Resource types
// ============================
@@ -108,7 +98,8 @@ interface SpriteSet {
operator fun get(idx: Int): Sprite
}
class AsyncSpriteSet(val targetAtlas: Atlas = Atlas.BLOCKS, val idFunc: (Int)->Identifier, val transform: (Identifier)->Identifier = { it }) : AsyncSpriteProvider<Any> {
class AsyncSpriteSet(val targetAtlas: Atlas = Atlas.BLOCKS, val idFunc: (Int)->Identifier, val transform: (Identifier)->Identifier = { it }) :
AsyncSpriteProvider<Any> {
var num = 0
protected set
protected var sprites: List<Sprite> = emptyList()
@@ -144,7 +135,7 @@ class ModelSet(val num: Int, val init: Model.(Int)->Unit): IConfigChangeListener
operator fun get(idx: Int) = models[idx % num]
}
class VectorSet(val num: Int, val init: (Int)->Double3): IConfigChangeListener {
class VectorSet(val num: Int, val init: (Int)-> Double3): IConfigChangeListener {
val models = Array(num) { Double3.zero }
override fun onConfigChange() { (0 until num).forEach { models[it] = init(it) } }
operator fun get(idx: Int) = models[idx % num]

View File

@@ -1,8 +1,8 @@
package mods.octarinecore.client.resource
import mods.betterfoliage.client.resource.Identifier
import mods.betterfoliage.client.resource.Sprite
import mods.octarinecore.common.map
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.resource.Sprite
import mods.betterfoliage.util.map
import net.minecraft.client.renderer.texture.AtlasTexture
import net.minecraft.client.renderer.texture.MissingTextureSprite
import net.minecraft.profiler.IProfiler

View File

@@ -1,21 +1,26 @@
package mods.octarinecore.client.resource
package mods.betterfoliage.resource.discovery
import com.google.common.base.Joiner
import mods.betterfoliage.client.resource.ModelIdentifier
import mods.octarinecore.HasLogger
import mods.octarinecore.client.render.BlockCtx
import mods.octarinecore.common.Int3
import mods.octarinecore.common.config.IBlockMatcher
import mods.octarinecore.common.config.ModelTextureList
import mods.octarinecore.common.plus
import mods.octarinecore.findFirst
import mods.octarinecore.common.sinkAsync
import mods.betterfoliage.render.old.BlockCtx
import mods.octarinecore.client.resource.AsyncSpriteProvider
import mods.octarinecore.client.resource.AtlasFuture
import mods.octarinecore.client.resource.StitchPhases
import mods.betterfoliage.util.Int3
import mods.betterfoliage.config.IBlockMatcher
import mods.betterfoliage.config.ModelTextureList
import mods.betterfoliage.util.HasLogger
import mods.betterfoliage.util.findFirst
import mods.betterfoliage.util.plus
import mods.betterfoliage.util.sinkAsync
import mods.betterfoliage.util.stripStart
import net.minecraft.block.BlockState
import net.minecraft.client.renderer.BlockModelShapes
import net.minecraft.client.renderer.model.BlockModel
import net.minecraft.client.renderer.model.IUnbakedModel
import net.minecraft.client.renderer.model.ModelBakery
import net.minecraft.client.renderer.model.ModelResourceLocation
import net.minecraft.client.renderer.model.VariantList
import net.minecraft.client.renderer.texture.MissingTextureSprite
import net.minecraft.resources.IResourceManager
import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos
@@ -40,7 +45,7 @@ abstract class ModelRenderRegistryRoot<T> : ModelRenderRegistry<T> {
class ModelDiscoveryContext(
bakery: ModelBakery,
val state: BlockState,
val modelId: ModelIdentifier
val modelId: ModelResourceLocation
) {
val models = bakery.unwrapVariants(bakery.getUnbakedModel(modelId) to modelId)
.filter { it.second != bakery.getUnbakedModel(ModelBakery.MODEL_MISSING) }
@@ -98,11 +103,11 @@ abstract class ConfigurableModelDiscovery<T> : ModelDiscovery<T>() {
abstract val matchClasses: IBlockMatcher
abstract val modelTextures: List<ModelTextureList>
abstract fun processModel(state: BlockState, textures: List<String>, atlas: AtlasFuture): CompletableFuture<T>?
abstract fun processModel(state: BlockState, textures: List<ResourceLocation>, atlas: AtlasFuture): CompletableFuture<T>?
override fun processModel(ctx: ModelDiscoveryContext, atlas: AtlasFuture): CompletableFuture<T>? {
val matchClass = matchClasses.matchingClass(ctx.state.block) ?: return null
log("block state ${ctx.state.toString()}")
log("block state ${ctx.state}")
log(" class ${ctx.state.block.javaClass.name} matches ${matchClass.name}")
if (ctx.models.isEmpty()) {
@@ -116,11 +121,11 @@ abstract class ConfigurableModelDiscovery<T> : ModelDiscovery<T>() {
if (modelMatch != null) {
log(" model ${model} matches ${modelMatch.modelLocation}")
val textures = modelMatch.textureNames.map { it to model.resolveTextureName(it) }
val textures = modelMatch.textureNames.map { it to model.resolveTextureName(it).textureLocation }
val texMapString = Joiner.on(", ").join(textures.map { "${it.first}=${it.second}" })
log(" sprites [$texMapString]")
if (textures.all { it.second != "missingno" }) {
if (textures.all { it.second != MissingTextureSprite.getLocation() }) {
// found a valid model (all required textures exist)
return processModel(ctx.state, textures.map { it.second}, atlas)
}
@@ -128,5 +133,11 @@ abstract class ConfigurableModelDiscovery<T> : ModelDiscovery<T>() {
}
return null
}
}
fun Pair<BlockModel, ResourceLocation>.derivesFrom(targetLocation: ResourceLocation): Boolean {
if (second.stripStart("models/") == targetLocation) return true
if (first.parent != null && first.parentLocation != null)
return Pair(first.parent!!, first.parentLocation!!).derivesFrom(targetLocation)
return false
}

View File

@@ -1,7 +1,9 @@
package mods.octarinecore.client.resource
package mods.betterfoliage.resource.generated
import mods.betterfoliage.client.resource.Identifier
import mods.betterfoliage.client.texture.loadSprite
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.texture.loadSprite
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.bytes
import net.minecraft.resources.IResourceManager
import java.awt.image.BufferedImage
import java.lang.Math.max

View File

@@ -1,6 +1,12 @@
package mods.betterfoliage.client.texture
package mods.betterfoliage.resource.generated
import mods.betterfoliage.client.resource.Identifier
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.texture.blendRGB
import mods.betterfoliage.texture.loadSprite
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.bytes
import mods.betterfoliage.util.get
import mods.betterfoliage.util.set
import mods.octarinecore.client.resource.*
import net.minecraft.resources.IResourceManager
import java.awt.image.BufferedImage

View File

@@ -1,6 +1,13 @@
package mods.betterfoliage.client.texture
package mods.betterfoliage.resource.generated
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.texture.loadSprite
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.bytes
import mods.betterfoliage.util.get
import mods.betterfoliage.util.loadImage
import mods.betterfoliage.util.resourceManager
import mods.betterfoliage.util.set
import mods.octarinecore.client.resource.*
import net.minecraft.resources.IResource
import net.minecraft.resources.IResourceManager

View File

@@ -1,9 +1,13 @@
package mods.octarinecore.client.resource
package mods.betterfoliage.resource.generated
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.HasLogger
import mods.octarinecore.common.completedVoid
import mods.octarinecore.common.map
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.HasLogger
import mods.betterfoliage.util.completedVoid
import mods.betterfoliage.util.map
import mods.octarinecore.client.resource.AsyncSpriteProvider
import mods.octarinecore.client.resource.AtlasFuture
import mods.octarinecore.client.resource.StitchPhases
import net.minecraft.client.renderer.model.ModelBakery
import net.minecraft.client.resources.ClientResourcePackInfo
import net.minecraft.resources.*
@@ -12,7 +16,6 @@ import net.minecraft.resources.data.IMetadataSectionSerializer
import net.minecraft.util.text.StringTextComponent
import org.apache.logging.log4j.Logger
import java.io.IOException
import java.lang.IllegalStateException
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutionException
@@ -25,13 +28,15 @@ import java.util.function.Supplier
* @param[name] Name of the resource pack
* @param[generators] List of resource generators
*/
class GeneratedBlockTexturePack(val nameSpace: String, val packName: String, override val logger: Logger) : HasLogger, IResourcePack, AsyncSpriteProvider<ModelBakery> {
class GeneratedBlockTexturePack(val nameSpace: String, val packName: String, override val logger: Logger) : HasLogger, IResourcePack,
AsyncSpriteProvider<ModelBakery> {
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, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<Identifier>()
override fun getAllResourceLocations(type: ResourcePackType, namespace:String, path: String, maxDepth: Int, filter: Predicate<String>) = emptyList<Identifier>()
override fun close() {}
protected var manager: CompletableFuture<IResourceManager>? = null

View File

@@ -1,13 +1,16 @@
package mods.betterfoliage.client.texture
package mods.betterfoliage.texture
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.render.lighting.HSB
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.render.lighting.HSB
import mods.betterfoliage.resource.discovery.ConfigurableModelDiscovery
import mods.betterfoliage.resource.discovery.ModelRenderRegistryRoot
import mods.octarinecore.client.resource.*
import mods.octarinecore.common.config.ConfigurableBlockMatcher
import mods.octarinecore.common.config.ModelTextureList
import mods.betterfoliage.config.ConfigurableBlockMatcher
import mods.betterfoliage.config.ModelTextureList
import mods.betterfoliage.util.averageColor
import net.minecraft.block.BlockState
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import org.apache.logging.log4j.Level
@@ -37,9 +40,9 @@ object AsyncGrassDiscovery : ConfigurableModelDiscovery<GrassInfo>() {
override val matchClasses: ConfigurableBlockMatcher get() = BlockConfig.grassBlocks
override val modelTextures: List<ModelTextureList> get() = BlockConfig.grassModels.modelList
override fun processModel(state: BlockState, textures: List<String>, atlas: AtlasFuture): CompletableFuture<GrassInfo> {
override fun processModel(state: BlockState, textures: List<Identifier>, atlas: AtlasFuture): CompletableFuture<GrassInfo> {
val textureName = textures[0]
val spriteF = atlas.sprite(Identifier(textureName))
val spriteF = atlas.sprite(textureName)
logger.log(Level.DEBUG, "$logName: texture $textureName")
return atlas.mapAfter {
val sprite = spriteF.get()

View File

@@ -1,13 +1,19 @@
package mods.betterfoliage.client.texture
package mods.betterfoliage.texture
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.client.resource.Identifier
import mods.betterfoliage.client.resource.Sprite
import mods.octarinecore.client.resource.*
import mods.octarinecore.stripStart
import mods.octarinecore.client.resource.Atlas
import mods.octarinecore.common.sinkAsync
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.resource.Sprite
import mods.betterfoliage.resource.SpriteSet
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.get
import mods.betterfoliage.util.getLines
import mods.betterfoliage.util.resourceManager
import mods.betterfoliage.util.sinkAsync
import mods.betterfoliage.util.stripStart
import mods.octarinecore.client.resource.AsyncSpriteProvider
import mods.octarinecore.client.resource.AtlasFuture
import mods.octarinecore.client.resource.StitchPhases
import net.minecraft.client.particle.ParticleManager
import net.minecraft.resources.IResourceManager
import java.util.concurrent.CompletableFuture

View File

@@ -1,12 +1,17 @@
package mods.betterfoliage.client.texture
package mods.betterfoliage.texture
import mods.betterfoliage.BetterFoliage
import mods.betterfoliage.client.config.BlockConfig
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.HasLogger
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.ConfigurableBlockMatcher
import mods.betterfoliage.config.ModelTextureList
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.resource.SpriteSet
import mods.betterfoliage.resource.discovery.ConfigurableModelDiscovery
import mods.betterfoliage.resource.discovery.ModelRenderRegistryRoot
import mods.betterfoliage.resource.generated.GeneratedLeaf
import mods.betterfoliage.util.HasLogger
import mods.betterfoliage.util.averageColor
import mods.octarinecore.client.resource.*
import mods.octarinecore.common.config.ConfigurableBlockMatcher
import mods.octarinecore.common.config.ModelTextureList
import net.minecraft.block.BlockState
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import java.util.concurrent.CompletableFuture
@@ -22,7 +27,7 @@ class LeafInfo(
val leafType: String,
/** Average color of the round leaf texture. */
val averageColor: Int = roundLeafTexture.averageColor
val averageColor: Int
) {
/** [IconSet] of the textures to use for leaf particles emitted from this block. */
val particleTextures: SpriteSet get() = LeafParticleRegistry[leafType]
@@ -35,7 +40,7 @@ object AsyncLeafDiscovery : ConfigurableModelDiscovery<LeafInfo>() {
override val matchClasses: ConfigurableBlockMatcher get() = BlockConfig.leafBlocks
override val modelTextures: List<ModelTextureList> get() = BlockConfig.leafModels.modelList
override fun processModel(state: BlockState, textures: List<String>, atlas: AtlasFuture) = defaultRegisterLeaf(Identifier(textures[0]), atlas)
override fun processModel(state: BlockState, textures: List<Identifier>, atlas: AtlasFuture) = defaultRegisterLeaf(textures[0], atlas)
fun init() {
LeafRegistry.registries.add(this)
@@ -47,10 +52,11 @@ fun HasLogger.defaultRegisterLeaf(sprite: Identifier, atlas: AtlasFuture): Compl
val leafType = LeafParticleRegistry.typeMappings.getType(sprite) ?: "default"
val generated = GeneratedLeaf(sprite, leafType).register(BetterFoliage.asyncPack)
val roundLeaf = atlas.sprite(generated)
val leafTex = atlas.sprite(sprite)
log(" leaf texture $sprite")
log(" particle $leafType")
return atlas.mapAfter {
LeafInfo(roundLeaf.get(), leafType)
LeafInfo(roundLeaf.get(), leafType, leafTex.get().averageColor)
}
}

View File

@@ -1,10 +1,9 @@
@file:JvmName("Utils")
package mods.betterfoliage.client.texture
package mods.betterfoliage.texture
import mods.betterfoliage.client.resource.Identifier
import mods.octarinecore.client.resource.Atlas
import mods.octarinecore.client.resource.get
import mods.octarinecore.client.resource.loadImage
import mods.betterfoliage.resource.Identifier
import mods.betterfoliage.util.get
import mods.betterfoliage.util.loadImage
import net.minecraft.resources.IResourceManager
import java.io.IOException

View File

@@ -0,0 +1,60 @@
package mods.betterfoliage.util
import java.lang.ref.WeakReference
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
interface Invalidator {
fun invalidate() {
val iterator = callbacks.iterator()
while(iterator.hasNext()) iterator.next().let { callback ->
callback.get()?.invoke() ?: iterator.remove()
}
}
val callbacks: MutableList<WeakReference<()->Unit>>
fun onInvalidate(callback: ()->Unit) {
callbacks.add(WeakReference(callback))
}
}
class LazyInvalidatable<V>(invalidator: Invalidator, val valueFactory: ()->V): ReadOnlyProperty<Any, V> {
init { invalidator.onInvalidate { value = null } }
var value: V? = null
override fun getValue(thisRef: Any, property: KProperty<*>): V {
value?.let { return it }
return synchronized(this) {
value?.let { return it }
valueFactory().apply { value = this }
}
}
}
class LazyMap<K, V>(val invalidator: Invalidator, val valueFactory: (K)->V) {
init { invalidator.onInvalidate { values.clear() } }
val values = mutableMapOf<K, V>()
operator fun get(key: K): V {
values[key]?.let { return it }
return synchronized(values) {
values[key]?.let { return it }
valueFactory(key).apply { values[key] = this }
}
}
operator fun set(key: K, value: V) { values[key] = value }
fun delegate(key: K) = Delegate(key)
inner class Delegate(val key: K) : ReadOnlyProperty<Any, V> {
init { invalidator.onInvalidate { cached = null } }
private var cached: V? = null
override fun getValue(thisRef: Any, property: KProperty<*>): V {
cached?.let { return it }
get(key).let { cached = it; return it }
}
}
}

View File

@@ -0,0 +1,63 @@
package mods.betterfoliage.util
import java.util.*
/**
* Starting with the second element of this [Iterable] until the last, call the supplied lambda with
* the parameters (index, element, previous element).
*/
inline fun <reified T> Iterable<T>.forEachPairIndexed(func: (Int, T, T)->Unit) {
var previous: T? = null
forEachIndexed { idx, current ->
if (previous != null) func(idx, current, previous!!)
previous = current
}
}
inline fun <T, C: Comparable<C>> Pair<T, T>.minBy(func: (T)->C) =
if (func(first) < func(second)) first else second
inline fun <T, C: Comparable<C>> Pair<T, T>.maxBy(func: (T)->C) =
if (func(first) > func(second)) first else second
inline fun <T, C: Comparable<C>> Triple<T, T, T>.maxValueBy(func: (T)->C): C {
var result = func(first)
func(second).let { if (it > result) result = it }
func(third).let { if (it > result) result = it }
return result
}
@Suppress("UNCHECKED_CAST")
inline fun <K, V> Map<K, V?>.filterValuesNotNull() = filterValues { it != null } as Map<K, V>
inline fun <reified T, R> Iterable<T>.findFirst(func: (T)->R?): R? {
forEach { func(it)?.let { return it } }
return null
}
inline fun <A1, reified A2, B> List<Pair<A1, B>>.filterIsInstanceFirst(cls: Class<A2>) = filter { it.first is A2 } as List<Pair<A2, B>>
/** Cross product of this [Iterable] with the parameter. */
fun <A, B> Iterable<A>.cross(other: Iterable<B>) = flatMap { a -> other.map { b -> a to b } }
inline fun <C, R, T> Iterable<T>.mapAs(transform: (C) -> R) = map { transform(it as C) }
inline fun <T1, T2> forEachNested(list1: Iterable<T1>, list2: Iterable<T2>, func: (T1, T2)-> Unit) =
list1.forEach { e1 ->
list2.forEach { e2 ->
func(e1, e2)
}
}
/** Mutating version of _map_. Replace each element of the list with the result of the given transformation. */
inline fun <reified T> MutableList<T>.replace(transform: (T) -> T) = forEachIndexed { idx, value -> this[idx] = transform(value) }
/** Exchange the two elements of the list with the given indices */
inline fun <T> MutableList<T>.exchange(idx1: Int, idx2: Int) {
val e = this[idx1]
this[idx1] = this[idx2]
this[idx2] = e
}
/** Return a random element from the array using the provided random generator */
inline operator fun <T> Array<T>.get(random: Random) = get(random.nextInt(Int.MAX_VALUE) % size)

View File

@@ -1,4 +1,4 @@
package mods.octarinecore.common
package mods.betterfoliage.util
import net.minecraft.client.Minecraft
import java.util.concurrent.CompletableFuture

View File

@@ -1,6 +1,5 @@
package mods.octarinecore.common
package mods.betterfoliage.util
import mods.octarinecore.cross
import net.minecraft.util.Direction
import net.minecraft.util.Direction.*
import net.minecraft.util.Direction.Axis.*

View File

@@ -1,5 +1,5 @@
@file:JvmName("Utils")
package mods.octarinecore.client.gui
package mods.betterfoliage.util
import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.Style

View File

@@ -1,15 +1,13 @@
@file:JvmName("Utils")
@file:Suppress("NOTHING_TO_INLINE")
package mods.octarinecore
package mods.betterfoliage.util
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos
import net.minecraft.world.*
import net.minecraft.world.World
import org.apache.logging.log4j.Level
import org.apache.logging.log4j.Logger
import kotlin.reflect.KProperty
import java.lang.Math.*
import kotlin.reflect.KProperty
const val PI2 = 2.0 * PI
@@ -21,36 +19,6 @@ inline fun String.stripEnd(str: String, ignoreCase: Boolean = true) = if (endsWi
inline fun ResourceLocation.stripStart(str: String) = ResourceLocation(namespace, path.stripStart(str))
inline fun ResourceLocation.stripEnd(str: String) = ResourceLocation(namespace, path.stripEnd(str))
/** Mutating version of _map_. Replace each element of the list with the result of the given transformation. */
inline fun <reified T> MutableList<T>.replace(transform: (T) -> T) = forEachIndexed { idx, value -> this[idx] = transform(value) }
/** Exchange the two elements of the list with the given indices */
inline fun <T> MutableList<T>.exchange(idx1: Int, idx2: Int) {
val e = this[idx1]
this[idx1] = this[idx2]
this[idx2] = e
}
/** Cross product of this [Iterable] with the parameter. */
fun <A, B> Iterable<A>.cross(other: Iterable<B>) = flatMap { a -> other.map { b -> a to b } }
inline fun <C, R, T> Iterable<T>.mapAs(transform: (C) -> R) = map { transform(it as C) }
inline fun <T1, T2> forEachNested(list1: Iterable<T1>, list2: Iterable<T2>, func: (T1, T2)-> Unit) =
list1.forEach { e1 ->
list2.forEach { e2 ->
func(e1, e2)
}
}
@Suppress("UNCHECKED_CAST")
inline fun <K, V> Map<K, V?>.filterValuesNotNull() = filterValues { it != null } as Map<K, V>
inline fun <reified T, R> Iterable<T>.findFirst(func: (T)->R?): R? {
forEach { func(it)?.let { return it } }
return null
}
/**
* Property-level delegate backed by a [ThreadLocal].
*
@@ -62,29 +30,9 @@ class ThreadLocalDelegate<T>(init: () -> T) {
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { tlVal.set(value) }
}
/**
* Starting with the second element of this [Iterable] until the last, call the supplied lambda with
* the parameters (index, element, previous element).
*/
inline fun <reified T> Iterable<T>.forEachPairIndexed(func: (Int, T, T)->Unit) {
var previous: T? = null
forEachIndexed { idx, current ->
if (previous != null) func(idx, current, previous!!)
previous = current
}
}
/** Call the supplied lambda and return its result, or the given default value if an exception is thrown. */
fun <T> tryDefault(default: T, work: ()->T) = try { work() } catch (e: Throwable) { default }
/** Return a random [Double] value between the given two limits (inclusive min, exclusive max). */
fun random(min: Double, max: Double) = Math.random().let { min + (max - min) * it }
fun semiRandom(x: Int, y: Int, z: Int, seed: Int): Int {
var value = (x * x + y * y + z * z + x * y + y * z + z * x + (seed * seed)) and 63
value = (3 * x * value + 5 * y * value + 7 * z * value + (11 * seed)) and 63
return value
}
/**
* Return this [Double] value if it lies between the two limits. If outside, return the
* minimum/maximum value correspondingly.
@@ -112,18 +60,16 @@ fun nextPowerOf2(x: Int): Int {
// else -> false
//}
/**
* Get the [TileEntity] at the given position, suppressing exceptions.
* Also returns null if the chunk is unloaded, which can happen because of multithreaded rendering.
*/
fun IWorldReader.getTileEntitySafe(pos: BlockPos): TileEntity? = tryDefault(null as TileEntity?) {
if (isBlockLoaded(pos)) getTileEntity(pos) else null
}
interface HasLogger {
val logger: Logger
val logName: String get() = this::class.simpleName!!
fun log(msg: String) = log(Level.DEBUG, msg)
fun log(msg: String) = log(Level.INFO, msg)
fun log(level: Level, msg: String) = logger.log(level, "[$logName] $msg")
}
fun log(msg: String, e: Throwable) = log(Level.WARN, msg, e)
fun log(level: Level, msg: String, e: Throwable) = logger.log(level, "[$logName] $msg", e)
}
//fun textComponent(msg: String, color: Formatting = Formatting.GRAY): LiteralText {
// val style = Style().apply { this.color = color }
// return LiteralText(msg).apply { this.style = style }
//}

View File

@@ -0,0 +1,18 @@
package mods.betterfoliage.util
import net.minecraft.util.math.BlockPos
import java.util.Random
val random = Random(System.nanoTime())
fun randomB() = random.nextBoolean()
fun randomI(min: Int = 0, max: Int = Int.MAX_VALUE) = min + random.nextInt(max - min)
fun randomD(min: Double = 0.0, max: Double = 1.0) = random.nextDouble() * (max - min) + min
fun semiRandom(x: Int, y: Int, z: Int, seed: Int): Int {
var value = (x * x + y * y + z * z + x * y + y * z + z * x + (seed * seed))
value = (3 * x * value + 5 * y * value + 7 * z * value + (11 * seed))
return value shr 4
}
fun BlockPos.semiRandom(seed: Int) = semiRandom(x, y, z, seed)

View File

@@ -1,12 +1,9 @@
@file:JvmName("Reflection")
package mods.octarinecore.metaprog
package mods.betterfoliage.util
import java.lang.reflect.Field
import java.lang.reflect.Method
import mods.octarinecore.metaprog.Namespace.*
import mods.octarinecore.tryDefault
import kotlin.reflect.KCallable
import kotlin.reflect.KFunction
import mods.betterfoliage.util.Namespace.*
/** Get a Java class with the given name. */
fun getJavaClass(name: String) = tryDefault(null) { Class.forName(name) }
@@ -106,10 +103,10 @@ class ClassRefPrimitive<T>(name: String, val clazz: Class<T>?) : ClassRef<T>(nam
* @param[returnType] references to the argument types
*/
class MethodRef<T: Any?>(val parentClass: ClassRef<*>,
val mcpName: String,
val srgName: String,
val returnType: ClassRef<T>,
vararg val argTypes: ClassRef<*>
val mcpName: String,
val srgName: String,
val returnType: ClassRef<T>,
vararg val argTypes: ClassRef<*>
) : Resolvable<Method>() {
constructor(parentClass: ClassRef<*>, mcpName: String, returnType: ClassRef<T>, vararg argTypes: ClassRef<*>) :
this(parentClass, mcpName, mcpName, returnType, *argTypes)
@@ -143,9 +140,9 @@ class MethodRef<T: Any?>(val parentClass: ClassRef<*>,
* @param[type] reference to the field type
*/
class FieldRef<T>(val parentClass: ClassRef<*>,
val mcpName: String,
val srgName: String,
val type: ClassRef<T>
val mcpName: String,
val srgName: String,
val type: ClassRef<T>
) : Resolvable<Field>() {
constructor(parentClass: ClassRef<*>, mcpName: String, type: ClassRef<T>) : this(parentClass, mcpName, mcpName, type)

View File

@@ -0,0 +1,26 @@
package mods.betterfoliage.util
import net.minecraft.client.Minecraft
import net.minecraft.resources.IReloadableResourceManager
import net.minecraft.resources.IResource
import net.minecraft.resources.IResourceManager
import net.minecraft.util.ResourceLocation
/** Concise getter for the Minecraft resource manager. */
val resourceManager: IReloadableResourceManager
get() = Minecraft.getInstance().resourceManager as IReloadableResourceManager
/** Append a string to the [ResourceLocation]'s path. */
operator fun ResourceLocation.plus(str: String) = ResourceLocation(namespace, path + str)
/** 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. */
operator fun IResourceManager.get(location: ResourceLocation): IResource? = tryDefault(null) { getResource(location) }
/** Get the lines of a text resource. */
fun IResource.getLines(): List<String> {
val result = arrayListOf<String>()
inputStream.bufferedReader().useLines { it.forEach { result.add(it) } }
return result
}

View File

@@ -0,0 +1,86 @@
package mods.betterfoliage.util
import mods.betterfoliage.render.lighting.HSB
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.texture.AtlasTexture
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.resources.IResource
import net.minecraft.resources.IResourceManager
import net.minecraft.util.ResourceLocation
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.io.IOException
import javax.imageio.ImageIO
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
enum class Atlas(val basePath: String, val resourceId: ResourceLocation) {
BLOCKS("textures", AtlasTexture.LOCATION_BLOCKS_TEXTURE),
PARTICLES("textures", AtlasTexture.LOCATION_PARTICLES_TEXTURE);
/** Get the fully-qualified resource name for sprites belonging to this atlas*/
fun wrap(resource: ResourceLocation) = ResourceLocation(resource.namespace, "$basePath/${resource.path}.png")
/** Get the short resource name for sprites belonging to this atlas*/
fun unwrap(resource: ResourceLocation) = resource.stripStart("$basePath/").stripEnd(".png")
/** Reference to the atlas itself */
val atlas: AtlasTexture get() = Minecraft.getInstance().textureManager.getTexture(resourceId) as AtlasTexture
}
inline operator fun AtlasTexture.get(res: ResourceLocation): TextureAtlasSprite? = this.getSprite(res)
inline operator fun AtlasTexture.get(name: String): TextureAtlasSprite? = get(ResourceLocation(name))
fun IResourceManager.loadSprite(id: ResourceLocation) = this.get(id)?.loadImage() ?: throw IOException("Cannot load resource $id")
fun IResource.loadImage(): BufferedImage? = ImageIO.read(this.inputStream)
/** Index operator to get the RGB value of a pixel. */
operator fun BufferedImage.get(x: Int, y: Int) = this.getRGB(x, y)
/** Index operator to set the RGB value of a pixel. */
operator fun BufferedImage.set(x: Int, y: Int, value: Int) = this.setRGB(x, y, value)
val BufferedImage.bytes: ByteArray get() =
ByteArrayOutputStream().let { ImageIO.write(this, "PNG", it); it.toByteArray() }
/**
* Calculate the average color of a texture.
*
* Only non-transparent pixels are considered. Averages are taken in the HSB color space (note: Hue is a circular average),
* and the result transformed back to the RGB color space.
*/
val TextureAtlasSprite.averageColor: Int get() {
var numOpaque = 0
var sumHueX = 0.0
var sumHueY = 0.0
var sumSaturation = 0.0f
var sumBrightness = 0.0f
for (x in 0 until width)
for (y in 0 until height) {
val pixel = getPixelRGBA(0, x, y)
val alpha = (pixel shr 24) and 255
val hsb = HSB.fromColor(pixel)
if (alpha == 255) {
numOpaque++
sumHueX += cos((hsb.hue.toDouble() - 0.5) * PI2)
sumHueY += sin((hsb.hue.toDouble() - 0.5) * PI2)
sumSaturation += hsb.saturation
sumBrightness += hsb.brightness
}
}
// circular average - transform sum vector to polar angle
val avgHue = (atan2(sumHueY, sumHueX) / PI2 + 0.5).toFloat()
return HSB(avgHue, sumSaturation / numOpaque.toFloat(), sumBrightness / numOpaque.toFloat()).asColor
}
/** Weighted blend of 2 packed RGB colors */
fun blendRGB(rgb1: Int, rgb2: Int, weight1: Int, weight2: Int): Int {
val r = (((rgb1 shr 16) and 255) * weight1 + ((rgb2 shr 16) and 255) * weight2) / (weight1 + weight2)
val g = (((rgb1 shr 8) and 255) * weight1 + ((rgb2 shr 8) and 255) * weight2) / (weight1 + weight2)
val b = ((rgb1 and 255) * weight1 + (rgb2 and 255) * weight2) / (weight1 + weight2)
val a = (rgb1 shr 24) and 255
val result = ((a shl 24) or (r shl 16) or (g shl 8) or b)
return result
}

View File

@@ -1,22 +0,0 @@
package mods.octarinecore.client
import net.minecraft.client.settings.KeyBinding
import net.minecraftforge.client.event.InputEvent
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.client.registry.ClientRegistry
class KeyHandler(val modId: String, val defaultKey: Int, val lang: String, val action: (InputEvent.KeyInputEvent)->Unit) {
val keyBinding = KeyBinding(lang, defaultKey, modId)
init {
ClientRegistry.registerKeyBinding(keyBinding)
MinecraftForge.EVENT_BUS.register(this)
}
@SubscribeEvent
fun handleKeyPress(event: InputEvent.KeyInputEvent) {
if (keyBinding.isPressed) action(event)
}
}

View File

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

View File

@@ -1,45 +0,0 @@
@file:JvmName("RendererHolder")
package mods.octarinecore.client.render
import mods.betterfoliage.client.render.canRenderInCutout
import mods.betterfoliage.client.render.isCutout
import mods.octarinecore.ThreadLocalDelegate
import mods.octarinecore.client.resource.ResourceHandler
import mods.octarinecore.common.Double3
import mods.octarinecore.common.Int3
import mods.octarinecore.common.allDirOffsets
import mods.octarinecore.common.plus
import mods.octarinecore.semiRandom
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.BlockRendererDispatcher
import net.minecraft.client.renderer.BufferBuilder
import net.minecraft.client.renderer.color.BlockColors
import net.minecraft.util.BlockRenderLayer
import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper
import net.minecraft.world.IEnviromentBlockReader
import net.minecraft.world.biome.Biome
import net.minecraftforge.client.model.data.IModelData
import net.minecraftforge.eventbus.api.IEventBus
import java.util.*
import kotlin.math.abs
abstract class RenderDecorator(modId: String, modBus: IEventBus) : ResourceHandler(modId, modBus) {
open val renderOnCutout: Boolean get() = true
open val onlyOnCutout: Boolean get() = false
// ============================
// Custom rendering
// ============================
abstract fun isEligible(ctx: CombinedContext): Boolean
abstract fun render(ctx: CombinedContext)
}
data class BlockData(val state: BlockState, val color: Int, val brightness: Int)

View File

@@ -1,5 +0,0 @@
@file:JvmName("PixelFormat")
package mods.octarinecore.client.render.lighting
import java.awt.Color

View File

@@ -1,108 +0,0 @@
@file:JvmName("Utils")
package mods.octarinecore.client.resource
import mods.octarinecore.PI2
import mods.octarinecore.client.render.lighting.HSB
import mods.octarinecore.stripStart
import mods.octarinecore.tryDefault
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.model.BlockModel
import net.minecraft.client.renderer.texture.AtlasTexture
import net.minecraft.client.renderer.texture.MissingTextureSprite
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.resources.IResource
import net.minecraft.resources.IResourceManager
import net.minecraft.resources.SimpleReloadableResourceManager
import net.minecraft.util.ResourceLocation
import java.awt.image.BufferedImage
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.lang.Math.*
import javax.imageio.ImageIO
import kotlin.math.atan2
/** Concise getter for the Minecraft resource manager. */
val resourceManager: SimpleReloadableResourceManager
get() =
Minecraft.getInstance().resourceManager as SimpleReloadableResourceManager
/** Append a string to the [ResourceLocation]'s path. */
operator fun ResourceLocation.plus(str: String) = ResourceLocation(namespace, path + str)
/** 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. */
operator fun IResourceManager.get(location: ResourceLocation): IResource? = tryDefault(null) { getResource(location) }
/** Index operator to get a texture sprite. */
operator fun AtlasTexture.get(res: ResourceLocation): TextureAtlasSprite? = getSprite(res)
operator fun AtlasTexture.get(name: String): TextureAtlasSprite? = getSprite(ResourceLocation(name))
val missingSprite: TextureAtlasSprite get() = MissingTextureSprite.func_217790_a()
/** Load an image resource. */
fun IResource.loadImage(): BufferedImage? = ImageIO.read(this.inputStream)
/** Get the lines of a text resource. */
fun IResource.getLines(): List<String> {
val result = arrayListOf<String>()
inputStream.bufferedReader().useLines { it.forEach { result.add(it) } }
return result
}
/** Index operator to get the RGB value of a pixel. */
operator fun BufferedImage.get(x: Int, y: Int) = this.getRGB(x, y)
/** Index operator to set the RGB value of a pixel. */
operator fun BufferedImage.set(x: Int, y: Int, value: Int) = this.setRGB(x, y, value)
/** Get an [InputStream] to an image object in PNG format. */
val BufferedImage.asStream: InputStream get() =
ByteArrayInputStream(ByteArrayOutputStream().let { ImageIO.write(this, "PNG", it); it.toByteArray() })
val BufferedImage.bytes: ByteArray get() =
ByteArrayOutputStream().let { ImageIO.write(this, "PNG", it); it.toByteArray() }
/**
* Calculate the average color of a texture.
*
* Only non-transparent pixels are considered. Averages are taken in the HSB color space (note: Hue is a circular average),
* and the result transformed back to the RGB color space.
*/
val TextureAtlasSprite.averageColor: Int get() {
var numOpaque = 0
var sumHueX = 0.0
var sumHueY = 0.0
var sumSaturation = 0.0f
var sumBrightness = 0.0f
for (x in 0 until width)
for (y in 0 until height) {
val pixel = getPixelRGBA(0, x, y)
val alpha = (pixel shr 24) and 255
val hsb = HSB.fromColor(pixel)
if (alpha == 255) {
numOpaque++
sumHueX += cos((hsb.hue.toDouble() - 0.5) * PI2)
sumHueY += sin((hsb.hue.toDouble() - 0.5) * PI2)
sumSaturation += hsb.saturation
sumBrightness += hsb.brightness
}
}
// circular average - transform sum vector to polar angle
val avgHue = (atan2(sumHueY, sumHueX) / PI2 + 0.5).toFloat()
return HSB(avgHue, sumSaturation / numOpaque.toFloat(), sumBrightness / numOpaque.toFloat()).asColor
}
/**
* Get the actual location of a texture from the name of its [TextureAtlasSprite].
*/
fun textureLocation(iconName: String) = ResourceLocation(iconName).let {
if (it.path.startsWith("mcpatcher")) it
else ResourceLocation(it.namespace, "textures/${it.path}")
}
fun Pair<BlockModel, ResourceLocation>.derivesFrom(targetLocation: ResourceLocation): Boolean {
if (second.stripStart("models/") == targetLocation) return true
if (first.parent != null && first.parentLocation != null)
return Pair(first.parent!!, first.parentLocation!!).derivesFrom(targetLocation)
return false
}