buildcraft.transport.gui.ContainerGateInterface.java Source code

Java tutorial

Introduction

Here is the source code for buildcraft.transport.gui.ContainerGateInterface.java

Source

/**
 * Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
 * http://www.mod-buildcraft.com
 *
 * BuildCraft is distributed under the terms of the Minecraft Mod Public
 * License 1.0, or MMPL. Please check the contents of the license located in
 * http://www.mod-buildcraft.com/MMPL-1.0.txt
 */
package buildcraft.transport.gui;

import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.TreeSet;

import io.netty.buffer.ByteBuf;

import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ICrafting;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;

import net.minecraftforge.common.util.ForgeDirection;

import buildcraft.BuildCraftTransport;
import buildcraft.api.gates.ActionManager;
import buildcraft.api.gates.IAction;
import buildcraft.api.gates.IOverrideDefaultTriggers;
import buildcraft.api.gates.ITrigger;
import buildcraft.api.gates.ITriggerParameter;
import buildcraft.api.gates.TriggerParameter;
import buildcraft.core.gui.BuildCraftContainer;
import buildcraft.core.network.PacketCoordinates;
import buildcraft.core.network.PacketIds;
import buildcraft.core.network.PacketPayload;
import buildcraft.core.network.PacketUpdate;
import buildcraft.core.utils.Utils;
import buildcraft.transport.Pipe;
import buildcraft.transport.gates.GateDefinition;

public class ContainerGateInterface extends BuildCraftContainer {

    public boolean[] triggerState = new boolean[8];

    IInventory playerIInventory;
    Pipe pipe;

    private final NavigableSet<ITrigger> potentialTriggers = new TreeSet<ITrigger>(new Comparator<ITrigger>() {
        @Override
        public int compare(ITrigger o1, ITrigger o2) {
            return o1.getUniqueTag().compareTo(o2.getUniqueTag());
        }
    });

    private final NavigableSet<IAction> potentialActions = new TreeSet<IAction>(new Comparator<IAction>() {
        @Override
        public int compare(IAction o1, IAction o2) {
            return o1.getUniqueTag().compareTo(o2.getUniqueTag());
        }
    });

    private boolean isSynchronized = false;
    private boolean isNetInitialized = false;
    private int lastTriggerState = 0;

    public ContainerGateInterface(IInventory playerInventory, Pipe pipe) {
        super(0);

        this.playerIInventory = playerInventory;

        for (int y = 0; y < 3; y++) {
            for (int x = 0; x < 9; x++) {
                addSlotToContainer(new Slot(playerInventory, x + y * 9 + 9, 8 + x * 18,
                        pipe.gate.material.guiHeight - 84 + y * 18));
            }
        }

        for (int x = 0; x < 9; x++) {
            addSlotToContainer(new Slot(playerInventory, x, 8 + x * 18, pipe.gate.material.guiHeight - 26));
        }

        this.pipe = pipe;

        // Do not attempt to create a list of potential actions and triggers on
        // the client.
        if (!pipe.container.getWorldObj().isRemote) {
            potentialActions.addAll(pipe.getActions());
            potentialTriggers.addAll(ActionManager.getPipeTriggers(pipe.container));

            if (pipe.container instanceof IOverrideDefaultTriggers) {
                potentialTriggers.addAll(((IOverrideDefaultTriggers) pipe.container).getTriggers());
            }

            for (ForgeDirection o : ForgeDirection.VALID_DIRECTIONS) {
                if (pipe.hasGate(o)) {
                    TileEntity tile = pipe.container.getTile(o);
                    Block block = pipe.container.getBlock(o);
                    potentialTriggers.addAll(ActionManager.getNeighborTriggers(block, tile));
                    potentialActions.addAll(ActionManager.getNeighborActions(block, tile));
                }
            }

            if (!pipe.gate.material.hasParameterSlot) {
                Iterator<ITrigger> it = potentialTriggers.iterator();

                while (it.hasNext()) {
                    ITrigger trigger = it.next();

                    if (trigger.requiresParameter()) {
                        it.remove();
                    }
                }
            }
        }
    }

    @Override
    public boolean canInteractWith(EntityPlayer player) {
        return !(pipe == null || pipe.gate == null);
    }

    /**
     * CLIENT SIDE *
     */
    /**
     * Marks client side gate container as needing to be synchronized with the
     * server.
     */
    public void markDirty() {
        isSynchronized = false;
    }

    /**
     * Clears list of potential actions and refills it according to packet.
     *
     * @param packet
     */
    public void updateActions(PacketUpdate packet) {
        potentialActions.clear();
        PacketPayload payload = packet.payload;

        int length = payload.stream.readInt();
        for (int i = 0; i < length; i++) {
            potentialActions.add(ActionManager.actions.get(Utils.readUTF(payload.stream)));
        }
    }

