From 6ddf56ef158af0282696f33d10ebed452a751375 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Sun, 25 Jul 2021 03:47:15 +0200 Subject: [PATCH] Added RegisterClientReloadListenersEvent which lets you register reload listeners with appropriate timing. Added new entity rendering events. - EntityRenderersEvent.RegisterLayerDefinitions: Used to register layer definitions for entity models. - EntityRenderersEvent.RegisterRenderers: Used to register entity renderers. - EntityRenderersEvent.AddLayers: Called during resource reload after all renderers have been constructed and it's safe to add layers. Removed RenderingRegistry, which is now not necessary. Removed a few unused things. Fixes #7920 --- .../net/minecraft/client/Minecraft.java.patch | 11 + .../model/geom/LayerDefinitions.java.patch | 2 +- .../entity/EntityRenderDispatcher.java.patch | 18 +- .../client/ForgeHooksClient.java | 19 ++ .../client/event/EntityRenderersEvent.java | 132 +++++++++++ .../RegisterClientReloadListenersEvent.java} | 23 +- .../fmlclient/ClientModLoader.java | 10 - .../fmlclient/registry/RenderingRegistry.java | 120 ---------- .../resources/META-INF/accesstransformer.cfg | 10 +- src/main/resources/forge.sas | 4 - .../rendering/EntityRendererEventsTest.java | 205 ++++++++++++++++++ src/test/resources/META-INF/mods.toml | 4 + .../textures/entity/test_entity.png | Bin 0 -> 915 bytes 13 files changed, 405 insertions(+), 153 deletions(-) create mode 100644 src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java rename src/main/java/net/minecraftforge/{fmlclient/registry/IRenderFactory.java => client/event/RegisterClientReloadListenersEvent.java} (50%) delete mode 100644 src/main/java/net/minecraftforge/fmlclient/registry/RenderingRegistry.java create mode 100644 src/test/java/net/minecraftforge/debug/client/rendering/EntityRendererEventsTest.java create mode 100644 src/test/resources/assets/entity_renderer_events_test/textures/entity/test_entity.png diff --git a/patches/minecraft/net/minecraft/client/Minecraft.java.patch b/patches/minecraft/net/minecraft/client/Minecraft.java.patch index 1c0c6d40e8..5f9d41700f 100644 --- a/patches/minecraft/net/minecraft/client/Minecraft.java.patch +++ b/patches/minecraft/net/minecraft/client/Minecraft.java.patch @@ -58,6 +58,17 @@ this.f_91064_ = new DebugRenderer(this); RenderSystem.m_69900_(this::m_91113_); if (this.f_91042_.f_83915_ == this.f_90990_.m_85441_() && this.f_91042_.f_83916_ == this.f_90990_.m_85442_()) { +@@ -531,6 +_,10 @@ + TinyFileDialogs.tinyfd_messageBox("Minecraft", stringbuilder.toString(), "ok", "error", false); + } + ++ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.RegisterClientReloadListenersEvent(this.f_91036_)); ++ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.EntityRenderersEvent.RegisterLayerDefinitions()); ++ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.EntityRenderersEvent.RegisterRenderers()); ++ + this.f_90990_.m_85409_(this.f_91066_.f_92041_); + this.f_90990_.m_85424_(this.f_91066_.f_92034_); + this.f_90990_.m_85426_(); @@ -546,13 +_,16 @@ } diff --git a/patches/minecraft/net/minecraft/client/model/geom/LayerDefinitions.java.patch b/patches/minecraft/net/minecraft/client/model/geom/LayerDefinitions.java.patch index 76293cd8c9..acf31ddefe 100644 --- a/patches/minecraft/net/minecraft/client/model/geom/LayerDefinitions.java.patch +++ b/patches/minecraft/net/minecraft/client/model/geom/LayerDefinitions.java.patch @@ -4,7 +4,7 @@ WoodType.m_61843_().forEach((p_171114_) -> { builder.put(ModelLayers.m_171291_(p_171114_), layerdefinition19); }); -+ net.minecraftforge.fmlclient.registry.RenderingRegistry.loadLayerDefinitions(builder); ++ net.minecraftforge.client.ForgeHooksClient.loadLayerDefinitions(builder); ImmutableMap immutablemap = builder.build(); List list = ModelLayers.m_171288_().filter((p_171117_) -> { return !immutablemap.containsKey(p_171117_); diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/EntityRenderDispatcher.java.patch b/patches/minecraft/net/minecraft/client/renderer/entity/EntityRenderDispatcher.java.patch index 60f65333a0..797d26d337 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/EntityRenderDispatcher.java.patch +++ b/patches/minecraft/net/minecraft/client/renderer/entity/EntityRenderDispatcher.java.patch @@ -15,14 +15,18 @@ p_114442_.m_85836_(); double d3 = d0 + Mth.m_14139_((double)p_114445_, enderdragonpart.f_19790_, enderdragonpart.m_20185_()); double d4 = d1 + Mth.m_14139_((double)p_114445_, enderdragonpart.f_19791_, enderdragonpart.m_20186_()); -@@ -322,6 +_,10 @@ - - public Quaternion m_114470_() { +@@ -324,9 +_,14 @@ return this.f_114367_; -+ } -+ -+ public Map> getSkinMap() { -+ return java.util.Collections.unmodifiableMap(f_114363_); } ++ public Map> getSkinMap() { ++ return java.util.Collections.unmodifiableMap(f_114363_); ++ } ++ public void m_6213_(ResourceManager p_174004_) { + EntityRendererProvider.Context entityrendererprovider$context = new EntityRendererProvider.Context(this, this.f_173995_, p_174004_, this.f_173996_, this.f_114365_); + this.f_114362_ = EntityRenderers.m_174049_(entityrendererprovider$context); + this.f_114363_ = EntityRenderers.m_174051_(entityrendererprovider$context); ++ net.minecraftforge.fml.ModLoader.get().postEvent(new net.minecraftforge.client.event.EntityRenderersEvent.AddLayers(f_114362_, f_114363_)); + } + } diff --git a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index 5666d619d9..9652e4d094 100644 --- a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -20,8 +20,12 @@ package net.minecraftforge.client; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.level.block.state.BlockState; import com.mojang.blaze3d.platform.Window; @@ -112,11 +116,13 @@ import java.io.File; import java.lang.reflect.Field; import java.nio.Buffer; import java.nio.ByteBuffer; +import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Random; import java.util.Set; +import java.util.function.Supplier; import java.util.stream.Stream; import static net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType.BOSSINFO; @@ -840,4 +846,17 @@ public class ForgeHooksClient ForgeTextureMetadata metadata = ForgeTextureMetadata.forResource(resource); return metadata.getLoader() == null ? null : metadata.getLoader().load(textureAtlas, resourceManager, textureInfo, resource, atlasWidth, atlasHeight, spriteX, spriteY, mipmapLevel, image); } + + + private static final Map> layerDefinitions = new HashMap<>(); + + public static void registerLayerDefinition(ModelLayerLocation layerLocation, Supplier supplier) + { + layerDefinitions.put(layerLocation, supplier); + } + + public static void loadLayerDefinitions(ImmutableMap.Builder builder) { + layerDefinitions.forEach((k, v) -> builder.put(k, v.get())); + } + } diff --git a/src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java b/src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java new file mode 100644 index 0000000000..53890758b6 --- /dev/null +++ b/src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java @@ -0,0 +1,132 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.event; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.EntityRenderers; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +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.minecraftforge.client.ForgeHooksClient; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.IModBusEvent; + +import javax.annotation.Nullable; +import java.util.Map; +import java.util.Set; +import java.util.function.Supplier; + +public class EntityRenderersEvent extends Event implements IModBusEvent +{ + public static class RegisterLayerDefinitions extends EntityRenderersEvent + { + /** + * Registers a layer definition supplier with the given {@link ModelLayerLocation}. + * These will be inserted into the main layer definition map for entity model layers at the appropriate time. + * + * @param layerLocation The model layer location, which should be used in conjunction with {@link EntityRendererProvider.Context#bakeLayer(ModelLayerLocation)} + * @param supplier A supplier to create a {@link LayerDefinition}, generally a static method reference in the entity model class + */ + public void registerLayerDefinition(ModelLayerLocation layerLocation, Supplier supplier) + { + ForgeHooksClient.registerLayerDefinition(layerLocation, supplier); + } + } + + /** + * Provides a safe place to register entity renderers and layer renderers. + */ + public static class RegisterRenderers extends EntityRenderersEvent + { + /** + * Registers an entity renderer. + * + * @param entityType The EntityType to register a renderer for + * @param entityRendererProvider The renderer provider, can be a lambda like MyRenderer::new + */ + public void registerEntityRenderer(EntityType entityType, EntityRendererProvider entityRendererProvider) + { + EntityRenderers.register(entityType, entityRendererProvider); + } + } + + /** + * Provides a safe place to register entity renderer layers. + */ + public static class AddLayers extends EntityRenderersEvent + { + private final Map, EntityRenderer> renderers; + private final Map> skinMap; + private final EntityModelSet entityModels = Minecraft.getInstance().getEntityModels(); + + public AddLayers(Map, EntityRenderer> renderers, Map> playerRenderers) + { + this.renderers = renderers; + this.skinMap = playerRenderers; + } + + /** + * Returns the list of skins. + */ + public Set getSkins() + { + return skinMap.keySet(); + } + + /** + * Returns a player skin renderer. Vanilla skins are "default" and "slim". + * @param skinName The name of the skin renderer to return + * @param The type of the skin renderer, usually PlayerRenderer + * @return The skin renderer, or null if not found + */ + @Nullable + @SuppressWarnings("unchecked") + public >> R getSkin(String skinName) + { + return (R) skinMap.get(skinName); + } + + /** + * Returns an entity renderer for the given entity type. + * @param entityType The entity to return a renderer for + * @param The type of entity the renderer is for + * @param The renderer type + * @return The renderer + */ + @Nullable + @SuppressWarnings("unchecked") + public >> R getRenderer(EntityType entityType) { + return (R) renderers.get(entityType); + } + + public EntityModelSet getEntityModels() + { + return entityModels; + } + } +} diff --git a/src/main/java/net/minecraftforge/fmlclient/registry/IRenderFactory.java b/src/main/java/net/minecraftforge/client/event/RegisterClientReloadListenersEvent.java similarity index 50% rename from src/main/java/net/minecraftforge/fmlclient/registry/IRenderFactory.java rename to src/main/java/net/minecraftforge/client/event/RegisterClientReloadListenersEvent.java index 3704e986ea..e4f09bf921 100644 --- a/src/main/java/net/minecraftforge/fmlclient/registry/IRenderFactory.java +++ b/src/main/java/net/minecraftforge/client/event/RegisterClientReloadListenersEvent.java @@ -17,13 +17,24 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.minecraftforge.fmlclient.registry; +package net.minecraftforge.client.event; -import net.minecraft.client.renderer.entity.EntityRenderer; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; -import net.minecraft.world.entity.Entity; +import net.minecraft.server.packs.resources.PreparableReloadListener; +import net.minecraft.server.packs.resources.ReloadableResourceManager; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.IModBusEvent; -public interface IRenderFactory +public class RegisterClientReloadListenersEvent extends Event implements IModBusEvent { - EntityRenderer createRenderFor(EntityRenderDispatcher manager); + private final ReloadableResourceManager resourceManager; + + public RegisterClientReloadListenersEvent(ReloadableResourceManager resourceManager) + { + this.resourceManager = resourceManager; + } + + public void registerReloadListener(PreparableReloadListener reloadListener) + { + resourceManager.registerReloadListener(reloadListener); + } } diff --git a/src/main/java/net/minecraftforge/fmlclient/ClientModLoader.java b/src/main/java/net/minecraftforge/fmlclient/ClientModLoader.java index 5872818db9..0b0f34a4af 100644 --- a/src/main/java/net/minecraftforge/fmlclient/ClientModLoader.java +++ b/src/main/java/net/minecraftforge/fmlclient/ClientModLoader.java @@ -39,7 +39,6 @@ import net.minecraft.server.packs.repository.Pack; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.world.level.DataPackConfig; import net.minecraftforge.fml.*; -import net.minecraftforge.fmlclient.registry.RenderingRegistry; import net.minecraftforge.fmllegacy.BrandingControl; import net.minecraftforge.fmllegacy.CrashReportExtender; import net.minecraftforge.fmllegacy.LogicalSidedProvider; @@ -137,15 +136,6 @@ public class ClientModLoader createRunnableWithCatch(() -> ModLoader.get().loadMods(syncExecutor, parallelExecutor, new SpacedRunnable(earlyLoaderGUI::renderTick))).run(); } - private static void postSidedRunnable() { - LOGGER.debug(LOADING, "Running post client event work"); - RenderingRegistry.loadEntityRenderers(); - } - - private static void preSidedRunnable() { - LOGGER.debug(LOADING, "Running pre client event work"); - } - private static void finishModLoading(ModWorkManager.DrivenExecutor syncExecutor, Executor parallelExecutor) { createRunnableWithCatch(() -> ModLoader.get().finishMods(syncExecutor, parallelExecutor, new SpacedRunnable(earlyLoaderGUI::renderTick))).run(); diff --git a/src/main/java/net/minecraftforge/fmlclient/registry/RenderingRegistry.java b/src/main/java/net/minecraftforge/fmlclient/registry/RenderingRegistry.java deleted file mode 100644 index 7eefaf8d1a..0000000000 --- a/src/main/java/net/minecraftforge/fmlclient/registry/RenderingRegistry.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2021. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.fmlclient.registry; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; - -import com.google.common.collect.ImmutableMap; -import net.minecraft.client.model.geom.ModelLayerLocation; -import net.minecraft.client.model.geom.builders.LayerDefinition; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.renderer.entity.EntityRenderers; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; - -public class RenderingRegistry -{ - private static final RenderingRegistry INSTANCE = new RenderingRegistry(); - - private final Map, EntityRendererProvider> entityRenderers = new ConcurrentHashMap<>(); - private final Map> layerDefinitions = new ConcurrentHashMap<>(); - - /** - * Register an entity rendering handler. This will, after mod initialization, be inserted into the main - * render map for entities. - * Call this during {@link net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent}. - * This method is safe to call during parallel mod loading. - */ - public static void registerEntityRenderingHandler(EntityType entityClass, EntityRendererProvider renderProvider) - { - INSTANCE.entityRenderers.put(entityClass, renderProvider); - } - - /** - * Registers a layer definition supplier with the given {@link ModelLayerLocation}. This will, after mod - * initialization, be inserted into the main layer definition map for entity model layers. - *

