Merge remote-tracking branch 'upstream/1.20/dev' into feat/multi-loader-1.21

# Conflicts:
#	common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java
#	common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelUtil.java
#	common/src/lib/java/dev/engine_room/flywheel/lib/model/Models.java
#	fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBakedModelBuilder.java
#	fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBlockModelBuilder.java
#	fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricMultiBlockModelBuilder.java
#	fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java
#	forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBakedModelBuilder.java
#	forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBlockModelBuilder.java
#	forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeMultiBlockModelBuilder.java
#	forge/src/main/java/dev/engine_room/flywheel/impl/FlywheelForge.java
#	neoforge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java
#	neoforge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java
This commit is contained in:
IThundxr 2024-12-27 11:19:33 -05:00
commit 14a6447806
Failed to generate hash of commit
19 changed files with 68 additions and 94 deletions

BIN
.github/logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -1,10 +1,13 @@
<div align="center">
<img src="https://i.imgur.com/yVFgPpr.png" alt="Logo by @voxel_dani on Twitter" width="250">
<img src=".github/logo.png" alt="Logo by jnix" width="250">
<h1>Flywheel</h1>
<h6>A modern engine for modded Minecraft.</h6>
<a href='https://ci.tterrag.com/job/Flywheel/job/Forge/job/1.18/'><img src='https://ci.tterrag.com/job/Flywheel/job/Forge/job/1.18/badge/icon' alt="Jenkins"></a>
<h6>Reinventing the wheel so you don't have to.</h6>
<a href='https://ci.tterrag.com/job/Flywheel/job/1.20.1/'><img src='https://ci.tterrag.com/job/Flywheel/job/1.20.1/badge/icon' alt="Jenkins"></a>
<a href="/LICENSE.md"><img src="https://img.shields.io/github/license/Engine-Room/Flywheel?style=flat&color=900c3f" alt="License"></a>
<br>
<a href="https://discord.gg/xjD59ThnXy"><img src="https://img.shields.io/discord/841464837406195712?color=5865f2&label=Discord&style=flat" alt="Discord"></a>
<a href="https://www.curseforge.com/minecraft/mc-mods/flywheel"><img src="http://cf.way2muchnoise.eu/486392.svg" alt="Curseforge Downloads"></a>
<a href="https://modrinth.com/mod/flywheel"><img src="https://img.shields.io/modrinth/dt/flywheel?logo=modrinth&label=&suffix=%20&style=flat&color=242629&labelColor=5ca424&logoColor=1c1c1c" alt="Modrinth"></a>
<br>
</div>
@ -16,22 +19,12 @@ graphics programming.
### Instancing
Flywheel provides an alternate, unified path for entity and tile entity rendering that takes advantage of GPU
instancing. In doing so, Flywheel gives the developer the flexibility to define their own vertex and instance formats,
and write custom shaders to ingest that data.
Flywheel provides an alternate, unified path for entity and block entity rendering that takes advantage of GPU
instancing. Flywheel gives the developer the flexibility to define their instance formats and write custom shaders
to ingest that data.
### Shaders
To accomodate the developer and leave more in the hands of the engine, Flywheel provides a custom shader loading and
templating system to hide the details of the CPU/GPU interface. This system is a work in progress. There will be
breaking changes, and I make no guarantees of backwards compatibility.
### Plans
- Vanilla performance improvements
- Compute shader particles
- Deferred rendering
- Different renderers for differently aged hardware
To accommodate the developer and leave more in the hands of the engine, Flywheel provides a custom shader loading and
templating system to hide the details of the CPU/GPU interface.
### Getting Started (For Developers)

View file

