package appeng.api.storage; import appeng.api.config.AccessRestriction; import appeng.api.config.Actionable; import appeng.api.networking.security.BaseActionSource; import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import com.google.common.collect.ImmutableList; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; /** * Common implementation of a simple class that monitors injection/extraction of a inventory to send events to a list of * listeners. * * @param <StackType> */ public class MEMonitorHandler<StackType extends IAEStack> implements IMEMonitor<StackType> { private final IMEInventoryHandler<StackType> internalHandler; private final IItemList<StackType> cachedList; private final HashMap<IMEMonitorHandlerReceiver<StackType>, Object> listeners = new HashMap<IMEMonitorHandlerReceiver<StackType>, Object>(); protected boolean hasChanged = true; protected IMEInventoryHandler<StackType> getHandler() { return internalHandler; } protected Iterator<Entry<IMEMonitorHandlerReceiver<StackType>, Object>> getListeners() { return listeners.entrySet().iterator(); } protected void postChangesToListeners( Iterable<StackType> changes, BaseActionSource src) { notifyListenersOfChange( changes, src ); } protected void notifyListenersOfChange(Iterable<StackType> diff, BaseActionSource src) { hasChanged = true;// need to update the cache. Iterator<Entry<IMEMonitorHandlerReceiver<StackType>, Object>> i = getListeners(); while (i.hasNext()) { Entry<IMEMonitorHandlerReceiver<StackType>, Object> o = i.next(); IMEMonitorHandlerReceiver<StackType> receiver = o.getKey(); if ( receiver.isValid( o.getValue() ) ) receiver.postChange( this, diff, src ); else i.remove(); } } private StackType monitorDifference(IAEStack original, StackType leftOvers, boolean extraction, BaseActionSource src) { StackType diff = (StackType) original.copy(); if ( extraction ) diff.setStackSize( leftOvers == null ? 0 : -leftOvers.getStackSize() ); else if ( leftOvers != null ) diff.decStackSize( leftOvers.getStackSize() ); if ( diff.getStackSize() != 0 ) postChangesToListeners( ImmutableList.of( diff ), src ); return leftOvers; } public MEMonitorHandler(IMEInventoryHandler<StackType> t) { internalHandler = t; cachedList = (IItemList<StackType>) t.getChannel().createList(); } public MEMonitorHandler(IMEInventoryHandler<StackType> t, StorageChannel chan) { internalHandler = t; cachedList = (IItemList<StackType>) chan.createList(); } @Override public void addListener(IMEMonitorHandlerReceiver<StackType> l, Object verificationToken) { listeners.put( l, verificationToken ); } @Override public void removeListener(IMEMonitorHandlerReceiver<StackType> l) { listeners.remove( l ); } @Override public StackType injectItems(StackType input, Actionable mode, BaseActionSource src) { if ( mode == Actionable.SIMULATE ) return getHandler().injectItems( input, mode, src ); return monitorDifference(input.copy(), getHandler().injectItems(input, mode, src), false, src); } @Override public StackType extractItems(StackType request, Actionable mode, BaseActionSource src) { if ( mode == Actionable.SIMULATE ) return getHandler().extractItems( request, mode, src ); return monitorDifference(request.copy(), getHandler().extractItems(request, mode, src), true, src); } @Override public IItemList<StackType> getStorageList() { if ( hasChanged ) { hasChanged = false; cachedList.resetStatus(); return getAvailableItems( cachedList ); } return cachedList; } @Override public IItemList<StackType> getAvailableItems(IItemList out) { return getHandler().getAvailableItems( out ); } @Override public StorageChannel getChannel() { return getHandler().getChannel(); } @Override public AccessRestriction getAccess() { return getHandler().getAccess(); } @Override public boolean isPrioritized(StackType input) { return getHandler().isPrioritized( input ); } @Override public boolean canAccept(StackType input) { return getHandler().canAccept( input ); } @Override public int getPriority() { return getHandler().getPriority(); } @Override public int getSlot() { return getHandler().getSlot(); } @Override public boolean validForPass(int i) { return getHandler().validForPass( i ); } }