package appeng.me.cache; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import appeng.api.networking.IGrid; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; import appeng.api.networking.IGridStorage; import appeng.api.networking.events.MENetworkCellArrayUpdate; import appeng.api.networking.events.MENetworkEventSubscribe; import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.ISecurityGrid; import appeng.api.networking.security.MachineSource; import appeng.api.networking.storage.IStackWatcher; import appeng.api.networking.storage.IStackWatcherHost; import appeng.api.networking.storage.IStorageGrid; import appeng.api.storage.ICellContainer; import appeng.api.storage.IMEInventoryHandler; import appeng.api.storage.IMEMonitor; import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.me.storage.ItemWatcher; import appeng.me.storage.NetworkInventoryHandler; import appeng.util.item.ItemList; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; public class GridStorageCache implements IStorageGrid { public SetMultimap interests = HashMultimap.create(); final HashSet activeCellContainers = new HashSet(); final HashSet inactiveCellContainers = new HashSet(); final public IGrid myGrid; private NetworkInventoryHandler myItemNetwork; private NetworkMonitor itemMonitor = new NetworkMonitor( this, StorageChannel.ITEMS ); private NetworkInventoryHandler myFluidNetwork; private NetworkMonitor fluidMonitor = new NetworkMonitor( this, StorageChannel.FLUIDS ); private HashMap watchers = new HashMap(); public GridStorageCache(IGrid g) { myGrid = g; } @Override public void onUpdateTick() { itemMonitor.onTick(); fluidMonitor.onTick(); } private void addCell(IGridNode node, ICellContainer cc) { if ( node.isActive() && inactiveCellContainers.contains( cc ) ) { inactiveCellContainers.remove( cc ); activeCellContainers.add( cc ); for (IMEInventoryHandler h : cc.getCellArray( StorageChannel.ITEMS )) { postChanges( StorageChannel.ITEMS, 1, h.getAvailableItems( new ItemList() ), new MachineSource( cc ) ); } for (IMEInventoryHandler h : cc.getCellArray( StorageChannel.FLUIDS )) { postChanges( StorageChannel.FLUIDS, 1, h.getAvailableItems( new ItemList() ), new MachineSource( cc ) ); } } } private void rmvCell(IGridNode node, ICellContainer cc) { if ( node.isActive() && activeCellContainers.contains( cc ) ) { inactiveCellContainers.add( cc ); activeCellContainers.remove( cc ); for (IMEInventoryHandler h : cc.getCellArray( StorageChannel.ITEMS )) { postChanges( StorageChannel.ITEMS, -1, h.getAvailableItems( new ItemList() ), new MachineSource( cc ) ); } for (IMEInventoryHandler h : cc.getCellArray( StorageChannel.FLUIDS )) { postChanges( StorageChannel.FLUIDS, -1, h.getAvailableItems( new ItemList() ), new MachineSource( cc ) ); } } } @MENetworkEventSubscribe public void cellUpdate(MENetworkCellArrayUpdate ev) { myItemNetwork = null; myFluidNetwork = null; LinkedList ll = new LinkedList(); ll.addAll( inactiveCellContainers ); ll.addAll( activeCellContainers ); for (ICellContainer cc : ll) { IGridNode node = cc.getActionableNode(); if ( node != null ) { if ( node.isActive() ) addCell( node, cc ); else rmvCell( node, cc ); } } itemMonitor.forceUpdate(); fluidMonitor.forceUpdate(); } @Override public void removeNode(IGridNode node, IGridHost machine) { if ( machine instanceof ICellContainer ) { ICellContainer cc = (ICellContainer) machine; myGrid.postEvent( new MENetworkCellArrayUpdate() ); rmvCell( node, cc ); inactiveCellContainers.remove( cc ); } if ( machine instanceof IStackWatcherHost ) { IStackWatcher myWatcher = watchers.get( machine ); if ( myWatcher != null ) { myWatcher.clear(); watchers.remove( machine ); } } } @Override public void addNode(IGridNode node, IGridHost machine) { if ( machine instanceof ICellContainer ) { ICellContainer cc = (ICellContainer) machine; inactiveCellContainers.add( cc ); myGrid.postEvent( new MENetworkCellArrayUpdate() ); addCell( node, cc ); } if ( machine instanceof IStackWatcherHost ) { IStackWatcherHost swh = (IStackWatcherHost) machine; ItemWatcher iw = new ItemWatcher( this, (IStackWatcherHost) swh ); watchers.put( node, iw ); swh.updateWatcher( iw ); } } private void buildNetworkStorage(StorageChannel chan) { SecurityCache security = myGrid.getCache( ISecurityGrid.class ); switch (chan) { case FLUIDS: myFluidNetwork = new NetworkInventoryHandler( StorageChannel.FLUIDS, security ); for (ICellContainer cc : activeCellContainers) { for (IMEInventoryHandler h : cc.getCellArray( chan )) myFluidNetwork.addNewStorage( h ); } break; case ITEMS: myItemNetwork = new NetworkInventoryHandler( StorageChannel.ITEMS, security ); for (ICellContainer cc : activeCellContainers) { for (IMEInventoryHandler h : cc.getCellArray( chan )) myItemNetwork.addNewStorage( h ); } break; default: } } private void postChanges(StorageChannel chan, int up_or_down, IItemList availableItems, BaseActionSource src) { switch (chan) { case FLUIDS: for (IAEFluidStack fs : ((IItemList) availableItems)) { if ( up_or_down > 0 ) fluidMonitor.postChange( fs, src ); else { fs.setStackSize( -fs.getStackSize() ); fluidMonitor.postChange( fs, src ); } } break; case ITEMS: for (IAEItemStack fs : ((IItemList) availableItems)) { if ( up_or_down > 0 ) itemMonitor.postChange( fs, src ); else { fs.setStackSize( -fs.getStackSize() ); itemMonitor.postChange( fs, src ); } } break; default: } } public IMEInventoryHandler getItemInventoryHandler() { if ( myItemNetwork == null ) buildNetworkStorage( StorageChannel.ITEMS ); return myItemNetwork; } public IMEInventoryHandler getFluidInventoryHandler() { if ( myFluidNetwork == null ) buildNetworkStorage( StorageChannel.FLUIDS ); return myFluidNetwork; } @Override public void postAlterationOfStoredItems(StorageChannel chan, IAEStack input, BaseActionSource src) { if ( chan == StorageChannel.ITEMS ) itemMonitor.postChange( (IAEItemStack) input, src ); else if ( chan == StorageChannel.FLUIDS ) fluidMonitor.postChange( (IAEFluidStack) input, src ); } @Override public IMEMonitor getFluidInventory() { return fluidMonitor; } @Override public IMEMonitor getItemInventory() { return itemMonitor; } @Override public void onSplit(IGridStorage storageB) { } @Override public void onJoin(IGridStorage storageB) { } @Override public void populateGridStorage(IGridStorage storage) { } }