Posted May 24, 20223 yr Hello, I am trying to replace every rendered mob's model (not the mob itself) with the model of a custom entity, under certain conditions. This is how it would work: @SubscribeEvent public static void replaceMobModel(RenderLivingEvent.Pre<LivingEntity, EntityModel<LivingEntity>> event) { if (condition A is reached) { // replace every rendered mob's model with the model of a custom entity } // if condition A is not met, then every rendered mob's model reverts back to normal (e.g. villagers start looking like villagers again) } I was looking at this forum (https://forums.minecraftforge.net/topic/75986-114-how-to-change-rendered-entity/) and found out that I need to use EntityRenderManager#renderEntity. But since that is from a previous version, I assume it would be EntityRenderDispatcher#render. Here's what I tried to do so far: @SubscribeEvent public static void replaceMobModel(RenderLivingEvent.Pre<LivingEntity, EntityModel<LivingEntity>> event) { LocalPlayer localPlayer = Minecraft.getInstance().player; if (localPlayer != null && event.getEntity() instanceof Mob mob) { // I'll set up the conditions later once I get this working event.setCanceled(true); CustomEntity customEntity = ModEntities.CUSTOM_ENTITY.get().create(localPlayer.clientLevel); if (customEntity != null) { customEntity.setXRot(mob.getXRot()); customEntity.setYRot(mob.getYRot()); Minecraft.getInstance().getEntityRenderDispatcher().render( customEntity, mob.getX(), mob.getY(), mob.getZ(), mob.getViewYRot(event.getPartialTick()), event.getPartialTick(), event.getPoseStack(), event.getMultiBufferSource(), event.getPackedLight() ); } } } This results in a stack overflow (EntityRenderDispatcher#render seems to cause RenderLivingEvent to fire, causing an infinite recursion). Is this even the right thing to do? Or do I have to go to my CustomEntity renderer class and override render()? If that's the case, I don't know what I should put in that method. Edited May 27, 20223 yr by LeeCrafts
May 25, 20223 yr Author Although I am not exactly sure how a try-finally block would help (i.e. what code I should run even if a runtime exception is thrown), I have made some progress. The custom mob renders, but it does not rotate--even when I apply rotations to it before calling render(). private static boolean renderingCustomEntity = false; private static CustomEntity customEntity; private static void initializeCustomEntityIfNull(LocalPlayer localPlayer) { if (customEntity == null) { customEntity = ModEntities.CUSTOM_ENTITY.get().create(localPlayer.clientLevel); } } @SubscribeEvent public static void replaceMobModel(RenderLivingEvent.Pre<LivingEntity, EntityModel<LivingEntity>> event) { LocalPlayer localPlayer = Minecraft.getInstance().player; if (localPlayer != null && event.getEntity() instanceof Mob mob) { try { if (!renderingCustomEntity) { renderingCustomEntity = true; event.setCanceled(true); initializeCustomEntityIfNull(localPlayer); // I try to apply rotations to the custom entity before it rendered, but it still does not rotate at all. customEntity.setYRot(mob.getYRot()); customEntity.setYHeadRot(mob.getYHeadRot()); customEntity.setPose(mob.getPose()); // For some reason, the custom mob did not render when I called EntityRenderDispatcher#render. // So I called render() from EntityRenderDispatcher#getRenderer instead. Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(customEntity).render( customEntity, customEntity.getYRot(), event.getPartialTick(), event.getPoseStack(), event.getMultiBufferSource(), event.getPackedLight() ); } } finally { renderingCustomEntity = false; } } } What would I be missing? Thank you for the help. Edited May 25, 20223 yr by LeeCrafts
May 25, 20223 yr Author Got the rotation working. I had to look at LivingEntityRenderer#render and setupRotations a little more closely, and I realized that I needed to change the custom entity's yBodyRot and yBodyRotO. private static boolean renderingCustomEntity = false; private static CustomEntity customEntity; private static void refreshCustomEntity(LocalPlayer localPlayer, LivingEntity livingEntity) { // If the level changes, remove the custom entity by assigning its reference to a new custom entity. // The previous custom entity will eventually be garbage collected. if (customEntity == null || customEntity.level != livingEntity.level) { customEntity = ModEntities.CUSTOM_ENTITY.get().create(localPlayer.clientLevel); } } @SubscribeEvent public static void replaceMobModel(RenderLivingEvent.Pre<LivingEntity, EntityModel<LivingEntity>> event) { LocalPlayer localPlayer = Minecraft.getInstance().player; if (localPlayer != null && event.getEntity() instanceof Mob mob) { if (/* put your own condition here */) { if (!renderingCustomEntity) { try { renderingCustomEntity = true; event.setCanceled(true); refreshCustomEntity(localPlayer, mob); // (truth be told, my custom entity does not have a "head", so these lines aren't needed) // customEntity.setYHeadRot(mob.getYHeadRot()); // customEntity.yHeadRotO = mob.yHeadRotO; customEntity.setYBodyRot(mob.yBodyRot); customEntity.yBodyRotO = mob.yBodyRotO; customEntity.setPose(mob.getPose()); Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(customEntity).render( customEntity, customEntity.yBodyRot, event.getPartialTick(), event.getPoseStack(), event.getMultiBufferSource(), event.getPackedLight() ); } finally { renderingCustomEntity = false; } } } } } On 5/25/2022 at 2:13 AM, diesieben07 said: This will create a memory leak if the level changes. You have to unload the entity with the level and also change the entity if the level changes. As shown in my code, if the mob whose model is replaced moves to a different dimension, I unload the custom entity with Entity#discard and then reinitialize it on the next tick. I wonder if I also have to unload the custom entity when the mob it is "replacing" dies. ^ Edit: I have changed the code due to @diesieben07's most recent comment. Edited May 27, 20223 yr by LeeCrafts i changed it a bunch of times, but hopefully this is the last edit lol
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.