diff --git a/src/api/java/appeng/api/features/IRegistryContainer.java b/src/api/java/appeng/api/features/IRegistryContainer.java index 8831ad13..393187f9 100644 --- a/src/api/java/appeng/api/features/IRegistryContainer.java +++ b/src/api/java/appeng/api/features/IRegistryContainer.java @@ -24,14 +24,11 @@ package appeng.api.features; -import net.minecraftforge.items.IItemHandler; - import appeng.api.AEInjectable; import appeng.api.movable.IMovableRegistry; import appeng.api.networking.IGridCacheRegistry; import appeng.api.parts.IPartModels; import appeng.api.storage.ICellRegistry; -import appeng.api.storage.IExternalStorageRegistry; /** @@ -54,15 +51,6 @@ public interface IRegistryContainer */ IGridCacheRegistry gridCache(); - /** - * Add additional storage bus handlers to improve interplay with mod blocks that contains special inventories that - * function unlike vanilla chests. AE uses this internally for barrels, DSU's, quantum chests, AE Networks and more. - * - * @deprecated in favour of {@link IItemHandler} - */ - @Deprecated - IExternalStorageRegistry externalStorage(); - /** * Add additional special comparison functionality, AE Uses this internally for Bees. */ diff --git a/src/api/java/appeng/api/implementations/tiles/IMEChest.java b/src/api/java/appeng/api/implementations/tiles/IMEChest.java index bbe957a9..794b45d7 100644 --- a/src/api/java/appeng/api/implementations/tiles/IMEChest.java +++ b/src/api/java/appeng/api/implementations/tiles/IMEChest.java @@ -27,7 +27,7 @@ package appeng.api.implementations.tiles; import appeng.api.networking.energy.IEnergySource; -public interface IMEChest extends IChestOrDrive, ITileStorageMonitorable, IEnergySource +public interface IMEChest extends IChestOrDrive, IEnergySource { } diff --git a/src/api/java/appeng/api/implementations/tiles/ITileStorageMonitorable.java b/src/api/java/appeng/api/implementations/tiles/ITileStorageMonitorable.java deleted file mode 100644 index 7da3efae..00000000 --- a/src/api/java/appeng/api/implementations/tiles/ITileStorageMonitorable.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2013 AlgorithmX2 - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package appeng.api.implementations.tiles; - - -import net.minecraft.util.EnumFacing; - -import appeng.api.networking.security.BaseActionSource; -import appeng.api.storage.IStorageMonitorable; - - -/** - * Implemented on inventories that can share their inventories with other networks, best example, ME Interface. - */ -public interface ITileStorageMonitorable -{ - - IStorageMonitorable getMonitorable( EnumFacing side, BaseActionSource src ); -} diff --git a/src/api/java/appeng/api/storage/IExternalStorageHandler.java b/src/api/java/appeng/api/storage/IExternalStorageHandler.java deleted file mode 100644 index ba902820..00000000 --- a/src/api/java/appeng/api/storage/IExternalStorageHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2013 AlgorithmX2 - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package appeng.api.storage; - - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.items.IItemHandler; - -import appeng.api.networking.security.BaseActionSource; - - -/** - * A Registration Record for {@link IExternalStorageRegistry} - * - * @deprecated in favour of {@link IItemHandler} - */ -@Deprecated -public interface IExternalStorageHandler -{ - - /** - * if this can handle the provided inventory, return true. ( Generally skipped by AE, and it just calls getInventory - * ) - * - * @param te to be handled tile entity - * @param mySrc source - * - * @return true, if it can get a handler via getInventory - */ - @Deprecated - boolean canHandle( TileEntity te, EnumFacing d, StorageChannel channel, BaseActionSource mySrc ); - - /** - * if this can handle the given inventory, return the a IMEInventory implementing class for it, if not return null - * - * please note that if your inventory changes and requires polling, you must use an {@link IMEMonitor} instead of an - * {@link IMEInventory} failure to do so will result in invalid item counts and reporting of the inventory. - * - * @param te to be handled tile entity - * @param d direction - * @param channel channel - * @param src source - * - * @return The Handler for the inventory - */ - @Deprecated - IMEInventory getInventory( TileEntity te, EnumFacing d, StorageChannel channel, BaseActionSource src ); -} \ No newline at end of file diff --git a/src/api/java/appeng/api/storage/IExternalStorageRegistry.java b/src/api/java/appeng/api/storage/IExternalStorageRegistry.java deleted file mode 100644 index 65cbbb21..00000000 --- a/src/api/java/appeng/api/storage/IExternalStorageRegistry.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2013 AlgorithmX2 - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package appeng.api.storage; - - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.items.IItemHandler; - -import appeng.api.IAppEngApi; -import appeng.api.networking.security.BaseActionSource; - - -/** - * A Registry of External Storage handlers. - * - * Do not implement obtain via {@link IAppEngApi}.registries().getExternalStorageRegistry() - * - * @deprecated in favour of {@link IItemHandler} - */ -@Deprecated -public interface IExternalStorageRegistry -{ - - /** - * A registry for StorageBus interactions - * - * @param esh storage handler - */ - @Deprecated - void addExternalStorageInterface( IExternalStorageHandler esh ); - - /** - * @param te tile entity - * @param opposite direction - * @param channel channel - * @param mySrc source - * - * @return the handler for a given tile / forge direction - */ - @Deprecated - IExternalStorageHandler getHandler( TileEntity te, EnumFacing opposite, StorageChannel channel, BaseActionSource mySrc ); -} \ No newline at end of file diff --git a/src/api/java/appeng/api/storage/IStorageMonitorable.java b/src/api/java/appeng/api/storage/IStorageMonitorable.java index 3a832c5f..09549809 100644 --- a/src/api/java/appeng/api/storage/IStorageMonitorable.java +++ b/src/api/java/appeng/api/storage/IStorageMonitorable.java @@ -24,15 +24,13 @@ package appeng.api.storage; -import appeng.api.implementations.tiles.ITileStorageMonitorable; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEItemStack; /** - * represents the internal behavior of a {@link ITileStorageMonitorable} use it to get this value for a tile, or part. - * - * never check a tile for this, always go though ITileStorageMonitorable if you wish to use this interface. + * Exposes the monitorable network inventories of a grid node that choses to export them. + * This interface can only be obtained using Forge capabilities for {@link IStorageMonitorableAccessor}. */ public interface IStorageMonitorable { diff --git a/src/api/java/appeng/api/storage/IStorageMonitorableAccessor.java b/src/api/java/appeng/api/storage/IStorageMonitorableAccessor.java new file mode 100644 index 00000000..33b0f306 --- /dev/null +++ b/src/api/java/appeng/api/storage/IStorageMonitorableAccessor.java @@ -0,0 +1,26 @@ + +package appeng.api.storage; + + +import javax.annotation.Nullable; + +import appeng.api.networking.security.BaseActionSource; + + +/** + * Allows storage buses to request access to another ME network so it can be used as a subnetwork. + * This interface is used in conjunction with capabilities, so when an object of this is obtained, + * it already knows about which face the access was requested from. + *

+ * To get access to the capability for this, use @CapabilityInject with this interface as the argument + * to the annotation. + */ +public interface IStorageMonitorableAccessor +{ + + /** + * @return Null if the network cannot be accessed by the given action source (i.e. security doesn't permit it). + */ + @Nullable + IStorageMonitorable getInventory( BaseActionSource src ); +} diff --git a/src/main/java/appeng/capabilities/Capabilities.java b/src/main/java/appeng/capabilities/Capabilities.java new file mode 100644 index 00000000..fd54930c --- /dev/null +++ b/src/main/java/appeng/capabilities/Capabilities.java @@ -0,0 +1,70 @@ +/* + * 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.capabilities; + + +import net.minecraft.nbt.NBTBase; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityInject; +import net.minecraftforge.common.capabilities.CapabilityManager; + +import appeng.api.storage.IStorageMonitorableAccessor; + + +/** + * Utility class that holds various capabilities, both by AE2 and other Mods. + */ +public final class Capabilities +{ + + private Capabilities() + { + } + + @CapabilityInject( IStorageMonitorableAccessor.class ) + public static Capability STORAGE_MONITORABLE_ACCESSOR; + + /** + * Register AE2 provided capabilities. + */ + public static void register() + { + CapabilityManager.INSTANCE.register( IStorageMonitorableAccessor.class, createNullStorage(), NullMENetworkAccessor::new ); + } + + // Create a storage implementation that does not do anything + private static Capability.IStorage createNullStorage() + { + return new Capability.IStorage() + { + @Override + public NBTBase writeNBT( Capability capability, T instance, EnumFacing side ) + { + return null; + } + + @Override + public void readNBT( Capability capability, T instance, EnumFacing side, NBTBase nbt ) + { + + } + }; + } +} diff --git a/src/main/java/appeng/parts/layers/LayerITileStorageMonitorable.java b/src/main/java/appeng/capabilities/NullMENetworkAccessor.java similarity index 63% rename from src/main/java/appeng/parts/layers/LayerITileStorageMonitorable.java rename to src/main/java/appeng/capabilities/NullMENetworkAccessor.java index e5d5bfe9..67496b5e 100644 --- a/src/main/java/appeng/parts/layers/LayerITileStorageMonitorable.java +++ b/src/main/java/appeng/capabilities/NullMENetworkAccessor.java @@ -16,29 +16,21 @@ * along with Applied Energistics 2. If not, see . */ -package appeng.parts.layers; +package appeng.capabilities; -import net.minecraft.util.EnumFacing; - -import appeng.api.implementations.tiles.ITileStorageMonitorable; import appeng.api.networking.security.BaseActionSource; -import appeng.api.parts.IPart; -import appeng.api.parts.LayerBase; import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.IStorageMonitorableAccessor; -public class LayerITileStorageMonitorable extends LayerBase implements ITileStorageMonitorable +class NullMENetworkAccessor implements IStorageMonitorableAccessor { @Override - public IStorageMonitorable getMonitorable( final EnumFacing side, final BaseActionSource src ) + public IStorageMonitorable getInventory( BaseActionSource src ) { - final IPart part = this.getPart( side ); - if( part instanceof ITileStorageMonitorable ) - { - return ( (ITileStorageMonitorable) part ).getMonitorable( side, src ); - } return null; } + } diff --git a/src/main/java/appeng/core/Registration.java b/src/main/java/appeng/core/Registration.java index c9dd7697..d7aea9ef 100644 --- a/src/main/java/appeng/core/Registration.java +++ b/src/main/java/appeng/core/Registration.java @@ -56,6 +56,7 @@ import appeng.api.networking.spatial.ISpatialCache; import appeng.api.networking.storage.IStorageGrid; import appeng.api.networking.ticking.ITickManager; import appeng.api.parts.IPartHelper; +import appeng.capabilities.Capabilities; import appeng.core.features.AEFeature; import appeng.core.features.registries.P2PTunnelRegistry; import appeng.core.features.registries.entries.BasicCellHandler; @@ -75,7 +76,6 @@ import appeng.me.cache.PathGridCache; import appeng.me.cache.SecurityCache; import appeng.me.cache.SpatialPylonCache; import appeng.me.cache.TickManagerCache; -import appeng.me.storage.AEExternalHandler; import appeng.parts.PartPlacement; import appeng.recipes.AEItemResolver; import appeng.recipes.CustomRecipeConfig; @@ -131,6 +131,8 @@ public final class Registration { this.registerSpatial( false ); + Capabilities.register(); + final Api api = Api.INSTANCE; final IRecipeHandlerRegistry recipeRegistry = api.registries().recipes(); this.registerCraftHandlers( recipeRegistry ); @@ -247,12 +249,6 @@ public final class Registration recipeLoader.run(); // TODO readd layers - // partHelper.registerNewLayer( "appeng.parts.layers.LayerISidedInventory", - // "net.minecraft.inventory.ISidedInventory" ); - // partHelper.registerNewLayer( "appeng.parts.layers.LayerIFluidHandler", - // "net.minecraftforge.fluids.IFluidHandler" ); - // partHelper.registerNewLayer( "appeng.parts.layers.LayerITileStorageMonitorable", - // "appeng.api.implementations.tiles.ITileStorageMonitorable" ); // if( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.IC2 ) ) // { @@ -292,8 +288,6 @@ public final class Registration gcr.registerGridCache( ISecurityGrid.class, SecurityCache.class ); gcr.registerGridCache( ICraftingGrid.class, CraftingGridCache.class ); - registries.externalStorage().addExternalStorageInterface( new AEExternalHandler() ); - registries.cell().addCellHandler( new BasicCellHandler() ); registries.cell().addCellHandler( new CreativeCellHandler() ); diff --git a/src/main/java/appeng/core/features/registries/ExternalStorageRegistry.java b/src/main/java/appeng/core/features/registries/ExternalStorageRegistry.java deleted file mode 100644 index 64436861..00000000 --- a/src/main/java/appeng/core/features/registries/ExternalStorageRegistry.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.core.features.registries; - - -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; - -import appeng.api.networking.security.BaseActionSource; -import appeng.api.storage.IExternalStorageHandler; -import appeng.api.storage.IExternalStorageRegistry; -import appeng.api.storage.StorageChannel; -import appeng.core.features.registries.entries.ExternalIInv; - - -public class ExternalStorageRegistry implements IExternalStorageRegistry -{ - - private final List Handlers; - private final ExternalIInv lastHandler = new ExternalIInv(); - - public ExternalStorageRegistry() - { - this.Handlers = new ArrayList(); - } - - @Override - public void addExternalStorageInterface( final IExternalStorageHandler ei ) - { - this.Handlers.add( ei ); - } - - @Override - public IExternalStorageHandler getHandler( final TileEntity te, final EnumFacing d, final StorageChannel chan, final BaseActionSource mySrc ) - { - for( final IExternalStorageHandler x : this.Handlers ) - { - if( x.canHandle( te, d, chan, mySrc ) ) - { - return x; - } - } - - if( this.lastHandler.canHandle( te, d, chan, mySrc ) ) - { - return this.lastHandler; - } - - return null; - } -} diff --git a/src/main/java/appeng/core/features/registries/RegistryContainer.java b/src/main/java/appeng/core/features/registries/RegistryContainer.java index 805cf1bf..e9f8a728 100644 --- a/src/main/java/appeng/core/features/registries/RegistryContainer.java +++ b/src/main/java/appeng/core/features/registries/RegistryContainer.java @@ -34,7 +34,6 @@ import appeng.api.movable.IMovableRegistry; import appeng.api.networking.IGridCacheRegistry; import appeng.api.parts.IPartModels; import appeng.api.storage.ICellRegistry; -import appeng.api.storage.IExternalStorageRegistry; /** @@ -49,7 +48,6 @@ public class RegistryContainer implements IRegistryContainer { private final IGrinderRegistry grinder = new GrinderRecipeManager(); private final IInscriberRegistry inscriber = new InscriberRegistry(); - private final IExternalStorageRegistry storage = new ExternalStorageRegistry(); private final ICellRegistry cell = new CellRegistry(); private final ILocatableRegistry locatable = new LocatableRegistry(); private final ISpecialComparisonRegistry comparison = new SpecialComparisonRegistry(); @@ -74,12 +72,6 @@ public class RegistryContainer implements IRegistryContainer return this.gridCache; } - @Override - public IExternalStorageRegistry externalStorage() - { - return this.storage; - } - @Override public ISpecialComparisonRegistry specialComparison() { diff --git a/src/main/java/appeng/core/features/registries/entries/ExternalIInv.java b/src/main/java/appeng/core/features/registries/entries/ExternalIInv.java deleted file mode 100644 index 5b781989..00000000 --- a/src/main/java/appeng/core/features/registries/entries/ExternalIInv.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.core.features.registries.entries; - - -import net.minecraft.inventory.IInventory; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; - -import appeng.api.networking.security.BaseActionSource; -import appeng.api.storage.IExternalStorageHandler; -import appeng.api.storage.IMEInventory; -import appeng.api.storage.StorageChannel; -import appeng.me.storage.MEMonitorIInventory; -import appeng.util.InventoryAdaptor; - - -public class ExternalIInv implements IExternalStorageHandler -{ - - @Override - public boolean canHandle( final TileEntity te, final EnumFacing d, final StorageChannel channel, final BaseActionSource mySrc ) - { - return channel == StorageChannel.ITEMS && te instanceof IInventory; - } - - @Override - public IMEInventory getInventory( final TileEntity te, final EnumFacing d, final StorageChannel channel, final BaseActionSource src ) - { - final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, d ); - - if( channel == StorageChannel.ITEMS && ad != null ) - { - return new MEMonitorIInventory( ad ); - } - - return null; - } -} diff --git a/src/main/java/appeng/helpers/DualityInterface.java b/src/main/java/appeng/helpers/DualityInterface.java index 99381902..0ad298e3 100644 --- a/src/main/java/appeng/helpers/DualityInterface.java +++ b/src/main/java/appeng/helpers/DualityInterface.java @@ -25,6 +25,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import javax.annotation.Nullable; import com.google.common.collect.ImmutableSet; @@ -75,6 +76,7 @@ import appeng.api.parts.IPart; import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEMonitor; import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.IStorageMonitorableAccessor; import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEItemStack; @@ -82,6 +84,7 @@ import appeng.api.util.AECableType; import appeng.api.util.AEPartLocation; import appeng.api.util.DimensionalCoord; import appeng.api.util.IConfigManager; +import appeng.capabilities.Capabilities; import appeng.core.settings.TickRates; import appeng.me.GridAccessException; import appeng.me.helpers.AENetworkProxy; @@ -134,6 +137,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn private IMEInventory destination; private boolean isWorking = false; private IItemHandler itemHandler = null; + private final Accessor accessor = new Accessor(); public DualityInterface( final AENetworkProxy networkProxy, final IInterfaceHost ih ) { @@ -869,7 +873,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn this.craftingTracker.cancel(); } - public IStorageMonitorable getMonitorable( final EnumFacing side, final BaseActionSource src, final IStorageMonitorable myInterface ) + public IStorageMonitorable getMonitorable( final BaseActionSource src, final IStorageMonitorable myInterface ) { if( Platform.canAccess( this.gridProxy, src ) ) { @@ -1269,7 +1273,8 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn public boolean hasCapability( Capability capabilityClass, EnumFacing facing ) { - return capabilityClass == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; + return capabilityClass == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY + || capabilityClass == Capabilities.STORAGE_MONITORABLE_ACCESSOR; } @SuppressWarnings( "unchecked" ) @@ -1283,6 +1288,10 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn } return (T) itemHandler; } + else if( capabilityClass == Capabilities.STORAGE_MONITORABLE_ACCESSOR ) + { + return (T) accessor; + } return null; } @@ -1327,4 +1336,16 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn } } + private class Accessor implements IStorageMonitorableAccessor + { + + @Nullable + @Override + public IStorageMonitorable getInventory( BaseActionSource src ) + { + return getMonitorable( src, DualityInterface.this ); + } + + } + } diff --git a/src/main/java/appeng/me/storage/AEExternalHandler.java b/src/main/java/appeng/me/storage/AEExternalHandler.java deleted file mode 100644 index 2ca96657..00000000 --- a/src/main/java/appeng/me/storage/AEExternalHandler.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.me.storage; - - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; - -import appeng.api.implementations.tiles.ITileStorageMonitorable; -import appeng.api.networking.security.BaseActionSource; -import appeng.api.storage.IExternalStorageHandler; -import appeng.api.storage.IMEInventory; -import appeng.api.storage.IStorageMonitorable; -import appeng.api.storage.StorageChannel; -import appeng.api.storage.data.IAEFluidStack; -import appeng.api.storage.data.IAEItemStack; -import appeng.tile.misc.TileCondenser; - - -public class AEExternalHandler implements IExternalStorageHandler -{ - - @Override - public boolean canHandle( final TileEntity te, final EnumFacing d, final StorageChannel channel, final BaseActionSource mySrc ) - { - if( channel == StorageChannel.ITEMS && te instanceof ITileStorageMonitorable ) - { - return ( (ITileStorageMonitorable) te ).getMonitorable( d, mySrc ) != null; - } - - return te instanceof TileCondenser; - } - - @Override - public IMEInventory getInventory( final TileEntity te, final EnumFacing d, final StorageChannel channel, final BaseActionSource src ) - { - if( te instanceof TileCondenser ) - { - if( channel == StorageChannel.ITEMS ) - { - return new VoidItemInventory( (TileCondenser) te ); - } - else - { - return new VoidFluidInventory( (TileCondenser) te ); - } - } - - if( te instanceof ITileStorageMonitorable ) - { - final ITileStorageMonitorable iface = (ITileStorageMonitorable) te; - final IStorageMonitorable sm = iface.getMonitorable( d, src ); - - if( channel == StorageChannel.ITEMS && sm != null ) - { - final IMEInventory ii = sm.getItemInventory(); - if( ii != null ) - { - return ii; - } - } - - if( channel == StorageChannel.FLUIDS && sm != null ) - { - final IMEInventory fi = sm.getFluidInventory(); - if( fi != null ) - { - return fi; - } - } - } - - return null; - } -} diff --git a/src/main/java/appeng/me/storage/ITickingMonitor.java b/src/main/java/appeng/me/storage/ITickingMonitor.java new file mode 100644 index 00000000..1dca452a --- /dev/null +++ b/src/main/java/appeng/me/storage/ITickingMonitor.java @@ -0,0 +1,33 @@ +/* + * 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.me.storage; + + +import appeng.api.networking.security.BaseActionSource; +import appeng.api.networking.ticking.TickRateModulation; + + +public interface ITickingMonitor +{ + + TickRateModulation onTick(); + + void setActionSource( BaseActionSource actionSource ); + +} diff --git a/src/main/java/appeng/me/storage/MEIInventoryWrapper.java b/src/main/java/appeng/me/storage/MEIInventoryWrapper.java deleted file mode 100644 index 25264e6f..00000000 --- a/src/main/java/appeng/me/storage/MEIInventoryWrapper.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * 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.me.storage; - - -import net.minecraft.inventory.IInventory; -import net.minecraft.item.ItemStack; - -import appeng.api.config.Actionable; -import appeng.api.networking.security.BaseActionSource; -import appeng.api.storage.IMEInventory; -import appeng.api.storage.StorageChannel; -import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IItemList; -import appeng.util.InventoryAdaptor; -import appeng.util.Platform; -import appeng.util.item.AEItemStack; - - -public class MEIInventoryWrapper implements IMEInventory -{ - - private final IInventory target; - private final InventoryAdaptor adaptor; - - public MEIInventoryWrapper( final IInventory m, final InventoryAdaptor ia ) - { - this.target = m; - this.adaptor = ia; - } - - @Override - public IAEItemStack injectItems( final IAEItemStack iox, final Actionable mode, final BaseActionSource src ) - { - final ItemStack input = iox.getItemStack(); - - if( this.adaptor != null ) - { - final ItemStack is = mode == Actionable.SIMULATE ? this.adaptor.simulateAdd( input ) : this.adaptor.addItems( input ); - if( is == null ) - { - return null; - } - return AEItemStack.create( is ); - } - - final ItemStack out = Platform.cloneItemStack( input ); - - if( mode == Actionable.MODULATE ) // absolutely no need for a first run in simulate mode. - { - for( int x = 0; x < this.target.getSizeInventory(); x++ ) - { - final ItemStack t = this.target.getStackInSlot( x ); - - if( Platform.isSameItem( t, input ) ) - { - final int oriStack = t.stackSize; - t.stackSize += out.stackSize; - - this.target.setInventorySlotContents( x, t ); - - if( t.stackSize > this.target.getInventoryStackLimit() ) - { - t.stackSize = this.target.getInventoryStackLimit(); - } - - if( t.stackSize > t.getMaxStackSize() ) - { - t.stackSize = t.getMaxStackSize(); - } - - out.stackSize -= t.stackSize - oriStack; - - if( out.stackSize <= 0 ) - { - return null; - } - } - } - } - - for( int x = 0; x < this.target.getSizeInventory(); x++ ) - { - ItemStack t = this.target.getStackInSlot( x ); - - if( t == null ) - { - t = Platform.cloneItemStack( input ); - t.stackSize = out.stackSize; - - if( t.stackSize > this.target.getInventoryStackLimit() ) - { - t.stackSize = this.target.getInventoryStackLimit(); - } - - out.stackSize -= t.stackSize; - if( mode == Actionable.MODULATE ) - { - this.target.setInventorySlotContents( x, t ); - } - - if( out.stackSize <= 0 ) - { - return null; - } - } - } - - return AEItemStack.create( out ); - } - - @Override - public IAEItemStack extractItems( final IAEItemStack request, final Actionable mode, final BaseActionSource src ) - { - final ItemStack Req = request.getItemStack(); - - int request_stackSize = Req.stackSize; - - if( request_stackSize > Req.getMaxStackSize() ) - { - request_stackSize = Req.getMaxStackSize(); - } - - Req.stackSize = request_stackSize; - - ItemStack Gathered = null; - if( this.adaptor != null ) - { - Gathered = this.adaptor.removeItems( Req.stackSize, Req, null ); - } - else - { - Gathered = request.getItemStack(); - Gathered.stackSize = 0; - - // try to find matching inventories that already have it... - for( int x = 0; x < this.target.getSizeInventory(); x++ ) - { - final ItemStack sub = this.target.getStackInSlot( x ); - - if( Platform.isSameItem( sub, Req ) ) - { - int reqNum = Req.stackSize; - - if( reqNum > sub.stackSize ) - { - reqNum = Req.stackSize; - } - - ItemStack retrieved = null; - - if( sub.stackSize < Req.stackSize ) - { - retrieved = Platform.cloneItemStack( sub ); - sub.stackSize = 0; - } - else - { - retrieved = sub.splitStack( Req.stackSize ); - } - - if( sub.stackSize <= 0 ) - { - this.target.setInventorySlotContents( x, null ); - } - else - { - this.target.setInventorySlotContents( x, sub ); - } - - if( retrieved != null ) - { - Gathered.stackSize += retrieved.stackSize; - Req.stackSize -= retrieved.stackSize; - } - - if( request_stackSize == Gathered.stackSize ) - { - return AEItemStack.create( Gathered ); - } - } - } - - if( Gathered.stackSize == 0 ) - { - return null; - } - } - - return AEItemStack.create( Gathered ); - } - - @Override - public IItemList getAvailableItems( final IItemList out ) - { - for( int x = 0; x < this.target.getSizeInventory(); x++ ) - { - out.addStorage( AEItemStack.create( this.target.getStackInSlot( x ) ) ); - } - - return out; - } - - @Override - public StorageChannel getChannel() - { - return StorageChannel.ITEMS; - } -} diff --git a/src/main/java/appeng/me/storage/MEMonitorIInventory.java b/src/main/java/appeng/me/storage/MEMonitorIInventory.java index 09f6c3c9..72f86bc4 100644 --- a/src/main/java/appeng/me/storage/MEMonitorIInventory.java +++ b/src/main/java/appeng/me/storage/MEMonitorIInventory.java @@ -44,7 +44,7 @@ import appeng.util.Platform; import appeng.util.inv.ItemSlot; -public class MEMonitorIInventory implements IMEMonitor +public class MEMonitorIInventory implements IMEMonitor, ITickingMonitor { private final InventoryAdaptor adaptor; @@ -139,6 +139,7 @@ public class MEMonitorIInventory implements IMEMonitor return StorageChannel.ITEMS; } + @Override public TickRateModulation onTick() { @@ -329,6 +330,7 @@ public class MEMonitorIInventory implements IMEMonitor return this.mySource; } + @Override public void setActionSource( final BaseActionSource mySource ) { this.mySource = mySource; diff --git a/src/main/java/appeng/me/storage/NetworkInventoryHandler.java b/src/main/java/appeng/me/storage/NetworkInventoryHandler.java index 82246cc5..bef23ef7 100644 --- a/src/main/java/appeng/me/storage/NetworkInventoryHandler.java +++ b/src/main/java/appeng/me/storage/NetworkInventoryHandler.java @@ -49,18 +49,11 @@ public class NetworkInventoryHandler> implements IMEInvent private static final ThreadLocal DEPTH_MOD = new ThreadLocal(); private static final ThreadLocal DEPTH_SIM = new ThreadLocal(); - private static final Comparator PRIORITY_SORTER = new Comparator(){ + private static final Comparator PRIORITY_SORTER = ( o1, o2 ) -> ItemSorters.compareInt( o2, o1 ); - @Override - public int compare( final Integer o1, final Integer o2 ) - { - return ItemSorters.compareInt( o2, o1 ); - } - }; private static int currentPass = 0; private final StorageChannel myChannel; private final SecurityCache security; - // final TreeMultimap> priorityInventory; private final NavigableMap>> priorityInventory; private int myPass = 0; @@ -68,9 +61,7 @@ public class NetworkInventoryHandler> implements IMEInvent { this.myChannel = chan; this.security = security; - this.priorityInventory = new TreeMap>>( PRIORITY_SORTER ); // TreeMultimap.create( - // prioritySorter, - // hashSorter ); + this.priorityInventory = new TreeMap<>( PRIORITY_SORTER ); } public void addNewStorage( final IMEInventoryHandler h ) @@ -79,7 +70,7 @@ public class NetworkInventoryHandler> implements IMEInvent List> list = this.priorityInventory.get( priority ); if( list == null ) { - this.priorityInventory.put( priority, list = new ArrayList>() ); + this.priorityInventory.put( priority, list = new ArrayList<>() ); } list.add( h ); diff --git a/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java b/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java new file mode 100644 index 00000000..558ce2de --- /dev/null +++ b/src/main/java/appeng/parts/misc/ItemHandlerAdapter.java @@ -0,0 +1,334 @@ +/* + * 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.parts.misc; + + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +import appeng.api.config.Actionable; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.networking.storage.IBaseMonitor; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEMonitorHandlerReceiver; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.core.AELog; +import appeng.me.storage.ITickingMonitor; +import appeng.util.Platform; +import appeng.util.item.AEItemStack; + + +/** + * Wraps an Item Handler in such a way that it can be used as an IMEInventory for items. + */ +class ItemHandlerAdapter implements IMEInventory, IBaseMonitor, ITickingMonitor +{ + + private final Map, Object> listeners = new HashMap<>(); + + private BaseActionSource mySource; + + private final IItemHandler itemHandler; + + private ItemStack[] cachedStacks = new ItemStack[0]; + + private IAEItemStack[] cachedAeStacks = new IAEItemStack[0]; + + ItemHandlerAdapter( IItemHandler itemHandler ) + { + this.itemHandler = itemHandler; + } + + @Override + public IAEItemStack injectItems( IAEItemStack iox, Actionable type, BaseActionSource src ) + { + ItemStack orgInput = iox.getItemStack(); + ItemStack remaining = orgInput; + + int slotCount = itemHandler.getSlots(); + boolean simulate = ( type == Actionable.SIMULATE ); + + // This uses a brute force approach and tries to jam it in every slot the inventory exposes. + for( int i = 0; i < slotCount && remaining != null; i++ ) + { + remaining = itemHandler.insertItem( i, remaining, simulate ); + } + + // At this point, we still have some items left... + if( remaining == orgInput ) + { + // The stack remained unmodified, target inventory is full + return iox; + } + + if( type == Actionable.MODULATE ) + { + this.onTick(); + } + + return AEItemStack.create( remaining ); + } + + @Override + public IAEItemStack extractItems( IAEItemStack request, Actionable mode, BaseActionSource src ) + { + + ItemStack req = request.getItemStack(); + int remainingSize = req.stackSize; + + // Use this to gather the requested items + ItemStack gathered = null; + + final boolean simulate = ( mode == Actionable.SIMULATE ); + + for( int i = 0; i < itemHandler.getSlots(); i++ ) + { + ItemStack sub = itemHandler.getStackInSlot( i ); + + if( !Platform.isSameItem( sub, req ) ) + { + continue; + } + + ItemStack extracted; + + // We have to loop here because according to the docs, the handler shouldn't return a stack with size > maxSize, even if we + // request more. So even if it returns a valid stack, it might have more stuff. + do + { + extracted = itemHandler.extractItem( i, remainingSize, simulate ); + if( extracted != null ) + { + if( extracted.stackSize > remainingSize ) + { + // Something broke. It should never return more than we requested... We're going to silently eat the remainder + AELog.warn( "Mod that provided item handler {} is broken. Returned {} items, even though we requested {}.", + itemHandler.getClass().getSimpleName(), extracted.stackSize, remainingSize ); + extracted.stackSize = remainingSize; + } + + // We're just gonna use the first stack we get our hands on as the template for the rest + if( gathered == null ) + { + gathered = extracted; + } + else + { + gathered.stackSize += extracted.stackSize; + } + remainingSize -= gathered.stackSize; + } + } + while( extracted != null && remainingSize > 0 ); + + // Done? + if( remainingSize <= 0 ) + { + break; + } + } + + if( gathered != null ) + { + if( mode == Actionable.MODULATE ) + { + this.onTick(); + } + + return AEItemStack.create( gathered ); + } + + return null; + } + + @Override + public TickRateModulation onTick() + { + LinkedList changes = new LinkedList<>(); + + int slots = itemHandler.getSlots(); + + // Make room for new slots + if( slots > cachedStacks.length ) + { + cachedStacks = Arrays.copyOf( cachedStacks, slots ); + cachedAeStacks = Arrays.copyOf( cachedAeStacks, slots ); + } + + for( int slot = 0; slot < slots; slot++ ) + { + // Save the old stuff + ItemStack oldIS = cachedStacks[slot]; + IAEItemStack oldAeIS = cachedAeStacks[slot]; + + ItemStack newIS = itemHandler.getStackInSlot( slot ); + + if( this.isDifferent( newIS, oldIS ) ) + { + addItemChange( slot, oldAeIS, newIS, changes ); + } + else if( newIS != null && oldIS != null ) + { + addPossibleStackSizeChange( slot, oldAeIS, newIS, changes ); + } + } + + // Handle cases where the number of slots actually is lower now than before + if( slots < cachedStacks.length ) + { + for( int slot = slots; slot < cachedStacks.length; slot++ ) + { + IAEItemStack aeStack = cachedAeStacks[slot]; + if( aeStack != null ) + { + IAEItemStack a = aeStack.copy(); + a.setStackSize( -a.getStackSize() ); + changes.add( a ); + } + } + + // Reduce the cache size + cachedStacks = Arrays.copyOf( cachedStacks, slots ); + cachedAeStacks = Arrays.copyOf( cachedAeStacks, slots ); + } + + if( !changes.isEmpty() ) + { + this.postDifference( changes ); + return TickRateModulation.URGENT; + } + else + { + return TickRateModulation.SLOWER; + } + } + + private void addItemChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List changes ) + { + // Completely different item + cachedStacks[slot] = newIS; + cachedAeStacks[slot] = AEItemStack.create( newIS ); + + // If we had a stack previously in this slot, notify the newtork about its disappearance + if( oldAeIS != null ) + { + oldAeIS.setStackSize( -oldAeIS.getStackSize() ); + changes.add( oldAeIS ); + } + + // Notify the network about the new stack. Note that this is null if newIS was null + if( cachedAeStacks[slot] != null ) + { + changes.add( cachedAeStacks[slot] ); + } + } + + private void addPossibleStackSizeChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List changes ) + { + // Still the same item, but amount might have changed + long diff = newIS.stackSize - oldAeIS.getStackSize(); + + if( diff != 0 ) + { + IAEItemStack stack = oldAeIS.copy(); + stack.setStackSize( newIS.stackSize ); + + cachedStacks[slot] = newIS; + cachedAeStacks[slot] = stack; + + final IAEItemStack a = stack.copy(); + a.setStackSize( diff ); + changes.add( a ); + } + } + + private boolean isDifferent( final ItemStack a, final ItemStack b ) + { + if( a == b && b == null ) + { + return false; + } + + return a == null || b == null || !Platform.isSameItemPrecise( a, b ); + } + + private void postDifference( Iterable a ) + { + final Iterator, Object>> i = this.listeners.entrySet().iterator(); + while( i.hasNext() ) + { + final Map.Entry, Object> l = i.next(); + final IMEMonitorHandlerReceiver key = l.getKey(); + if( key.isValid( l.getValue() ) ) + { + key.postChange( this, a, mySource ); + } + else + { + i.remove(); + } + } + } + + @Override + public void setActionSource( final BaseActionSource mySource ) + { + this.mySource = mySource; + } + + @Override + public IItemList getAvailableItems( IItemList out ) + { + + for( int i = 0; i < itemHandler.getSlots(); i++ ) + { + out.addStorage( AEItemStack.create( itemHandler.getStackInSlot( i ) ) ); + } + + return out; + } + + @Override + public StorageChannel getChannel() + { + return StorageChannel.ITEMS; + } + + @Override + public void addListener( final IMEMonitorHandlerReceiver l, final Object verificationToken ) + { + this.listeners.put( l, verificationToken ); + } + + @Override + public void removeListener( final IMEMonitorHandlerReceiver l ) + { + this.listeners.remove( l ); + } +} diff --git a/src/main/java/appeng/parts/misc/PartInterface.java b/src/main/java/appeng/parts/misc/PartInterface.java index 8ddeb47b..513d00e7 100644 --- a/src/main/java/appeng/parts/misc/PartInterface.java +++ b/src/main/java/appeng/parts/misc/PartInterface.java @@ -38,11 +38,9 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.items.CapabilityItemHandler; import appeng.api.config.Actionable; import appeng.api.config.Upgrades; -import appeng.api.implementations.tiles.ITileStorageMonitorable; import appeng.api.networking.IGridNode; import appeng.api.networking.crafting.ICraftingLink; import appeng.api.networking.crafting.ICraftingPatternDetails; @@ -50,7 +48,6 @@ import appeng.api.networking.crafting.ICraftingProviderHelper; import appeng.api.networking.events.MENetworkChannelsChanged; import appeng.api.networking.events.MENetworkEventSubscribe; import appeng.api.networking.events.MENetworkPowerStatusChange; -import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.ticking.IGridTickable; import appeng.api.networking.ticking.TickRateModulation; import appeng.api.networking.ticking.TickingRequest; @@ -75,7 +72,7 @@ import appeng.util.Platform; import appeng.util.inv.IInventoryDestination; -public class PartInterface extends PartBasicState implements IGridTickable, IStorageMonitorable, IInventoryDestination, IInterfaceHost, ISidedInventory, IAEAppEngInventory, ITileStorageMonitorable, IPriorityHost +public class PartInterface extends PartBasicState implements IGridTickable, IStorageMonitorable, IInventoryDestination, IInterfaceHost, ISidedInventory, IAEAppEngInventory, IPriorityHost { public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/interface_base" ); @@ -345,12 +342,6 @@ public class PartInterface extends PartBasicState implements IGridTickable, ISto return super.getHost().getTile(); } - @Override - public IStorageMonitorable getMonitorable( final EnumFacing side, final BaseActionSource src ) - { - return this.duality.getMonitorable( side, src, this ); - } - @Override public boolean pushPattern( final ICraftingPatternDetails patternDetails, final InventoryCrafting table ) { diff --git a/src/main/java/appeng/parts/misc/PartStorageBus.java b/src/main/java/appeng/parts/misc/PartStorageBus.java index 0611cf5c..cea8cae7 100644 --- a/src/main/java/appeng/parts/misc/PartStorageBus.java +++ b/src/main/java/appeng/parts/misc/PartStorageBus.java @@ -30,9 +30,12 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.Vec3d; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; import appeng.api.AEApi; import appeng.api.config.AccessRestriction; @@ -56,17 +59,19 @@ import appeng.api.networking.ticking.TickingRequest; import appeng.api.parts.IPartCollisionHelper; import appeng.api.parts.IPartHost; import appeng.api.storage.ICellContainer; -import appeng.api.storage.IExternalStorageHandler; import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventoryHandler; -import appeng.api.storage.IMEMonitor; import appeng.api.storage.IMEMonitorHandlerReceiver; +import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.IStorageMonitorableAccessor; import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.api.util.AECableType; import appeng.api.util.AEPartLocation; import appeng.api.util.IConfigManager; +import appeng.capabilities.Capabilities; import appeng.core.AppEng; import appeng.core.settings.TickRates; import appeng.core.stats.Achievements; @@ -76,6 +81,7 @@ import appeng.helpers.IPriorityHost; import appeng.helpers.Reflected; import appeng.items.parts.PartModels; import appeng.me.GridAccessException; +import appeng.me.storage.ITickingMonitor; import appeng.me.storage.MEInventoryHandler; import appeng.me.storage.MEMonitorIInventory; import appeng.parts.automation.PartUpgradeable; @@ -86,12 +92,7 @@ import appeng.util.prioitylist.FuzzyPriorityList; import appeng.util.prioitylist.PrecisePriorityList; -// TODO: BC Integration -//@Interface( iname = IntegrationType.BuildCraftTransport, iface = "buildcraft.api.transport.IPipeConnection" ) -public class PartStorageBus extends PartUpgradeable implements IGridTickable, ICellContainer, IMEMonitorHandlerReceiver /* - * , - * IPipeConnection - */, IPriorityHost +public class PartStorageBus extends PartUpgradeable implements IGridTickable, ICellContainer, IMEMonitorHandlerReceiver, IPriorityHost { public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/storage_bus_base" ); @@ -115,8 +116,8 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC private final AppEngInternalAEInventory Config = new AppEngInternalAEInventory( this, 63 ); private int priority = 0; private boolean cached = false; - private MEMonitorIInventory monitor = null; - private MEInventoryHandler handler = null; + private ITickingMonitor monitor = null; + private MEInventoryHandler handler = null; private int handlerHash = 0; private boolean wasActive = false; private byte resetCacheLogic = 0; @@ -367,6 +368,41 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC Platform.postListChanges( before, after, this, this.mySrc ); } + @SuppressWarnings( "unchecked" ) + private IMEInventory getInventoryWrapper( TileEntity target ) + { + + EnumFacing targetSide = this.getSide().getFacing().getOpposite(); + + // Prioritize a handler to directly link to another ME network + IStorageMonitorableAccessor accessor = target.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, targetSide ); + + if( accessor != null ) + { + IStorageMonitorable inventory = accessor.getInventory( mySrc ); + if( inventory != null ) + { + return inventory.getItemInventory(); + } + + // So this could / can be a design decision. If the tile does support our custom capability, + // but it does not return an inventory for the action source, we do NOT fall back to using + // IItemHandler's, as that might circumvent the security setings, and might also cause + // performance issues. + return null; + } + + // Check via cap for IItemHandler + IItemHandler handlerExt = target.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide ); + if( handlerExt != null ) + { + return new ItemHandlerAdapter( handlerExt ); + } + + return null; + + } + public MEInventoryHandler getInternalHandler() { if( this.cached ) @@ -391,58 +427,54 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC this.monitor = null; if( target != null ) { - final IExternalStorageHandler esh = AEApi.instance().registries().externalStorage().getHandler( target, this.getSide().getFacing().getOpposite(), StorageChannel.ITEMS, this.mySrc ); - if( esh != null ) + IMEInventory inv = getInventoryWrapper( target ); + + if( inv instanceof MEMonitorIInventory ) { - final IMEInventory inv = esh.getInventory( target, this.getSide().getFacing().getOpposite(), StorageChannel.ITEMS, this.mySrc ); + final MEMonitorIInventory h = (MEMonitorIInventory) inv; + h.setMode( (StorageFilter) this.getConfigManager().getSetting( Settings.STORAGE_FILTER ) ); + } - if( inv instanceof MEMonitorIInventory ) + if( inv instanceof ITickingMonitor ) + { + this.monitor = (ITickingMonitor) inv; + this.monitor.setActionSource( new MachineSource( this ) ); + } + + if( inv != null ) + { + this.checkInterfaceVsStorageBus( target, this.getSide().getOpposite() ); + + this.handler = new MEInventoryHandler<>( inv, StorageChannel.ITEMS ); + + this.handler.setBaseAccess( (AccessRestriction) this.getConfigManager().getSetting( Settings.ACCESS ) ); + this.handler.setWhitelist( this.getInstalledUpgrades( Upgrades.INVERTER ) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST ); + this.handler.setPriority( this.priority ); + + final IItemList priorityList = AEApi.instance().storage().createItemList(); + + final int slotsToUse = 18 + this.getInstalledUpgrades( Upgrades.CAPACITY ) * 9; + for( int x = 0; x < this.Config.getSizeInventory() && x < slotsToUse; x++ ) { - final MEMonitorIInventory h = (MEMonitorIInventory) inv; - h.setMode( (StorageFilter) this.getConfigManager().getSetting( Settings.STORAGE_FILTER ) ); - h.setActionSource( new MachineSource( this ) ); + final IAEItemStack is = this.Config.getAEStackInSlot( x ); + if( is != null ) + { + priorityList.add( is ); + } } - if( inv instanceof MEMonitorIInventory ) + if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) { - this.monitor = (MEMonitorIInventory) inv; + this.handler.setPartitionList( new FuzzyPriorityList( priorityList, (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ) ) ); + } + else + { + this.handler.setPartitionList( new PrecisePriorityList( priorityList ) ); } - if( inv != null ) + if( inv instanceof IBaseMonitor ) { - this.checkInterfaceVsStorageBus( target, this.getSide().getOpposite() ); - - this.handler = new MEInventoryHandler( inv, StorageChannel.ITEMS ); - - this.handler.setBaseAccess( (AccessRestriction) this.getConfigManager().getSetting( Settings.ACCESS ) ); - this.handler.setWhitelist( this.getInstalledUpgrades( Upgrades.INVERTER ) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST ); - this.handler.setPriority( this.priority ); - - final IItemList priorityList = AEApi.instance().storage().createItemList(); - - final int slotsToUse = 18 + this.getInstalledUpgrades( Upgrades.CAPACITY ) * 9; - for( int x = 0; x < this.Config.getSizeInventory() && x < slotsToUse; x++ ) - { - final IAEItemStack is = this.Config.getAEStackInSlot( x ); - if( is != null ) - { - priorityList.add( is ); - } - } - - if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) - { - this.handler.setPartitionList( new FuzzyPriorityList( priorityList, (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ) ) ); - } - else - { - this.handler.setPartitionList( new PrecisePriorityList( priorityList ) ); - } - - if( inv instanceof IMEMonitor ) - { - ( (IBaseMonitor) inv ).addListener( this, this.handler ); - } + ( (IBaseMonitor) inv ).addListener( this, this.handler ); } } } diff --git a/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java b/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java index 58d240a0..1cb5bfbb 100644 --- a/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java +++ b/src/main/java/appeng/tile/inventory/AppEngInternalInventory.java @@ -27,9 +27,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.text.ITextComponent; -import appeng.api.storage.IMEInventory; import appeng.core.AELog; -import appeng.me.storage.MEIInventoryWrapper; import appeng.util.Platform; import appeng.util.iterators.InvIterator; @@ -50,11 +48,6 @@ public class AppEngInternalInventory implements IInventory, Iterable this.inv = new ItemStack[size]; } - public IMEInventory getMEInventory() - { - return new MEIInventoryWrapper( this, null ); - } - public boolean isEmpty() { for( int x = 0; x < this.size; x++ ) diff --git a/src/main/java/appeng/me/storage/VoidFluidInventory.java b/src/main/java/appeng/tile/misc/CondenserFluidInventory.java similarity index 75% rename from src/main/java/appeng/me/storage/VoidFluidInventory.java rename to src/main/java/appeng/tile/misc/CondenserFluidInventory.java index af98dc6e..8bd07af7 100644 --- a/src/main/java/appeng/me/storage/VoidFluidInventory.java +++ b/src/main/java/appeng/tile/misc/CondenserFluidInventory.java @@ -16,25 +16,26 @@ * along with Applied Energistics 2. If not, see . */ -package appeng.me.storage; +package appeng.tile.misc; import appeng.api.config.AccessRestriction; import appeng.api.config.Actionable; import appeng.api.networking.security.BaseActionSource; -import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMonitorHandlerReceiver; import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IItemList; -import appeng.tile.misc.TileCondenser; +import appeng.util.item.FluidList; -public class VoidFluidInventory implements IMEInventoryHandler +class CondenserFluidInventory implements IMEMonitor { private final TileCondenser target; - public VoidFluidInventory( final TileCondenser te ) + CondenserFluidInventory( final TileCondenser te ) { this.target = te; } @@ -66,6 +67,12 @@ public class VoidFluidInventory implements IMEInventoryHandler return out; } + @Override + public IItemList getStorageList() + { + return new FluidList(); + } + @Override public StorageChannel getChannel() { @@ -107,4 +114,16 @@ public class VoidFluidInventory implements IMEInventoryHandler { return i == 2; } + + @Override + public void addListener( IMEMonitorHandlerReceiver l, Object verificationToken ) + { + // Not implemented since the Condenser automatically voids everything, and there are no updates + } + + @Override + public void removeListener( IMEMonitorHandlerReceiver l ) + { + // Not implemented since we don't remember registered listeners anyway + } } diff --git a/src/main/java/appeng/me/storage/VoidItemInventory.java b/src/main/java/appeng/tile/misc/CondenserItemInventory.java similarity index 73% rename from src/main/java/appeng/me/storage/VoidItemInventory.java rename to src/main/java/appeng/tile/misc/CondenserItemInventory.java index 57ed06fc..a782e2c5 100644 --- a/src/main/java/appeng/me/storage/VoidItemInventory.java +++ b/src/main/java/appeng/tile/misc/CondenserItemInventory.java @@ -16,25 +16,26 @@ * along with Applied Energistics 2. If not, see . */ -package appeng.me.storage; +package appeng.tile.misc; import appeng.api.config.AccessRestriction; import appeng.api.config.Actionable; import appeng.api.networking.security.BaseActionSource; -import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMonitorHandlerReceiver; import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; -import appeng.tile.misc.TileCondenser; +import appeng.util.item.ItemList; -public class VoidItemInventory implements IMEInventoryHandler +class CondenserItemInventory implements IMEMonitor { private final TileCondenser target; - public VoidItemInventory( final TileCondenser te ) + CondenserItemInventory( final TileCondenser te ) { this.target = te; } @@ -42,15 +43,11 @@ public class VoidItemInventory implements IMEInventoryHandler @Override public IAEItemStack injectItems( final IAEItemStack input, final Actionable mode, final BaseActionSource src ) { - if( mode == Actionable.SIMULATE ) - { - return null; - } - - if( input != null ) + if( mode == Actionable.MODULATE && input != null ) { this.target.addPower( input.getStackSize() ); } + return null; } @@ -66,6 +63,12 @@ public class VoidItemInventory implements IMEInventoryHandler return out; } + @Override + public IItemList getStorageList() + { + return new ItemList(); + } + @Override public StorageChannel getChannel() { @@ -107,4 +110,16 @@ public class VoidItemInventory implements IMEInventoryHandler { return i == 2; } + + @Override + public void addListener( IMEMonitorHandlerReceiver l, Object verificationToken ) + { + // Not implemented since the Condenser automatically voids everything, and there are no updates + } + + @Override + public void removeListener( IMEMonitorHandlerReceiver l ) + { + // Not implemented since we don't remember registered listeners anyway + } } diff --git a/src/main/java/appeng/tile/misc/TileCondenser.java b/src/main/java/appeng/tile/misc/TileCondenser.java index ebd80770..937192d4 100644 --- a/src/main/java/appeng/tile/misc/TileCondenser.java +++ b/src/main/java/appeng/tile/misc/TileCondenser.java @@ -19,22 +19,35 @@ package appeng.tile.misc; +import javax.annotation.Nullable; + import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; -import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTankInfo; -import net.minecraftforge.fluids.IFluidHandler; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.FluidTankProperties; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; import appeng.api.AEApi; import appeng.api.config.CondenserOutput; import appeng.api.config.Settings; import appeng.api.definitions.IMaterials; import appeng.api.implementations.items.IStorageComponent; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.IStorageMonitorableAccessor; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; import appeng.api.util.IConfigManager; import appeng.api.util.IConfigurableObject; +import appeng.capabilities.Capabilities; import appeng.tile.AEBaseInvTile; import appeng.tile.TileEvent; import appeng.tile.events.TileEventType; @@ -45,15 +58,20 @@ import appeng.util.IConfigManagerHost; import appeng.util.Platform; -public class TileCondenser extends AEBaseInvTile implements IFluidHandler, IConfigManagerHost, IConfigurableObject +public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost, IConfigurableObject { public static final int BYTE_MULTIPLIER = 8; - private static final FluidTankInfo[] EMPTY = { new FluidTankInfo( null, 10 ) }; - private final int[] sides = { 0, 1 }; + private final int[] sides = { + 0, + 1 + }; private final AppEngInternalInventory inv = new AppEngInternalInventory( this, 3 ); private final ConfigManager cm = new ConfigManager( this ); + private final IItemHandler itemHandler = new ItemHandler(); + private final IFluidHandler fluidHandler = new FluidHandler(); + private final MEHandler meHandler = new MEHandler(); private double storedPower = 0; @@ -222,47 +240,6 @@ public class TileCondenser extends AEBaseInvTile implements IFluidHandler, IConf return this.sides; } - @Override - public int fill( final EnumFacing from, final FluidStack resource, final boolean doFill ) - { - if( doFill ) - { - this.addPower( ( resource == null ? 0.0 : (double) resource.amount ) / 500.0 ); - } - - return resource == null ? 0 : resource.amount; - } - - @Override - public FluidStack drain( final EnumFacing from, final FluidStack resource, final boolean doDrain ) - { - return null; - } - - @Override - public FluidStack drain( final EnumFacing from, final int maxDrain, final boolean doDrain ) - { - return null; - } - - @Override - public boolean canFill( final EnumFacing from, final Fluid fluid ) - { - return true; - } - - @Override - public boolean canDrain( final EnumFacing from, final Fluid fluid ) - { - return false; - } - - @Override - public FluidTankInfo[] getTankInfo( final EnumFacing from ) - { - return EMPTY; - } - @Override public void updateSetting( final IConfigManager manager, final Enum settingName, final Enum newValue ) { @@ -284,4 +261,154 @@ public class TileCondenser extends AEBaseInvTile implements IFluidHandler, IConf { this.storedPower = storedPower; } + + @Override + public boolean hasCapability( Capability capability, EnumFacing facing ) + { + if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ) + { + return true; + } + else if( capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ) + { + return true; + } + else if( capability == Capabilities.STORAGE_MONITORABLE_ACCESSOR ) + { + return true; + } + return super.hasCapability( capability, facing ); + } + + @SuppressWarnings( "unchecked" ) + @Override + public T getCapability( Capability capability, @Nullable EnumFacing facing ) + { + if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ) + { + return (T) itemHandler; + } + else if( capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ) + { + return (T) fluidHandler; + } + else if( capability == Capabilities.STORAGE_MONITORABLE_ACCESSOR ) + { + return (T) meHandler; + } + return super.getCapability( capability, facing ); + } + + private class ItemHandler implements IItemHandler + { + + @Override + public int getSlots() + { + // We only expose the void slot + return 1; + } + + @Override + public ItemStack getStackInSlot( int slot ) + { + // The void slot never has any content + return null; + } + + @Override + public ItemStack insertItem( int slot, ItemStack stack, boolean simulate ) + { + if( slot != 0 ) + { + return stack; + } + if( !simulate && stack != null ) + { + addPower( stack.stackSize ); + } + return null; + } + + @Override + public ItemStack extractItem( int slot, int amount, boolean simulate ) + { + return null; + } + } + + + private static final IFluidTankProperties[] EMPTY = { new FluidTankProperties( null, 10, true, false ) }; + + + /** + * A fluid handler that exposes a 10 bucket tank that can only be filled, and - when filled - will add power + * to this condenser. + */ + private class FluidHandler implements IFluidHandler + { + + @Override + public IFluidTankProperties[] getTankProperties() + { + return EMPTY; + } + + @Override + public int fill( FluidStack resource, boolean doFill ) + { + if( doFill ) + { + addPower( ( resource == null ? 0.0 : (double) resource.amount ) / 500.0 ); + } + + return resource == null ? 0 : resource.amount; + } + + @Nullable + @Override + public FluidStack drain( FluidStack resource, boolean doDrain ) + { + return null; + } + + @Nullable + @Override + public FluidStack drain( int maxDrain, boolean doDrain ) + { + return null; + } + } + + + /** + * This is used to expose a fake ME subnetwork that is only composed of this condenser tile. The purpose of this is to enable the condenser to + * override the {@link appeng.api.storage.IMEInventoryHandler#validForPass(int)} method to make sure a condenser is only ever used if an item + * can't go anywhere else. + */ + private class MEHandler implements IStorageMonitorableAccessor, IStorageMonitorable + { + private final CondenserFluidInventory fluidInventory = new CondenserFluidInventory( TileCondenser.this ); + + private final CondenserItemInventory itemInventory = new CondenserItemInventory( TileCondenser.this ); + + @Nullable + @Override + public IStorageMonitorable getInventory( BaseActionSource src ) + { + return this; + } + + @Override + public IMEMonitor getItemInventory() + { + return itemInventory; + } + + @Override + public IMEMonitor getFluidInventory() + { + return fluidInventory; + } + } } diff --git a/src/main/java/appeng/tile/misc/TileInterface.java b/src/main/java/appeng/tile/misc/TileInterface.java index 03aa79be..3ec12854 100644 --- a/src/main/java/appeng/tile/misc/TileInterface.java +++ b/src/main/java/appeng/tile/misc/TileInterface.java @@ -40,7 +40,6 @@ import net.minecraftforge.common.capabilities.Capability; import appeng.api.config.Actionable; import appeng.api.config.Upgrades; -import appeng.api.implementations.tiles.ITileStorageMonitorable; import appeng.api.networking.IGridNode; import appeng.api.networking.crafting.ICraftingLink; import appeng.api.networking.crafting.ICraftingPatternDetails; @@ -71,7 +70,7 @@ import appeng.util.Platform; import appeng.util.inv.IInventoryDestination; -public class TileInterface extends AENetworkInvTile implements IGridTickable, ITileStorageMonitorable, IStorageMonitorable, IInventoryDestination, IInterfaceHost, IPriorityHost +public class TileInterface extends AENetworkInvTile implements IGridTickable, IInventoryDestination, IInterfaceHost, IPriorityHost { private final DualityInterface duality = new DualityInterface( this.getProxy(), this ); @@ -223,18 +222,6 @@ public class TileInterface extends AENetworkInvTile implements IGridTickable, IT return this.duality.canInsert( stack ); } - @Override - public IMEMonitor getItemInventory() - { - return this.duality.getItemInventory(); - } - - @Override - public IMEMonitor getFluidInventory() - { - return this.duality.getFluidInventory(); - } - @Override public IInventory getInventoryByName( final String name ) { @@ -293,12 +280,6 @@ public class TileInterface extends AENetworkInvTile implements IGridTickable, IT return this; } - @Override - public IStorageMonitorable getMonitorable( final EnumFacing side, final BaseActionSource src ) - { - return this.duality.getMonitorable( side, src, this ); - } - @Override public IConfigManager getConfigManager() { diff --git a/src/main/java/appeng/tile/storage/TileChest.java b/src/main/java/appeng/tile/storage/TileChest.java index dca430ca..4ba80666 100644 --- a/src/main/java/appeng/tile/storage/TileChest.java +++ b/src/main/java/appeng/tile/storage/TileChest.java @@ -22,6 +22,7 @@ package appeng.tile.storage; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.annotation.Nullable; import io.netty.buffer.ByteBuf; @@ -32,6 +33,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTankInfo; @@ -71,6 +73,7 @@ import appeng.api.storage.IMEInventoryHandler; import appeng.api.storage.IMEMonitor; import appeng.api.storage.IMEMonitorHandlerReceiver; import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.IStorageMonitorableAccessor; import appeng.api.storage.ITerminalHost; import appeng.api.storage.MEMonitorHandler; import appeng.api.storage.StorageChannel; @@ -79,6 +82,7 @@ import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack; import appeng.api.util.AEColor; import appeng.api.util.IConfigManager; +import appeng.capabilities.Capabilities; import appeng.helpers.IPriorityHost; import appeng.me.GridAccessException; import appeng.me.storage.MEInventoryHandler; @@ -113,6 +117,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, IFluidHan private ICellHandler cellHandler; private MEMonitorHandler itemCell; private MEMonitorHandler fluidCell; + private final Accessor accessor = new Accessor(); public TileChest() { @@ -771,16 +776,6 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, IFluidHan return null; } - @Override - public IStorageMonitorable getMonitorable( final EnumFacing side, final BaseActionSource src ) - { - if( Platform.canAccess( this.getProxy(), src ) && side != this.getForward() ) - { - return this; - } - return null; - } - public ItemStack getStorageType() { if( this.isPowered() ) @@ -991,4 +986,39 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, IFluidHan } } + @Override + public boolean hasCapability( Capability capability, EnumFacing facing ) + { + if( capability == Capabilities.STORAGE_MONITORABLE_ACCESSOR && facing != getForward() ) + { + return true; + } + return super.hasCapability( capability, facing ); + } + + @SuppressWarnings( "unchecked" ) + @Override + public T getCapability( Capability capability, @Nullable EnumFacing facing ) + { + if( capability == Capabilities.STORAGE_MONITORABLE_ACCESSOR && facing != getForward() ) + { + return (T) accessor; + } + return super.getCapability( capability, facing ); + } + + private class Accessor implements IStorageMonitorableAccessor + { + @Nullable + @Override + public IStorageMonitorable getInventory( BaseActionSource src ) + { + if( Platform.canAccess( getProxy(), src ) ) + { + return TileChest.this; + } + return null; + } + } + } diff --git a/src/main/java/appeng/util/InventoryAdaptor.java b/src/main/java/appeng/util/InventoryAdaptor.java index 624a4149..8c9a6939 100644 --- a/src/main/java/appeng/util/InventoryAdaptor.java +++ b/src/main/java/appeng/util/InventoryAdaptor.java @@ -27,12 +27,16 @@ import net.minecraft.inventory.ISidedInventory; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; import appeng.api.config.FuzzyMode; import appeng.integration.IntegrationRegistry; import appeng.integration.IntegrationType; import appeng.integration.abstraction.IBetterStorage; import appeng.util.inv.AdaptorIInventory; +import appeng.util.inv.AdaptorItemHandler; import appeng.util.inv.AdaptorList; import appeng.util.inv.AdaptorPlayerInventory; import appeng.util.inv.IInventoryDestination; @@ -40,6 +44,10 @@ import appeng.util.inv.ItemSlot; import appeng.util.inv.WrapperMCISidedInventory; +/** + * Universal Facade for other inventories. Used to conveniently interact with various types of inventories. This is not used for + * actually monitoring an inventory. It is just for insertion and extraction, and is primarily used by import/export buses. + */ public abstract class InventoryAdaptor implements Iterable { @@ -51,6 +59,18 @@ public abstract class InventoryAdaptor implements Iterable return null; } + if ( te instanceof ICapabilityProvider ) + { + ICapabilityProvider capProvider = (ICapabilityProvider) te; + + // Attempt getting an IItemHandler for the given side via caps + IItemHandler itemHandler = capProvider.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, d ); + if( itemHandler != null && itemHandler.getSlots() > 0 ) + { + return new AdaptorItemHandler( itemHandler ); + } + } + final IBetterStorage bs = (IBetterStorage) ( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.BetterStorage ) ? IntegrationRegistry.INSTANCE.getInstance( IntegrationType.BetterStorage ) : null ); if( te instanceof EntityPlayer ) diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index 866e108c..c9bb1a19 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -101,7 +101,6 @@ import appeng.api.definitions.IMaterials; import appeng.api.definitions.IParts; import appeng.api.implementations.items.IAEItemPowerStorage; import appeng.api.implementations.items.IAEWrench; -import appeng.api.implementations.tiles.ITileStorageMonitorable; import appeng.api.networking.IGrid; import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergyGrid; @@ -124,6 +123,7 @@ import appeng.api.storage.data.IItemList; import appeng.api.util.AEColor; import appeng.api.util.AEPartLocation; import appeng.api.util.DimensionalCoord; +import appeng.capabilities.Capabilities; import appeng.core.AEConfig; import appeng.core.AELog; import appeng.core.AppEng; @@ -1753,7 +1753,7 @@ public class Platform int hash = target.hashCode(); - if( target instanceof ITileStorageMonitorable ) + if( target.hasCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, null ) ) { return 0; } diff --git a/src/main/java/appeng/util/inv/AdaptorBCPipe.java b/src/main/java/appeng/util/inv/AdaptorBCPipe.java deleted file mode 100644 index da476396..00000000 --- a/src/main/java/appeng/util/inv/AdaptorBCPipe.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2015, 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.util.inv; - - -//public class AdaptorBCPipe extends InventoryAdaptor -//{ -// private final IBuildCraftTransport bc; -// private final TileEntity i; -// private final ForgeDirection d; -// -// public AdaptorBCPipe( TileEntity s, ForgeDirection dd ) -// { -// this.bc = (IBuildCraftTransport) IntegrationRegistry.INSTANCE.getInstance( IntegrationType.BC ); -// if( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.BuildCraftTransport ) ) -// { -// if( this.bc.isPipe( s, dd ) ) -// { -// this.i = s; -// this.d = dd; -// return; -// } -// } -// this.i = null; -// this.d = null; -// } -// -// @Override -// public ItemStack removeItems( int amount, ItemStack filter, IInventoryDestination destination ) -// { -// return null; -// } -// -// @Override -// public ItemStack simulateRemove( int amount, ItemStack filter, IInventoryDestination destination ) -// { -// return null; -// } -// -// @Override -// public ItemStack removeSimilarItems( int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination ) -// { -// return null; -// } -// -// @Override -// public ItemStack simulateSimilarRemove( int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination ) -// { -// return null; -// } -// -// @Override -// public ItemStack addItems( ItemStack toBeAdded ) -// { -// if( this.i == null ) -// { -// return toBeAdded; -// } -// if( toBeAdded == null ) -// { -// return null; -// } -// if( toBeAdded.stackSize == 0 ) -// { -// return null; -// } -// -// if( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.BuildCraftTransport ) && this.bc.addItemsToPipe( this.i, toBeAdded, this.d ) ) -// { -// return null; -// } -// return toBeAdded; -// } -// -// @Override -// public ItemStack simulateAdd( ItemStack toBeSimulated ) -// { -// if( this.i == null ) -// { -// return toBeSimulated; -// } -// return null; -// } -// -// @Override -// public boolean containsItems() -// { -// return false; -// } -// -// @Override -// public Iterator iterator() -// { -// return new NullIterator(); -// } -// } diff --git a/src/main/java/appeng/util/inv/AdaptorItemHandler.java b/src/main/java/appeng/util/inv/AdaptorItemHandler.java new file mode 100644 index 00000000..12fb68aa --- /dev/null +++ b/src/main/java/appeng/util/inv/AdaptorItemHandler.java @@ -0,0 +1,265 @@ +/* + * 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.util.inv; + + +import java.util.Iterator; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +import appeng.api.config.FuzzyMode; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; + + +public class AdaptorItemHandler extends InventoryAdaptor +{ + private final IItemHandler itemHandler; + + public AdaptorItemHandler( IItemHandler itemHandler ) + { + this.itemHandler = itemHandler; + } + + @Override + public ItemStack removeItems( int amount, ItemStack filter, IInventoryDestination destination ) + { + int slots = itemHandler.getSlots(); + ItemStack rv = null; + + for( int slot = 0; slot < slots && amount > 0; slot++ ) + { + final ItemStack is = itemHandler.getStackInSlot( slot ); + if( is == null || ( filter != null && !Platform.isSameItemPrecise( is, filter ) ) ) + { + continue; + } + + if( destination != null ) + { + ItemStack extracted = itemHandler.extractItem( slot, amount, true ); + if( extracted == null ) + { + continue; + } + + if( !destination.canInsert( extracted ) ) + { + continue; + } + } + + // Attempt extracting it + ItemStack extracted = itemHandler.extractItem( slot, amount, false ); + + if( extracted == null ) + { + continue; + } + + if( rv == null ) + { + // Use the first stack as a template for the result + rv = extracted; + filter = extracted; + amount -= extracted.stackSize; + } + else + { + // Subsequent stacks will just increase the extracted size + rv.stackSize += extracted.stackSize; + amount -= extracted.stackSize; + } + } + + return rv; + } + + @Override + public ItemStack simulateRemove( int amount, ItemStack filter, IInventoryDestination destination ) + { + int slots = itemHandler.getSlots(); + ItemStack rv = null; + + for( int slot = 0; slot < slots && amount > 0; slot++ ) + { + final ItemStack is = itemHandler.getStackInSlot( slot ); + if( is != null && ( filter == null || Platform.isSameItemPrecise( is, filter ) ) ) + { + ItemStack extracted = itemHandler.extractItem( slot, amount, true ); + + if( extracted == null ) + { + continue; + } + + if( destination != null ) + { + if( !destination.canInsert( extracted ) ) + { + continue; + } + } + + if( rv == null ) + { + // Use the first stack as a template for the result + rv = extracted.copy(); + filter = extracted; + amount -= extracted.stackSize; + } + else + { + // Subsequent stacks will just increase the extracted size + rv.stackSize += extracted.stackSize; + amount -= extracted.stackSize; + } + } + } + + return rv; + } + + /** + * For fuzzy extract, we will only ever extract one slot, since we're afraid of merging two item stacks with different damage values. + */ + @Override + public ItemStack removeSimilarItems( int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination ) + { + int slots = itemHandler.getSlots(); + ItemStack extracted = null; + + for( int slot = 0; slot < slots && extracted == null; slot++ ) + { + final ItemStack is = itemHandler.getStackInSlot( slot ); + if( is == null || ( filter != null && !Platform.isSameItemFuzzy( is, filter, fuzzyMode ) ) ) + { + continue; + } + + if( destination != null ) + { + ItemStack simulated = itemHandler.extractItem( slot, amount, true ); + if( simulated == null ) + { + continue; + } + + if( !destination.canInsert( simulated ) ) + { + continue; + } + } + + // Attempt extracting it + extracted = itemHandler.extractItem( slot, amount, false ); + } + + return extracted; + } + + @Override + public ItemStack simulateSimilarRemove( int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination ) + { + int slots = itemHandler.getSlots(); + ItemStack extracted = null; + + for( int slot = 0; slot < slots && extracted == null; slot++ ) + { + final ItemStack is = itemHandler.getStackInSlot( slot ); + if( is == null || ( filter != null && !Platform.isSameItemFuzzy( is, filter, fuzzyMode ) ) ) + { + continue; + } + + // Attempt extracting it + extracted = itemHandler.extractItem( slot, amount, true ); + + if( extracted != null && destination != null ) + { + if( !destination.canInsert( extracted ) ) + { + extracted = null; // Keep on looking... + } + } + } + + return extracted; + } + + @Override + public ItemStack addItems( ItemStack toBeAdded ) + { + return addItems( toBeAdded, false ); + } + + @Override + public ItemStack simulateAdd( ItemStack toBeSimulated ) + { + return addItems( toBeSimulated, true ); + } + + private ItemStack addItems( final ItemStack itemsToAdd, final boolean simulate ) + { + if( itemsToAdd == null || itemsToAdd.stackSize == 0 ) + { + return null; + } + + ItemStack left = itemsToAdd.copy(); + + for( int slot = 0; slot < itemHandler.getSlots(); slot++ ) + { + ItemStack is = itemHandler.getStackInSlot( slot ); + + if( is == null || Platform.isSameItemPrecise( is, left ) ) + { + left = itemHandler.insertItem( slot, left, simulate ); + + if( left == null || left.stackSize <= 0 ) + { + return null; + } + } + } + + return left; + } + + @Override + public boolean containsItems() + { + int slots = itemHandler.getSlots(); + for( int slot = 0; slot < slots; slot++ ) + { + if( itemHandler.getStackInSlot( slot ) != null ) + { + return true; + } + } + return false; + } + + @Override + public Iterator iterator() + { + return new ItemHandlerIterator( itemHandler ); + } +} diff --git a/src/main/java/appeng/util/inv/ItemHandlerIterator.java b/src/main/java/appeng/util/inv/ItemHandlerIterator.java new file mode 100644 index 00000000..714aab3a --- /dev/null +++ b/src/main/java/appeng/util/inv/ItemHandlerIterator.java @@ -0,0 +1,62 @@ +/* + * 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.util.inv; + + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import net.minecraftforge.items.IItemHandler; + + +class ItemHandlerIterator implements Iterator +{ + + private final IItemHandler itemHandler; + + private final ItemSlot itemSlot = new ItemSlot(); + + private int slot = 0; + + ItemHandlerIterator( IItemHandler itemHandler ) + { + this.itemHandler = itemHandler; + } + + @Override + public boolean hasNext() + { + return slot < itemHandler.getSlots(); + } + + @Override + public ItemSlot next() + { + if( slot >= itemHandler.getSlots() ) + { + throw new NoSuchElementException(); + } + itemSlot.setExtractable( itemHandler.extractItem( slot, 1, true ) != null ); + itemSlot.setItemStack( itemHandler.getStackInSlot( slot ) ); + itemSlot.setSlot( slot ); + slot++; + return itemSlot; + } + +} diff --git a/src/main/java/appeng/util/inv/WrapperTEPipe.java b/src/main/java/appeng/util/inv/WrapperTEPipe.java deleted file mode 100644 index ccf8ec42..00000000 --- a/src/main/java/appeng/util/inv/WrapperTEPipe.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.util.inv; - - -//public class WrapperTEPipe implements IInventory -//{ -// -// final TileEntity ad; -// final ForgeDirection dir; -// -// public WrapperTEPipe( TileEntity te, ForgeDirection d ) -// { -// this.ad = te; -// this.dir = d; -// } -// -// @Override -// public int getSizeInventory() -// { -// return 1; -// } -// -// @Override -// public ItemStack getStackInSlot( int i ) -// { -// return null; -// } -// -// @Override -// public ItemStack decrStackSize( int i, int j ) -// { -// return null; -// } -// -// @Override -// public ItemStack getStackInSlotOnClosing( int i ) -// { -// return null; -// } -// -// @Override -// public void setInventorySlotContents( int i, ItemStack itemstack ) -// { -// // ITE.addItemsToPipe( ad, itemstack, dir ); -// } -// -// @Override -// public String getInventoryName() -// { -// return null; -// } -// -// @Override -// public boolean hasCustomInventoryName() -// { -// return false; -// } -// -// @Override -// public int getInventoryStackLimit() -// { -// return 64; -// } -// -// @Override -// public void markDirty() -// { -// -// } -// -// @Override -// public boolean isUseableByPlayer( EntityPlayer entityplayer ) -// { -// return false; -// } -// -// @Override -// public void openInventory() -// { -// -// } -// -// @Override -// public void closeInventory() -// { -// -// } -// -// @Override -// public boolean isItemValidForSlot( int i, ItemStack itemstack ) -// { -// return false; -// } -// }