package openblocks.client.model; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityOtherPlayerMP; import net.minecraft.client.model.ModelBiped; import net.minecraft.client.model.ModelRenderer; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.common.MinecraftForge; import openblocks.common.CraneRegistry; import openblocks.common.entity.EntityMagnet; import openblocks.common.item.ItemCraneBackpack; import org.lwjgl.opengl.GL11; public class ModelCraneBackpack extends ModelBiped { public static final ModelCraneBackpack instance = new ModelCraneBackpack(); private static final ResourceLocation texture = new ResourceLocation(ItemCraneBackpack.TEXTURE_CRANE); private static final float DEG_TO_RAD = (float)Math.PI / 180; private final ModelRenderer arm; public ModelCraneBackpack() { textureWidth = 128; textureHeight = 64; bipedBody = new ModelRenderer(this, 0, 0); bipedBody.setTextureSize(textureWidth, textureHeight); bipedBody.setRotationPoint(0, 0, 0); // main body bipedBody.addBox(-4, 0, -2, 8, 12, 8); // support bipedBody.setTextureOffset(32, 0); bipedBody.addBox(-1, -16, 6, 2, 24, 2); // arm arm = new ModelRenderer(this, 0, 0); arm.setTextureSize(textureWidth, textureHeight); arm.setRotationPoint(0, -16, 7); arm.addBox(-1, 0, 1, 2, 2, 42); } @Override public void setRotationAngles(float swingTime, float swingAmpl, float rightArmAngle, float headAngleX, float headAngleY, float scale, Entity entity) { super.setRotationAngles(swingTime, swingAmpl, rightArmAngle, headAngleX, headAngleY, scale, entity); if (isSneak) { arm.rotationPointZ = -0.15f; // good enough values arm.offsetY = -0.125f; } else { arm.rotationPointZ = 7; arm.offsetY = 0; } } @Override public void render(Entity entity, float swingTime, float swingAmpl, float rightArmAngle, float headAngleX, float headAngleY, float scale) { isSneak = entity != null && entity.isSneaking(); setRotationAngles(swingTime, swingAmpl, rightArmAngle, headAngleX, headAngleY, scale, entity); bipedBody.render(scale); arm.rotateAngleY = (float)Math.PI + bipedHead.rotateAngleY; arm.render(scale); } private static float interpolateAngle(float current, float prev, float partialTickTime) { float interpolated = prev + partialTickTime * (current - prev); return (90 + interpolated) * DEG_TO_RAD; } private static double interpolatePos(double current, double prev, float partialTickTime) { return prev + partialTickTime * (current - prev); } @SubscribeEvent public void renderLines(RenderPlayerEvent.Pre evt) { final EntityPlayer player = evt.entityPlayer; if (!ItemCraneBackpack.isWearingCrane(player)) return; final EntityMagnet magnet = CraneRegistry.instance.getMagnetForPlayer(player); if (magnet == null) return; double playerX = interpolatePos(player.posX, player.lastTickPosX, evt.partialRenderTick) - RenderManager.renderPosX; double playerY = interpolatePos(player.posY, player.lastTickPosY, evt.partialRenderTick) - RenderManager.renderPosY; double playerZ = interpolatePos(player.posZ, player.lastTickPosZ, evt.partialRenderTick) - RenderManager.renderPosZ; if (player instanceof EntityOtherPlayerMP) playerY += 1.62; final float offset = interpolateAngle(player.renderYawOffset, player.prevRenderYawOffset, evt.partialRenderTick); final float head = interpolateAngle(player.rotationYawHead, player.prevRotationYawHead, evt.partialRenderTick); double armX = playerX; double armY = playerY; double armZ = playerZ; double armLength; if (player.isSneaking()) { armY += 0.70; armLength = 2; } else { armX += -0.45 * MathHelper.cos(offset); armY += 0.65; armZ += -0.45 * MathHelper.sin(offset); armLength = 2.4; } armX += armLength * MathHelper.cos(head); armZ += armLength * MathHelper.sin(head); final double magnetX = interpolatePos(magnet.posX, magnet.lastTickPosX, evt.partialRenderTick) - RenderManager.renderPosX; final double magnetY = interpolatePos(magnet.posY, magnet.lastTickPosY, evt.partialRenderTick) - RenderManager.renderPosY + magnet.height - 0.1; final double magnetZ = interpolatePos(magnet.posZ, magnet.lastTickPosZ, evt.partialRenderTick) - RenderManager.renderPosZ; GL11.glLineWidth(2); GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_LINE_STIPPLE); GL11.glColor3f(1, 1, 0); GL11.glLineStipple(3, (short)0x0555); GL11.glBegin(GL11.GL_LINES); GL11.glVertex3d(armX, armY, armZ); GL11.glVertex3d(magnetX, magnetY, magnetZ); GL11.glEnd(); GL11.glDisable(GL11.GL_LINE_STIPPLE); GL11.glEnable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_TEXTURE_2D); drawLine(magnetX, magnetY, magnetZ, armX, armY, armZ); } private static void drawLineFPP(EntityPlayer player, float partialTickTime) { EntityMagnet magnet = CraneRegistry.instance.getMagnetForPlayer(player); if (magnet == null) return; final float yaw = interpolateAngle(player.rotationYaw, player.prevRotationYaw, partialTickTime); final double posX = 1.9 * MathHelper.cos(yaw); final double posZ = 1.9 * MathHelper.sin(yaw); final double centerX = interpolatePos(player.posX, player.lastTickPosX, partialTickTime); final double centerY = interpolatePos(player.posY, player.lastTickPosY, partialTickTime); final double centerZ = interpolatePos(player.posZ, player.lastTickPosZ, partialTickTime); final double magnetX = interpolatePos(magnet.posX, magnet.lastTickPosX, partialTickTime) - centerX; final double magnetY = interpolatePos(magnet.posY, magnet.lastTickPosY, partialTickTime) - centerY + magnet.height - 0.05; final double magnetZ = interpolatePos(magnet.posZ, magnet.lastTickPosZ, partialTickTime) - centerZ; drawLine(magnetX, magnetY, magnetZ, posX, 0.6, posZ); } private static void drawLine(double x1, double y1, double z1, double x2, double y2, double z2) { GL11.glLineWidth(2); GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_LINE_STIPPLE); GL11.glColor3f(0, 0, 0); GL11.glLineStipple(5, (short)0x5555); GL11.glBegin(GL11.GL_LINES); GL11.glVertex3d(x1, y1, z1); GL11.glVertex3d(x2, y2, z2); GL11.glEnd(); GL11.glColor3f(1, 1, 0); GL11.glLineStipple(5, (short)0xAAAA); GL11.glBegin(GL11.GL_LINES); GL11.glVertex3d(x1, y1, z1); GL11.glVertex3d(x2, y2, z2); GL11.glEnd(); GL11.glDisable(GL11.GL_LINE_STIPPLE); GL11.glEnable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_TEXTURE_2D); } private void drawArm(RenderWorldLastEvent evt, final EntityPlayer player) { final TextureManager tex = Minecraft.getMinecraft().getTextureManager(); tex.bindTexture(texture); GL11.glColor3f(1, 1, 1); GL11.glDisable(GL11.GL_LIGHTING); GL11.glPushMatrix(); // values adjusted to roughly match TPP crane position GL11.glRotated(-player.rotationYaw, 0, 1, 0); GL11.glTranslatef(0, 1.6f, -1f); arm.rotateAngleY = 0; arm.render(1.0f / 16.0f); GL11.glPopMatrix(); GL11.glEnable(GL11.GL_LIGHTING); } @SubscribeEvent public void renderFppArm(RenderWorldLastEvent evt) { final Minecraft mc = Minecraft.getMinecraft(); if (mc.gameSettings.thirdPersonView != 0) return; final Entity rve = mc.renderViewEntity; if (!(rve instanceof EntityPlayer)) return; final EntityPlayer player = (EntityPlayer)rve; if (!ItemCraneBackpack.isWearingCrane(player)) return; drawArm(evt, player); drawLineFPP(player, evt.partialTicks); } public void init() { MinecraftForge.EVENT_BUS.register(this); } }