/* * Copyright (c) CovertJaguar, 2014 http://railcraft.info * * This code is the property of CovertJaguar * and may only be used with explicit written * permission unless otherwise specified on the * license page at http://railcraft.info/wiki/info:license. */ package mods.railcraft.common.blocks.machine.gamma; import mods.railcraft.api.carts.CartTools; import mods.railcraft.common.blocks.machine.IEnumMachine; import mods.railcraft.common.gui.EnumGui; import mods.railcraft.common.gui.GuiHandler; import mods.railcraft.common.gui.slots.SlotOutput; import mods.railcraft.common.util.inventory.*; import mods.railcraft.common.util.inventory.wrappers.InventoryMapper; import mods.railcraft.common.util.misc.Game; import mods.railcraft.common.util.misc.ITileFilter; import net.minecraft.entity.item.EntityMinecart; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraftforge.common.util.ForgeDirection; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; public class TileItemUnloader extends TileLoaderItemBase { private static final EnumRedstoneMode[] REDSTONE_MODES = new EnumRedstoneMode[]{EnumRedstoneMode.IMMEDIATE, EnumRedstoneMode.COMPLETE, EnumRedstoneMode.MANUAL}; private final IInventory invBuffer; private final Map<ItemStack, Short> transferedItems = new ItemStackMap<Short>(); private final Set<ItemStack> checkedItems = new ItemStackSet(); private final LinkedList<IInventory> chests = new LinkedList<IInventory>(); private AdjacentInventoryCache invCache = new AdjacentInventoryCache(this, tileCache, new ITileFilter() { @Override public boolean matches(TileEntity tile) { if (tile instanceof TileItemUnloader) { return false; } return true; } }, InventorySorter.SIZE_DECENDING); public TileItemUnloader() { super(); setInventorySize(9); invBuffer = new InventoryMapper(getInventory(), false); } @Override public EnumRedstoneMode[] getValidRedstoneModes() { return REDSTONE_MODES; } @Override public IEnumMachine getMachineType() { return EnumMachineGamma.ITEM_UNLOADER; } @Override public Slot getBufferSlot(int id, int x, int y) { return new SlotOutput(this, id, x, y); } @Override public IIcon getIcon(int side) { return getMachineType().getTexture(side); } @Override public void updateEntity() { super.updateEntity(); if (Game.isNotHost(getWorld())) { return; } emptyCart(); clearInv(); } private void emptyCart() { movedItemCart = false; EntityMinecart cart = CartTools.getMinecartOnSide(worldObj, xCoord, yCoord, zCoord, 0.1f, getOrientation()); if (cart == null) { setPowered(false); currentCart = null; return; } if (cart != currentCart) { setPowered(false); currentCart = cart; transferedItems.clear(); cartWasSent(); } if (!canHandleCart(cart)) { sendCart(cart); return; } if (isPaused()) return; chests.clear(); chests.addAll(invCache.getAdjacentInventories()); chests.addFirst(invBuffer); checkedItems.clear(); IInventory cartInv = (IInventory) cart; switch (getMode()) { case TRANSFER: { boolean hasFilter = false; for (ItemStack filter : getItemFilters().getContents()) { if (filter == null) { continue; } if (!checkedItems.add(filter)) { continue; } hasFilter = true; Short numMoved = transferedItems.get(filter); if (numMoved == null) { numMoved = 0; } if (numMoved < InvTools.countItems(getItemFilters(), filter)) { ItemStack moved = InvTools.moveOneItem(cartInv, chests, filter); if (moved != null) { movedItemCart = true; numMoved++; transferedItems.put(moved, numMoved); break; } } } if (!hasFilter) { ItemStack moved = InvTools.moveOneItem(cartInv, chests); if (moved != null) { movedItemCart = true; break; } } break; } case STOCK: { for (ItemStack filter : getItemFilters().getContents()) { if (filter == null) { continue; } if (!checkedItems.add(filter)) { continue; } int stocked = InvTools.countItems(chests, filter); if (stocked < InvTools.countItems(getItemFilters(), filter)) { ItemStack moved = InvTools.moveOneItem(cartInv, chests, filter); if (moved != null) { movedItemCart = true; break; } } } break; } case EXCESS: { for (ItemStack filter : getItemFilters().getContents()) { if (filter == null) { continue; } if (!checkedItems.add(filter)) { continue; } int stocked = InvTools.countItems(cartInv, filter); if (stocked > InvTools.countItems(getItemFilters(), filter)) { ItemStack moved = InvTools.moveOneItem(cartInv, chests, filter); if (moved != null) { movedItemCart = true; break; } } } if (!movedItemCart) { movedItemCart = InvTools.moveOneItemExcept(cartInv, chests, getItemFilters().getContents()) != null; } break; } case ALL: { boolean hasFilter = false; for (ItemStack filter : getItemFilters().getContents()) { if (filter == null) { continue; } if (!checkedItems.add(filter)) { continue; } hasFilter = true; ItemStack moved = InvTools.moveOneItem(cartInv, chests, filter); if (moved != null) { movedItemCart = true; break; } } if (!hasFilter) { ItemStack moved = InvTools.moveOneItem(cartInv, chests); if (moved != null) { movedItemCart = true; break; } } break; } } EnumRedstoneMode state = getRedstoneModeController().getButtonState(); if (state != EnumRedstoneMode.MANUAL && !isPowered() && shouldSendCart(cart)) { sendCart(cart); } } @Override public boolean canHandleCart(EntityMinecart cart) { if (!super.canHandleCart(cart)) return false; return !InvTools.isInventoryEmpty((IInventory) cart); } @Override protected boolean shouldSendCart(EntityMinecart cart) { if (!(cart instanceof IInventory)) return true; IInventory cartInv = (IInventory) cart; EnumRedstoneMode state = getRedstoneModeController().getButtonState(); if (!movedItemCart && state != EnumRedstoneMode.COMPLETE) { return true; } else if (getMode() == EnumTransferMode.TRANSFER && isTransferComplete(getItemFilters().getContents())) { return true; } else if (getMode() == EnumTransferMode.STOCK && isStockComplete(chests, getItemFilters().getContents())) { return true; } else if (getMode() == EnumTransferMode.EXCESS && isExcessComplete(cartInv, getItemFilters().getContents())) { return true; } else if (getMode() == EnumTransferMode.ALL && isAllComplete(chests, getItemFilters().getContents())) { return true; } else if (!movedItemCart && InvTools.isAccessibleInventoryEmpty(cartInv, getOrientation().getOpposite())) { return true; } return false; } private boolean isTransferComplete(ItemStack[] filters) { checkedItems.clear(); boolean hasFilter = false; for (ItemStack filter : filters) { if (filter == null) { continue; } if (!checkedItems.add(filter)) { continue; } hasFilter = true; Short numMoved = transferedItems.get(filter); if (numMoved == null || numMoved < InvTools.countItems(getItemFilters(), filter)) { return false; } } return hasFilter; } private boolean isStockComplete(List<IInventory> chests, ItemStack[] filters) { checkedItems.clear(); for (ItemStack filter : filters) { if (filter == null) { continue; } if (!checkedItems.add(filter)) { continue; } int stocked = InvTools.countItems(chests, filter); if (stocked < InvTools.countItems(getItemFilters(), filter)) { return false; } } return true; } private boolean isExcessComplete(IInventory cartInv, ItemStack[] filters) { checkedItems.clear(); int max = 0; for (ItemStack filter : filters) { if (filter == null) { continue; } if (!checkedItems.add(filter)) { continue; } int stocked = InvTools.countItems(cartInv, filter); max += filter.stackSize; if (stocked > InvTools.countItems(getItemFilters(), filter)) { return false; } } if (InvTools.countItems(cartInv) > max) { return false; } return true; } private boolean isAllComplete(List<IInventory> chests, ItemStack[] filters) { checkedItems.clear(); boolean hasFilter = false; for (ItemStack filter : filters) { if (filter == null) { continue; } if (!checkedItems.add(filter)) { continue; } hasFilter = true; if (InvTools.countItems(chests, filter) > 0) { return false; } } return hasFilter; } private void clearInv() { if (!InvTools.isInventoryEmpty(invBuffer)) { InvTools.moveOneItem(invBuffer, invCache.getAdjacentInventories()); } } @Override public boolean openGui(EntityPlayer player) { GuiHandler.openGui(EnumGui.LOADER_ITEM, player, worldObj, xCoord, yCoord, zCoord); return true; } public ForgeDirection getOrientation() { return ForgeDirection.UP; } @Override public boolean canExtractItem(int slot, ItemStack stack, int side) { return true; } @Override public boolean isItemValidForSlot(int slot, ItemStack stack) { return false; } }