PatrickKR Posted June 4, 2020 Posted June 4, 2020 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 Quote
PatrickKR Posted June 4, 2020 Author Posted June 4, 2020 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()); Quote
PatrickKR Posted June 4, 2020 Author Posted June 4, 2020 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>? Quote
PatrickKR Posted June 4, 2020 Author Posted June 4, 2020 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? Quote
PatrickKR Posted June 4, 2020 Author Posted June 4, 2020 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); } } Quote
Recommended Posts
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.