    /**
     * Clears list of potential triggers and refills it according to packet.
     *
     * @param packet
     */
    public void updateTriggers(PacketUpdate packet) {
        potentialTriggers.clear();
        PacketPayload payload = packet.payload;

        int length = payload.stream.readInt();

        for (int i = 0; i < length; i++) {
            String trigger = Utils.readUTF(payload.stream);
            potentialTriggers.add(ActionManager.triggers.get(trigger));
        }
    }

    /**
     * Sets the currently selected actions and triggers according to packet.
     *
     * @param packet
     */
    public void setSelection(PacketUpdate packet, boolean notify) {
        PacketPayload payload = packet.payload;
        ByteBuf data = payload.stream;

        int position = data.readInt();

        setTrigger(position, ActionManager.triggers.get(Utils.readUTF(data)), notify);
        setAction(position, ActionManager.actions.get(Utils.readUTF(data)), notify);

        ItemStack parameter = Utils.readStack(data);

        if (parameter != null) {
            ITriggerParameter param = new TriggerParameter();
            param.set(parameter);
            setTriggerParameter(position, param, notify);
        } else {
            setTriggerParameter(position, null, notify);
        }
    }

    private PacketPayload getSelectionPayload(final int position) {
        PacketPayload payload = new PacketPayload(new PacketPayload.StreamWriter() {
            @Override
            public void writeData(ByteBuf data) {
                data.writeInt(position);

                if (pipe.gate.triggers[position] != null) {
                    Utils.writeUTF(data, pipe.gate.triggers[position].getUniqueTag());
                } else {
                    Utils.writeUTF(data, "");
                }

                if (pipe.gate.actions[position] != null) {
                    Utils.writeUTF(data, pipe.gate.actions[position].getUniqueTag());
                } else {
                    Utils.writeUTF(data, "");
                }

                if (pipe.gate.triggerParameters[position] != null
                        && pipe.gate.triggerParameters[position].getItemStack() != null) {
                    Utils.writeStack(data, pipe.gate.triggerParameters[position].getItemStack());
                } else {
                    Utils.writeStack(data, null);
                }
            }
        });

        return payload;
    }

    public void sendSelectionChange(int position) {
        if (pipe.container.getWorld().isRemote) {
            BuildCraftTransport.instance
                    .sendToServer(new PacketUpdate(PacketIds.GATE_SELECTION_CHANGE, pipe.container.xCoord,
                            pipe.container.yCoord, pipe.container.zCoord, getSelectionPayload(position)));
        }
    }

    /**
     * Initializes the list of triggers and actions on the gate and
     * (re-)requests the current selection on the gate if needed.
     */
    public void synchronize() {
        if (!isNetInitialized && pipe.container.getWorldObj().isRemote) {
            isNetInitialized = true;
            BuildCraftTransport.instance.sendToServer(new PacketCoordinates(PacketIds.GATE_REQUEST_INIT,
                    pipe.container.xCoord, pipe.container.yCoord, pipe.container.zCoord));
        }

        if (!isSynchronized && pipe.container.getWorldObj().isRemote) {
            isSynchronized = true;
            BuildCraftTransport.instance.sendToServer(new PacketCoordinates(PacketIds.GATE_REQUEST_SELECTION,
                    pipe.container.xCoord, pipe.container.yCoord, pipe.container.zCoord));
        }
    }

    @Override
    public void updateProgressBar(int id, int state) {
        if (id == 0 /* Trigger state update */) {
            for (int i = 0; i < 8; i++) {
                /* Bit mask of triggers */
                triggerState[i] = ((state >> i) & 0x01) == 0x01;
            }
        }
    }

    /**
     * SERVER SIDE *
     */
    private int calculateTriggerState() {
        if (pipe.gate == null) {
            return 0;
        }

        int state = 0;

        for (int i = 0; i < triggerState.length; i++) {
            if (pipe.gate.triggers[i] != null) {
                triggerState[i] = isNearbyTriggerActive(pipe.gate.triggers[i], pipe.gate.getTriggerParameter(i));
            }

            state |= triggerState[i] ? 0x01 << i : 0x0;
        }

        return state;
    }

    @Override
    public void detectAndSendChanges() {
        super.detectAndSendChanges();

        int state = calculateTriggerState();

        if (state != lastTriggerState) {
            for (int i = 0; i < this.crafters.size(); i++) {
                ICrafting viewingPlayer = (ICrafting) this.crafters.get(i);

                viewingPlayer.sendProgressBarUpdate(this, 0 /* State update */, state);
            }

            lastTriggerState = state;
        }
    }

