/* * This file is part of Applied Energistics 2. * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. * * Applied Energistics 2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Applied Energistics 2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Applied Energistics 2. If not, see . */ package appeng.tile.inventory; import java.util.Iterator; import javax.annotation.Nonnull; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemHandlerHelper; import appeng.api.AEApi; import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEItemStack; import appeng.core.AELog; import appeng.util.Platform; import appeng.util.inv.IAEAppEngInventory; import appeng.util.inv.InvOperation; import appeng.util.item.AEItemStack; import appeng.util.iterators.AEInvIterator; import appeng.util.iterators.InvIterator; public class AppEngInternalAEInventory implements IItemHandlerModifiable, Iterable { private final IAEAppEngInventory te; private final IAEItemStack[] inv; private final int size; private int maxStack; private boolean dirtyFlag = false; public AppEngInternalAEInventory( final IAEAppEngInventory te, final int s ) { this.te = te; this.size = s; this.maxStack = 64; this.inv = new IAEItemStack[s]; } public void setMaxStackSize( final int s ) { this.maxStack = s; } public IAEItemStack getAEStackInSlot( final int var1 ) { return this.inv[var1]; } public void writeToNBT( final CompoundNBT data, final String name ) { final CompoundNBT c = new CompoundNBT(); this.writeToNBT( c ); data.put( name, c ); } private void writeToNBT( final CompoundNBT target ) { for( int x = 0; x < this.size; x++ ) { try { final CompoundNBT c = new CompoundNBT(); if( this.inv[x] != null ) { this.inv[x].write(c); } target.put( "#" + x, c ); } catch( final Exception ignored ) { } } } public void readFromNBT( final CompoundNBT data, final String name ) { final CompoundNBT c = data.getCompound( name ); if( c != null ) { this.readFromNBT( c ); } } private void readFromNBT( final CompoundNBT target ) { for( int x = 0; x < this.size; x++ ) { try { final CompoundNBT c = target.getCompound( "#" + x ); if( c != null ) { this.inv[x] = AEItemStack.fromNBT( c ); } } catch( final Exception e ) { AELog.debug( e ); } } } protected int getStackLimit( int slot, @Nonnull ItemStack stack ) { return Math.min( this.getSlotLimit( slot ), stack.getMaxStackSize() ); } @Override public int getSlots() { return this.size; } @Override public ItemStack getStackInSlot( final int var1 ) { if( this.inv[var1] == null ) { return ItemStack.EMPTY; } return this.inv[var1].createItemStack(); } @Override public ItemStack insertItem( int slot, ItemStack stack, boolean simulate ) { if( stack.isEmpty() ) { return ItemStack.EMPTY; } ItemStack existing = this.getStackInSlot( slot ); int limit = this.getStackLimit( slot, stack ); if( !existing.isEmpty() ) { if( !ItemHandlerHelper.canItemStacksStack( stack, existing ) ) { return stack; } limit -= existing.getCount(); } if( limit <= 0 ) { return stack; } boolean reachedLimit = stack.getCount() > limit; if( !simulate ) { if( existing.isEmpty() ) { this.inv[slot] = Api.INSTANCE .storage() .getStorageChannel( IItemStorageChannel.class ) .createStack( reachedLimit ? ItemHandlerHelper.copyStackWithSize( stack, limit ) : stack ); } else { existing.grow( reachedLimit ? limit : stack.getCount() ); } this.fireOnChangeInventory( slot, InvOperation.INSERT, ItemStack.EMPTY, reachedLimit ? ItemHandlerHelper.copyStackWithSize( stack, limit ) : stack ); } return reachedLimit ? ItemHandlerHelper.copyStackWithSize( stack, stack.getCount() - limit ) : ItemStack.EMPTY; } @Override public ItemStack extractItem( int slot, int amount, boolean simulate ) { if( this.inv[slot] != null ) { final ItemStack split = this.getStackInSlot( slot ); if( amount >= split.getCount() ) { if( !simulate ) { this.inv[slot] = null; this.fireOnChangeInventory( slot, InvOperation.EXTRACT, split, ItemStack.EMPTY ); } return split; } else { if( !simulate ) { split.grow( -amount ); this.fireOnChangeInventory( slot, InvOperation.EXTRACT, ItemHandlerHelper.copyStackWithSize( split, amount ), ItemStack.EMPTY ); } return ItemHandlerHelper.copyStackWithSize( split, amount ); } } return ItemStack.EMPTY; } @Override public void setStackInSlot( final int slot, final ItemStack newItemStack ) { ItemStack oldStack = this.getStackInSlot( slot ).copy(); this.inv[slot] = Api.INSTANCE.storage().getStorageChannel( IItemStorageChannel.class ).createStack( newItemStack ); if( this.te != null && Platform.isServer() ) { ItemStack newStack = newItemStack.copy(); InvOperation op = InvOperation.SET; if( ItemStack.areItemsEqual( oldStack, newStack ) ) { if( newStack.getCount() > oldStack.getCount() ) { newStack.shrink( oldStack.getCount() ); oldStack = ItemStack.EMPTY; op = InvOperation.INSERT; } else { oldStack.shrink( newStack.getCount() ); newStack = ItemStack.EMPTY; op = InvOperation.EXTRACT; } } this.fireOnChangeInventory( slot, op, oldStack, newStack ); } } private void fireOnChangeInventory( int slot, InvOperation op, ItemStack removed, ItemStack inserted ) { if( this.te != null && Platform.isServer() && !this.dirtyFlag ) { this.dirtyFlag = true; this.te.onChangeInventory( this, slot, op, removed, inserted ); this.te.saveChanges(); this.dirtyFlag = false; } } @Override public int getSlotLimit( int slot ) { return this.maxStack > 64 ? 64 : this.maxStack; } @Override public Iterator iterator() { return new InvIterator( this ); } public Iterator getNewAEIterator() { return new AEInvIterator( this ); } @Override public boolean isItemValid( int slot, ItemStack stack ) { return true; } }