@ -7,7 +7,6 @@ import dev.engine_room.flywheel.lib.model.SimpleModel;
import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.BlockModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.MultiBlockModelBuilder;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.resources.ResourceLocation;
@ -18,8 +17,6 @@ public interface FlwLibXplat {
@UnknownNullability
BakedModel getBakedModel(ModelManager modelManager, ResourceLocation location);
BlockRenderDispatcher createVanillaBlockRenderDispatcher();
SimpleModel buildBakedModelBuilder(BakedModelBuilder builder);
SimpleModel buildBlockModelBuilder(BlockModelBuilder builder);

View file

@ -10,20 +10,13 @@ import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.model.Mesh;
import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.api.vertex.VertexList;
import dev.engine_room.flywheel.lib.internal.FlwLibXplat;
import dev.engine_room.flywheel.lib.material.Materials;
import dev.engine_room.flywheel.lib.memory.MemoryBlock;
import dev.engine_room.flywheel.lib.vertex.PosVertexView;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
public final class ModelUtil {
/**
* An alternative BlockRenderDispatcher that circumvents the NeoForge rendering pipeline to ensure consistency.
* Meant to be used for virtual rendering.
*/
public static final BlockRenderDispatcher VANILLA_RENDERER = FlwLibXplat.INSTANCE.createVanillaBlockRenderDispatcher();
private static final float BOUNDING_SPHERE_EPSILON = 1e-4f;
private ModelUtil() {

View file

@ -9,7 +9,7 @@ import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.BlockModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
import dev.engine_room.flywheel.lib.transform.TransformStack;
import dev.engine_room.flywheel.lib.util.ResourceReloadCache;
import dev.engine_room.flywheel.lib.util.RendererReloadCache;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
@ -20,11 +20,11 @@ import net.minecraft.world.level.block.state.BlockState;
* method with the same parameters will return the same object.
*/
public final class Models {
private static final ResourceReloadCache<BlockState, Model> BLOCK_STATE = new ResourceReloadCache<>(it -> new BlockModelBuilder(it)
private static final RendererReloadCache<BlockState, Model> BLOCK_STATE = new RendererReloadCache<>(it -> new BlockModelBuilder(it)
.build());
private static final ResourceReloadCache<PartialModel, Model> PARTIAL = new ResourceReloadCache<>(it -> new BakedModelBuilder(it.get())
private static final RendererReloadCache<PartialModel, Model> PARTIAL = new RendererReloadCache<>(it -> new BakedModelBuilder(it.get())
.build());
private static final ResourceReloadCache<TransformedPartial<?>, Model> TRANSFORMED_PARTIAL = new ResourceReloadCache<>(TransformedPartial::create);
private static final RendererReloadCache<TransformedPartial<?>, Model> TRANSFORMED_PARTIAL = new RendererReloadCache<>(TransformedPartial::create);
private Models() {
}

View file

@ -11,7 +11,7 @@ import dev.engine_room.flywheel.api.model.Mesh;
import dev.engine_room.flywheel.lib.internal.FlwLibLink;
import dev.engine_room.flywheel.lib.memory.MemoryBlock;
import dev.engine_room.flywheel.lib.model.SimpleQuadMesh;
import dev.engine_room.flywheel.lib.util.ResourceReloadCache;
import dev.engine_room.flywheel.lib.util.RendererReloadCache;
import dev.engine_room.flywheel.lib.vertex.PosTexNormalVertexView;
import dev.engine_room.flywheel.lib.vertex.VertexView;
import net.minecraft.client.Minecraft;
@ -25,7 +25,7 @@ import net.minecraft.client.renderer.texture.OverlayTexture;
public final class MeshTree {
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
private static final PoseStack.Pose IDENTITY_POSE = new PoseStack().last();
private static final ResourceReloadCache<ModelLayerLocation, MeshTree> CACHE = new ResourceReloadCache<>(MeshTree::convert);
private static final RendererReloadCache<ModelLayerLocation, MeshTree> CACHE = new RendererReloadCache<>(MeshTree::convert);
@Nullable
private final Mesh mesh;

View file

@ -12,12 +12,12 @@ import dev.engine_room.flywheel.api.model.Mesh;
import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.lib.model.RetexturedMesh;
import dev.engine_room.flywheel.lib.model.SingleMeshModel;
import dev.engine_room.flywheel.lib.util.ResourceReloadCache;
import dev.engine_room.flywheel.lib.util.RendererReloadCache;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
public final class ModelTrees {
private static final ResourceReloadCache<ModelTreeKey, ModelTree> CACHE = new ResourceReloadCache<>(k -> {
private static final RendererReloadCache<ModelTreeKey, ModelTree> CACHE = new RendererReloadCache<>(k -> {
ModelTree tree = convert("", MeshTree.of(k.layer), k.pathsToPrune, k.texture != null ? k.texture.sprite() : null, k.material);
if (tree == null) {

View file

@ -9,12 +9,12 @@ import java.util.function.Function;
import org.jetbrains.annotations.ApiStatus;
public final class ResourceReloadCache<T, U> implements Function<T, U> {
private static final Set<ResourceReloadCache<?, ?>> ALL = Collections.newSetFromMap(new WeakHashMap<>());
public final class RendererReloadCache<T, U> implements Function<T, U> {
private static final Set<RendererReloadCache<?, ?>> ALL = Collections.newSetFromMap(new WeakHashMap<>());
private final Function<T, U> factory;
private final Map<T, U> map = new ConcurrentHashMap<>();
public ResourceReloadCache(Function<T, U> factory) {
public RendererReloadCache(Function<T, U> factory) {
this.factory = factory;
synchronized (ALL) {
@ -36,8 +36,8 @@ public final class ResourceReloadCache<T, U> implements Function<T, U> {
}
@ApiStatus.Internal
public static void onEndClientResourceReload() {
for (ResourceReloadCache<?, ?> cache : ALL) {
public static void onReloadLevelRenderer() {
for (RendererReloadCache<?, ?> cache : ALL) {
cache.clear();
}
}

View file

@ -17,7 +17,7 @@ import dev.engine_room.flywheel.lib.material.Materials;
import dev.engine_room.flywheel.lib.material.SimpleMaterial;
import dev.engine_room.flywheel.lib.model.QuadMesh;
import dev.engine_room.flywheel.lib.model.SingleMeshModel;
import dev.engine_room.flywheel.lib.util.ResourceReloadCache;
import dev.engine_room.flywheel.lib.util.RendererReloadCache;
import dev.engine_room.flywheel.lib.visual.util.SmartRecycler;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@ -36,7 +36,7 @@ public final class FireComponent implements EntityComponent {
// Parameterize by the material instead of the sprite
// because Material#sprite is a surprisingly heavy operation
// and because sprites are invalidated after a resource reload.
private static final ResourceReloadCache<net.minecraft.client.resources.model.Material, Model> FIRE_MODELS = new ResourceReloadCache<>(texture -> {
private static final RendererReloadCache<net.minecraft.client.resources.model.Material, Model> FIRE_MODELS = new RendererReloadCache<>(texture -> {
return new SingleMeshModel(new FireMesh(texture.sprite()), FIRE_MATERIAL);
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -9,6 +9,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
@ -32,7 +33,7 @@ final class BakedModelBufferer {
private BakedModelBufferer() {
}
public static void bufferSingle(ModelBlockRenderer blockRenderer, @Nullable BlockAndTintGetter level, BakedModel model, @Nullable BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) {
public static void bufferSingle(@Nullable BlockAndTintGetter level, BakedModel model, @Nullable BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) {
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
if (level == null) {
if (state == null) {
@ -60,7 +61,10 @@ final class BakedModelBufferer {
model = universalEmitter.wrapModel(model);
poseStack.pushPose();
blockRenderer.tesselateBlock(level, model, state, BlockPos.ZERO, poseStack, universalEmitter, false, random, 42L, OverlayTexture.NO_OVERLAY);
Minecraft.getInstance()
.getBlockRenderer()
.getModelRenderer()
.tesselateBlock(level, model, state, BlockPos.ZERO, poseStack, universalEmitter, false, random, 42L, OverlayTexture.NO_OVERLAY);
poseStack.popPose();
universalEmitter.clear();
@ -70,15 +74,18 @@ final class BakedModelBufferer {
}
}
public static void bufferBlock(BlockRenderDispatcher renderDispatcher, @Nullable BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) {
public static void bufferBlock(@Nullable BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) {
if (state.getRenderShape() != RenderShape.MODEL) {
return;
}
bufferSingle(renderDispatcher.getModelRenderer(), level, renderDispatcher.getBlockModel(state), state, poseStack, resultConsumer);
var blockModel = Minecraft.getInstance()
.getBlockRenderer()
.getBlockModel(state);
bufferSingle(level, blockModel, state, poseStack, resultConsumer);
}
public static void bufferMultiBlock(BlockRenderDispatcher renderDispatcher, Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, boolean renderFluids, ResultConsumer resultConsumer) {
public static void bufferMultiBlock(Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, boolean renderFluids, ResultConsumer resultConsumer) {
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
if (poseStack == null) {
poseStack = objects.identityPoseStack;
@ -93,6 +100,9 @@ final class BakedModelBufferer {
emitter.prepare(resultConsumer);
}
BlockRenderDispatcher renderDispatcher = Minecraft.getInstance()
.getBlockRenderer();
ModelBlockRenderer blockRenderer = renderDispatcher.getModelRenderer();
ModelBlockRenderer.enableCaching();

View file

@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus;
import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.model.Mesh;
import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.lib.model.ModelUtil;
import dev.engine_room.flywheel.lib.model.SimpleModel;
@ApiStatus.Internal
@ -16,7 +15,7 @@ public final class ModelBuilderImpl {
public static SimpleModel buildBakedModelBuilder(BakedModelBuilder builder) {
var builder1 = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>getThreadLocal();
BakedModelBufferer.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), builder.level, builder.bakedModel, builder.blockState, builder.poseStack, (renderType, shaded, data) -> {
BakedModelBufferer.bufferSingle(builder.level, builder.bakedModel, builder.blockState, builder.poseStack, (renderType, shaded, data) -> {
Material material = builder.materialFunc.apply(renderType, shaded);
if (material != null) {
Mesh mesh = MeshHelper.blockVerticesToMesh(data, "source=BakedModelBuilder," + "bakedModel=" + builder.bakedModel + ",renderType=" + renderType + ",shaded=" + shaded);
@ -30,7 +29,7 @@ public final class ModelBuilderImpl {
public static SimpleModel buildBlockModelBuilder(BlockModelBuilder builder) {
var builder1 = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>getThreadLocal();
BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, builder.level, builder.state, builder.poseStack, (renderType, shaded, data) -> {
BakedModelBufferer.bufferBlock(builder.level, builder.state, builder.poseStack, (renderType, shaded, data) -> {
Material material = builder.materialFunc.apply(renderType, shaded);
if (material != null) {
Mesh mesh = MeshHelper.blockVerticesToMesh(data, "source=BlockModelBuilder," + "blockState=" + builder.state + ",renderType=" + renderType + ",shaded=" + shaded);
@ -44,7 +43,7 @@ public final class ModelBuilderImpl {
public static SimpleModel buildMultiBlockModelBuilder(MultiBlockModelBuilder builder) {
var builder1 = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>getThreadLocal();
BakedModelBufferer.bufferMultiBlock(ModelUtil.VANILLA_RENDERER, builder.positions.iterator(), builder.level, builder.poseStack, builder.renderFluids, (renderType, shaded, data) -> {
BakedModelBufferer.bufferMultiBlock(builder.positions.iterator(), builder.level, builder.poseStack, builder.renderFluids, (renderType, shaded, data) -> {
Material material = builder.materialFunc.apply(renderType, shaded);
if (material != null) {
Mesh mesh = MeshHelper.blockVerticesToMesh(data, "source=MultiBlockModelBuilder," + "renderType=" + renderType + ",shaded=" + shaded);

View file

@ -8,8 +8,6 @@ import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.BlockModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.ModelBuilderImpl;
import dev.engine_room.flywheel.lib.model.baked.MultiBlockModelBuilder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.resources.ResourceLocation;
@ -21,11 +19,6 @@ public class FlwLibXplatImpl implements FlwLibXplat {
return modelManager.getModel(location);
}
@Override
public BlockRenderDispatcher createVanillaBlockRenderDispatcher() {
return Minecraft.getInstance().getBlockRenderer();
}
@Override
public SimpleModel buildBakedModelBuilder(BakedModelBuilder builder) {
return ModelBuilderImpl.buildBakedModelBuilder(builder);

View file

@ -9,7 +9,7 @@ import dev.engine_room.flywheel.backend.compile.FlwProgramsReloader;
import dev.engine_room.flywheel.backend.engine.uniform.Uniforms;
import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
import dev.engine_room.flywheel.lib.util.ResourceReloadCache;
import dev.engine_room.flywheel.lib.util.RendererReloadCache;
import dev.engine_room.flywheel.lib.util.ResourceReloadHolder;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
@ -66,7 +66,7 @@ public final class FlywheelFabric implements ClientModInitializer {
}
private static void setupLib() {
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) -> ResourceReloadCache.onEndClientResourceReload());
ReloadLevelRendererCallback.EVENT.register(level -> RendererReloadCache.onReloadLevelRenderer());
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) -> ResourceReloadHolder.onEndClientResourceReload());
ModelLoadingPlugin.register(ctx -> {

View file

@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
@ -32,7 +33,7 @@ final class BakedModelBufferer {
private BakedModelBufferer() {
}
public static void bufferSingle(ModelBlockRenderer blockRenderer, @Nullable BlockAndTintGetter level, BakedModel model, @Nullable BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) {
public static void bufferSingle(@Nullable BlockAndTintGetter level, BakedModel model, @Nullable BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) {
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
if (level == null) {
if (state == null) {
@ -54,6 +55,10 @@ final class BakedModelBufferer {
random.setSeed(42L);
ChunkRenderTypeSet renderTypes = model.getRenderTypes(state, random, modelData);
ModelBlockRenderer blockRenderer = Minecraft.getInstance()
.getBlockRenderer()
.getModelRenderer();
for (RenderType renderType : renderTypes) {
int layerIndex = renderType.getChunkLayerId();
MeshEmitter emitter = emitters[layerIndex];
@ -68,15 +73,18 @@ final class BakedModelBufferer {
}
}
public static void bufferBlock(BlockRenderDispatcher renderDispatcher, @Nullable BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) {
public static void bufferBlock(@Nullable BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) {
if (state.getRenderShape() != RenderShape.MODEL) {
return;
}
bufferSingle(renderDispatcher.getModelRenderer(), level, renderDispatcher.getBlockModel(state), state, poseStack, resultConsumer);
var blockModel = Minecraft.getInstance()
.getBlockRenderer()
.getBlockModel(state);
bufferSingle(level, blockModel, state, poseStack, resultConsumer);
}
public static void bufferMultiBlock(BlockRenderDispatcher renderDispatcher, Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, boolean renderFluids, ResultConsumer resultConsumer) {
public static void bufferMultiBlock(Iterator<BlockPos> posIterator, BlockAndTintGetter level, @Nullable PoseStack poseStack, boolean renderFluids, ResultConsumer resultConsumer) {
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
if (poseStack == null) {
poseStack = objects.identityPoseStack;
@ -89,6 +97,9 @@ final class BakedModelBufferer {
emitter.prepare(resultConsumer);
}
BlockRenderDispatcher renderDispatcher = Minecraft.getInstance()
.getBlockRenderer();
ModelBlockRenderer blockRenderer = renderDispatcher.getModelRenderer();
ModelBlockRenderer.enableCaching();

View file

@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus;
import dev.engine_room.flywheel.api.material.Material;
import dev.engine_room.flywheel.api.model.Mesh;
import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.lib.model.ModelUtil;
import dev.engine_room.flywheel.lib.model.SimpleModel;
@ApiStatus.Internal
@ -16,7 +15,7 @@ public final class ModelBuilderImpl {
public static SimpleModel buildBakedModelBuilder(BakedModelBuilder builder) {
var builder1 = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>getThreadLocal();
BakedModelBufferer.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), builder.level, builder.bakedModel, builder.blockState, builder.poseStack, (renderType, shaded, data) -> {
BakedModelBufferer.bufferSingle(builder.level, builder.bakedModel, builder.blockState, builder.poseStack, (renderType, shaded, data) -> {
Material material = builder.materialFunc.apply(renderType, shaded);
if (material != null) {
Mesh mesh = MeshHelper.blockVerticesToMesh(data, "source=BakedModelBuilder," + "bakedModel=" + builder.bakedModel + ",renderType=" + renderType + ",shaded=" + shaded);
@ -30,7 +29,7 @@ public final class ModelBuilderImpl {
public static SimpleModel buildBlockModelBuilder(BlockModelBuilder builder) {
var builder1 = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>getThreadLocal();
BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, builder.level, builder.state, builder.poseStack, (renderType, shaded, data) -> {
BakedModelBufferer.bufferBlock(builder.level, builder.state, builder.poseStack, (renderType, shaded, data) -> {
Material material = builder.materialFunc.apply(renderType, shaded);
if (material != null) {
Mesh mesh = MeshHelper.blockVerticesToMesh(data, "source=BlockModelBuilder," + "blockState=" + builder.state + ",renderType=" + renderType + ",shaded=" + shaded);
@ -44,7 +43,7 @@ public final class ModelBuilderImpl {
public static SimpleModel buildMultiBlockModelBuilder(MultiBlockModelBuilder builder) {
var builder1 = ChunkLayerSortedListBuilder.<Model.ConfiguredMesh>getThreadLocal();
BakedModelBufferer.bufferMultiBlock(ModelUtil.VANILLA_RENDERER, builder.positions.iterator(), builder.level, builder.poseStack, builder.renderFluids, (renderType, shaded, data) -> {
BakedModelBufferer.bufferMultiBlock(builder.positions.iterator(), builder.level, builder.poseStack, builder.renderFluids, (renderType, shaded, data) -> {
Material material = builder.materialFunc.apply(renderType, shaded);
if (material != null) {
Mesh mesh = MeshHelper.blockVerticesToMesh(data, "source=MultiBlockModelBuilder," + "renderType=" + renderType + ",shaded=" + shaded);

View file

@ -1,7 +1,5 @@
package dev.engine_room.flywheel.impl;
import java.lang.reflect.Field;
import org.jetbrains.annotations.UnknownNullability;
import dev.engine_room.flywheel.lib.internal.FlwLibXplat;
@ -10,14 +8,12 @@ import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.BlockModelBuilder;
import dev.engine_room.flywheel.lib.model.baked.ModelBuilderImpl;
import dev.engine_room.flywheel.lib.model.baked.MultiBlockModelBuilder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public class FlwLibXplatImpl implements FlwLibXplat {
@Override
@ -26,23 +22,6 @@ public class FlwLibXplatImpl implements FlwLibXplat {
return modelManager.getModel(ModelResourceLocation.standalone(location));
}
@Override
public BlockRenderDispatcher createVanillaBlockRenderDispatcher() {
BlockRenderDispatcher defaultDispatcher = Minecraft.getInstance().getBlockRenderer();
BlockRenderDispatcher dispatcher = new BlockRenderDispatcher(null, null, null);
try {
for (Field field : BlockRenderDispatcher.class.getDeclaredFields()) {
field.setAccessible(true);
field.set(dispatcher, field.get(defaultDispatcher));
}
ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "modelRenderer");
} catch (Exception e) {
FlwImpl.LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e);
return defaultDispatcher;
}
return dispatcher;
}
@Override
public SimpleModel buildBakedModelBuilder(BakedModelBuilder builder) {
return ModelBuilderImpl.buildBakedModelBuilder(builder);

View file

@ -12,7 +12,7 @@ import dev.engine_room.flywheel.impl.compat.EmbeddiumCompat;
import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler;
import dev.engine_room.flywheel.lib.model.baked.PartialModelEventHandler;
import dev.engine_room.flywheel.lib.util.LevelAttached;
import dev.engine_room.flywheel.lib.util.ResourceReloadCache;
import dev.engine_room.flywheel.lib.util.RendererReloadCache;
import dev.engine_room.flywheel.lib.util.ResourceReloadHolder;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
@ -99,7 +99,7 @@ public final class FlywheelNeoForge {
private static void registerLibEventListeners(IEventBus gameEventBus, IEventBus modEventBus) {
gameEventBus.addListener((LevelEvent.Unload e) -> LevelAttached.invalidateLevel(e.getLevel()));
modEventBus.addListener((EndClientResourceReloadEvent e) -> ResourceReloadCache.onEndClientResourceReload());
modEventBus.addListener((EndClientResourceReloadEvent e) -> RendererReloadCache.onReloadLevelRenderer());
modEventBus.addListener((EndClientResourceReloadEvent e) -> ResourceReloadHolder.onEndClientResourceReload());
modEventBus.addListener(PartialModelEventHandler::onRegisterAdditional);