• Recently Browsing

    No registered users viewing this page.

  • Posts

    • Perfect explanation! Thanks
    • Fabric is not supported here, this site is for using/making Forge mods.   If you meant Forge, please post the entire debug.log on a hosting site (such as a github gist) and link to it here.
    • The game crashed whilst exception in server tick loop Error: java.lang.NoClassDefFoundError: com/mojang/datafixers/types/DynamicOps It says like this. Please Help me!
    • So... it's generating a renderer class at runtime. Why? What is the purpose of this? I'm not going to decypher all that ASM code.
    • 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); } }  
  • Topics

  • Who's Online (See full list)