sokobanMod.client.HandlerLevelPreviewRenderer.java Source code

Java tutorial

Introduction

Here is the source code for sokobanMod.client.HandlerLevelPreviewRenderer.java

Source

package sokobanMod.client;

import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.common.util.ForgeDirection;

import org.lwjgl.opengl.GL11;

import sokobanMod.common.LevelRegistrator;
import sokobanMod.common.SokobanMod;
import sokobanMod.common.SokobanUtils;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

/**
 * Sokoban Mod
 * @author MineMaarten
 * www.minemaarten.com
 * @license Lesser GNU Public License v3 (http://www.gnu.org/licenses/lgpl.html)
 *
 * This class is derived from Equivalent Exchange 3's DrawBlockHighlightHandler, found at https://github.com/pahimar/Equivalent-Exchange-3/blob/master/common/com/pahimar/ee3/core/handlers/DrawBlockHighlightHandler.java
 */

@SideOnly(Side.CLIENT)
public class HandlerLevelPreviewRenderer {

    private static float time = 0;
    private static boolean colliding = false;

    @SubscribeEvent
    public void onDrawBlockHighlightEvent(DrawBlockHighlightEvent event) {
        if (event.currentItem != null && (event.currentItem == new ItemStack(SokobanMod.ItemLevelGeneratorTutorial)
                || event.currentItem == new ItemStack(SokobanMod.ItemLevelConverter))) {
            renderPreview(event);
        }
    }

    private void renderPreview(DrawBlockHighlightEvent event) {

        double x = event.target.blockX + 0.5F;
        double y = event.target.blockY + 0.5F;
        double z = event.target.blockZ + 0.5F;
        double iPX = event.player.prevPosX + (event.player.posX - event.player.prevPosX) * event.partialTicks;
        double iPY = event.player.prevPosY + (event.player.posY - event.player.prevPosY) * event.partialTicks;
        double iPZ = event.player.prevPosZ + (event.player.posZ - event.player.prevPosZ) * event.partialTicks;

        int baseX = event.target.blockX;
        int baseY = event.target.blockY + 1;
        int baseZ = event.target.blockZ;

        float xScale = 0.1F;
        float yScale = 0.1F;
        float zScale = 0.1F;
        float xShift = 0.0F;
        float yShift = 1.0F;
        float zShift = 0.0F;
        // determine the line color

        int[] levelBounds;
        int[] rawLevelBounds;
        ForgeDirection sideHit = ForgeDirection.UP;
        if (event.currentItem == new ItemStack(SokobanMod.ItemLevelGeneratorTutorial)) {
            rawLevelBounds = LevelRegistrator.getLevelBounds(event.currentItem.getItemDamage());
            levelBounds = rawLevelBounds.clone();
            levelBounds[0]++;
            levelBounds[1]++;
            levelBounds[2]++;
            yShift += levelBounds[1] / 2;

            int orientation = SokobanUtils.determineOrientation(event.player);
            switch (orientation) {
            case 0:
                orientation = 3;
                break;
            case 3:
                orientation = 5;
                break;
            case 1:
                orientation = 4;
                break;
            }
            sideHit = ForgeDirection.getOrientation(orientation);

            xShift += (1 - levelBounds[0] % 2) / 2F;
            yShift -= (1 - levelBounds[1] % 2) / 2F;
            zShift += (1 - levelBounds[2] % 2) / 2F;

        } else {
            colliding = false; // always render the wireframe green.
            NBTTagCompound nbt = event.player.getCurrentEquippedItem().stackTagCompound;
            if (nbt != null && nbt.hasKey("x")) {
                int startX = nbt.getInteger("x");
                int startY = nbt.getInteger("y");
                int startZ = nbt.getInteger("z");
                int endX = event.target.blockX;
                int endY = event.target.blockY;
                int endZ = event.target.blockZ;

                rawLevelBounds = new int[] { Math.abs(endX - startX), Math.abs(endY - startY),
                        Math.abs(endZ - startZ) };
                levelBounds = new int[] { rawLevelBounds[0] + 1, rawLevelBounds[1] + 1, rawLevelBounds[2] + 1 };

                xShift -= (endX - startX) / 2F;
                yShift -= (endY - startY) / 2F + 1F;
                zShift -= (endZ - startZ) / 2F;
            } else {
                rawLevelBounds = new int[] { 1, 1, 1 };
                levelBounds = new int[] { 1, 1, 1 };
                yShift = 0F;
            }

        }
        switch (sideHit) {
        case NORTH:
            zShift += levelBounds[2] / 2;
            zShift -= 1 - levelBounds[2] % 2;
            zShift = -zShift;

            baseZ -= rawLevelBounds[2];// +2
            baseX -= rawLevelBounds[0] / 2;
            break;
        case SOUTH:
            zShift += levelBounds[2] / 2;
            zShift -= 1 - levelBounds[2] % 2;

            baseX -= rawLevelBounds[0] / 2;
            break;
        case EAST:
            // zShift = 0;
            xShift += levelBounds[0] / 2;
            xShift -= 1 - levelBounds[0] % 2;
            baseZ -= rawLevelBounds[2] / 2;
            break;
        case WEST:
            xShift += levelBounds[0] / 2;
            xShift -= 1 - levelBounds[0] % 2;
            xShift = -xShift;

            baseX -= rawLevelBounds[0];
            baseZ -= rawLevelBounds[2] / 2;
            break;
        default:
        }

        colliding = SokobanUtils.isCollidingWithLevel(event.player.worldObj, baseX, baseY, baseZ,
                baseX + rawLevelBounds[0], baseY + rawLevelBounds[1], baseZ + rawLevelBounds[2]);

        GL11.glDepthMask(false);
        GL11.glDisable(GL11.GL_TEXTURE_2D);
        // GL11.glDisable(GL11.GL_CULL_FACE);

        for (int i = 0; i < 6; i++) {
            ForgeDirection forgeDir = ForgeDirection.getOrientation(i);
            int zCorrection = i == 2 ? -1 : 1;
            GL11.glPushMatrix();
            GL11.glTranslated(-iPX + x + xShift, -iPY + y + yShift, -iPZ + z + zShift);
            GL11.glScalef(levelBounds[0] + xScale, levelBounds[1] + yScale, levelBounds[2] + zScale);
            GL11.glRotatef(90, forgeDir.offsetX, forgeDir.offsetY, forgeDir.offsetZ);
            GL11.glTranslated(0, 0, 0.5f * zCorrection);
            GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
            renderPulsingQuad();
            GL11.glPopMatrix();
        }

        GL11.glDepthMask(true);
        GL11.glEnable(GL11.GL_TEXTURE_2D);

    }