- * Call this during {@link net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent}. - * This method is safe to call during parallel mod loading. - * @param layerLocation The model layer location, which should be used in conjunction with {@link EntityRendererProvider.Context#bakeLayer(ModelLayerLocation)} - * @param supplier A supplier to create a {@link LayerDefinition}, generally a static method reference in the entity model class - */ - public static void registerLayerDefinition(ModelLayerLocation layerLocation, Supplier supplier) - { - INSTANCE.layerDefinitions.put(layerLocation, supplier); - } - - public static void loadEntityRenderers() - { - INSTANCE.entityRenderers.forEach(RenderingRegistry::register); - EntityRenderers.validateRegistrations(); - } - - public static void loadLayerDefinitions(ImmutableMap.Builder builder) { - INSTANCE.layerDefinitions.forEach((k, v) -> builder.put(k, v.get())); - } - - @SuppressWarnings("unchecked") - private static void register(EntityType entityType, EntityRendererProvider renderProvider) - { - EntityRenderers.register(entityType, ((EntityRendererProvider)renderProvider)); - } - - private static ModelLayerLocation registerModelLayer(ResourceLocation model, String layer) - { - return new ModelLayerLocation(model, layer); - } - - /** - * Registers a model layer location for the main layer definition of an entity. - * - * @param model The model {@link ResourceLocation} - * @return A main model layer location - */ - public static ModelLayerLocation registerMainModelLayer(ResourceLocation model) - { - return registerModelLayer(model, "main"); - } - - /** - * Registers a model layer location for the inner armor layer definition of an entity. - * - * @param model The model {@link ResourceLocation} - * @return An inner armor model layer location - */ - public static ModelLayerLocation registerInnerArmorModelLayer(ResourceLocation model) - { - return registerModelLayer(model, "inner_armor"); - } - - /** - * Registers a model layer location for the outer armor layer definition of an entity. - * - * @param model The model {@link ResourceLocation} - * @return An outer armor model layer location - */ - public static ModelLayerLocation registerOuterArmorModelLayer(ResourceLocation model) - { - return registerModelLayer(model, "outer_armor"); - } -} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index bfc0edd0df..42e3e1b126 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -72,9 +72,6 @@ public net.minecraft.client.particle.ParticleEngine m_107381_(Lnet/minecraft/cor public net.minecraft.client.particle.ParticleEngine$SpriteParticleRegistration public net.minecraft.client.renderer.GameRenderer m_109128_(Lnet/minecraft/resources/ResourceLocation;)V # loadEffect protected-f net.minecraft.client.renderer.RenderStateShard f_110131_ # setupState -public net.minecraft.client.renderer.RenderStateShard$TextureStateShard -protected-f net.minecraft.client.renderer.RenderStateShard$TextureStateShard f_110329_ # blur -protected-f net.minecraft.client.renderer.RenderStateShard$TextureStateShard f_110330_ # mipmap public net.minecraft.client.renderer.RenderStateShard$BooleanStateShard public net.minecraft.client.renderer.RenderStateShard$CullStateShard public net.minecraft.client.renderer.RenderStateShard$DepthTestStateShard @@ -86,8 +83,11 @@ public net.minecraft.client.renderer.RenderStateShard$OffsetTexturingStateShard public net.minecraft.client.renderer.RenderStateShard$OutputStateShard public net.minecraft.client.renderer.RenderStateShard$OverlayStateShard public net.minecraft.client.renderer.RenderStateShard$ShaderStateShard -public net.minecraft.client.renderer.RenderStateShard$TransparencyStateShard +public net.minecraft.client.renderer.RenderStateShard$TextureStateShard +protected-f net.minecraft.client.renderer.RenderStateShard$TextureStateShard f_110329_ # blur +protected-f net.minecraft.client.renderer.RenderStateShard$TextureStateShard f_110330_ # mipmap public net.minecraft.client.renderer.RenderStateShard$TexturingStateShard +public net.minecraft.client.renderer.RenderStateShard$TransparencyStateShard public net.minecraft.client.renderer.RenderStateShard$WriteMaskStateShard public net.minecraft.client.renderer.RenderType m_173215_(Ljava/lang/String;Lcom/mojang/blaze3d/vertex/VertexFormat;Lcom/mojang/blaze3d/vertex/VertexFormat$Mode;IZZLnet/minecraft/client/renderer/RenderType$CompositeState;)Lnet/minecraft/client/renderer/RenderType$CompositeRenderType; # create public net.minecraft.client.renderer.RenderType$CompositeState @@ -412,4 +412,4 @@ public net.minecraft.world.level.newbiome.layer.Layers m_76729_(JLnet/minecraft/ protected net.minecraft.world.level.portal.PortalForcer f_77648_ # level public net.minecraft.world.level.storage.LevelResource (Ljava/lang/String;)V # constructor private-f net.minecraft.world.level.storage.loot.LootPool f_79028_ # rolls -private-f net.minecraft.world.level.storage.loot.LootPool f_79029_ # bonusRolls +private-f net.minecraft.world.level.storage.loot.LootPool f_79029_ # bonusRolls \ No newline at end of file diff --git a/src/main/resources/forge.sas b/src/main/resources/forge.sas index 7aa71f6787..dad053a69d 100644 --- a/src/main/resources/forge.sas +++ b/src/main/resources/forge.sas @@ -75,10 +75,6 @@ net/minecraft/world/item/crafting/Recipe m_6076_()Ljava/lang/String; # getGroup net/minecraft/world/item/crafting/ShapedRecipe m_6076_()Ljava/lang/String; net/minecraft/world/item/crafting/ShapelessRecipe m_6076_()Ljava/lang/String; net/minecraft/world/item/crafting/SingleItemRecipe m_6076_()Ljava/lang/String; -net/minecraft/network/PacketBuffer m_130105_([J)[J -net/minecraft/network/PacketBuffer m_130093_([JI)[J -net/minecraft/network/PacketBuffer m_130277_()Ljava/lang/String; -net/minecraft/network/PacketBuffer m_130157_()Lnet/minecraft/util/math/SectionPos; net/minecraft/nbt/NbtIo m_128953_(Ljava/io/File;)Lnet/minecraft/nbt/CompoundTag; # read net/minecraft/nbt/NbtIo m_128955_(Lnet/minecraft/nbt/CompoundTag;Ljava/io/File;)V # write net/minecraft/network/protocol/game/ClientboundCommandsPacket m_131884_()Lcom/mojang/brigadier/tree/RootCommandNode; # getRoot diff --git a/src/test/java/net/minecraftforge/debug/client/rendering/EntityRendererEventsTest.java b/src/test/java/net/minecraftforge/debug/client/rendering/EntityRendererEventsTest.java new file mode 100644 index 0000000000..48055ec73f --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/client/rendering/EntityRendererEventsTest.java @@ -0,0 +1,205 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.debug.client.rendering; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.EntityRenderersEvent; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.event.entity.EntityAttributeCreationEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.registries.ObjectHolder; + +import java.util.Collections; + +@Mod("entity_renderer_events_test") +@Mod.EventBusSubscriber(value= Dist.CLIENT, bus= Mod.EventBusSubscriber.Bus.MOD) +public class EntityRendererEventsTest +{ + private static final ResourceLocation MY_ENTITY = new ResourceLocation("entity_renderer_events_test", "test_entity"); + private static final ModelLayerLocation MAIN_LAYER = new ModelLayerLocation(MY_ENTITY, "main"); + private static final ModelLayerLocation OUTER_LAYER = new ModelLayerLocation(MY_ENTITY, "main"); + private static final ModelLayerLocation ADDED_LAYER = new ModelLayerLocation(MY_ENTITY, "added"); + + @ObjectHolder("entity_renderer_events_test:test_entity") + public static EntityType MY_ENTITY_TYPE; + + @SubscribeEvent + public static void entityRegistry(RegistryEvent.Register> event) + { + event.getRegistry().register(EntityType.Builder.of(MyEntity::new, MobCategory.MONSTER).build("test_entity").setRegistryName("test_entity")); + } + + @SubscribeEvent + public static void entityRegistry(EntityAttributeCreationEvent event) + { + event.put(MY_ENTITY_TYPE, Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 1.0D).build()); + } + + @SubscribeEvent + public static void layerDefinitions(EntityRenderersEvent.RegisterLayerDefinitions event) + { + event.registerLayerDefinition(MAIN_LAYER, MyEntityModel::createMainLayer); + event.registerLayerDefinition(OUTER_LAYER, () -> MyEntityModel.createLayer(new CubeDeformation(1.0f))); + event.registerLayerDefinition(ADDED_LAYER, () -> MyEntityModel.createLayer(new CubeDeformation(2.0f))); + } + + @SubscribeEvent + public static void entityRenderers(EntityRenderersEvent.RegisterRenderers event) + { + event.registerEntityRenderer(MY_ENTITY_TYPE, MyEntityRenderer::new); + } + + @SubscribeEvent + public static void entityLayers(EntityRenderersEvent.AddLayers event) + { + MyEntityRenderer renderer = event.getRenderer(MY_ENTITY_TYPE); + renderer.addLayer(new MyEntityLayer(renderer, new MyEntityModel(event.getEntityModels().bakeLayer(ADDED_LAYER)), 0.5f)); + } + + private static class MyEntityModel extends EntityModel + { + public static final String BODY = "body"; + public static final String HEAD = "head"; + + public static LayerDefinition createMainLayer() + { + return createLayer(CubeDeformation.NONE); + } + + public static LayerDefinition createLayer(CubeDeformation deformation) + { + MeshDefinition definition = new MeshDefinition(); + PartDefinition root = definition.getRoot(); + root.addOrReplaceChild(BODY, CubeListBuilder.create().addBox(-4,0,-4,4,10,4, deformation), PartPose.ZERO); + root.addOrReplaceChild(HEAD, CubeListBuilder.create().addBox(-2,10,-2,2,4,2, deformation), PartPose.ZERO); + return LayerDefinition.create(definition, 64, 32); + } + + private final ModelPart headRenderer; + private final ModelPart bodyRenderer; + + public MyEntityModel(ModelPart modelPart) + { + this.headRenderer = modelPart.getChild(HEAD); + this.bodyRenderer = modelPart.getChild(BODY); + } + + @Override + public void setupAnim(MyEntity p_102618_, float p_102619_, float p_102620_, float p_102621_, float p_102622_, float p_102623_) + { + + } + + @Override + public void renderToBuffer(PoseStack poseStack, VertexConsumer vertexConsumer, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha) + { + headRenderer.render(poseStack, vertexConsumer, packedLightIn, packedOverlayIn, red, green, blue, alpha); + bodyRenderer.render(poseStack, vertexConsumer, packedLightIn, packedOverlayIn, red, green, blue, alpha); + } + } + + private static class MyEntityRenderer extends LivingEntityRenderer + { + private static final ResourceLocation TEXTURE = new ResourceLocation("entity_renderer_events_test:textures/entity/test_entity.png"); + + public MyEntityRenderer(EntityRendererProvider.Context context) + { + super(context, new MyEntityModel(context.bakeLayer(MAIN_LAYER)), 1.0f); + addLayer(new MyEntityLayer(this, new MyEntityModel(context.bakeLayer(OUTER_LAYER)), 0.1f)); + } + + @Override + public ResourceLocation getTextureLocation(MyEntity p_114482_) + { + return TEXTURE; + } + } + + private static class MyEntityLayer extends RenderLayer + { + private final MyEntityModel model; + private final float r; + + public MyEntityLayer(MyEntityRenderer renderer, MyEntityModel model, float r) + { + super(renderer); + this.model = model; + this.r = r; + } + + @Override + public void render(PoseStack poseStack, MultiBufferSource bufferSource, int lightness, MyEntity entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) + { + VertexConsumer vertexConsumer = bufferSource.getBuffer(this.getParentModel().renderType(this.getTextureLocation(entity))); + model.renderToBuffer(poseStack, vertexConsumer, lightness, OverlayTexture.NO_OVERLAY, r, 1.0f, 1.0f, 1.0f); + } + } + + private static class MyEntity extends LivingEntity + { + protected MyEntity(EntityType p_20966_, Level p_20967_) + { + super(p_20966_, p_20967_); + } + + @Override + public Iterable getArmorSlots() + { + return Collections.emptyList(); + } + + @Override + public ItemStack getItemBySlot(EquipmentSlot p_21127_) + { + return ItemStack.EMPTY; + } + + @Override + public void setItemSlot(EquipmentSlot p_21036_, ItemStack p_21037_) + { + + } + + @Override + public HumanoidArm getMainArm() + { + return HumanoidArm.LEFT; + } + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 8b79299800..1de4b0f4d4 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -140,3 +140,7 @@ license="LGPL v2.1" modId="player_attack_knockback_test" [[mods]] modId="overlay_layers_test" +[[mods]] + modId="entity_renderer_events_test" + +# ADD ABOVE THIS LINE diff --git a/src/test/resources/assets/entity_renderer_events_test/textures/entity/test_entity.png b/src/test/resources/assets/entity_renderer_events_test/textures/entity/test_entity.png new file mode 100644 index 0000000000000000000000000000000000000000..088ddd8e09c05aabbd3e147f89453ffd97799ac8 GIT binary patch literal 915 zcmV;E18n?>P)*Wb;fg}|n33)rv2z&)D0I!4wr4bruL4b2Aa0OT=9Otjs zp#Y?pN|kaul%U-bZM$fUnG%Xp`Vbrg4gfoVAHpc(W^}z!wo$>Ghd$t>LcR&u z91_Uh0!M+FKnE}Y907I-2D%PB2O1)B^MGFhJ|7+dJAt=Cd3(c54oV1?Y;^^<#L_bL zv+baO?|8_6NgnV`7;OoLfm;>ilid6BL!Ht@Xsb{TPm=Npxa9h~BKpIMu_Q^<+E8cu z8kC^f1*21=Q~;rTU>5LMK{=2lNt>@z8-Nm4S9mFBu>rW|>9aXVwSp_DL@kiT?1Fky zEb+*VDV_fq69^>WGBB}b>E zZpm8#P0CY0i-o|;GW0E;X1?nby1Rk*u56AYC%I@=CO(ox=AlBrzd-$9vB#G%ggG*MWzR=V$O%X5CQ zB8On?g#BiWsTUYHSio_M zT19YU529!PM*uADL=5XF;P{&YPieR-(ucPH6#$D~5BZG(&TlK|e5pOo;XEDE2|@bL z5IKjGeMJnTj*SV*mLWB0@aW3R$jg)_G?6WM!;S-)(I=`3^R3%6i!oIsV}>1(bl zFB{xbRC_G)4l`U0KW>oZ0b`MS_(7_+u2VSQGTzR|kWGY2iO!ak!@a<&l+1J?cjC*; pCK8G~iP^XLdV%v32Hq_I{0884jHk7AfIa{K002ovPDHLkV1iH7sUiRX literal 0 HcmV?d00001