    public void handleInitRequest(EntityPlayer player) {
        sendActions(player);
        sendTriggers(player);
        sendSelection(player);
    }

    /**
     * Sends the list of potential actions to the client
     *
     * @param player
     */
    private void sendActions(EntityPlayer player) {
        // Compose update packet
        PacketPayload payload = new PacketPayload(new PacketPayload.StreamWriter() {
            @Override
            public void writeData(ByteBuf data) {
                int length = potentialActions.size();
                data.writeInt(length);

                for (IAction action : potentialActions) {
                    Utils.writeUTF(data, action.getUniqueTag());
                }
            }
        });

        PacketUpdate packet = new PacketUpdate(PacketIds.GATE_ACTIONS, pipe.container.xCoord, pipe.container.yCoord,
                pipe.container.zCoord, payload);

        // Send to player
        BuildCraftTransport.instance.sendToPlayer(player, packet);
    }

    /**
     * Sends the list of potential triggers to the client
     *
     * @param player
     */
    private void sendTriggers(EntityPlayer player) {
        PacketPayload payload = new PacketPayload(new PacketPayload.StreamWriter() {
            @Override
            public void writeData(ByteBuf data) {

                int length = potentialTriggers.size();
                data.writeInt(length);

                for (ITrigger trigger : potentialTriggers) {
                    Utils.writeUTF(data, trigger.getUniqueTag());
                }
            }
        });

        PacketUpdate packet = new PacketUpdate(PacketIds.GATE_TRIGGERS, pipe.container.xCoord,
                pipe.container.yCoord, pipe.container.zCoord, payload);

        // Send to player
        BuildCraftTransport.instance.sendToPlayer(player, packet);
    }

    /**
     * Sends the current selection on the gate to the client.
     *
     * @param player
     */
    public void sendSelection(EntityPlayer player) {
        if (pipe == null || pipe.gate == null) {
            return;
        }

        for (int position = 0; position < pipe.gate.material.numSlots; position++) {
            BuildCraftTransport.instance.sendToPlayer(player,
                    new PacketUpdate(PacketIds.GATE_SELECTION, pipe.container.xCoord, pipe.container.yCoord,
                            pipe.container.zCoord, getSelectionPayload(position)));
        }
    }

    /**
     * TRIGGERS *
     */
    public boolean hasTriggers() {
        return potentialTriggers.size() > 0;
    }

    public ITrigger getFirstTrigger() {
        if (potentialTriggers.isEmpty()) {
            return null;
        } else {
            return potentialTriggers.first();
        }
    }

    public ITrigger getLastTrigger() {
        if (potentialTriggers.isEmpty()) {
            return null;
        } else {
            return potentialTriggers.last();
        }
    }

    public Iterator<ITrigger> getTriggerIterator(boolean descending) {
        return descending ? potentialTriggers.descendingIterator() : potentialTriggers.iterator();
    }

    public boolean isNearbyTriggerActive(ITrigger trigger, ITriggerParameter parameter) {
        if (pipe.gate == null) {
            return false;
        } else {
            return pipe.gate.isNearbyTriggerActive(trigger, parameter);
        }
    }

    public void setTrigger(int position, ITrigger trigger, boolean notify) {
        if (pipe.gate == null) {
            return;
        }

        pipe.gate.setTrigger(position, trigger);

        if (pipe.container.getWorldObj().isRemote && notify) {
            sendSelectionChange(position);
        }
    }

    public void setTriggerParameter(int position, ITriggerParameter parameter, boolean notify) {
        if (pipe.gate == null) {
            return;
        }

        pipe.gate.setTriggerParameter(position, parameter);

        if (pipe.container.getWorldObj().isRemote && notify) {
            sendSelectionChange(position);
        }
    }

    /**
     * ACTIONS *
     */
    public boolean hasActions() {
        return !potentialActions.isEmpty();
    }

    public IAction getFirstAction() {
        if (potentialActions.isEmpty()) {
            return null;
        } else {
            return potentialActions.first();
        }
    }

    public IAction getLastAction() {
        if (potentialActions.isEmpty()) {
            return null;
        } else {
            return potentialActions.last();
        }
    }

    public Iterator<IAction> getActionIterator(boolean descending) {
        return descending ? potentialActions.descendingIterator() : potentialActions.iterator();
    }

    public void setAction(int position, IAction action, boolean notify) {
        pipe.gate.setAction(position, action);

        if (pipe.container.getWorldObj().isRemote && notify) {
            sendSelectionChange(position);
        }
    }

    /**
     * GATE INFORMATION *
     */
    public ResourceLocation getGateGuiFile() {
        return pipe.gate.material.guiFile;
    }

    public String getGateName() {
        return GateDefinition.getLocalizedName(pipe.gate.material, pipe.gate.logic);
    }
}