Package mrtjp.projectred.integration

Source Code of mrtjp.projectred.integration.GatePart

package mrtjp.projectred.integration;

import codechicken.lib.data.MCDataInput;
import codechicken.lib.data.MCDataOutput;
import codechicken.lib.raytracer.IndexedCuboid6;
import codechicken.lib.render.CCRenderState;
import codechicken.lib.render.TextureUtils;
import codechicken.lib.vec.*;
import codechicken.microblock.FaceMicroClass;
import codechicken.multipart.*;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import mrtjp.core.world.PlacementLib;
import mrtjp.projectred.api.IConnectable;
import mrtjp.projectred.api.IScrewdriver;
import mrtjp.projectred.core.Configurator;
import mrtjp.projectred.core.libmc.PRLib;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import org.lwjgl.opengl.GL11;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@SuppressWarnings({"rawtypes", "unchecked"})
public abstract class GatePart extends JCuboidPart implements JNormalOcclusion, IConnectable, TFacePart, JIconHitEffects
{
    public static Cuboid6[][] oBoxes = new Cuboid6[6][2];

    static
    {
        oBoxes[0][0] = new Cuboid6(1/8D, 0, 0, 7/8D, 1/8D, 1);
        oBoxes[0][1] = new Cuboid6(0, 0, 1/8D, 1, 1/8D, 7/8D);
        for (int s = 1; s < 6; s++)
        {
            Transformation t = Rotation.sideRotations[s].at(Vector3.center);
            oBoxes[s][0] = oBoxes[0][0].copy().apply(t);
            oBoxes[s][1] = oBoxes[0][1].copy().apply(t);
        }
    }

    public byte orientation;
    public byte subID;
    public byte shape;

    public int connMap;
    public long schedTime;

    public abstract GateLogic getLogic();

    public int side()
    {
        return orientation>>2;
    }

    public void setSide(int s)
    {
        orientation = (byte)(orientation&0x3|s<<2);
    }

    public int rotation()
    {
        return orientation&0x3;
    }

    public void setRotation(int r)
    {
        orientation = (byte)(orientation&0xFC|r);
    }

    public int shape()
    {
        return shape&0xFF;
    }

    public void setShape(int s)
    {
        shape = (byte)s;
    }

    public Transformation rotationT()
    {
        return Rotation.sideOrientation(side(), rotation()).at(Vector3.center);
    }

    public void preparePlacement(EntityPlayer player, BlockCoord pos, int side, int meta)
    {
        subID = (byte)meta;
        setSide(side^1);
        setRotation((Rotation.getSidedRotation(player, side)+2)%4);//temporary fix for getSidedRotation bug
    }

    @Override
    public void save(NBTTagCompound tag)
    {
        tag.setByte("orient", orientation);
        tag.setByte("subID", subID);
        tag.setByte("shape", shape);
        tag.setShort("connMap", (short)connMap);
        tag.setLong("schedTime", schedTime);
    }

    @Override
    public void load(NBTTagCompound tag)
    {
        orientation = tag.getByte("orient");
        subID = tag.getByte("subID");
        shape = tag.getByte("shape");
        connMap = tag.getShort("connMap")&0xFFFF;
        schedTime = tag.getLong("schedTime");
    }

    @Override
    public void readDesc(MCDataInput packet)
    {
        orientation = packet.readByte();
        subID = packet.readByte();
        shape = packet.readByte();
    }

    @Override
    public void read(MCDataInput packet)
    {
        read(packet, packet.readUByte());
    }

    public void read(MCDataInput packet, int switch_key)
    {
        if (switch_key == 0)
        {
            orientation = packet.readByte();
            if (Configurator.staticGates)
                tile().markRender();
        }
        else if (switch_key == 1)
        {
            shape = packet.readByte();
            if (Configurator.staticGates)
                tile().markRender();
        }
    }

    @Override
    public void writeDesc(MCDataOutput packet)
    {
        packet.writeByte(orientation);
        packet.writeByte(subID);
        packet.writeByte(shape);
    }

    @Override
    public void scheduleTick(int ticks)
    {
        if (schedTime < 0)
            schedTime = world().getTotalWorldTime()+ticks;
    }

