Jump to content

[SOLVED] Custom render layer doesn't respect a players crouching pose


Recommended Posts

Posted (edited)

Hi, I'm trying to add this as a constant render layer on the player. This works perfectly, unless the player crouches:

java_0557.pngjava_0559.png

Interestingly enough, if I add the model as a model for armor, it works just fine:

java_0560.png

I almost feel like I'm missing something obvious, like getting the rotation angles from somewhere, but am oblivious to where it could get them from.

In my RenderSetup I add the render layer:

@Mod.EventBusSubscriber(modid = Main.MODID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public class RenderSetup
{
	public static final ResourceLocation KNIGHT_LAYER_TEXTURE = new ResourceLocation(Main.MODID, "textures/models/armor/knight_layer_1.png");
	public static final ModelLayerLocation KNIGHT_LAYER_LOCATION = new ModelLayerLocation(KNIGHT_LAYER_TEXTURE, "knight");

	@SubscribeEvent
	public static void onRegisterLayerDefinition(final EntityRenderersEvent.RegisterLayerDefinitions evt)
	{
		evt.registerLayerDefinition(KNIGHT_LAYER_LOCATION, ModelKnight::createLayer);
	}

	@SubscribeEvent
	public static void onEntityAddLayers(final EntityRenderersEvent.AddLayers evt)
	{
		for (String skin : evt.getSkins())
		{
			final LivingEntityRenderer<Player, EntityModel<Player>> renderer = evt.getSkin(skin);
			renderer.addLayer(new LayerTT<>(renderer));
		}
	}
}

 

And my LayerTT looks like this:

public class LayerTT<T extends LivingEntity, M extends EntityModel<T>> extends RenderLayer<T, M>
{
	private final ModelKnight<T> MODEL_KNIGHT_HEAD;
	private final ModelKnight<T> MODEL_KNIGHT_CHEST;
	private final ModelKnight<T> MODEL_KNIGHT_LEGS;
	private final ModelKnight<T> MODEL_KNIGHT_FEET;

	public LayerTT(RenderLayerParent<T, M> entityRendererOwner)
	{
		super(entityRendererOwner);

		final ModelPart bakedKnight = Minecraft.getInstance().getEntityModels().bakeLayer(RenderSetup.KNIGHT_LAYER_LOCATION);
		this.MODEL_KNIGHT_HEAD = new ModelKnight<>(EquipmentSlot.HEAD, bakedKnight);
		this.MODEL_KNIGHT_CHEST = new ModelKnight<>(EquipmentSlot.CHEST, bakedKnight);
		this.MODEL_KNIGHT_LEGS = new ModelKnight<>(EquipmentSlot.LEGS, bakedKnight);
		this.MODEL_KNIGHT_FEET = new ModelKnight<>(EquipmentSlot.FEET, bakedKnight);
	}

	@Override
	public void render(PoseStack pMatrixStack, MultiBufferSource pBuffer, int pPackedLight, T pLivingEntity, float pLimbSwing, float pLimbSwingAmount, float pPartialTicks, float pAgeInTicks, float pNetHeadYaw, float pHeadPitch)
	{
		pMatrixStack.pushPose();
          
		M parentModel = this.getParentModel();
		coloredCutoutModelCopyLayerRender(parentModel, MODEL_KNIGHT_HEAD, RenderSetup.KNIGHT_LAYER_TEXTURE, pMatrixStack, pBuffer, pPackedLight, pLivingEntity, pLimbSwing, pLimbSwingAmount, pAgeInTicks, pNetHeadYaw, pHeadPitch, pPartialTicks, 1, 1, 1);
		coloredCutoutModelCopyLayerRender(parentModel, MODEL_KNIGHT_CHEST, RenderSetup.KNIGHT_LAYER_TEXTURE, pMatrixStack, pBuffer, pPackedLight, pLivingEntity, pLimbSwing, pLimbSwingAmount, pAgeInTicks, pNetHeadYaw, pHeadPitch, pPartialTicks, 1, 1, 1);
		coloredCutoutModelCopyLayerRender(parentModel, MODEL_KNIGHT_LEGS, RenderSetup.KNIGHT_LAYER_TEXTURE, pMatrixStack, pBuffer, pPackedLight, pLivingEntity, pLimbSwing, pLimbSwingAmount, pAgeInTicks, pNetHeadYaw, pHeadPitch, pPartialTicks, 1, 1, 1);
		coloredCutoutModelCopyLayerRender(parentModel, MODEL_KNIGHT_FEET, RenderSetup.KNIGHT_LAYER_TEXTURE, pMatrixStack, pBuffer, pPackedLight, pLivingEntity, pLimbSwing, pLimbSwingAmount, pAgeInTicks, pNetHeadYaw, pHeadPitch, pPartialTicks, 1, 1, 1);

		pMatrixStack.popPose();
	}
}

 

I'd be happy if anyone could give me a direction of where to look. Thanks :)

Edited by trienow
Solved
Posted (edited)

Hi diesieben! Thanks for your swift reply.

I thought I called it through coloredCutoutModelCopyLayerRender, but I was wrong!

As I made LayerTT's parent Model to an EntityModel and not a HumanoidModel, copyPropertiesTo was not copying all the expected model parts.

 

Unfortunatly the EntityRenderersEvent.AddLayers Event only gives me a renderer for EntityModel<Player> and not HumanoidModel<Player>, so I'll have to figure something out there.

Hopefully, without having to make my own Version of the PlayerRenderer.

 

Thanks for giving me a direction :)

