Jump to content

[1.15.2] Trying to render a specific entity


PatrickKR

Recommended Posts

I'm trying to update a custom entity rendering mod from 1.12.2 to 1.15.2

Minecraft.getMinecraft().getRenderManager().renderEntityStatic(fake, Animation.getPartialTickTime(), false);

I've been keep trying to change this to 1.15.2 method, but can't find a single clue.
Minecraft.getInstance().getRenderManager().renderEntityStatic(fake, fake.getPosX(), fake.getPosY(), fake.getPosZ(), fake.rotationYaw, Animation.getPartialTickTime(), new MatrixStack());

Minecraft.getInstance().getRenderManager().renderEntityStatic(fake, fake.getPosX(), fake.getPosY(), fake.getPosZ(), fake.rotationYaw, Animation.getPartialTickTime(), ?, ?, ?);

Can't find a way to complete this..

 

@SubscribeEvent
    public void render(final RenderLivingEvent.Pre pre) {
        if (CustomEntityEvent.rendering != null) return;
        final EntityLivingBase entity = pre.getEntity();
        final CustomEntity custom = manager.getCustomEntity(entity.getEntityId());
        if (custom != null) {
            CustomEntityEvent.rendering = custom;
            final EntityLivingBase fake = custom.fakeEntity;
            if (fake != null) {
                final RenderLivingBase render = pre.getRenderer();
                if (render instanceof CustomRenderer) ((CustomRenderer)render).setShadowSize(0.0f);
                pre.setCanceled(true);
                Minecraft.getMinecraft().getRenderManager().renderEntityStatic(custom.fakeEntity, Animation.getPartialTickTime(), false);
            }
        }
    }

Old (1.12.2)

 

@SubscribeEvent
    public void render(final RenderLivingEvent.Pre pre) {
        if (CustomEntityEvent.rendering != null) return;
        final LivingEntity entity = pre.getEntity();
        final CustomEntity custom = manager.getCustomEntity(entity.getEntityId());
        if (custom != null) {
            CustomEntityEvent.rendering = custom;
            final LivingEntity fake = custom.fakeEntity;
            if (fake != null) {
                final LivingRenderer render = pre.getRenderer();
                if (render instanceof CustomRenderer) ((CustomRenderer)render).setShadowSize(0.0f);
                pre.setCanceled(true);
                Minecraft.getInstance().getRenderManager().renderEntityStatic(fake, fake.getPosX(), fake.getPosY(), fake.getPosZ(), fake.rotationYaw, Animation.getPartialTickTime(), ?, ?, ?);
            }
        }
    }

New (1.15.2), WIP

Link to comment
Share on other sites

So, would this work?

 

Minecraft.getInstance().getRenderManager().renderEntityStatic(fake, fake.getPosX(), fake.getPosY(), fake.getPosZ(), fake.rotationYaw, Animation.getPartialTickTime(), pre.getMatrixStack(), pre.getBuffers(), pre.getLight());

 

Link to comment
Share on other sites

14 minutes ago, diesieben07 said:

No. Why do you need the class?

What i'm trying to do, is injecting the original rendering class.

The part of this code is not written by me, so i'm not sure about how to inject (ASM Library).

To do this, i need an original class extending Entity, and the original Renderer.

Is it not possible at all?

Link to comment
Share on other sites

2 minutes ago, diesieben07 said:

No, an EntityType does not know about it's entity class. 

Can you please show the code where the class is needed?

I'm not even sure whether this code from 1.12.2 will work (if not work, i will have to learn bci, which would be terrible)

package com.github.patrick.customentity.renderer.asm;

import com.github.patrick.customentity.client.CustomEntity;
import com.github.patrick.customentity.client.CustomEntityEvent;
import com.github.patrick.customentity.renderer.CustomRenderer;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.client.renderer.entity.GiantZombieRenderer;
import net.minecraft.client.renderer.entity.LivingRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.FieldVisitor;
import net.minecraft.client.Minecraft;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;

