diff --git a/patches/net/minecraft/client/renderer/entity/EntityRenderer.java.patch b/patches/net/minecraft/client/renderer/entity/EntityRenderer.java.patch index 2e7b86b284..afd1c5bf4b 100644 --- a/patches/net/minecraft/client/renderer/entity/EntityRenderer.java.patch +++ b/patches/net/minecraft/client/renderer/entity/EntityRenderer.java.patch @@ -23,11 +23,13 @@ if (flag) { p_361028_.nameTag = this.getNameTag(p_362104_); p_361028_.nameTagAttachment = p_362104_.getAttachments().getNullable(EntityAttachment.NAME_TAG, 0, p_362104_.getYRot(p_362204_)); -@@ -302,5 +_,7 @@ +@@ -302,5 +_,9 @@ } p_361028_.displayFireAnimation = p_362104_.displayFireAnimation(); + + p_361028_.partialTick = p_362204_; ++ net.neoforged.neoforge.attachment.AttachmentInternals.copyEntityAttachments(p_362104_, p_362104_, false); ++ net.neoforged.neoforge.common.NeoForge.EVENT_BUS.post(new net.neoforged.neoforge.client.event.UpdateRenderStateEvent<>(p_362104_, p_361028_)); } } diff --git a/patches/net/minecraft/client/renderer/entity/state/EntityRenderState.java.patch b/patches/net/minecraft/client/renderer/entity/state/EntityRenderState.java.patch index a9fd80707c..140d55ccd4 100644 --- a/patches/net/minecraft/client/renderer/entity/state/EntityRenderState.java.patch +++ b/patches/net/minecraft/client/renderer/entity/state/EntityRenderState.java.patch @@ -1,5 +1,14 @@ --- a/net/minecraft/client/renderer/entity/state/EntityRenderState.java +++ b/net/minecraft/client/renderer/entity/state/EntityRenderState.java +@@ -7,7 +_,7 @@ + import net.neoforged.api.distmarker.OnlyIn; + + @OnlyIn(Dist.CLIENT) +-public class EntityRenderState { ++public class EntityRenderState extends net.neoforged.neoforge.attachment.AttachmentHolder { + public double x; + public double y; + public double z; @@ -27,6 +_,7 @@ public Vec3 nameTagAttachment; @Nullable diff --git a/src/main/java/net/neoforged/neoforge/attachment/AttachmentInternals.java b/src/main/java/net/neoforged/neoforge/attachment/AttachmentInternals.java index b4b33eacca..783e707293 100644 --- a/src/main/java/net/neoforged/neoforge/attachment/AttachmentInternals.java +++ b/src/main/java/net/neoforged/neoforge/attachment/AttachmentInternals.java @@ -53,6 +53,10 @@ public static void copyEntityAttachments(Entity from, Entity to, boolean isDeath copyAttachments(from.registryAccess(), from, to, isDeath ? type -> type.copyOnDeath : type -> true); } + public static void copyEntityAttachments(Entity from, H to, boolean isDeath) { + copyAttachments(from.registryAccess(), from, to, isDeath ? type -> type.copyOnDeath : type -> true); + } + @SubscribeEvent public static void onPlayerClone(PlayerEvent.Clone event) { event.getEntity().copyAttachmentsFrom(event.getOriginal(), event.isWasDeath()); diff --git a/src/main/java/net/neoforged/neoforge/client/event/UpdateRenderStateEvent.java b/src/main/java/net/neoforged/neoforge/client/event/UpdateRenderStateEvent.java new file mode 100644 index 0000000000..4239d59a55 --- /dev/null +++ b/src/main/java/net/neoforged/neoforge/client/event/UpdateRenderStateEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) NeoForged and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.neoforged.neoforge.client.event; + +import net.minecraft.client.renderer.entity.state.EntityRenderState; +import net.minecraft.world.entity.Entity; +import net.neoforged.bus.api.Event; +import org.jetbrains.annotations.ApiStatus; + +public class UpdateRenderStateEvent extends Event { + private final E entity; + private final S renderState; + + @ApiStatus.Internal + public UpdateRenderStateEvent(E entity, S renderState) { + this.entity = entity; + this.renderState = renderState; + } + + public E getEntity() { + return entity; + } + + public S getCurrentState() { + return renderState; + } +} diff --git a/tests/src/main/java/net/neoforged/neoforge/debug/client/ClientEventTests.java b/tests/src/main/java/net/neoforged/neoforge/debug/client/ClientEventTests.java index 6b724e66b9..90f86c0cc7 100644 --- a/tests/src/main/java/net/neoforged/neoforge/debug/client/ClientEventTests.java +++ b/tests/src/main/java/net/neoforged/neoforge/debug/client/ClientEventTests.java @@ -9,6 +9,7 @@ import java.util.Map; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.SectionPos; import net.minecraft.network.chat.Component; import net.minecraft.world.level.block.Blocks; @@ -19,6 +20,7 @@ import net.neoforged.neoforge.client.event.ClientPlayerChangeGameTypeEvent; import net.neoforged.neoforge.client.event.RegisterRenderBuffersEvent; import net.neoforged.neoforge.client.event.RenderLevelStageEvent; +import net.neoforged.neoforge.client.event.RenderPlayerEvent; import net.neoforged.neoforge.client.model.data.ModelData; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.testframework.DynamicTest; @@ -103,4 +105,21 @@ static void addSectionGeometryTest(final ClientChatEvent chatEvent, final Dynami test.requestConfirmation(player, Component.literal("Is a diamond block rendered above you?")); } } + + @TestHolder(description = { "" }, enabledByDefault = true) + static void updateRenderState(final DynamicTest test) { + var testAttachment = test.registrationHelper().attachments().registerSimpleAttachment("test", () -> 3); + test.whenEnabled(listeners -> { + listeners.forge().addListener((RenderPlayerEvent.Post event) -> { + int numRender = event.getRenderState().getData(testAttachment); + var poseStack = event.getPoseStack(); + poseStack.pushPose(); + for (int i = 0; i < numRender; i++) { + poseStack.translate(0, 1, 0); + Minecraft.getInstance().getBlockRenderer().renderSingleBlock(Blocks.CALCITE.defaultBlockState(), poseStack, event.getMultiBufferSource(), event.getPackedLight(), OverlayTexture.NO_OVERLAY, ModelData.EMPTY, RenderType.solid()); + } + poseStack.popPose(); + }); + }); + } }