Edited by trienow
Posted (edited)

I got it to work.

Just for future reference, I decided to take your advice and use instanceof and cast by dropping the generics (which do add up).

It isn't pretty as Java gives me warnings, but at least no errors.

public static void onEntityAddLayers(final EntityRenderersEvent.AddLayers evt)
{
	for (String skin : evt.getSkins())
	{
		final LivingEntityRenderer livingEntityRenderer = evt.getSkin(skin);
		if (livingEntityRenderer instanceof LivingEntityRenderer)
		{
			livingEntityRenderer.addLayer(new LayerTT<>(livingEntityRenderer));
		}
	}
}

I then was able to make my layer class reference HumanoidModel<T> and also call copyPropertiesTo before calling the coloredCutoutModelCopyLayerRender.

Take care!

Edited by trienow
Decided to sum up other changes I made to get the code to work
  • trienow changed the title to [SOLVED] Custom render layer doesn't respect a players crouching pose

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • But what could be the issue with that? Maybe the confiq file?  
    • There is an issue with legendarysurvivaloverhaul
    • I am playing on a nitrado server with friends and everytime i try to join i am getting the same crash.log Does somebody understand what the problem here could be?  Crash Log
    • I see. I'm sure I tried again with a lower case word, a few times. I ended up doing the same thing as pixxy in the end. Is this beyond the scope of the admins to fix? Are they already aware of it, or should I use 'contact us' to post a ticket?
    • I’m working on a Manta Ray entity in MCreator using GeckoLib animations, and my goal is to have a looping (flip) animation that ends at −360°, then transitions seamlessly into a swim animation starting at 0°. However, every method I’ve tried—like quickly interpolating the angle, inserting a brief keyframe at 0°, or using a micro “bridge” animation—still causes a visible “flash” https://imgur.com/a/5ucjUb9 or "jump" when the rotation resets. I want a perfectly smooth motion from the flip’s final rotation to the swim’s initial rotation. If anyone has solved this in MCreator/GeckoLib, or found a better trick for handling the −360° →0° gap without a snap, I’d appreciate some advice ! P.S.- I cannot set swim to start at -360 because I would have the same issue but in reverse. Here's the custom LoopingAnimationGoal :   class LoopingAnimationGoal extends Goal { private final MantaRayEntity entity; private final int cooldownTime; private int animationTimer; private int cooldownTimer; // New boolean to prevent double calls private boolean isLoopingActive = false; public LoopingAnimationGoal(MantaRayEntity entity, int cooldownTime) { this.entity = entity; this.cooldownTime = cooldownTime; this.animationTimer = 0; this.cooldownTimer = 0; this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK)); } @Override public boolean canUse() { System.out.println("[DEBUG] LoopingGoal canUse => cooldownTimer=" + cooldownTimer); if (cooldownTimer > 0) { cooldownTimer--; return false; } BlockPos entityPos = entity.blockPosition(); boolean canUse = entity.isWaterAbove(entityPos, 4); System.out.println("[DEBUG] LoopingGoal canUse => WATER " + (canUse ? "DETECTED" : "NOT DETECTED") + " at " + entityPos + ", returning " + canUse); return canUse; } @Override public void start() { entity.setAnimation("looping"); animationTimer = 63; isLoopingActive = true; System.out.println("[DEBUG] Looping animation STARTED. Timer=" + animationTimer + ", gameTime=" + entity.level().getGameTime()); } @Override public boolean canContinueToUse() { System.out.println("[DEBUG] LoopingGoal canContinueToUse => animationTimer=" + animationTimer); return animationTimer > 0; } @Override public void tick() { animationTimer--; System.out.println("[DEBUG] LoopingGoal TICK => animationTimer=" + animationTimer); // We stop ONLY if we are still looping if (animationTimer <= 0 && isLoopingActive) { System.out.println("[DEBUG] condition => animationTimer <= 0 && isLoopingActive"); stop(); } } @Override public void stop() { // Check if already stopped if (!isLoopingActive) { System.out.println("[DEBUG] stop() called again, but isLoopingActive = false. Doing nothing."); return; } System.out.println("[DEBUG] Looping STOP at tick=" + entity.level().getGameTime() + ", last known rotation=" + entity.getXRot() + "/" + entity.getYRot() + ", animationTimer=" + animationTimer); // Immediately switch to "swim" entity.setAnimation("swim"); // Reset cooldown cooldownTimer = cooldownTime; // Disable looping to prevent a second stop isLoopingActive = false; System.out.println("[DEBUG] Looping STOP => setAnimation('swim'), cooldownTimer=" + cooldownTimer); } }  
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.