    private void processScheduled()
    {
        if (schedTime >= 0 && world().getTotalWorldTime() >= schedTime)
        {
            schedTime = -1;
            scheduledTick();
        }
    }

    public void onChange()
    {
        processScheduled();
        getLogic().onChange(this);
    }

    @Override
    public void update()
    {
        if (!world().isRemote)
            processScheduled();

        getLogic().onTick(this);
    }

    @Override
    public void onPartChanged(TMultiPart part)
    {
        if (!world().isRemote)
        {
            updateInternalConnections();
            onChange();
        }
    }

    @Override
    public void onNeighborChanged()
    {
        if (!world().isRemote)
        {
            if (dropIfCantStay())
                return;

            updateExternalConnections();
            onChange();
        }
    }

    @Override
    public void onAdded()
    {
        super.onAdded();
        if (!world().isRemote)
        {
            getLogic().setup(this);
            updateConnections();
            onChange();
        }
    }

    @Override
    public void onRemoved()
    {
        super.onRemoved();
        if (!world().isRemote)
            notifyNeighbors(0xF);
    }

    public boolean canStay()
    {
        BlockCoord pos = new BlockCoord(tile()).offset(side());
        return PlacementLib.canPlaceGateOnSide(world(), pos.x, pos.y, pos.z, side()^1);
    }

    public boolean dropIfCantStay()
    {
        if (!canStay())
        {
            drop();
            return true;
        }
        return false;
    }

    public void drop()
    {
        TileMultipart.dropItem(getItem(), world(), Vector3.fromTileEntityCenter(tile()));
        tile().remPart(this);
    }

    public EnumGate getGateType()
    {
        return EnumGate.VALID_GATES[subID&0xFF];
    }

    protected void updateConnections()
    {
        updateInternalConnections();
        updateExternalConnections();
    }

    /**
     * Recalculates connections to blocks outside this sapce
     *
     * @return true if a new connection was added or one was removed
     */
    protected boolean updateExternalConnections()
    {
        int newConn = 0;
        for (int r = 0; r < 4; r++)
            if (connectStraight(r))
                newConn |= 0x10<<r;
            else if (connectCorner(r))
                newConn |= 1<<r;

        if (newConn != (connMap&0xF000FF))
        {
            int diff = connMap^newConn;
            connMap = connMap&~0xF000FF|newConn;

            // notify corner disconnections
            for (int r = 0; r < 4; r++)
                if ((diff&1<<r) != 0)
                    notifyCornerChange(r);

            return true;
        }
        return false;
    }

    /**
     * Recalculates connections to other parts within this space
     *
     * @return true if a new connection was added or one was removed
     */
    protected boolean updateInternalConnections()
    {
        int newConn = 0;
        for (int r = 0; r < 4; r++)
            if (connectInternal(r))
                newConn |= 0x100<<r;

        if (newConn != (connMap&0x10F00))
        {
            connMap = connMap&~0x10F00|newConn;
            return true;
        }
        return false;
    }

    public boolean connectCorner(int r)
    {
        int absDir = Rotation.rotateSide(side(), r);

        BlockCoord pos = new BlockCoord(tile()).offset(absDir);
        if (!world().isAirBlock(pos.x, pos.y, pos.z))
        {
            int side1 = absDir^1;
            int side2 = side();
            TileMultipart t = PRLib.getMultipartTile(world(), pos);
            if (t != null)
                if (t.partMap(side1) != null || t.partMap(side2) != null ||
                        t.partMap(PartMap.edgeBetween(side1, side2)) != null)
                    return false;
        }

        pos.offset(side());
        TileMultipart t = PRLib.getMultipartTile(world(), pos);
        if (t != null)
        {
            TMultiPart tp = t.partMap(absDir^1);
            if (tp instanceof IConnectable)
            {
                IConnectable conn = (IConnectable)tp;
                int r2 = Rotation.rotationTo(absDir^1, side()^1);
                return canConnectTo(conn, r) && conn.canConnectCorner(r2) && conn.connectCorner(this, r2, -1);
            }
        }

        return false;
    }

