Skip to content

Commit

Permalink
Add SpecialBlockRendererRegistry (#4271)
Browse files Browse the repository at this point in the history
  • Loading branch information
PepperCode1 authored Dec 5, 2024
1 parent efb4f0f commit 7e7568b
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<Block, SpecialModelRenderer.Unbaked> MAP = new HashMap<>();
private static BiConsumer<Block, SpecialModelRenderer.Unbaked> handler = MAP::put;

public static void setup(BiConsumer<Block, SpecialModelRenderer.Unbaked> vanillaHandler) {
MAP.forEach(vanillaHandler);
handler = vanillaHandler;
}

public static void register(Block block, SpecialModelRenderer.Unbaked unbakedRenderer) {
handler.accept(block, unbakedRenderer);
}
}
Original file line number Diff line number Diff line change
@@ -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, SpecialModelRenderer.Unbaked> BLOCK_TO_MODEL_TYPE;

@Inject(at = @At("RETURN"), method = "<clinit>*")
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"EntityRenderersMixin",
"InGameHudMixin",
"LivingEntityRendererAccessor",
"SpecialModelTypesMixin",
"TooltipComponentMixin",
"WorldRendererMixin"
],
Expand Down
1 change: 1 addition & 0 deletions fabric-rendering-v1/src/testmod/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
Expand Down
Original file line number Diff line number Diff line change
@@ -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<? extends SpecialModelRenderer.Unbaked> getCodec() {
return null;
}
});
}
}

0 comments on commit 7e7568b

Please sign in to comment.