package slimeknights.tconstruct.library.client.renderer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraftforge.fml.client.registry.IRenderFactory; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import javax.annotation.Nonnull; import slimeknights.tconstruct.TConstruct; import slimeknights.tconstruct.library.capability.projectile.CapabilityTinkerProjectile; import slimeknights.tconstruct.library.capability.projectile.ITinkerProjectile; import slimeknights.tconstruct.library.entity.EntityProjectileBase; public class RenderProjectileBase<T extends EntityProjectileBase> extends Render<T> { protected RenderProjectileBase(RenderManager renderManager) { super(renderManager); } @Override public void doRender(@Nonnull T entity, double x, double y, double z, float entityYaw, float partialTicks) { // preface: Remember that the rotations are applied in reverse order. // the rendering call does not apply any transformations. // That'd screw things up, since it'd be applied before our transformations // So remember to read this from the rendering call up to this line // can be overwritten in customRendering //toolCoreRenderer.setDepth(1/32f); ITinkerProjectile handler = entity.getCapability(CapabilityTinkerProjectile.PROJECTILE_CAPABILITY, null); if(handler == null) { return; } ItemStack item = handler.getItemStack(); GL11.glPushMatrix(); GL11.glEnable(GL12.GL_RESCALE_NORMAL); // last step: translate from 0/0/0 to correct position in world GL11.glTranslated(x, y, z); // mkae it smaller GL11.glScalef(0.5F, 0.5F, 0.5F); customRendering(entity, x, y, z, entityYaw, partialTicks); // arrow shake float f11 = (float) entity.arrowShake - partialTicks; if(f11 > 0.0F) { float f12 = -MathHelper.sin(f11 * 3.0F) * f11; GL11.glRotatef(f12, 0.0F, 0.0F, 1.0F); } if(renderManager == null || renderManager.renderEngine == null) { return; } // draw correct texture. not some weird block fragments. renderManager.renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); if(item != null) { Minecraft.getMinecraft().getRenderItem().renderItem(item, ItemCameraTransforms.TransformType.NONE); } else { ItemStack dummy = new ItemStack(Items.STICK); Minecraft.getMinecraft().getRenderItem().renderItem(dummy, Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getModelManager().getMissingModel()); } GL11.glDisable(GL12.GL_RESCALE_NORMAL); GL11.glPopMatrix(); super.doRender(entity, x, y, z, entityYaw, partialTicks); } public void customRendering(T entity, double x, double y, double z, float entityYaw, float partialTicks) { // flip it, flop it, pop it, pull it, push it, rotate it, translate it, TECHNOLOGY // rotate it into the direction we threw it GL11.glRotatef(entity.rotationYaw, 0f, 1f, 0f); GL11.glRotatef(-entity.rotationPitch, 1f, 0f, 0f); // adjust "stuck" depth if(entity.inGround) { GL11.glTranslated(0, 0, -entity.getStuckDepth()); } customCustomRendering(entity, x, y, z, entityYaw, partialTicks); // rotate it so it faces forward GL11.glRotatef(-90f, 0f, 1f, 0f); // rotate the projectile it so it faces upwards GL11.glRotatef(-45, 0f, 0f, 1f); } /** If you just want to rotate it or something but the overall "have it heading towards the target" should stay the same */ protected void customCustomRendering(T entity, double x, double y, double z, float entityYaw, float partialTicks) {} @Nonnull @Override protected ResourceLocation getEntityTexture(@Nonnull T entity) { return TextureMap.LOCATION_MISSING_TEXTURE; } public static <T extends EntityProjectileBase> IRenderFactory<T> getFactory(Class<? extends Render<? super T>> clazz) { try { final Constructor<? extends Render<? super T>> constr = clazz.getDeclaredConstructor(RenderManager.class); return new IRenderFactory<T>() { @Override public Render<? super T> createRenderFor(RenderManager manager) { try { return constr.newInstance(manager); } catch(InstantiationException e) { TConstruct.log.error(e); } catch(IllegalAccessException e) { TConstruct.log.error(e); } catch(InvocationTargetException e) { TConstruct.log.error(e); } return null; } }; } catch(NoSuchMethodException e) { TConstruct.log.error(e); } return null; } }