    public boolean connectStraight(int r)
    {
        int absDir = Rotation.rotateSide(side(), r);

        BlockCoord pos = new BlockCoord(tile()).offset(absDir);
        TileMultipart t = PRLib.getMultipartTile(world(), pos);
        if (t != null)
        {
            TMultiPart tp = t.partMap(side());
            if (tp instanceof IConnectable)
            {
                IConnectable conn = (IConnectable)tp;
                return canConnectTo(conn, r) && conn.connectStraight(this, (r+2)%4, -1);
            }
        }

        return connectStraightOverride(absDir);
    }

    public boolean connectStraightOverride(int absDir)
    {
        return false;
    }

    public boolean connectInternal(int r)
    {
        int absDir = Rotation.rotateSide(side(), r);

        if (tile().partMap(PartMap.edgeBetween(absDir, side())) != null)
            return false;

        TMultiPart tp = tile().partMap(absDir);
        if (tp instanceof IConnectable)
        {
            IConnectable conn = (IConnectable)tp;
            return canConnectTo(conn, r) && conn.connectInternal(this, Rotation.rotationTo(absDir, side()));
        }

        return false;
    }

    public void notifyCornerChange(int r)
    {
        int absDir = Rotation.rotateSide(side(), r);

        BlockCoord pos = new BlockCoord(tile()).offset(absDir).offset(side());
        world().notifyBlockOfNeighborChange(pos.x, pos.y, pos.z, tile().getBlockType());
    }

    public void notifyStraightChange(int r)
    {
        int absDir = Rotation.rotateSide(side(), r);

        BlockCoord pos = new BlockCoord(tile()).offset(absDir);
        world().notifyBlockOfNeighborChange(pos.x, pos.y, pos.z, tile().getBlockType());
    }

    public boolean maskConnects(int r)
    {
        return (connMap&0x111<<r) != 0;
    }

    @Override
    public Cuboid6 getBounds()
    {
        return FaceMicroClass.aBounds()[0x10|side()];
    }

    @Override
    public Iterable<IndexedCuboid6> getSubParts()
    {
        List<IndexedCuboid6> list = new ArrayList<IndexedCuboid6>();
        list.add(new IndexedCuboid6(-1, getBounds()));
        getLogic().addSubParts(this, list);
        return list;
    }

    @Override
    public Iterable<Cuboid6> getOcclusionBoxes()
    {
        return Arrays.asList(oBoxes[side()]);
    }

    @Override
    public boolean occlusionTest(TMultiPart npart)
    {
        return NormalOcclusionTest.apply(this, npart);
    }

    @Override
    public float getStrength(MovingObjectPosition hit, EntityPlayer player)
    {
        return hit.sideHit == 1 ? 1.75f : 1.5f;
    }

    public ItemStack getItem()
    {
        return getGateType().makeStack();
    }

    @Override
    public ItemStack pickItem(MovingObjectPosition hit)
    {
        return getItem();
    }

    @Override
    public Iterable<ItemStack> getDrops()
    {
        return Arrays.asList(getItem());
    }

    @Override
    public boolean activate(EntityPlayer player, MovingObjectPosition hit, ItemStack held)
    {
        if (getLogic().activate(this, player, held, hit))
            return true;

        if (held != null && held.getItem() instanceof IScrewdriver)
        {
            if (!world().isRemote)
            {
                if (player.isSneaking())
                    configure();
                else
                    rotate();
                ((IScrewdriver)held.getItem()).damageScrewdriver(world(), player);
            }

            return true;
        }

        return false;
    }

    public void configure()
    {
        boolean changed = getLogic().cycleShape(this);
        if (changed)
        {
            updateConnections();
            tile().markDirty();
            tile().notifyPartChange(this);
            sendShapeUpdate();
            notifyNeighbors(0xF);
            onChange();
        }
    }

    public void rotate()
    {
        setRotation((rotation()+1)%4);

        updateConnections();
        tile().markDirty();
        tile().notifyPartChange(this);
        sendOrientationUpdate();
        notifyNeighbors(0xF);
        onChange();
    }

    public MCDataOutput getWriteStream(int switch_key)
    {
        return tile().getWriteStream(this).writeByte(switch_key);
    }

    public void sendShapeUpdate()
    {
        getWriteStream(1).writeByte(shape);
    }

    public void sendOrientationUpdate()
    {
        getWriteStream(0).writeByte(orientation);
    }