    public static void renderPulsingQuad() {
        time += 0.001;
        if (time > 2 * Math.PI)
            time = 0;
        float quadPosX = (float) Math.sin(time) * 0.2F;
        float quadPosY = (float) Math.cos(time) * 0.2F;

        GL11.glColor4f(colliding ? 1F : 0F, colliding ? 0F : 1F, 0F, 1F);

        GL11.glLineWidth(3.0F);
        GL11.glBegin(GL11.GL_LINES);

        // the lines around the whole level
        GL11.glVertex3f(-0.5F, 0.5F, 0F);
        GL11.glVertex3f(0.5F, 0.5F, 0F);
        GL11.glVertex3f(0.5F, -0.5F, 0F);
        GL11.glVertex3f(-0.5F, -0.5F, 0F);

        // draw the lines from the bigger quad's corner to the small quad's
        // corner
        float quadSize = 0.1F;
        GL11.glVertex3f(-0.5F, 0.5F, 0F);
        GL11.glVertex3f(-quadSize + quadPosX, quadSize + quadPosY, 0F);
        GL11.glVertex3f(0.5F, 0.5F, 0F);
        GL11.glVertex3f(quadSize + quadPosX, quadSize + quadPosY, 0F);
        GL11.glVertex3f(0.5F, -0.5F, 0F);
        GL11.glVertex3f(quadSize + quadPosX, -quadSize + quadPosY, 0F);
        GL11.glVertex3f(-0.5F, -0.5F, 0F);
        GL11.glVertex3f(-quadSize + quadPosX, -quadSize + quadPosY, 0F);
        GL11.glEnd();

        // draw the quad inside the big quad
        GL11.glBegin(GL11.GL_LINE_LOOP);
        GL11.glVertex3f(-quadSize + quadPosX, quadSize + quadPosY, 0F);
        GL11.glVertex3f(quadSize + quadPosX, quadSize + quadPosY, 0F);
        GL11.glVertex3f(quadSize + quadPosX, -quadSize + quadPosY, 0F);
        GL11.glVertex3f(-quadSize + quadPosX, -quadSize + quadPosY, 0F);
        GL11.glEnd();
    }

}