From 7e7568bf8994cb3d0a03d66300a7958c93c96ee8 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:15:42 -0800 Subject: [PATCH] Add SpecialBlockRendererRegistry (#4271) --- .../v1/SpecialBlockRendererRegistry.java | 43 ++++++++++ .../SpecialBlockRendererRegistryImpl.java | 38 +++++++++ .../rendering/SpecialModelTypesMixin.java | 52 ++++++++++++ .../resources/fabric-rendering-v1.mixins.json | 1 + .../src/testmod/resources/fabric.mod.json | 1 + .../client/SpecialBlockRendererTest.java | 80 +++++++++++++++++++ 6 files changed, 215 insertions(+) create mode 100644 fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/SpecialBlockRendererRegistry.java create mode 100644 fabric-rendering-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/SpecialBlockRendererRegistryImpl.java create mode 100644 fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/SpecialModelTypesMixin.java create mode 100644 fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/SpecialBlockRendererTest.java diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/SpecialBlockRendererRegistry.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/SpecialBlockRendererRegistry.java new file mode 100644 index 0000000000..9821c41165 --- /dev/null +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/SpecialBlockRendererRegistry.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.rendering.v1; + +import net.minecraft.block.Block; +import net.minecraft.client.render.block.BlockRenderManager; +import net.minecraft.client.render.block.entity.LoadedBlockEntityModels; +import net.minecraft.client.render.item.model.special.SpecialModelRenderer; + +import net.fabricmc.fabric.impl.client.rendering.SpecialBlockRendererRegistryImpl; + +/** + * Allows registering special renderers for certain blocks, such that they are used when + * {@link LoadedBlockEntityModels#render} is invoked. The most common use of this method is through + * {@link BlockRenderManager#renderBlockAsEntity}, which is used for rendering blocks in minecarts, blocks held by + * endermen, and other cases. + */ +public final class SpecialBlockRendererRegistry { + private SpecialBlockRendererRegistry() { + } + + /** + * Assign the given unbaked renderer to the given block. {@link SpecialModelRenderer.Unbaked#getCodec()} will not be + * used and can return {@code null}. + */ + public static void register(Block block, SpecialModelRenderer.Unbaked unbakedRenderer) { + SpecialBlockRendererRegistryImpl.register(block, unbakedRenderer); + } +} diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/SpecialBlockRendererRegistryImpl.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/SpecialBlockRendererRegistryImpl.java new file mode 100644 index 0000000000..208cfef2ae --- /dev/null +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/impl/client/rendering/SpecialBlockRendererRegistryImpl.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.client.rendering; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +import net.minecraft.block.Block; +import net.minecraft.client.render.item.model.special.SpecialModelRenderer; + +public final class SpecialBlockRendererRegistryImpl { + private static final Map MAP = new HashMap<>(); + private static BiConsumer handler = MAP::put; + + public static void setup(BiConsumer vanillaHandler) { + MAP.forEach(vanillaHandler); + handler = vanillaHandler; + } + + public static void register(Block block, SpecialModelRenderer.Unbaked unbakedRenderer) { + handler.accept(block, unbakedRenderer); + } +} diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/SpecialModelTypesMixin.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/SpecialModelTypesMixin.java new file mode 100644 index 0000000000..219cca3f48 --- /dev/null +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/SpecialModelTypesMixin.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.client.rendering; + +import java.util.HashMap; +import java.util.Map; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +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.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.client.render.item.model.special.SpecialModelRenderer; +import net.minecraft.client.render.item.model.special.SpecialModelTypes; + +import net.fabricmc.fabric.impl.client.rendering.SpecialBlockRendererRegistryImpl; + +@Mixin(SpecialModelTypes.class) +abstract class SpecialModelTypesMixin { + @Shadow + @Final + @Mutable + private static Map BLOCK_TO_MODEL_TYPE; + + @Inject(at = @At("RETURN"), method = "*") + private static void onReturnClinit(CallbackInfo ci) { + // The map is normally an ImmutableMap. + if (!(BLOCK_TO_MODEL_TYPE instanceof HashMap)) { + BLOCK_TO_MODEL_TYPE = new HashMap<>(BLOCK_TO_MODEL_TYPE); + } + + SpecialBlockRendererRegistryImpl.setup(BLOCK_TO_MODEL_TYPE::put); + } +} diff --git a/fabric-rendering-v1/src/client/resources/fabric-rendering-v1.mixins.json b/fabric-rendering-v1/src/client/resources/fabric-rendering-v1.mixins.json index 58e0b7c8ba..e0e8f9c415 100644 --- a/fabric-rendering-v1/src/client/resources/fabric-rendering-v1.mixins.json +++ b/fabric-rendering-v1/src/client/resources/fabric-rendering-v1.mixins.json @@ -15,6 +15,7 @@ "EntityRenderersMixin", "InGameHudMixin", "LivingEntityRendererAccessor", + "SpecialModelTypesMixin", "TooltipComponentMixin", "WorldRendererMixin" ], diff --git a/fabric-rendering-v1/src/testmod/resources/fabric.mod.json b/fabric-rendering-v1/src/testmod/resources/fabric.mod.json index 57107b39f9..1c57a5f298 100644 --- a/fabric-rendering-v1/src/testmod/resources/fabric.mod.json +++ b/fabric-rendering-v1/src/testmod/resources/fabric.mod.json @@ -18,6 +18,7 @@ "net.fabricmc.fabric.test.rendering.client.DimensionalRenderingTest", "net.fabricmc.fabric.test.rendering.client.FeatureRendererTest", "net.fabricmc.fabric.test.rendering.client.HudAndShaderTest", + "net.fabricmc.fabric.test.rendering.client.SpecialBlockRendererTest", "net.fabricmc.fabric.test.rendering.client.TooltipComponentTests", "net.fabricmc.fabric.test.rendering.client.WorldRenderEventsTests" ] diff --git a/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/SpecialBlockRendererTest.java b/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/SpecialBlockRendererTest.java new file mode 100644 index 0000000000..4b8a51c218 --- /dev/null +++ b/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/SpecialBlockRendererTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.rendering.client; + +import com.mojang.serialization.MapCodec; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.block.Blocks; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.model.AllayEntityModel; +import net.minecraft.client.render.entity.model.EntityModelLayers; +import net.minecraft.client.render.entity.model.LoadedEntityModels; +import net.minecraft.client.render.item.model.special.SpecialModelRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ModelTransformationMode; +import net.minecraft.util.Identifier; +import net.minecraft.util.Util; +import net.minecraft.util.math.RotationAxis; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.rendering.v1.SpecialBlockRendererRegistry; + +/** + * Tests {@link SpecialBlockRendererRegistry} by rendering an allay model above TNT blocks in a minecart. + */ +public class SpecialBlockRendererTest implements ClientModInitializer { + private static final Identifier ALLAY_TEXTURE = Identifier.ofVanilla("textures/entity/allay/allay.png"); + + @Override + public void onInitializeClient() { + SpecialBlockRendererRegistry.register(Blocks.TNT, new SpecialModelRenderer.Unbaked() { + @Override + public SpecialModelRenderer bake(LoadedEntityModels entityModels) { + AllayEntityModel allayModel = new AllayEntityModel(entityModels.getModelPart(EntityModelLayers.ALLAY)); + + return new SpecialModelRenderer<>() { + @Override + public void render(@Nullable Object data, ModelTransformationMode modelTransformationMode, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, boolean glint) { + matrices.push(); + matrices.translate(0.5f, 0.0f, 0.5f); + matrices.translate(0, 1.46875f, 0); + matrices.scale(1, -1, 1); + matrices.multiply(RotationAxis.POSITIVE_Y.rotation((float) (Util.getMeasuringTimeMs() * 0.001))); + matrices.translate(0, -1.46875f, 0); + VertexConsumer vertexConsumer = vertexConsumers.getBuffer(allayModel.getLayer(ALLAY_TEXTURE)); + allayModel.render(matrices, vertexConsumer, light, overlay); + matrices.pop(); + } + + @Override + @Nullable + public Object getData(ItemStack stack) { + return null; + } + }; + } + + @Override + public MapCodec getCodec() { + return null; + } + }); + } +}