    /**
     * Notify neighbor blocks
     *
     * @param mask A bitmask of absolute rotation sides to notify
     */
    public void notifyNeighbors(int mask)
    {
        for (int r = 0; r < 4; r++)
            if ((mask&1<<r) != 0)
                notifyCornerChange(r);
            else if ((mask&0x10<<r) != 0)
                notifyStraightChange(r);
    }

    @Override
    public void scheduledTick()
    {
        getLogic().scheduledTick(this);
    }

    @Override
    public boolean connectCorner(IConnectable part, int r, int edgeSide)
    {
        if (canConnectTo(part, r))
        {
            connMap |= 0x1<<r;
            return true;
        }
        return false;
    }

    @Override
    public boolean connectStraight(IConnectable part, int r, int edgeSide)
    {
        if (canConnectTo(part, r))
        {
            connMap |= 0x10<<r;
            return true;
        }
        return false;
    }

    @Override
    public boolean connectInternal(IConnectable part, int r)
    {
        if (r < 0)
            return false;

        if (canConnectTo(part, r))
        {
            connMap |= 0x100<<r;
            return true;
        }
        return false;
    }

    @Override
    public boolean canConnectCorner(int r)
    {
        return false;
    }

    public int toInternal(int absRot)
    {
        return (absRot+6-rotation())%4;
    }

    public int toAbsolute(int r)
    {
        return (r+rotation()+2)%4;
    }

    public static int shiftMask(int mask, int r)
    {
        return (mask<<r|mask>>4-r)&0xF;
    }

    public static int flipMaskZ(int mask)
    {
        return mask&5|mask<<2&8|mask>>2&2;
    }

    public int toAbsoluteMask(int mask)
    {
        return shiftMask(mask, toAbsolute(0));
    }

    public int toInternalMask(int mask)
    {
        return shiftMask(mask, toInternal(0));
    }

    public int relRot(int side)
    {
        return toInternal(Rotation.rotationTo(side(), side));
    }

    public boolean canConnectTo(IConnectable part, int r)
    {
        return getLogic().canConnectTo(this, part, toInternal(r));
    }

    @Override
    @SideOnly(Side.CLIENT)
    public boolean renderStatic(Vector3 pos, int pass)
    {
        if (pass == 0 && Configurator.staticGates)
        {
            TextureUtils.bindAtlas(0);
            CCRenderState.setBrightness(world(), x(), y(), z());
            RenderGate.renderStatic(this, pos);
            return true;
        }
        else return false;
    }

    @Override
    @SideOnly(Side.CLIENT)
    public void renderDynamic(Vector3 pos, float frame, int pass)
    {
        if (pass == 0)
        {
            TextureUtils.bindAtlas(0);
            if (!Configurator.staticGates)
            {
                GL11.glDisable(GL11.GL_LIGHTING);
                CCRenderState.startDrawing();
                RenderGate.renderStatic(this, pos);
                CCRenderState.draw();
                GL11.glEnable(GL11.GL_LIGHTING);
            }

            RenderGate.renderDynamic(this, pos, frame);
        }
    }

    @Override
    public int getSlotMask()
    {
        return 1<<side();
    }

    @Override
    public int redstoneConductionMap()
    {
        return 0;
    }

    @Override
    public boolean solid(int side)
    {
        return false;
    }

    @Override
    public int getLightValue()
    {
        return getLogic().lightLevel();
    }

    @Override
    @SideOnly(Side.CLIENT)
    public IIcon getBreakingIcon(Object arg0, int arg1)
    {
        return getBrokenIcon(arg1);
    }

    @Override
    @SideOnly(Side.CLIENT)
    public IIcon getBrokenIcon(int arg0)
    {
        return ComponentStore.baseIcon;
    }

    @Override
    public void addHitEffects(MovingObjectPosition hit, EffectRenderer effectRenderer)
    {
        IconHitEffects.addHitEffects(this, hit, effectRenderer);
    }

    @Override
    public void addDestroyEffects(EffectRenderer effectRenderer)
    {
        IconHitEffects.addDestroyEffects(this, effectRenderer, false);
    }

    @Override
    public abstract String getType();
}
TOP

Related Classes of mrtjp.projectred.integration.GatePart

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.