From b0a64ff8ac3a3f55fe9b0e8848fb8ed4f5f2a138 Mon Sep 17 00:00:00 2001 From: KnightMiner Date: Tue, 22 Mar 2022 20:50:50 -0400 Subject: [PATCH] [1.18] Make it easier to register custom skull blocks models (#8351) --- .../blockentity/SkullBlockRenderer.java.patch | 10 ++ .../client/event/EntityRenderersEvent.java | 36 +++++ .../resources/META-INF/accesstransformer.cfg | 1 + .../debug/block/CustomHeadTest.java | 147 ++++++++++++++++++ src/test/resources/META-INF/mods.toml | 2 + .../blockstates/blaze_head.json | 7 + .../blockstates/blaze_wall_head.json | 7 + .../models/item/blaze_head.json | 3 + 8 files changed, 213 insertions(+) create mode 100644 patches/minecraft/net/minecraft/client/renderer/blockentity/SkullBlockRenderer.java.patch create mode 100644 src/test/java/net/minecraftforge/debug/block/CustomHeadTest.java create mode 100644 src/test/resources/assets/custom_head_test/blockstates/blaze_head.json create mode 100644 src/test/resources/assets/custom_head_test/blockstates/blaze_wall_head.json create mode 100644 src/test/resources/assets/custom_head_test/models/item/blaze_head.json diff --git a/patches/minecraft/net/minecraft/client/renderer/blockentity/SkullBlockRenderer.java.patch b/patches/minecraft/net/minecraft/client/renderer/blockentity/SkullBlockRenderer.java.patch new file mode 100644 index 0000000000..902d8fe755 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/renderer/blockentity/SkullBlockRenderer.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/client/renderer/blockentity/SkullBlockRenderer.java ++++ b/net/minecraft/client/renderer/blockentity/SkullBlockRenderer.java +@@ -52,6 +_,7 @@ + builder.put(SkullBlock.Types.ZOMBIE, new SkullModel(p_173662_.m_171103_(ModelLayers.f_171224_))); + builder.put(SkullBlock.Types.CREEPER, new SkullModel(p_173662_.m_171103_(ModelLayers.f_171130_))); + builder.put(SkullBlock.Types.DRAGON, new DragonHeadModel(p_173662_.m_171103_(ModelLayers.f_171135_))); ++ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.EntityRenderersEvent.CreateSkullModels(builder, p_173662_)); + return builder.build(); + } + diff --git a/src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java b/src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java index 04209b48d6..d3bdd84783 100644 --- a/src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java +++ b/src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java @@ -5,8 +5,10 @@ package net.minecraftforge.client.event; +import com.google.common.collect.ImmutableMap; import net.minecraft.client.Minecraft; import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.SkullModelBase; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.model.geom.ModelLayerLocation; import net.minecraft.client.model.geom.builders.LayerDefinition; @@ -20,6 +22,8 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.SkullBlock; +import net.minecraft.world.level.block.SkullBlock.Type; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraftforge.client.ForgeHooksClient; @@ -130,4 +134,36 @@ public class EntityRenderersEvent extends Event implements IModBusEvent return entityModels; } } + + /** + * Provides a safe place to register models for the skull block + */ + public static class CreateSkullModels extends EntityRenderersEvent + { + private final ImmutableMap.Builder builder; + private final EntityModelSet entityModelSet; + + public CreateSkullModels(ImmutableMap.Builder builder, EntityModelSet entityModelSet) + { + this.builder = builder; + this.entityModelSet = entityModelSet; + } + + public EntityModelSet getEntityModelSet() + { + return entityModelSet; + } + + /** + * Registers the constructor for a skull block with the given {@link SkullBlock.Type}. + * These will be inserted into the maps used by the item, entity, and block model renderers at the appropiate time. + * + * @param type Unique skull type. Will cause an exception if multiple mods (including vanilla) register models for the same type + * @param model Model instance. A typical implementation will simply do {@code new SkullModel(entityModelSet.bakeLayer(layerLocation))} + */ + public void registerSkullModel(SkullBlock.Type type, SkullModelBase model) + { + builder.put(type, model); + } + } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 519a7ea8b6..5af9e86723 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -121,6 +121,7 @@ public net.minecraft.client.renderer.block.model.ItemTransforms$Deserializer BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID); + private static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); + private static final DeferredRegister> BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITIES, MODID); + private static final RegistryObject BLAZE_HEAD = BLOCKS.register("blaze_head", () -> new CustomSkullBlock(SkullType.BLAZE, BlockBehaviour.Properties.of(Material.DECORATION).strength(1.0F))); + private static final RegistryObject BLAZE_HEAD_WALL = BLOCKS.register("blaze_wall_head", () -> new CustomWallSkullBlock(SkullType.BLAZE, BlockBehaviour.Properties.of(Material.DECORATION).strength(1.0F).lootFrom(BLAZE_HEAD))); + private static final RegistryObject BLAZE_HEAD_ITEM = ITEMS.register("blaze_head", () -> new StandingAndWallBlockItem(BLAZE_HEAD.get(), BLAZE_HEAD_WALL.get(), new Item.Properties().tab(CreativeModeTab.TAB_DECORATIONS).rarity(Rarity.UNCOMMON))); + private static final RegistryObject> CUSTOM_SKULL = BLOCK_ENTITIES.register("custom_skull", () -> BlockEntityType.Builder.of(CustomSkullBlockEntity::new, BLAZE_HEAD.get(), BLAZE_HEAD_WALL.get()).build(null)); + + public CustomHeadTest() + { + IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); + BLOCKS.register(modBus); + ITEMS.register(modBus); + BLOCK_ENTITIES.register(modBus); + } + + private static class CustomSkullBlock extends SkullBlock + { + public CustomSkullBlock(Type type, Properties props) + { + super(type, props); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) + { + return new CustomSkullBlockEntity(pos, state); + } + } + + private static class CustomWallSkullBlock extends WallSkullBlock + { + public CustomWallSkullBlock(SkullBlock.Type type, Properties props) + { + super(type, props); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) + { + return new CustomSkullBlockEntity(pos, state); + } + } + + private static class CustomSkullBlockEntity extends SkullBlockEntity + { + public CustomSkullBlockEntity(BlockPos pos, BlockState state) + { + super(pos, state); + } + + @Override + public BlockEntityType getType() + { + return CUSTOM_SKULL.get(); + } + } + + private enum SkullType implements SkullBlock.Type + { + BLAZE + } + + @Mod.EventBusSubscriber(value= Dist.CLIENT, bus = Bus.MOD, modid = MODID) + private static class ClientEvents + { + static final ModelLayerLocation BLAZE_HEAD_LAYER = new ModelLayerLocation(BLAZE_HEAD.getId(), "main"); + + @SubscribeEvent + static void registerLayerDefinitions(EntityRenderersEvent.RegisterLayerDefinitions event) + { + event.registerLayerDefinition(BLAZE_HEAD_LAYER, Lazy.of(SkullModel::createMobHeadLayer)); + } + + @SubscribeEvent + static void registerLayerDefinitions(EntityRenderersEvent.RegisterRenderers event) + { + event.registerBlockEntityRenderer(CUSTOM_SKULL.get(), SkullBlockRenderer::new); + } + + @SubscribeEvent + static void clientSetupEvent(FMLClientSetupEvent event) + { + event.enqueueWork(() -> SkullBlockRenderer.SKIN_BY_TYPE.put(SkullType.BLAZE, new ResourceLocation("textures/entity/blaze.png"))); + } + + @SubscribeEvent + static void registerSkullModel(EntityRenderersEvent.CreateSkullModels event) + { + event.registerSkullModel(SkullType.BLAZE, new SkullModel(event.getEntityModelSet().bakeLayer(ClientEvents.BLAZE_HEAD_LAYER))); + } + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 545bdc63d9..ace159af99 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -76,6 +76,8 @@ license="LGPL v2.1" modId="create_entity_classification_test" [[mods]] modId="ender_mask_test" +[[mods]] + modId="custom_head_test" [[mods]] modId="raid_enum_test" [[mods]] diff --git a/src/test/resources/assets/custom_head_test/blockstates/blaze_head.json b/src/test/resources/assets/custom_head_test/blockstates/blaze_head.json new file mode 100644 index 0000000000..3951e3eea5 --- /dev/null +++ b/src/test/resources/assets/custom_head_test/blockstates/blaze_head.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "minecraft:block/skull" + } + } +} \ No newline at end of file diff --git a/src/test/resources/assets/custom_head_test/blockstates/blaze_wall_head.json b/src/test/resources/assets/custom_head_test/blockstates/blaze_wall_head.json new file mode 100644 index 0000000000..3951e3eea5 --- /dev/null +++ b/src/test/resources/assets/custom_head_test/blockstates/blaze_wall_head.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "minecraft:block/skull" + } + } +} \ No newline at end of file diff --git a/src/test/resources/assets/custom_head_test/models/item/blaze_head.json b/src/test/resources/assets/custom_head_test/models/item/blaze_head.json new file mode 100644 index 0000000000..364b6e65fb --- /dev/null +++ b/src/test/resources/assets/custom_head_test/models/item/blaze_head.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_skull" +} \ No newline at end of file