Jump to content

[1.17.1] Replacing Player Model with a Mob Model


Skyriis

Recommended Posts

Hello Guys,

i'm working on a Mod which allows you to play Minecraft as one of the existing Mobs.

i'm currently struggling on the player rendering since the player model should be replaced with the Mob Model.

I guess i need to cancel the RenderPlayerEvent, get my capability and then render the mob which i can identify by the value in my capability.

Canceling the Event and getting the Capability isn't a thing but how do i render render the Mob?

 

i would be really grateful for help.

Thanks in advance!

Link to comment
Share on other sites

i kinda managed to render a Mob instead of the player using

    @OnlyIn(Dist.CLIENT)
    @Override
    public void renderPlayer(final Player player, final PoseStack poseStack, final MultiBufferSource buffer, final int light, final float partialTicks) {
        final Slime entity = EntityType.SLIME.create(player.level);
        entity.setSize(0, false);
        entity.setPos(player.getX(), player.getY(), player.getZ());
        entity.setXRot(player.getXRot());
        entity.setYRot(player.getYRot());
        entity.setYHeadRot(player.getYHeadRot());
        entity.setOldPosAndRot();

        Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(entity).render(entity, 0F, partialTicks, poseStack, buffer, light);
    }

but the rotations won't be applied. 

Any ideas how to fix that?

Edited by Skyriis
Link to comment
Share on other sites

21 hours ago, Skyriis said:

That doesn't seems to work since the RenderPlayerEvent.Pre renderer is a PlayerRenderer and not a LivingEntityRenderer.

Which means that the model needs to be a PlayerModel (or extend it) and can't be a normal EntityModel.

that's correct but the model is stored in the LivingEntityRenderer, and this is OOP

also do never use @OnlyIn, and if you want to use your code above I think you need to render the EntityModel manually 

16 hours ago, Skyriis said:

okay... i've managed to create a model which rotates with the player rotation and looks like whatever i want.

The only problem is that holding items (or weared items) are on the wrong spot.

How can i change the position?

that's because the Slime dosen't have the ArmorLayer and ItemHandLayer you need to add a custom Layer to the EntityRenderer or you disable the rendering of Armor and hold items

Link to comment
Share on other sites

Here is just the current state of my code.

RenderEvent:

public static void onPreRenderPlayer(final RenderPlayerEvent.Pre e) {
        if (!(e.getPlayer() instanceof AbstractClientPlayer)) return;
        final AbstractClientPlayer player = (AbstractClientPlayer) e.getPlayer();
        player.getCapability(Capabilities.BEING).ifPresent(beingCapability -> {
            final LivingBeing being = beingCapability.getLivingBeing();
            being.getModelTexture().ifPresent(textureLocation -> {
                //Replace Texture with Slime Texture
                try {
                    player.getPlayerInfo().textureLocations.remove(MinecraftProfileTexture.Type.SKIN);
                    player.getPlayerInfo().textureLocations.put(MinecraftProfileTexture.Type.SKIN, textureLocation);
                } catch (NullPointerException npe) {
                    //TODO real exception handling
                    OtherLivingBeings.getLogger().fatal("Could not get Player Information.");
                    npe.printStackTrace();
                }
            });
            //Replace Model
            being.getModel(e.getRenderer()).ifPresent(model -> e.getRenderer().model = model);
        });
    }

getModel Method:

@OnlyIn(Dist.CLIENT)
    @Override
    public Optional<PlayerModel<AbstractClientPlayer>> getModel(final PlayerRenderer renderer) {
        final PlayerModelReplacement replacement = new PlayerModelReplacement(
                SmallSlimeModel.createHead().bakeRoot(),
                SmallSlimeModel.createHat().bakeRoot(),
                SmallSlimeModel.createBody().bakeRoot(),
                emptyPart,
                emptyPart,
                emptyPart,
                emptyPart,
                emptyPart,
                emptyPart,
                emptyPart,
                emptyPart,
                emptyPart,
                emptyPart,
                emptyPart);
        final SmallSlimeModel model = new SmallSlimeModel(replacement.toModelPart());
        //Remove Player Model Layers
        renderer.layers.clear();
        //Add Armor Layer
        renderer.addLayer(new SmallSlimeArmorLayer<>(renderer));

        return Optional.of(model);
    }

Test Model (SmallSlimeModel):

@OnlyIn(Dist.CLIENT)
public class SmallSlimeModel extends PlayerModel<AbstractClientPlayer> {
    private final ModelPart root;

