diff --git a/parts/layers/InvSot.java b/parts/layers/InvSot.java new file mode 100644 index 000000000..320a72196 --- /dev/null +++ b/parts/layers/InvSot.java @@ -0,0 +1,47 @@ +package appeng.api.parts.layers; + +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; + +public class InvSot +{ + + final public ISidedInventory partInv; + final public int index; + + public InvSot(ISidedInventory part, int slot) { + partInv = part; + index = slot; + } + + public ItemStack decrStackSize(int j) + { + return partInv.decrStackSize( index, j ); + } + + public ItemStack getStackInSlot() + { + return partInv.getStackInSlot( index ); + } + + public boolean isItemValidForSlot(ItemStack itemstack) + { + return partInv.isItemValidForSlot( index, itemstack ); + } + + public void setInventorySlotContents(ItemStack itemstack) + { + partInv.setInventorySlotContents( index, itemstack ); + } + + public boolean canExtractItem(ItemStack itemstack, int side) + { + return partInv.canExtractItem( index, itemstack, side ); + } + + public boolean canInsertItem(ItemStack itemstack, int side) + { + return partInv.canInsertItem( index, itemstack, side ); + } + +} diff --git a/parts/layers/LayerIBatteryProvider.java b/parts/layers/LayerIBatteryProvider.java new file mode 100644 index 000000000..99d990ee0 --- /dev/null +++ b/parts/layers/LayerIBatteryProvider.java @@ -0,0 +1,23 @@ +package appeng.api.parts.layers; + +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.LayerBase; +import buildcraft.api.mj.IBatteryObject; +import buildcraft.api.mj.ISidedBatteryProvider; + +public class LayerIBatteryProvider extends LayerBase implements ISidedBatteryProvider +{ + + @Override + public IBatteryObject getMjBattery(String kind, ForgeDirection direction) + { + IPart p = getPart( direction ); + + if ( p instanceof ISidedBatteryProvider ) + return ((ISidedBatteryProvider) p).getMjBattery( kind, direction ); + + return null; + } + +} diff --git a/parts/layers/LayerIEnergyHandler.java b/parts/layers/LayerIEnergyHandler.java new file mode 100644 index 000000000..6b6b71f8d --- /dev/null +++ b/parts/layers/LayerIEnergyHandler.java @@ -0,0 +1,61 @@ +package appeng.api.parts.layers; + +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.LayerBase; +import cofh.api.energy.IEnergyHandler; + +public class LayerIEnergyHandler extends LayerBase implements IEnergyHandler +{ + + @Override + public int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate) + { + IPart part = getPart( from ); + if ( part instanceof IEnergyHandler ) + return ((IEnergyHandler) part).receiveEnergy( from, maxReceive, simulate ); + + return 0; + } + + @Override + public int extractEnergy(ForgeDirection from, int maxExtract, boolean simulate) + { + IPart part = getPart( from ); + if ( part instanceof IEnergyHandler ) + return ((IEnergyHandler) part).extractEnergy( from, maxExtract, simulate ); + + return 0; + } + + @Override + public int getEnergyStored(ForgeDirection from) + { + IPart part = getPart( from ); + if ( part instanceof IEnergyHandler ) + return ((IEnergyHandler) part).getEnergyStored( from ); + + return 0; + } + + @Override + public int getMaxEnergyStored(ForgeDirection from) + { + IPart part = getPart( from ); + if ( part instanceof IEnergyHandler ) + return ((IEnergyHandler) part).getMaxEnergyStored( from ); + + return 0; + } + + @Override + public boolean canConnectEnergy(ForgeDirection from) + { + IPart part = getPart( from ); + if ( part instanceof IEnergyHandler ) + return ((IEnergyHandler) part).canConnectEnergy( from ); + + return false; + } + +} diff --git a/parts/layers/LayerIEnergySink.java b/parts/layers/LayerIEnergySink.java new file mode 100644 index 000000000..cbb47e63f --- /dev/null +++ b/parts/layers/LayerIEnergySink.java @@ -0,0 +1,146 @@ +package appeng.api.parts.layers; + +import ic2.api.energy.tile.IEnergySink; +import ic2.api.energy.tile.IEnergyTile; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; +import appeng.api.parts.LayerBase; +import appeng.api.parts.LayerFlags; +import appeng.util.Platform; + +public class LayerIEnergySink extends LayerBase implements IEnergySink +{ + + private boolean isInIC2() + { + return getLayerFlags().contains( LayerFlags.IC2_ENET ); + } + + private TileEntity getEnergySinkTile() + { + IPartHost host = (IPartHost) this; + return host.getTile(); + } + + private World getEnergySinkWorld() + { + if ( getEnergySinkTile() == null ) + return null; + + return getEnergySinkTile().getWorldObj(); + } + + final private void addToENet() + { + if ( getEnergySinkWorld() == null ) + return; + + // re-add + removeFromENet(); + + if ( !isInIC2() && Platform.isServer() ) + { + getLayerFlags().add( LayerFlags.IC2_ENET ); + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileLoadEvent( (IEnergySink) getEnergySinkTile() ) ); + } + } + + final private void removeFromENet() + { + if ( getEnergySinkWorld() == null ) + return; + + if ( isInIC2() && Platform.isServer() ) + { + getLayerFlags().remove( LayerFlags.IC2_ENET ); + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileUnloadEvent( (IEnergySink) getEnergySinkTile() ) ); + } + } + + final private boolean interestedInIC2() + { + int interested = 0; + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + IPart part = getPart( dir ); + if ( part instanceof IEnergyTile ) + { + interested++; + } + } + return interested == 1;// if more then one tile is interested we need to abandonship... + } + + @Override + public void partChanged() + { + super.partChanged(); + + if ( interestedInIC2() ) + addToENet(); + else + removeFromENet(); + } + + @Override + public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) + { + if ( !isInIC2() ) + return false; + + IPart part = getPart( direction ); + if ( part instanceof IEnergySink ) + return ((IEnergySink) part).acceptsEnergyFrom( emitter, direction ); + return false; + } + + @Override + public double demandedEnergyUnits() + { + if ( !isInIC2() ) + return 0; + + // this is a flawed implementation, that requires a change to the IC2 API. + + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + IPart part = getPart( dir ); + if ( part instanceof IEnergySink ) + { + // use lower number cause ic2 deletes power it sends that isn't recieved. + return ((IEnergySink) part).demandedEnergyUnits(); + } + } + + return 0; + } + + @Override + public double injectEnergyUnits(ForgeDirection directionFrom, double amount) + { + if ( !isInIC2() ) + return amount; + + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + IPart part = getPart( dir ); + if ( part instanceof IEnergySink ) + { + return ((IEnergySink) part).injectEnergyUnits( directionFrom, amount ); + } + } + + return amount; + } + + @Override + public int getMaxSafeInput() + { + return Integer.MAX_VALUE; // no real options here... + } + +} diff --git a/parts/layers/LayerIEnergySource.java b/parts/layers/LayerIEnergySource.java new file mode 100644 index 000000000..255988e20 --- /dev/null +++ b/parts/layers/LayerIEnergySource.java @@ -0,0 +1,139 @@ +package appeng.api.parts.layers; + +import ic2.api.energy.tile.IEnergyEmitter; +import ic2.api.energy.tile.IEnergySink; +import ic2.api.energy.tile.IEnergySource; +import ic2.api.energy.tile.IEnergyTile; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; +import appeng.api.parts.LayerBase; +import appeng.api.parts.LayerFlags; +import appeng.util.Platform; + +public class LayerIEnergySource extends LayerBase implements IEnergySource +{ + + private boolean isInIC2() + { + return getLayerFlags().contains( LayerFlags.IC2_ENET ); + } + + private TileEntity getEnergySourceTile() + { + IPartHost host = (IPartHost) this; + return host.getTile(); + } + + private World getEnergySourceWorld() + { + if ( getEnergySourceTile() == null ) + return null; + return getEnergySourceTile().getWorldObj(); + } + + final private void addToENet() + { + if ( getEnergySourceWorld() == null ) + return; + + // re-add + removeFromENet(); + + if ( !isInIC2() && Platform.isServer() ) + { + getLayerFlags().add( LayerFlags.IC2_ENET ); + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileLoadEvent( (IEnergySink) getEnergySourceTile() ) ); + } + } + + final private void removeFromENet() + { + if ( getEnergySourceWorld() == null ) + return; + + if ( isInIC2() && Platform.isServer() ) + { + getLayerFlags().remove( LayerFlags.IC2_ENET ); + MinecraftForge.EVENT_BUS.post( new ic2.api.energy.event.EnergyTileUnloadEvent( (IEnergySink) getEnergySourceTile() ) ); + } + } + + final private boolean interestedInIC2() + { + int interested = 0; + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + IPart part = getPart( dir ); + if ( part instanceof IEnergyTile ) + { + interested++; + } + } + return interested == 1;// if more then one tile is interested we need to abandonship... + } + + @Override + public void partChanged() + { + super.partChanged(); + + if ( interestedInIC2() ) + addToENet(); + else + removeFromENet(); + } + + @Override + public boolean emitsEnergyTo(TileEntity receiver, ForgeDirection direction) + { + if ( !isInIC2() ) + return false; + + IPart part = getPart( direction ); + if ( part instanceof IEnergySink ) + return ((IEnergyEmitter) part).emitsEnergyTo( receiver, direction ); + return false; + } + + @Override + public double getOfferedEnergy() + { + if ( !isInIC2() ) + return 0; + + // this is a flawed implementation, that requires a change to the IC2 API. + + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + IPart part = getPart( dir ); + if ( part instanceof IEnergySource ) + { + // use lower number cause ic2 deletes power it sends that isn't recieved. + return ((IEnergySource) part).getOfferedEnergy(); + } + } + + return 0; + } + + @Override + public void drawEnergy(double amount) + { + // this is a flawed implementation, that requires a change to the IC2 API. + + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) + { + IPart part = getPart( dir ); + if ( part instanceof IEnergySource ) + { + ((IEnergySource) part).drawEnergy( amount ); + return; + } + } + } + +} diff --git a/parts/layers/LayerIFluidHandler.java b/parts/layers/LayerIFluidHandler.java new file mode 100644 index 000000000..96168f2b2 --- /dev/null +++ b/parts/layers/LayerIFluidHandler.java @@ -0,0 +1,69 @@ +package appeng.api.parts.layers; + +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidHandler; +import appeng.api.parts.IPart; +import appeng.api.parts.LayerBase; + +public class LayerIFluidHandler extends LayerBase implements IFluidHandler +{ + + static final FluidTankInfo[] emptyList = new FluidTankInfo[0]; + + @Override + public int fill(ForgeDirection from, FluidStack resource, boolean doFill) + { + IPart part = getPart( from ); + if ( part instanceof IFluidHandler ) + return ((IFluidHandler) part).fill( from, resource, doFill ); + return 0; + } + + @Override + public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) + { + IPart part = getPart( from ); + if ( part instanceof IFluidHandler ) + return ((IFluidHandler) part).drain( from, resource, doDrain ); + return null; + } + + @Override + public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) + { + IPart part = getPart( from ); + if ( part instanceof IFluidHandler ) + return ((IFluidHandler) part).drain( from, maxDrain, doDrain ); + return null; + } + + @Override + public boolean canFill(ForgeDirection from, net.minecraftforge.fluids.Fluid fluid) + { + IPart part = getPart( from ); + if ( part instanceof IFluidHandler ) + return ((IFluidHandler) part).canFill( from, fluid ); + return false; + } + + @Override + public boolean canDrain(ForgeDirection from, net.minecraftforge.fluids.Fluid fluid) + { + IPart part = getPart( from ); + if ( part instanceof IFluidHandler ) + return ((IFluidHandler) part).canDrain( from, fluid ); + return false; + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection from) + { + IPart part = getPart( from ); + if ( part instanceof IFluidHandler ) + return ((IFluidHandler) part).getTankInfo( from ); + return emptyList; + } + +} diff --git a/parts/layers/LayerIPipeConnection.java b/parts/layers/LayerIPipeConnection.java new file mode 100644 index 000000000..bbe939f59 --- /dev/null +++ b/parts/layers/LayerIPipeConnection.java @@ -0,0 +1,21 @@ +package appeng.api.parts.layers; + +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.LayerBase; +import buildcraft.api.transport.IPipeConnection; +import buildcraft.api.transport.IPipeTile.PipeType; + +public class LayerIPipeConnection extends LayerBase implements IPipeConnection +{ + + @Override + public ConnectOverride overridePipeConnection(PipeType type, ForgeDirection with) + { + IPart part = getPart( with ); + if ( part instanceof IPipeConnection ) + return ((IPipeConnection) part).overridePipeConnection( type, with ); + return ConnectOverride.DEFAULT; + } + +} diff --git a/parts/layers/LayerIPowerEmitter.java b/parts/layers/LayerIPowerEmitter.java new file mode 100644 index 000000000..2d7b34077 --- /dev/null +++ b/parts/layers/LayerIPowerEmitter.java @@ -0,0 +1,19 @@ +package appeng.api.parts.layers; + +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.LayerBase; +import buildcraft.api.power.IPowerEmitter; + +public class LayerIPowerEmitter extends LayerBase implements IPowerEmitter +{ + + @Override + public boolean canEmitPowerFrom(ForgeDirection side) + { + IPart part = getPart( side ); + if ( part instanceof IPowerEmitter ) + return ((IPowerEmitter) part).canEmitPowerFrom( side ); + return false; + } +} diff --git a/parts/layers/LayerIPowerReceptor.java b/parts/layers/LayerIPowerReceptor.java new file mode 100644 index 000000000..f82d658cf --- /dev/null +++ b/parts/layers/LayerIPowerReceptor.java @@ -0,0 +1,36 @@ +package appeng.api.parts.layers; + +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; +import appeng.api.parts.LayerBase; +import buildcraft.api.power.IPowerReceptor; +import buildcraft.api.power.PowerHandler; +import buildcraft.api.power.PowerHandler.PowerReceiver; + +public class LayerIPowerReceptor extends LayerBase implements IPowerReceptor +{ + + @Override + public PowerReceiver getPowerReceiver(ForgeDirection side) + { + IPart part = getPart( side ); + if ( part instanceof IPowerReceptor ) + return ((IPowerReceptor) part).getPowerReceiver( side ); + return null; + } + + @Override + public void doWork(PowerHandler workProvider) + { + // do nothing, this seems pointless. + } + + @Override + public World getWorld() + { + return ((IPartHost) this).getTile().getWorldObj(); + } + +} diff --git a/parts/layers/LayerISidedInventory.java b/parts/layers/LayerISidedInventory.java new file mode 100644 index 000000000..7a96b8c0b --- /dev/null +++ b/parts/layers/LayerISidedInventory.java @@ -0,0 +1,228 @@ +package appeng.api.parts.layers; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.ForgeDirection; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartHost; +import appeng.api.parts.LayerBase; + +/** + * Inventory wrapper for parts, + * + * this is considerably more complicated then the other wrappers as it requires creating a "unified inventory". + * + * You must use {@link ISidedInventory} instead of {@link IInventory}. + * + * If your inventory changes in between placement and removal, you must trigger a PartChange on the {@link IPartHost} so + * it can recalculate the inventory wrapper. + */ +public class LayerISidedInventory extends LayerBase implements ISidedInventory +{ + + // a simple empty array for empty stuff.. + private final static int[] nullSides = new int[] {}; + + // cache of inventory state. + private int sides[][] = null; + private List invs = null; + private List slots = null; + + /** + * Recalculate inventory wrapper cache. + */ + @Override + public void partChanged() + { + invs = new ArrayList(); + int slotCount = 0; + + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + { + IPart bp = getPart( side ); + if ( bp instanceof ISidedInventory ) + { + ISidedInventory part = (ISidedInventory) bp; + slotCount += part.getSizeInventory(); + invs.add( part ); + } + } + + if ( invs.isEmpty() || slotCount == 0 ) + { + invs = null; + sides = null; + slots = null; + } + else + { + sides = new int[][] { nullSides, nullSides, nullSides, nullSides, nullSides, nullSides }; + slots = new ArrayList( Collections.nCopies( slotCount, (InvSot) null ) ); + + int offsetForLayer = 0; + int offsetForPart = 0; + for (ISidedInventory sides : invs) + { + offsetForPart = 0; + slotCount = sides.getSizeInventory(); + + ForgeDirection currentSide = ForgeDirection.UNKNOWN; + for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) + if ( getPart( side ) == sides ) + { + currentSide = side; + break; + } + + int cSidesList[] = this.sides[currentSide.ordinal()] = new int[slotCount]; + for (int cSlot = 0; cSlot < slotCount; cSlot++) + { + cSidesList[cSlot] = offsetForLayer; + slots.set( offsetForLayer++, new InvSot( sides, offsetForPart++ ) ); + } + } + } + + // make sure inventory is updated before we call FMP. + super.partChanged(); + } + + /** + * check if a slot index is valid, prevent crashes from bad code :) + * + * @param slot + * @return true, if the slot exists. + */ + boolean isSlotValid(int slot) + { + return slots != null && slot >= 0 && slot < slots.size(); + } + + @Override + public ItemStack decrStackSize(int slot, int amount) + { + if ( isSlotValid( slot ) ) + return slots.get( slot ).decrStackSize( amount ); + + return null; + } + + @Override + public int getSizeInventory() + { + if ( slots == null ) + return 0; + + return slots.size(); + } + + @Override + public ItemStack getStackInSlot(int slot) + { + if ( isSlotValid( slot ) ) + return slots.get( slot ).getStackInSlot(); + + return null; + } + + @Override + public boolean isItemValidForSlot(int slot, ItemStack itemstack) + { + if ( isSlotValid( slot ) ) + return slots.get( slot ).isItemValidForSlot( itemstack ); + + return false; + } + + @Override + public void setInventorySlotContents(int slot, ItemStack itemstack) + { + if ( isSlotValid( slot ) ) + slots.get( slot ).setInventorySlotContents( itemstack ); + } + + @Override + public boolean canExtractItem(int slot, ItemStack itemstack, int side) + { + if ( isSlotValid( slot ) ) + return slots.get( slot ).canExtractItem( itemstack, side ); + + return false; + } + + @Override + public boolean canInsertItem(int slot, ItemStack itemstack, int side) + { + if ( isSlotValid( slot ) ) + return slots.get( slot ).canInsertItem( itemstack, side ); + + return false; + } + + @Override + public void markDirty() + { + super.markForSave(); + + if ( invs != null ) + { + for (IInventory inv : invs) + inv.markDirty(); + } + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + if ( sides == null || side < 0 || side > 5 ) + return nullSides; + return sides[side]; + } + + @Override + public int getInventoryStackLimit() + { + return 64; // no options here. + } + + @Override + public String getInventoryName() + { + return "AEMultiPart"; + } + + @Override + public boolean hasCustomInventoryName() + { + return false; + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) + { + return null; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer entityplayer) + { + return false; + } + + @Override + public void closeInventory() + { + } + + @Override + public void openInventory() + { + } + +} diff --git a/parts/layers/LayerITileStorageMonitorable.java b/parts/layers/LayerITileStorageMonitorable.java new file mode 100644 index 000000000..7ebf8ee7e --- /dev/null +++ b/parts/layers/LayerITileStorageMonitorable.java @@ -0,0 +1,22 @@ +package appeng.api.parts.layers; + +import net.minecraftforge.common.util.ForgeDirection; +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; + +public class LayerITileStorageMonitorable extends LayerBase implements ITileStorageMonitorable +{ + + @Override + public IStorageMonitorable getMonitorable(ForgeDirection side, BaseActionSource src) + { + IPart part = getPart( side ); + if ( part instanceof ITileStorageMonitorable ) + return ((ITileStorageMonitorable) part).getMonitorable( side, src ); + return null; + } + +}