Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

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

  • Author

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());

 

  • Author

Hmmm. Thanks.
I have another question.
i am getting a renderer map from
 

manager.renderers.entrySet()

and it returns 

Map<EntityType<?>, EntityRenderer<?>> 

Is there anyway to convert EntityType<?> to Class<? extends Entity>?

  • Author
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?

  • Author
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);
    }
}

 

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...

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.