    public SmallSlimeModel(ModelPart parent) {
        super(parent, false);
        this.root = parent;

    }

    public static LayerDefinition createHat() {
        MeshDefinition meshdefinition = new MeshDefinition();
        PartDefinition partdefinition = meshdefinition.getRoot();
        partdefinition.addOrReplaceChild("hat", CubeListBuilder.create()
                        .texOffs(32, 0)
                        .addBox(-4.0F, 17.0F, -4.0F, 8.0F, 8.0F, 8.0F, CubeDeformation.NONE),
                PartPose.ZERO);
        return LayerDefinition.create(meshdefinition, 64, 32);
    }

    public static LayerDefinition createHead() {
        MeshDefinition meshdefinition = new MeshDefinition();
        PartDefinition partdefinition = meshdefinition.getRoot();
        partdefinition.addOrReplaceChild("cube", CubeListBuilder.create()
                .texOffs(0, 16)
                .addBox(-3.0F, 17.0F, -3.0F, 6.0F, 6.0F, 6.0F), PartPose.ZERO);
        partdefinition.addOrReplaceChild("right_eye", CubeListBuilder.create().texOffs(32, 0).addBox(-3.25F, 18.0F, -3.5F, 2.0F, 2.0F, 2.0F), PartPose.ZERO);
        partdefinition.addOrReplaceChild("left_eye", CubeListBuilder.create().texOffs(32, 4).addBox(1.25F, 18.0F, -3.5F, 2.0F, 2.0F, 2.0F), PartPose.ZERO);
        partdefinition.addOrReplaceChild("mouth", CubeListBuilder.create().texOffs(32, 8).addBox(0.0F, 21.0F, -3.5F, 1.0F, 1.0F, 1.0F), PartPose.ZERO);
        return LayerDefinition.create(meshdefinition, 64, 32);
    }

    public static LayerDefinition createBody() {
        MeshDefinition meshdefinition = new MeshDefinition();
        PartDefinition partdefinition = meshdefinition.getRoot();
        partdefinition.addOrReplaceChild("cube", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, 16.0F, -4.0F, 8.0F, 8.0F, 8.0F), PartPose.ZERO);
        return LayerDefinition.create(meshdefinition, 64, 32);
    }

    public ModelPart root() {
        return this.root;
    }
}

Custom armor layer:

public class SmallSlimeArmorLayer<T extends LivingEntity, M extends HumanoidModel<T>, A extends HumanoidModel<T>> extends HumanoidArmorLayer<T, M, A> {

    public SmallSlimeArmorLayer(RenderLayerParent<T, M> parent) {
        super(parent,
                (A) new HumanoidModel(PlayerRendererUtils.getEntityRendererContext(parent).bakeLayer(ModelLayers.PLAYER_INNER_ARMOR)),
                (A) new HumanoidModel(PlayerRendererUtils.getEntityRendererContext(parent).bakeLayer(ModelLayers.PLAYER_OUTER_ARMOR)));
    }

    @Override
    public void render(PoseStack stack, MultiBufferSource bufferSource, int p_117098_, T player, float p_117100_, float p_117101_, float p_117102_, float p_117103_, float p_117104_, float p_117105_) {
        super.render(stack, bufferSource, p_117098_, player, p_117100_, p_117101_, p_117102_, p_117103_, p_117104_, p_117105_);
    }
}

 

Edited by Skyriis
Link to comment
Share on other sites

i'm currently struggling on the rotation for the held item layer.

This is how it should look like:

image.png.5ca59578f944e42fe495f49a943cc5eb.png

This is how it looks after the invisible arm has moved:

image.png.f1eea7ecd37338065c89f3c4e188a9ff.png

This is the layer:

public class CustomItemInHandLayer<T extends Player, M extends PlayerModel<T>> extends ItemInHandLayer<T, M> {
    @SuppressWarnings("unchecked")
    public CustomItemInHandLayer(PlayerRenderer renderer) {
        super((RenderLayerParent<T, M>) renderer);
    }

    @ParametersAreNonnullByDefault
    @Override
    public void render(PoseStack stack, MultiBufferSource bufferSource, int light, T player, float p_117208_, float p_117209_, float p_117210_, float p_117211_, float p_117212_, float p_117213_) {
        if (MinecraftForge.EVENT_BUS.post(new RenderItemInHandEvent.Pre(stack, bufferSource, player, (PlayerRenderer) this.renderer))) return;
        super.render(stack, bufferSource, light, player, p_117208_, p_117209_, p_117210_, p_117211_, p_117212_, p_117213_);
    }

