/* * 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.container; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IContainerListener; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.config.SecurityPermissions; import appeng.api.implementations.guiobjects.IGuiItemObject; import appeng.api.networking.IGrid; import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergySource; import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.IActionHost; import appeng.api.networking.security.ISecurityGrid; import appeng.api.networking.security.PlayerSource; import appeng.api.parts.IPart; import appeng.api.storage.IMEInventoryHandler; import appeng.api.storage.data.IAEItemStack; import appeng.client.me.InternalSlotME; import appeng.client.me.SlotME; import appeng.container.guisync.GuiSync; import appeng.container.guisync.SyncData; import appeng.container.slot.AppEngSlot; import appeng.container.slot.SlotCraftingMatrix; import appeng.container.slot.SlotCraftingTerm; import appeng.container.slot.SlotDisabled; import appeng.container.slot.SlotFake; import appeng.container.slot.SlotInaccessible; import appeng.container.slot.SlotPlayerHotBar; import appeng.container.slot.SlotPlayerInv; import appeng.core.AELog; import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.packets.PacketInventoryAction; import appeng.core.sync.packets.PacketPartialItem; import appeng.core.sync.packets.PacketValueConfig; import appeng.helpers.ICustomNameObject; import appeng.helpers.InventoryAction; import appeng.util.InventoryAdaptor; import appeng.util.Platform; import appeng.util.inv.AdaptorPlayerHand; import appeng.util.item.AEItemStack; public abstract class AEBaseContainer extends Container { private final InventoryPlayer invPlayer; private final BaseActionSource mySrc; private final HashSet locked = new HashSet(); private final TileEntity tileEntity; private final IPart part; private final IGuiItemObject obj; private final List dataChunks = new LinkedList(); private final HashMap syncData = new HashMap(); private boolean isContainerValid = true; private String customName; private ContainerOpenContext openContext; private IMEInventoryHandler cellInv; private IEnergySource powerSrc; private boolean sentCustomName; private int ticksSinceCheck = 900; private IAEItemStack clientRequestedTargetItem = null; public AEBaseContainer( final InventoryPlayer ip, final TileEntity myTile, final IPart myPart ) { this( ip, myTile, myPart, null ); } public AEBaseContainer( final InventoryPlayer ip, final TileEntity myTile, final IPart myPart, final IGuiItemObject gio ) { this.invPlayer = ip; this.tileEntity = myTile; this.part = myPart; this.obj = gio; this.mySrc = new PlayerSource( ip.player, this.getActionHost() ); this.prepareSync(); } protected IActionHost getActionHost() { if( this.obj instanceof IActionHost ) { return (IActionHost) this.obj; } if( this.tileEntity instanceof IActionHost ) { return (IActionHost) this.tileEntity; } if( this.part instanceof IActionHost ) { return (IActionHost) this.part; } return null; } private void prepareSync() { for( final Field f : this.getClass().getFields() ) { if( f.isAnnotationPresent( GuiSync.class ) ) { final GuiSync annotation = f.getAnnotation( GuiSync.class ); if( this.syncData.containsKey( annotation.value() ) ) { AELog.warn( "Channel already in use: " + annotation.value() + " for " + f.getName() ); } else { this.syncData.put( annotation.value(), new SyncData( this, f, annotation ) ); } } } } public AEBaseContainer( final InventoryPlayer ip, final Object anchor ) { this.invPlayer = ip; this.tileEntity = anchor instanceof TileEntity ? (TileEntity) anchor : null; this.part = anchor instanceof IPart ? (IPart) anchor : null; this.obj = anchor instanceof IGuiItemObject ? (IGuiItemObject) anchor : null; if( this.tileEntity == null && this.part == null && this.obj == null ) { throw new IllegalArgumentException( "Must have a valid anchor, instead " + anchor + " in " + ip ); } this.mySrc = new PlayerSource( ip.player, this.getActionHost() ); this.prepareSync(); } public void postPartial( final PacketPartialItem packetPartialItem ) { this.dataChunks.add( packetPartialItem ); if( packetPartialItem.getPageCount() == this.dataChunks.size() ) { this.parsePartials(); } } private void parsePartials() { int total = 0; for( final PacketPartialItem ppi : this.dataChunks ) { total += ppi.getSize(); } final byte[] buffer = new byte[total]; int cursor = 0; for( final PacketPartialItem ppi : this.dataChunks ) { cursor = ppi.write( buffer, cursor ); } try { final NBTTagCompound data = CompressedStreamTools.readCompressed( new ByteArrayInputStream( buffer ) ); if( data != null ) { this.setTargetStack( AEApi.instance().storage().createItemStack( ItemStack.loadItemStackFromNBT( data ) ) ); } } catch( final IOException e ) { AELog.debug( e ); } this.dataChunks.clear(); } public IAEItemStack getTargetStack() { return this.clientRequestedTargetItem; } public void setTargetStack( final IAEItemStack stack ) { // client doesn't need to re-send, makes for lower overhead rapid packets. if( Platform.isClient() ) { final ItemStack a = stack == null ? null : stack.getItemStack(); final ItemStack b = this.clientRequestedTargetItem == null ? null : this.clientRequestedTargetItem.getItemStack(); if( Platform.itemComparisons().isSameItem( a, b ) ) { return; } final ByteArrayOutputStream stream = new ByteArrayOutputStream(); final NBTTagCompound item = new NBTTagCompound(); if( stack != null ) { stack.writeToNBT( item ); } try { CompressedStreamTools.writeCompressed( item, stream ); final int maxChunkSize = 30000; final List miniPackets = new LinkedList(); final byte[] data = stream.toByteArray(); final ByteArrayInputStream bis = new ByteArrayInputStream( data, 0, stream.size() ); while( bis.available() > 0 ) { final int nextBLock = bis.available() > maxChunkSize ? maxChunkSize : bis.available(); final byte[] nextSegment = new byte[nextBLock]; bis.read( nextSegment ); miniPackets.add( nextSegment ); } bis.close(); stream.close(); int page = 0; for( final byte[] packet : miniPackets ) { final PacketPartialItem ppi = new PacketPartialItem( page, miniPackets.size(), packet ); page++; NetworkHandler.instance.sendToServer( ppi ); } } catch( final IOException e ) { AELog.debug( e ); return; } } this.clientRequestedTargetItem = stack == null ? null : stack.copy(); } public BaseActionSource getActionSource() { return this.mySrc; } public void verifyPermissions( final SecurityPermissions security, final boolean requirePower ) { if( Platform.isClient() ) { return; } this.ticksSinceCheck++; if( this.ticksSinceCheck < 20 ) { return; } this.ticksSinceCheck = 0; this.setValidContainer( this.isValidContainer() && this.hasAccess( security, requirePower ) ); } protected boolean hasAccess( final SecurityPermissions perm, final boolean requirePower ) { final IActionHost host = this.getActionHost(); if( host != null ) { final IGridNode gn = host.getActionableNode(); if( gn != null ) { final IGrid g = gn.getGrid(); if( g != null ) { if( requirePower ) { final IEnergyGrid eg = g.getCache( IEnergyGrid.class ); if( !eg.isNetworkPowered() ) { return false; } } final ISecurityGrid sg = g.getCache( ISecurityGrid.class ); if( sg.hasPermission( this.getInventoryPlayer().player, perm ) ) { return true; } } } } return false; } public void lockPlayerInventorySlot( final int idx ) { this.locked.add( idx ); } public Object getTarget() { if( this.tileEntity != null ) { return this.tileEntity; } if( this.part != null ) { return this.part; } if( this.obj != null ) { return this.obj; } return null; } public InventoryPlayer getPlayerInv() { return this.getInventoryPlayer(); } public TileEntity getTileEntity() { return this.tileEntity; } public final void updateFullProgressBar( final int idx, final long value ) { if( this.syncData.containsKey( idx ) ) { this.syncData.get( idx ).update( value ); return; } this.updateProgressBar( idx, (int) value ); } public void stringSync( final int idx, final String value ) { if( this.syncData.containsKey( idx ) ) { this.syncData.get( idx ).update( value ); } } protected void bindPlayerInventory( final InventoryPlayer inventoryPlayer, final int offsetX, final int offsetY ) { // bind player inventory for( int i = 0; i < 3; i++ ) { for( int j = 0; j < 9; j++ ) { if( this.locked.contains( j + i * 9 + 9 ) ) { this.addSlotToContainer( new SlotDisabled( inventoryPlayer, j + i * 9 + 9, 8 + j * 18 + offsetX, offsetY + i * 18 ) ); } else { this.addSlotToContainer( new SlotPlayerInv( inventoryPlayer, j + i * 9 + 9, 8 + j * 18 + offsetX, offsetY + i * 18 ) ); } } } // bind player hotbar for( int i = 0; i < 9; i++ ) { if( this.locked.contains( i ) ) { this.addSlotToContainer( new SlotDisabled( inventoryPlayer, i, 8 + i * 18 + offsetX, 58 + offsetY ) ); } else { this.addSlotToContainer( new SlotPlayerHotBar( inventoryPlayer, i, 8 + i * 18 + offsetX, 58 + offsetY ) ); } } } @Override protected Slot addSlotToContainer( final Slot newSlot ) { if( newSlot instanceof AppEngSlot ) { final AppEngSlot s = (AppEngSlot) newSlot; s.setContainer( this ); return super.addSlotToContainer( newSlot ); } else { throw new IllegalArgumentException( "Invalid Slot [" + newSlot + "]for AE Container instead of AppEngSlot." ); } } @Override public void detectAndSendChanges() { this.sendCustomName(); if( Platform.isServer() ) { for( final IContainerListener listener : this.listeners ) { for( final SyncData sd : this.syncData.values() ) { sd.tick( listener ); } } } super.detectAndSendChanges(); } @Override public ItemStack transferStackInSlot( final EntityPlayer p, final int idx ) { if( Platform.isClient() ) { return null; } boolean hasMETiles = false; for( final Object is : this.inventorySlots ) { if( is instanceof InternalSlotME ) { hasMETiles = true; break; } } if( hasMETiles && Platform.isClient() ) { return null; } final AppEngSlot clickSlot = (AppEngSlot) this.inventorySlots.get( idx ); // require AE SLots! if( clickSlot instanceof SlotDisabled || clickSlot instanceof SlotInaccessible ) { return null; } if( clickSlot != null && clickSlot.getHasStack() ) { ItemStack tis = clickSlot.getStack(); if( tis == null ) { return null; } final List selectedSlots = new ArrayList(); /** * Gather a list of valid destinations. */ if( clickSlot.isPlayerSide() ) { tis = this.shiftStoreItem( tis ); // target slots in the container... for( final Object inventorySlot : this.inventorySlots ) { final AppEngSlot cs = (AppEngSlot) inventorySlot; if( !( cs.isPlayerSide() ) && !( cs instanceof SlotFake ) && !( cs instanceof SlotCraftingMatrix ) ) { if( cs.isItemValid( tis ) ) { selectedSlots.add( cs ); } } } } else { // target slots in the container... for( final Object inventorySlot : this.inventorySlots ) { final AppEngSlot cs = (AppEngSlot) inventorySlot; if( ( cs.isPlayerSide() ) && !( cs instanceof SlotFake ) && !( cs instanceof SlotCraftingMatrix ) ) { if( cs.isItemValid( tis ) ) { selectedSlots.add( cs ); } } } } /** * Handle Fake Slot Shift clicking. */ if( selectedSlots.isEmpty() && clickSlot.isPlayerSide() ) { if( tis != null ) { // target slots in the container... for( final Object inventorySlot : this.inventorySlots ) { final AppEngSlot cs = (AppEngSlot) inventorySlot; final ItemStack destination = cs.getStack(); if( !( cs.isPlayerSide() ) && cs instanceof SlotFake ) { if( Platform.itemComparisons().isSameItem( destination, tis ) ) { break; } else if( destination == null ) { cs.putStack( tis.copy() ); cs.onSlotChanged(); this.updateSlot( cs ); break; } } } } } if( tis != null ) { // find partials.. for( final Slot d : selectedSlots ) { if( d instanceof SlotDisabled || d instanceof SlotME ) { continue; } if( d.isItemValid( tis ) ) { if( d.getHasStack() ) { final ItemStack t = d.getStack(); if( Platform.itemComparisons().isSameItem( tis, t ) ) // t.isItemEqual(tis)) { int maxSize = t.getMaxStackSize(); if( maxSize > d.getSlotStackLimit() ) { maxSize = d.getSlotStackLimit(); } int placeAble = maxSize - t.stackSize; if( tis.stackSize < placeAble ) { placeAble = tis.stackSize; } t.stackSize += placeAble; tis.stackSize -= placeAble; if( tis.stackSize <= 0 ) { clickSlot.putStack( null ); d.onSlotChanged(); // if ( hasMETiles ) updateClient(); this.updateSlot( clickSlot ); this.updateSlot( d ); return null; } else { this.updateSlot( d ); } } } } } // any match.. for( final Slot d : selectedSlots ) { if( d instanceof SlotDisabled || d instanceof SlotME ) { continue; } if( d.isItemValid( tis ) ) { if( d.getHasStack() ) { final ItemStack t = d.getStack(); if( Platform.itemComparisons().isSameItem( t, tis ) ) { int maxSize = t.getMaxStackSize(); if( d.getSlotStackLimit() < maxSize ) { maxSize = d.getSlotStackLimit(); } int placeAble = maxSize - t.stackSize; if( tis.stackSize < placeAble ) { placeAble = tis.stackSize; } t.stackSize += placeAble; tis.stackSize -= placeAble; if( tis.stackSize <= 0 ) { clickSlot.putStack( null ); d.onSlotChanged(); // if ( worldEntity != null ) // worldEntity.markDirty(); // if ( hasMETiles ) updateClient(); this.updateSlot( clickSlot ); this.updateSlot( d ); return null; } else { this.updateSlot( d ); } } } else { int maxSize = tis.getMaxStackSize(); if( maxSize > d.getSlotStackLimit() ) { maxSize = d.getSlotStackLimit(); } final ItemStack tmp = tis.copy(); if( tmp.stackSize > maxSize ) { tmp.stackSize = maxSize; } tis.stackSize -= tmp.stackSize; d.putStack( tmp ); if( tis.stackSize <= 0 ) { clickSlot.putStack( null ); d.onSlotChanged(); // if ( worldEntity != null ) // worldEntity.markDirty(); // if ( hasMETiles ) updateClient(); this.updateSlot( clickSlot ); this.updateSlot( d ); return null; } else { this.updateSlot( d ); } } } } } clickSlot.putStack( tis != null ? tis.copy() : null ); } this.updateSlot( clickSlot ); return null; } @Override public final void updateProgressBar( final int idx, final int value ) { if( this.syncData.containsKey( idx ) ) { this.syncData.get( idx ).update( (long) value ); } } @Override public boolean canInteractWith( final EntityPlayer entityplayer ) { if( this.isValidContainer() ) { if( this.tileEntity instanceof IInventory ) { return ( (IInventory) this.tileEntity ).isUseableByPlayer( entityplayer ); } return true; } return false; } @Override public boolean canDragIntoSlot( final Slot s ) { return ( (AppEngSlot) s ).isDraggable(); } public void doAction( final EntityPlayerMP player, final InventoryAction action, final int slot, final long id ) { if( slot >= 0 && slot < this.inventorySlots.size() ) { final Slot s = this.getSlot( slot ); if( s instanceof SlotCraftingTerm ) { switch( action ) { case CRAFT_SHIFT: case CRAFT_ITEM: case CRAFT_STACK: ( (SlotCraftingTerm) s ).doClick( action, player ); this.updateHeld( player ); default: } } if( s instanceof SlotFake ) { final ItemStack hand = player.inventory.getItemStack(); switch( action ) { case PICKUP_OR_SET_DOWN: if( hand == null ) { s.putStack( null ); } else { s.putStack( hand.copy() ); } break; case PLACE_SINGLE: if( hand != null ) { final ItemStack is = hand.copy(); is.stackSize = 1; s.putStack( is ); } break; case SPLIT_OR_PLACE_SINGLE: ItemStack is = s.getStack(); if( is != null ) { if( hand == null ) { is.stackSize--; } else if( hand.isItemEqual( is ) ) { is.stackSize = Math.min( is.getMaxStackSize(), is.stackSize + 1 ); } else { is = hand.copy(); is.stackSize = 1; } s.putStack( is ); } else if( hand != null ) { is = hand.copy(); is.stackSize = 1; s.putStack( is ); } break; case CREATIVE_DUPLICATE: case MOVE_REGION: case SHIFT_CLICK: default: break; } } if( action == InventoryAction.MOVE_REGION ) { final List from = new LinkedList(); for( final Object j : this.inventorySlots ) { if( j instanceof Slot && j.getClass() == s.getClass() ) { from.add( (Slot) j ); } } for( final Slot fr : from ) { this.transferStackInSlot( player, fr.slotNumber ); } } return; } // get target item. final IAEItemStack slotItem = this.clientRequestedTargetItem; switch( action ) { case SHIFT_CLICK: if( this.getPowerSource() == null || this.getCellInventory() == null ) { return; } if( slotItem != null ) { IAEItemStack ais = slotItem.copy(); ItemStack myItem = ais.getItemStack(); ais.setStackSize( myItem.getMaxStackSize() ); final InventoryAdaptor adp = InventoryAdaptor.getAdaptor( player, EnumFacing.UP ); myItem.stackSize = (int) ais.getStackSize(); myItem = adp.simulateAdd( myItem ); if( myItem != null ) { ais.setStackSize( ais.getStackSize() - myItem.stackSize ); } ais = Platform.poweredExtraction( this.getPowerSource(), this.getCellInventory(), ais, this.getActionSource() ); if( ais != null ) { adp.addItems( ais.getItemStack() ); } } break; case ROLL_DOWN: if( this.getPowerSource() == null || this.getCellInventory() == null ) { return; } final int releaseQty = 1; final ItemStack isg = player.inventory.getItemStack(); if( isg != null && releaseQty > 0 ) { IAEItemStack ais = AEApi.instance().storage().createItemStack( isg ); ais.setStackSize( 1 ); final IAEItemStack extracted = ais.copy(); ais = Platform.poweredInsert( this.getPowerSource(), this.getCellInventory(), ais, this.getActionSource() ); if( ais == null ) { final InventoryAdaptor ia = new AdaptorPlayerHand( player ); final ItemStack fail = ia.removeItems( 1, extracted.getItemStack(), null ); if( fail == null ) { this.getCellInventory().extractItems( extracted, Actionable.MODULATE, this.getActionSource() ); } this.updateHeld( player ); } } break; case ROLL_UP: case PICKUP_SINGLE: if( this.getPowerSource() == null || this.getCellInventory() == null ) { return; } if( slotItem != null ) { int liftQty = 1; final ItemStack item = player.inventory.getItemStack(); if( item != null ) { if( item.stackSize >= item.getMaxStackSize() ) { liftQty = 0; } if( !Platform.itemComparisons().isSameItem( slotItem.getItemStack(), item ) ) { liftQty = 0; } } if( liftQty > 0 ) { IAEItemStack ais = slotItem.copy(); ais.setStackSize( 1 ); ais = Platform.poweredExtraction( this.getPowerSource(), this.getCellInventory(), ais, this.getActionSource() ); if( ais != null ) { final InventoryAdaptor ia = new AdaptorPlayerHand( player ); final ItemStack fail = ia.addItems( ais.getItemStack() ); if( fail != null ) { this.getCellInventory().injectItems( ais, Actionable.MODULATE, this.getActionSource() ); } this.updateHeld( player ); } } } break; case PICKUP_OR_SET_DOWN: if( this.getPowerSource() == null || this.getCellInventory() == null ) { return; } if( player.inventory.getItemStack() == null ) { if( slotItem != null ) { IAEItemStack ais = slotItem.copy(); ais.setStackSize( ais.getItemStack().getMaxStackSize() ); ais = Platform.poweredExtraction( this.getPowerSource(), this.getCellInventory(), ais, this.getActionSource() ); if( ais != null ) { player.inventory.setItemStack( ais.getItemStack() ); } else { player.inventory.setItemStack( null ); } this.updateHeld( player ); } } else { IAEItemStack ais = AEApi.instance().storage().createItemStack( player.inventory.getItemStack() ); ais = Platform.poweredInsert( this.getPowerSource(), this.getCellInventory(), ais, this.getActionSource() ); if( ais != null ) { player.inventory.setItemStack( ais.getItemStack() ); } else { player.inventory.setItemStack( null ); } this.updateHeld( player ); } break; case SPLIT_OR_PLACE_SINGLE: if( this.getPowerSource() == null || this.getCellInventory() == null ) { return; } if( player.inventory.getItemStack() == null ) { if( slotItem != null ) { IAEItemStack ais = slotItem.copy(); final long maxSize = ais.getItemStack().getMaxStackSize(); ais.setStackSize( maxSize ); ais = this.getCellInventory().extractItems( ais, Actionable.SIMULATE, this.getActionSource() ); if( ais != null ) { final long stackSize = Math.min( maxSize, ais.getStackSize() ); ais.setStackSize( ( stackSize + 1 ) >> 1 ); ais = Platform.poweredExtraction( this.getPowerSource(), this.getCellInventory(), ais, this.getActionSource() ); } if( ais != null ) { player.inventory.setItemStack( ais.getItemStack() ); } else { player.inventory.setItemStack( null ); } this.updateHeld( player ); } } else { IAEItemStack ais = AEApi.instance().storage().createItemStack( player.inventory.getItemStack() ); ais.setStackSize( 1 ); ais = Platform.poweredInsert( this.getPowerSource(), this.getCellInventory(), ais, this.getActionSource() ); if( ais == null ) { final ItemStack is = player.inventory.getItemStack(); is.stackSize--; if( is.stackSize <= 0 ) { player.inventory.setItemStack( null ); } this.updateHeld( player ); } } break; case CREATIVE_DUPLICATE: if( player.capabilities.isCreativeMode && slotItem != null ) { final ItemStack is = slotItem.getItemStack(); is.stackSize = is.getMaxStackSize(); player.inventory.setItemStack( is ); this.updateHeld( player ); } break; case MOVE_REGION: if( this.getPowerSource() == null || this.getCellInventory() == null ) { return; } if( slotItem != null ) { final int playerInv = 9 * 4; for( int slotNum = 0; slotNum < playerInv; slotNum++ ) { IAEItemStack ais = slotItem.copy(); ItemStack myItem = ais.getItemStack(); ais.setStackSize( myItem.getMaxStackSize() ); final InventoryAdaptor adp = InventoryAdaptor.getAdaptor( player, EnumFacing.UP ); myItem.stackSize = (int) ais.getStackSize(); myItem = adp.simulateAdd( myItem ); if( myItem != null ) { ais.setStackSize( ais.getStackSize() - myItem.stackSize ); } ais = Platform.poweredExtraction( this.getPowerSource(), this.getCellInventory(), ais, this.getActionSource() ); if( ais != null ) { adp.addItems( ais.getItemStack() ); } else { return; } } } break; default: break; } } protected void updateHeld( final EntityPlayerMP p ) { if( Platform.isServer() ) { try { NetworkHandler.instance.sendTo( new PacketInventoryAction( InventoryAction.UPDATE_HAND, 0, AEItemStack.create( p.inventory.getItemStack() ) ), p ); } catch( final IOException e ) { AELog.debug( e ); } } } private ItemStack shiftStoreItem( final ItemStack input ) { if( this.getPowerSource() == null || this.getCellInventory() == null ) { return input; } final IAEItemStack ais = Platform.poweredInsert( this.getPowerSource(), this.getCellInventory(), AEApi.instance().storage().createItemStack( input ), this.getActionSource() ); if( ais == null ) { return null; } return ais.getItemStack(); } private void updateSlot( final Slot clickSlot ) { // ??? this.detectAndSendChanges(); } private void sendCustomName() { if( !this.sentCustomName ) { this.sentCustomName = true; if( Platform.isServer() ) { ICustomNameObject name = null; if( this.part instanceof ICustomNameObject ) { name = (ICustomNameObject) this.part; } if( this.tileEntity instanceof ICustomNameObject ) { name = (ICustomNameObject) this.tileEntity; } if( this.obj instanceof ICustomNameObject ) { name = (ICustomNameObject) this.obj; } if( this instanceof ICustomNameObject ) { name = (ICustomNameObject) this; } if( name != null ) { if( name.hasCustomName() ) { this.setCustomName( name.getCustomName() ); } if( this.getCustomName() != null ) { try { NetworkHandler.instance.sendTo( new PacketValueConfig( "CustomName", this.getCustomName() ), (EntityPlayerMP) this.getInventoryPlayer().player ); } catch( final IOException e ) { AELog.debug( e ); } } } } } } public void swapSlotContents( final int slotA, final int slotB ) { final Slot a = this.getSlot( slotA ); final Slot b = this.getSlot( slotB ); // NPE protection... if( a == null || b == null ) { return; } final ItemStack isA = a.getStack(); final ItemStack isB = b.getStack(); // something to do? if( isA == null && isB == null ) { return; } // can take? if( isA != null && !a.canTakeStack( this.getInventoryPlayer().player ) ) { return; } if( isB != null && !b.canTakeStack( this.getInventoryPlayer().player ) ) { return; } // swap valid? if( isB != null && !a.isItemValid( isB ) ) { return; } if( isA != null && !b.isItemValid( isA ) ) { return; } ItemStack testA = isB == null ? null : isB.copy(); ItemStack testB = isA == null ? null : isA.copy(); // can put some back? if( testA != null && testA.stackSize > a.getSlotStackLimit() ) { if( testB != null ) { return; } final int totalA = testA.stackSize; testA.stackSize = a.getSlotStackLimit(); testB = testA.copy(); testB.stackSize = totalA - testA.stackSize; } if( testB != null && testB.stackSize > b.getSlotStackLimit() ) { if( testA != null ) { return; } final int totalB = testB.stackSize; testB.stackSize = b.getSlotStackLimit(); testA = testB.copy(); testA.stackSize = totalB - testA.stackSize; } a.putStack( testA ); b.putStack( testB ); } public void onUpdate( final String field, final Object oldValue, final Object newValue ) { } public void onSlotChange( final Slot s ) { } public boolean isValidForSlot( final Slot s, final ItemStack i ) { return true; } public IMEInventoryHandler getCellInventory() { return this.cellInv; } public void setCellInventory( final IMEInventoryHandler cellInv ) { this.cellInv = cellInv; } public String getCustomName() { return this.customName; } public void setCustomName( final String customName ) { this.customName = customName; } public InventoryPlayer getInventoryPlayer() { return this.invPlayer; } public boolean isValidContainer() { return this.isContainerValid; } public void setValidContainer( final boolean isContainerValid ) { this.isContainerValid = isContainerValid; } public ContainerOpenContext getOpenContext() { return this.openContext; } public void setOpenContext( final ContainerOpenContext openContext ) { this.openContext = openContext; } public IEnergySource getPowerSource() { return this.powerSrc; } public void setPowerSource( final IEnergySource powerSrc ) { this.powerSrc = powerSrc; } }