@SuppressWarnings("rawtypes")
public class ASMRenderer implements Opcodes {
    private static final Field SHADOW_SIZE;
    private static final Method PRE_RENDER_CALL_BACK;
    private static final ASMClassLoader CLASS_LOADER;
    private static int count;

    static {
        CLASS_LOADER = new ASMClassLoader();
        PRE_RENDER_CALL_BACK = getPreRenderCallback();
        SHADOW_SIZE = getShadowSize();
    }

    public static LivingRenderer createRenderClass(final Class<? extends Entity> entityClass, final LivingRenderer render) throws Exception {
        final Class<?> superClass = render.getClass();
        final String className = "com/github/patrick/customentity/renderer/" + superClass.getSimpleName() + "Custom" + count++;
        final ClassWriter writer = new ClassWriter(0);
        writer.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, Type.getInternalName(superClass), new String[] { Type.getInternalName(CustomRenderer.class) });
        writer.visitSource(".dynamic", null);
        final FieldVisitor fv = writer.visitField(ACC_PRIVATE + ACC_FINAL, "defaultShadowSize", "F", null, null);
        fv.visitEnd();
        int stack = 0;
        Constructor<?> con;
        if (GiantZombieRenderer.class.isAssignableFrom(superClass)) {
            con = findConstructor(superClass, EntityRendererManager.class, Float.TYPE);
            stack = 1;
        }
        else con = findConstructor(superClass, EntityRendererManager.class);
        if (con == null) return null;
        MethodVisitor visitor = writer.visitMethod(ACC_PUBLIC, "<init>", "(" + Type.getDescriptor(EntityRendererManager.class) + ")V", null, null);
        visitor.visitCode();
        visitor.visitVarInsn(ALOAD, 0);
        visitor.visitVarInsn(ALOAD, 1);
        if (stack == 1) visitor.visitLdcInsn(6F);
        visitor.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(superClass), "<init>", Type.getConstructorDescriptor(con), false);
        visitor.visitVarInsn(ALOAD, 0);
        visitor.visitVarInsn(ALOAD, 0);
        visitor.visitFieldInsn(GETFIELD, Type.getInternalName(superClass), SHADOW_SIZE.getName(), "F");
        visitor.visitFieldInsn(PUTFIELD, className, "defaultShadowSize", "F");
        visitor.visitInsn(RETURN);
        visitor.visitMaxs(2 + stack, 2);
        visitor.visitEnd();

        final Label ifLabel = new Label();
        final Method preRenderCallback = findPreRenderCallback(entityClass, superClass);
        if (preRenderCallback == null) return null;
        visitor = writer.visitMethod(ACC_PUBLIC, preRenderCallback.getName(), "(" + Type.getDescriptor(entityClass) + "F)V", null, null);
        visitor.visitCode();
        if (preRenderCallback.getDeclaringClass() != LivingRenderer.class) {
            visitor.visitVarInsn(ALOAD, 0);
            visitor.visitVarInsn(ALOAD, 1);
            visitor.visitVarInsn(FLOAD, 2);
            visitor.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(superClass), preRenderCallback.getName(), Type.getMethodDescriptor(preRenderCallback), false);
        }
        visitor.visitFieldInsn(GETSTATIC, Type.getInternalName(CustomEntityEvent.class), "rendering", Type.getDescriptor(CustomEntity.class));
        visitor.visitVarInsn(ASTORE, 3);
        visitor.visitVarInsn(ALOAD, 0);
        visitor.visitFieldInsn(GETFIELD, className, "defaultShadowSize", "F");
        visitor.visitVarInsn(FSTORE, 4);
        visitor.visitVarInsn(ALOAD, 3);
        visitor.visitJumpInsn(IFNULL, ifLabel);
        visitor.visitVarInsn(FLOAD, 4);
        visitor.visitVarInsn(ALOAD, 3);
        visitor.visitVarInsn(ALOAD, 1);
        visitor.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(CustomEntity.class), "applyGraphic", "(" + Type.getDescriptor(LivingEntity.class) + ")F", false);
        visitor.visitInsn(FMUL);
        visitor.visitVarInsn(FSTORE, 4);
        visitor.visitLabel(ifLabel);
        visitor.visitLineNumber(33, ifLabel);
        visitor.visitFrame(1, 2, new Object[] { Type.getInternalName(CustomEntity.class), FLOAT }, 0, null);
        visitor.visitVarInsn(ALOAD, 0);
        visitor.visitVarInsn(FLOAD, 4);
        visitor.visitFieldInsn(PUTFIELD, className, SHADOW_SIZE.getName(), "F");
        visitor.visitInsn(RETURN);
        visitor.visitMaxs(3, 5);
        visitor.visitEnd();

        visitor = writer.visitMethod(ACC_PUBLIC, "setShadowSize", "(F)V", null, null);
        visitor.visitCode();
        visitor.visitVarInsn(ALOAD, 0);
        visitor.visitVarInsn(FLOAD, 1);
        visitor.visitFieldInsn(PUTFIELD, className, SHADOW_SIZE.getName(), "F");
        visitor.visitInsn(RETURN);
        visitor.visitMaxs(2, 2);
        visitor.visitEnd();

        if (preRenderCallback.getParameterTypes()[0] != entityClass) {
            visitor = writer.visitMethod(ACC_PROTECTED + ACC_VOLATILE + ACC_SYNTHETIC, PRE_RENDER_CALL_BACK.getName(), Type.getMethodDescriptor(preRenderCallback), null, null);
            visitor.visitCode();
            visitor.visitVarInsn(ALOAD, 0);
            visitor.visitVarInsn(ALOAD, 1);
            visitor.visitTypeInsn(CHECKCAST, Type.getInternalName(entityClass));
            visitor.visitVarInsn(FLOAD, 2);
            visitor.visitMethodInsn(INVOKEVIRTUAL, className, PRE_RENDER_CALL_BACK.getName(), "(" + Type.getDescriptor(entityClass) + "F)V", false);
            visitor.visitInsn(RETURN);
            visitor.visitMaxs(3, 3);
            visitor.visitEnd();
        }
        writer.visitEnd();

        return (LivingRenderer) CLASS_LOADER.define(className.replace('/', '.'), writer.toByteArray()).getConstructor(EntityRendererManager.class).newInstance(Minecraft.getInstance().getRenderManager());
    }

    private static Constructor<?> findConstructor(final Class<?> c, final Class... parameterTypes) {
        try {
            return c.getConstructor((Class<?>[])parameterTypes);
        } catch (Exception e) {
            return null;
        }
    }

    private static Method findPreRenderCallback(final Class<? extends Entity> entityClass, Class<?> renderClass) {
        while (LivingRenderer.class.isAssignableFrom(renderClass)) {
            Class<?> superEntityClass = entityClass;
            while (LivingEntity.class.isAssignableFrom(superEntityClass)) {
                try {
                    return renderClass.getDeclaredMethod(PRE_RENDER_CALL_BACK.getName(), superEntityClass, Float.TYPE);
                } catch (Exception ex) {
                    superEntityClass = superEntityClass.getSuperclass();
                }
            }
            renderClass = renderClass.getSuperclass();
        }
        return null;
    }

    private static Field getShadowSize() throws RuntimeException {
        Exception failed = null;
        for (String fieldName : new HashSet<>(Arrays.asList("shadowSize", "field_76989_e"))) try {
            Field field = EntityRenderer.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field;
        } catch (Exception e) {
            failed = e;
        }
        throw new RuntimeException(failed);
    }

    private static Method getPreRenderCallback() throws RuntimeException {
        Exception failed = null;
        for (String fieldName : new HashSet<>(Arrays.asList("func_77041_b", "preRenderCallback"))) try {
            Method method = LivingRenderer.class.getDeclaredMethod(fieldName, LivingEntity.class, Float.TYPE);
            method.setAccessible(true);
            return method;
        } catch (Exception e) {
            failed = e;
        }
        throw new RuntimeException(failed);
    }
}

 

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.