    @ParametersAreNonnullByDefault
    @Override
    protected void renderArmWithItem(LivingEntity player, ItemStack itemStack, ItemTransforms.TransformType transformType, HumanoidArm arm, PoseStack stack, MultiBufferSource bufferSource, int light) {
        if (itemStack.is(Items.SPYGLASS) && player.getUseItem() == itemStack && player.swingTime == 0) {
            this.renderArmWithSpyglass(player, itemStack, arm, stack, bufferSource, light);
        } else {
            if (!itemStack.isEmpty()) {
                stack.pushPose();
                MinecraftForge.EVENT_BUS.post(new RenderItemInHandEvent.ApplyModifier(stack, bufferSource, (Player) player, itemStack, arm, (PlayerRenderer) this.renderer));
                this.getParentModel().translateToHand(arm, stack);
                stack.mulPose(Vector3f.XP.rotationDegrees(-90.0F));
                stack.mulPose(Vector3f.YP.rotationDegrees(180.0F));
                boolean flag = arm == HumanoidArm.LEFT;
                stack.translate((flag ? -1d : 1d) / 16.0d, 0.125D, -0.625D);
                Minecraft.getInstance().getItemInHandRenderer().renderItem(player, itemStack, transformType, flag, stack, bufferSource, light);
                MinecraftForge.EVENT_BUS.post(new RenderItemInHandEvent.ResetModifier(stack, bufferSource, (Player) player, itemStack, arm, (PlayerRenderer) this.renderer));
                stack.popPose();
            }
        }
    }

    private void renderArmWithSpyglass(LivingEntity player, ItemStack itemStack, HumanoidArm arm, PoseStack stack, MultiBufferSource bufferSource, int light) {
        stack.pushPose();
        MinecraftForge.EVENT_BUS.post(new RenderItemInHandEvent.ApplyModifier(stack, bufferSource, (Player) player, itemStack, arm, (PlayerRenderer) this.renderer));
        ModelPart modelpart = this.getParentModel().getHead();
        float f = modelpart.xRot;
        modelpart.xRot = Mth.clamp(modelpart.xRot, (-(float) Math.PI / 6F), ((float) Math.PI / 2F));
        modelpart.translateAndRotate(stack);
        modelpart.xRot = f;
        CustomHeadLayer.translateToHead(stack, false);
        boolean flag = arm == HumanoidArm.LEFT;
        stack.translate((flag ? -2.5F : 2.5F) / 16.0F, -0.0625D, 0.0D);
        Minecraft.getInstance().getItemInHandRenderer().renderItem(player, itemStack, ItemTransforms.TransformType.HEAD, false, stack, bufferSource, light);
        MinecraftForge.EVENT_BUS.post(new RenderItemInHandEvent.ResetModifier(stack, bufferSource, (Player) player, itemStack, arm, (PlayerRenderer) this.renderer));
        stack.popPose();
    }
}

 

i've tried a few things but haven't found a way to prevent the item to move (even if the arm doesn't move the item does). 

Edited by Skyriis
Link to comment
Share on other sites

1 hour ago, Luis_ST said:

did you look at the vanilla code?

I'm still looking for the method which rotates the item.

#Edit 1

The only rotation i've found is in ItemInHandLayer#renderArmWithItem (L45-46).

#Edit 2

Overriding the translateToHand method doesn't work.

Rotating the matix stack to -armModelPart.zRot doesn't work too. :(

 

Edited by Skyriis
Link to comment
Share on other sites

On 9/5/2021 at 10:50 AM, Luis_ST said:

the base Entity is still a Player I think you can simply copy the vanilla ItemInHandLayer code, it will render a the item at the normal position (which is the player hand) then you need to move the x, y and z position to the position you want

Changing (translating) the position to where i want isn't the problem. That works like it should but the rotation of the item in the hand isn't. Like i've mentioned here.

I still haven't figured out how to avoid the item to rotate on the z-axe.

The weird thing is that i can rotate it on X and Y but not on Z

Edited by Skyriis
Link to comment
Share on other sites

1 hour ago, Luis_ST said:

Did you try some random values, only for testing because it should work this way

I tried -45, -180, 180, 90.

 

Could it be possible that the arm isn't moving but the item in the hand still translates to the point where the player hand would be?

Link to comment
Share on other sites

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



×
×
  • Create New...

Important Information

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