From 54e66540783cad9e0c094e1b6f98bf58feb16359 Mon Sep 17 00:00:00 2001 From: GlodBlock <1356392126@qq.com> Date: Wed, 11 May 2022 18:32:49 +0800 Subject: [PATCH] fluid cells --- README.MD | 4 +- .../java/com/glodblock/github/FluidCraft.java | 5 + .../item/ItemBasicFluidStorageCell.java | 326 ++++++++++++ .../item/ItemBasicFluidStoragePart.java | 64 +++ .../github/common/storage/CellType.java | 59 +++ .../common/storage/FluidCellHandler.java | 69 +++ .../common/storage/FluidCellInventory.java | 486 ++++++++++++++++++ .../storage/FluidCellInventoryHandler.java | 80 +++ .../common/storage/IFluidCellInventory.java | 74 +++ .../storage/IFluidCellInventoryHandler.java | 13 + .../common/storage/IStorageFluidCell.java | 23 + .../github/loader/ItemAndBlockHolder.java | 24 +- .../com/glodblock/github/util/Ae2Reflect.java | 28 +- .../com/glodblock/github/util/NameConst.java | 2 + .../java/com/glodblock/github/util/Util.java | 5 + .../resources/assets/ae2fc/lang/en_US.lang | 14 + .../ae2fc/textures/items/fluid_part.0.png | Bin 0 -> 205 bytes .../ae2fc/textures/items/fluid_part.1.png | Bin 0 -> 220 bytes .../ae2fc/textures/items/fluid_part.2.png | Bin 0 -> 232 bytes .../ae2fc/textures/items/fluid_part.3.png | Bin 0 -> 302 bytes .../ae2fc/textures/items/fluid_part.4.png | Bin 0 -> 382 bytes .../ae2fc/textures/items/fluid_part.5.png | Bin 0 -> 523 bytes .../ae2fc/textures/items/fluid_part.6.png | Bin 0 -> 536 bytes .../ae2fc/textures/items/fluid_storage.1.png | Bin 0 -> 345 bytes .../textures/items/fluid_storage.1024.png | Bin 0 -> 342 bytes .../ae2fc/textures/items/fluid_storage.16.png | Bin 0 -> 376 bytes .../textures/items/fluid_storage.256.png | Bin 0 -> 336 bytes .../ae2fc/textures/items/fluid_storage.4.png | Bin 0 -> 360 bytes .../textures/items/fluid_storage.4096.png | Bin 0 -> 371 bytes .../ae2fc/textures/items/fluid_storage.64.png | Bin 0 -> 344 bytes 30 files changed, 1254 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/glodblock/github/common/item/ItemBasicFluidStorageCell.java create mode 100644 src/main/java/com/glodblock/github/common/item/ItemBasicFluidStoragePart.java create mode 100644 src/main/java/com/glodblock/github/common/storage/CellType.java create mode 100644 src/main/java/com/glodblock/github/common/storage/FluidCellHandler.java create mode 100644 src/main/java/com/glodblock/github/common/storage/FluidCellInventory.java create mode 100644 src/main/java/com/glodblock/github/common/storage/FluidCellInventoryHandler.java create mode 100644 src/main/java/com/glodblock/github/common/storage/IFluidCellInventory.java create mode 100644 src/main/java/com/glodblock/github/common/storage/IFluidCellInventoryHandler.java create mode 100644 src/main/java/com/glodblock/github/common/storage/IStorageFluidCell.java create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_part.0.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_part.1.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_part.2.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_part.3.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_part.4.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_part.5.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_part.6.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_storage.1.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_storage.1024.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_storage.16.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_storage.256.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_storage.4.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_storage.4096.png create mode 100644 src/main/resources/assets/ae2fc/textures/items/fluid_storage.64.png diff --git a/README.MD b/README.MD index 635f9a92..c3709f96 100644 --- a/README.MD +++ b/README.MD @@ -69,6 +69,6 @@ E. Geng(@phantamanta44) and KilaBash (@Yefancy) - Their amazing origin work in 1 ## To-Do - -[ ] Port to 1.12, with supporting for PAE2 + - [ ] Port to 1.12, with supporting for PAE2 - -[ ] Port to 1.16.5 + - [ ] Port to 1.16.5 diff --git a/src/main/java/com/glodblock/github/FluidCraft.java b/src/main/java/com/glodblock/github/FluidCraft.java index 99a78e43..3f2c51af 100644 --- a/src/main/java/com/glodblock/github/FluidCraft.java +++ b/src/main/java/com/glodblock/github/FluidCraft.java @@ -1,7 +1,10 @@ package com.glodblock.github; +import appeng.api.AEApi; +import com.glodblock.github.common.storage.FluidCellHandler; import com.glodblock.github.inventory.InventoryHandler; import com.glodblock.github.loader.ChannelLoader; +import com.glodblock.github.loader.ItemAndBlockHolder; import com.glodblock.github.loader.ListenerLoader; import com.glodblock.github.loader.RenderLoader; import com.glodblock.github.nei.recipes.DefaultExtractorLoader; @@ -40,6 +43,8 @@ public class FluidCraft { (new RenderLoader()).run(); (new ListenerLoader()).run(); ModAndClassUtil.init(); + AEApi.instance().registries().cell().addCellHandler(new FluidCellHandler()); + ItemAndBlockHolder.loadSetting(); proxy.init(event); } diff --git a/src/main/java/com/glodblock/github/common/item/ItemBasicFluidStorageCell.java b/src/main/java/com/glodblock/github/common/item/ItemBasicFluidStorageCell.java new file mode 100644 index 00000000..fe745218 --- /dev/null +++ b/src/main/java/com/glodblock/github/common/item/ItemBasicFluidStorageCell.java @@ -0,0 +1,326 @@ +package com.glodblock.github.common.item; + +import appeng.api.AEApi; +import appeng.api.config.FuzzyMode; +import appeng.api.config.IncludeExclude; +import appeng.api.exceptions.MissingDefinition; +import appeng.api.implementations.items.IUpgradeModule; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.core.AEConfig; +import appeng.core.features.AEFeature; +import appeng.core.localization.GuiText; +import appeng.items.AEBaseItem; +import appeng.items.contents.CellConfig; +import appeng.items.contents.CellUpgrades; +import appeng.util.InventoryAdaptor; +import appeng.util.Platform; +import com.glodblock.github.FluidCraft; +import com.glodblock.github.common.storage.CellType; +import com.glodblock.github.common.storage.IFluidCellInventory; +import com.glodblock.github.common.storage.IFluidCellInventoryHandler; +import com.glodblock.github.common.storage.IStorageFluidCell; +import com.glodblock.github.util.NameConst; +import com.google.common.base.Optional; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.event.ForgeEventFactory; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; + +public class ItemBasicFluidStorageCell extends AEBaseItem implements IStorageFluidCell +{ + private final CellType component; + private final int totalBytes; + private final int perType; + private final double idleDrain; + @SideOnly(Side.CLIENT) + private final static HashMap icon = new HashMap<>(); + + public ItemBasicFluidStorageCell( final CellType whichCell, final int kilobytes ) + { + super( Optional.of( kilobytes + "k" ) ); + setUnlocalizedName(NameConst.ITEM_FLUID_STORAGE + kilobytes); + this.setFeature( EnumSet.of( AEFeature.StorageCells ) ); + this.setMaxStackSize( 1 ); + this.totalBytes = kilobytes * 1024; + this.component = whichCell; + + switch( this.component ) + { + case Cell1kPart: + this.idleDrain = 0.5; + this.perType = 8; + break; + case Cell4kPart: + this.idleDrain = 1.0; + this.perType = 8; + break; + case Cell16kPart: + this.idleDrain = 1.5; + this.perType = 8; + break; + case Cell64kPart: + this.idleDrain = 2.0; + this.perType = 8; + break; + case Cell256kPart: + this.idleDrain = 2.5; + this.perType = 8; + break; + case Cell1024kPart: + this.idleDrain = 3.0; + this.perType = 8; + break; + case Cell4096kPart: + this.idleDrain = 3.5; + this.perType = 8; + break; + default: + this.idleDrain = 0.0; + this.perType = 8; + } + } + + @Override + public String getItemStackDisplayName(ItemStack stack) { + return I18n.format("item.fluid_storage." + this.totalBytes / 1024 + ".name"); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IIconRegister iconRegister) { + icon.put(this.totalBytes / 1024, iconRegister.registerIcon(NameConst.RES_KEY + NameConst.ITEM_FLUID_STORAGE + "." + this.totalBytes / 1024)); + } + + @Override + @SideOnly(Side.CLIENT) + public IIcon getIconFromDamage(int meta) { + int id = this.totalBytes / 1024; + return icon.get(id); + } + + @Override + public void addCheckedInformation(final ItemStack stack, final EntityPlayer player, final List lines, final boolean displayMoreInfo ) + { + final IMEInventoryHandler inventory = AEApi.instance().registries().cell().getCellInventory( stack, null, StorageChannel.FLUIDS ); + + if( inventory instanceof IFluidCellInventoryHandler) + { + final IFluidCellInventoryHandler handler = (IFluidCellInventoryHandler) inventory; + final IFluidCellInventory cellInventory = handler.getCellInv(); + + if( cellInventory != null ) + { + lines.add( cellInventory.getUsedBytes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalBytes() + ' ' + GuiText.BytesUsed.getLocal() ); + + lines.add( cellInventory.getStoredFluidTypes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalFluidTypes() + ' ' + GuiText.Types.getLocal() ); + + if( handler.isPreformatted() ) + { + final String list = (handler.getIncludeExcludeMode() == IncludeExclude.WHITELIST ? GuiText.Included : GuiText.Excluded).getLocal(); + lines.add(GuiText.Partitioned.getLocal() + " - " + list + ' ' + GuiText.Precise.getLocal()); + } + } + } + } + + @Override + public int getBytes( final ItemStack cellItem ) + { + return this.totalBytes; + } + + @Override + public int getBytesPerType( final ItemStack cellItem ) + { + return this.perType; + } + + @Override + public boolean isBlackListed(ItemStack cellItem, IAEFluidStack requestedAddition) { + return false; + } + + @Override + public int getTotalTypes( final ItemStack cellItem ) + { + return 1; + } + + @Override + public boolean storableInStorageCell() + { + return false; + } + + @Override + public boolean isStorageCell( final ItemStack i ) + { + return true; + } + + @Override + public double getIdleDrain() + { + return this.idleDrain; + } + + @Override + public boolean isEditable( final ItemStack is ) + { + return true; + } + + @Override + public IInventory getUpgradesInventory(final ItemStack is ) + { + return new CellUpgrades( is, 0 ); + } + + @Override + public IInventory getConfigInventory( final ItemStack is ) + { + return new CellConfig( is ); + } + + @Override + public FuzzyMode getFuzzyMode(final ItemStack is ) + { + final String fz = Platform.openNbtData( is ).getString( "FuzzyMode" ); + try + { + return FuzzyMode.valueOf( fz ); + } + catch( final Throwable t ) + { + return FuzzyMode.IGNORE_ALL; + } + } + + @Override + public void setFuzzyMode( final ItemStack is, final FuzzyMode fzMode ) + { + Platform.openNbtData( is ).setString( "FuzzyMode", fzMode.name() ); + } + + public String getOreFilter(ItemStack is) { + return Platform.openNbtData( is ).getString( "OreFilter" ); + } + + public void setOreFilter(ItemStack is, String filter) { + Platform.openNbtData( is ).setString("OreFilter", filter); + } + + @Override + public ItemStack onItemRightClick(final ItemStack stack, final World world, final EntityPlayer player ) + { + this.disassembleDrive( stack, world, player ); + return stack; + } + + private boolean disassembleDrive( final ItemStack stack, final World world, final EntityPlayer player ) + { + if( player.isSneaking() ) + { + if( Platform.isClient() ) + { + return false; + } + final InventoryPlayer playerInventory = player.inventory; + final IMEInventoryHandler inv = AEApi.instance().registries().cell().getCellInventory( stack, null, StorageChannel.FLUIDS ); + if( inv != null && playerInventory.getCurrentItem() == stack ) + { + final InventoryAdaptor ia = InventoryAdaptor.getAdaptor( player, ForgeDirection.UNKNOWN ); + final IItemList list = inv.getAvailableItems( StorageChannel.FLUIDS.createList() ); + if( list.isEmpty() && ia != null ) + { + playerInventory.setInventorySlotContents( playerInventory.currentItem, null ); + + // drop core + final ItemStack extraB = ia.addItems( this.component.stack( 1 ) ); + if( extraB != null ) + { + player.dropPlayerItemWithRandomChoice( extraB, false ); + } + + // drop upgrades + final IInventory upgradesInventory = this.getUpgradesInventory( stack ); + for( int upgradeIndex = 0; upgradeIndex < upgradesInventory.getSizeInventory(); upgradeIndex++ ) + { + final ItemStack upgradeStack = upgradesInventory.getStackInSlot( upgradeIndex ); + final ItemStack leftStack = ia.addItems( upgradeStack ); + if( leftStack != null && upgradeStack.getItem() instanceof IUpgradeModule) + { + player.dropPlayerItemWithRandomChoice( upgradeStack, false ); + } + } + + // drop empty storage cell case + for( final ItemStack storageCellStack : AEApi.instance().definitions().materials().emptyStorageCell().maybeStack( 1 ).asSet() ) + { + final ItemStack extraA = ia.addItems( storageCellStack ); + if( extraA != null ) + { + player.dropPlayerItemWithRandomChoice( extraA, false ); + } + } + + if( player.inventoryContainer != null ) + { + player.inventoryContainer.detectAndSendChanges(); + } + + return true; + } + } + } + return false; + } + + @Override + public boolean onItemUseFirst( final ItemStack stack, final EntityPlayer player, final World world, final int x, final int y, final int z, final int side, final float hitX, final float hitY, final float hitZ ) + { + if( ForgeEventFactory.onItemUseStart( player, stack, 1 ) <= 0 ) + return true; + + return this.disassembleDrive( stack, world, player ); + } + + @Override + public ItemStack getContainerItem( final ItemStack itemStack ) + { + for( final ItemStack stack : AEApi.instance().definitions().materials().emptyStorageCell().maybeStack( 1 ).asSet() ) + { + return stack; + } + + throw new MissingDefinition( "Tried to use empty storage cells while basic storage cells are defined." ); + } + + @Override + public boolean hasContainerItem( final ItemStack stack ) + { + return AEConfig.instance.isFeatureEnabled( AEFeature.EnableDisassemblyCrafting ); + } + + public ItemBasicFluidStorageCell register() { + GameRegistry.registerItem(this, NameConst.ITEM_FLUID_STORAGE + this.totalBytes / 1024 , FluidCraft.MODID); + return this; + } + +} diff --git a/src/main/java/com/glodblock/github/common/item/ItemBasicFluidStoragePart.java b/src/main/java/com/glodblock/github/common/item/ItemBasicFluidStoragePart.java new file mode 100644 index 00000000..097ebe53 --- /dev/null +++ b/src/main/java/com/glodblock/github/common/item/ItemBasicFluidStoragePart.java @@ -0,0 +1,64 @@ +package com.glodblock.github.common.item; + +import com.glodblock.github.FluidCraft; +import com.glodblock.github.util.NameConst; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.client.resources.I18n; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; + +import java.util.HashMap; +import java.util.List; + +public class ItemBasicFluidStoragePart extends Item { + + public static final int types = 7; + @SideOnly(Side.CLIENT) + private final static HashMap icon = new HashMap<>(); + + public ItemBasicFluidStoragePart() { + super(); + setHasSubtypes(true); + setUnlocalizedName(NameConst.ITEM_FLUID_PART); + } + + @Override + @SideOnly(Side.CLIENT) + @SuppressWarnings("unchecked") + public void getSubItems(Item item, CreativeTabs tab, List list) { + for (int i = 0; i < types; ++i) { + list.add(new ItemStack(item, 1, i)); + } + } + + @Override + public String getItemStackDisplayName(ItemStack stack) { + int meta = stack.getItemDamage(); + return I18n.format("item.fluid_part." + meta + ".name"); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IIconRegister iconRegister) { + for (int i = 0; i < types; i ++) { + icon.put(i, iconRegister.registerIcon(NameConst.RES_KEY + NameConst.ITEM_FLUID_PART + "." + i)); + } + } + + @Override + @SideOnly(Side.CLIENT) + public IIcon getIconFromDamage(int meta) { + return icon.get(meta); + } + + public ItemBasicFluidStoragePart register() { + GameRegistry.registerItem(this, NameConst.ITEM_FLUID_PART, FluidCraft.MODID); + return this; + } + +} diff --git a/src/main/java/com/glodblock/github/common/storage/CellType.java b/src/main/java/com/glodblock/github/common/storage/CellType.java new file mode 100644 index 00000000..7ca28158 --- /dev/null +++ b/src/main/java/com/glodblock/github/common/storage/CellType.java @@ -0,0 +1,59 @@ +package com.glodblock.github.common.storage; + +import appeng.core.features.AEFeature; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.util.EnumSet; + +public enum CellType { + + Cell1kPart( 0, AEFeature.StorageCells ), + Cell4kPart( 1, AEFeature.StorageCells ), + Cell16kPart( 2, AEFeature.StorageCells ), + Cell64kPart( 3, AEFeature.StorageCells ), + Cell256kPart( 4, AEFeature.StorageCells ), + Cell1024kPart( 5, AEFeature.StorageCells ), + Cell4096kPart( 6, AEFeature.StorageCells ); + + private final EnumSet features; + private int damageValue; + private Item itemInstance; + + CellType( final int metaValue, final AEFeature part ) + { + this.setDamageValue( metaValue ); + this.features = EnumSet.of( part ); + } + + void setDamageValue( final int damageValue ) + { + this.damageValue = damageValue; + } + + public int getDamageValue() + { + return this.damageValue; + } + + EnumSet getFeature() + { + return this.features; + } + + public ItemStack stack(final int size ) + { + return new ItemStack( this.getItemInstance(), size, this.getDamageValue() ); + } + + public Item getItemInstance() + { + return this.itemInstance; + } + + public void setItemInstance( final Item itemInstance ) + { + this.itemInstance = itemInstance; + } + +} diff --git a/src/main/java/com/glodblock/github/common/storage/FluidCellHandler.java b/src/main/java/com/glodblock/github/common/storage/FluidCellHandler.java new file mode 100644 index 00000000..240cdeb6 --- /dev/null +++ b/src/main/java/com/glodblock/github/common/storage/FluidCellHandler.java @@ -0,0 +1,69 @@ +package com.glodblock.github.common.storage; + +import appeng.api.implementations.tiles.IChestOrDrive; +import appeng.api.storage.*; +import appeng.client.texture.ExtraBlockTextures; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; + +public class FluidCellHandler implements ICellHandler +{ + + @Override + public boolean isCell( final ItemStack is ) + { + return FluidCellInventory.isCell( is ); + } + + @Override + public IMEInventoryHandler getCellInventory(final ItemStack is, final ISaveProvider container, final StorageChannel channel ) + { + if( channel == StorageChannel.FLUIDS ) + { + return FluidCellInventory.getCell( is, container ); + } + return null; + } + + @Override + public IIcon getTopTexture_Light() + { + return ExtraBlockTextures.BlockMEChestItems_Light.getIcon(); + } + + @Override + public IIcon getTopTexture_Medium() + { + return ExtraBlockTextures.BlockMEChestItems_Medium.getIcon(); + } + + @Override + public IIcon getTopTexture_Dark() + { + return ExtraBlockTextures.BlockMEChestItems_Dark.getIcon(); + } + + @Override + public void openChestGui(final EntityPlayer player, final IChestOrDrive chest, final ICellHandler cellHandler, final IMEInventoryHandler inv, final ItemStack is, final StorageChannel chan ) + { + } + + @Override + public int getStatusForCell( final ItemStack is, final IMEInventory handler ) + { + if( handler instanceof FluidCellInventoryHandler) + { + final FluidCellInventoryHandler ci = (FluidCellInventoryHandler) handler; + return ci.getStatusForCell(); + } + return 0; + } + + @Override + public double cellIdleDrain( final ItemStack is, final IMEInventory handler ) + { + final IFluidCellInventory inv = ( (IFluidCellInventoryHandler) handler ).getCellInv(); + return inv.getIdleDrain(); + } +} diff --git a/src/main/java/com/glodblock/github/common/storage/FluidCellInventory.java b/src/main/java/com/glodblock/github/common/storage/FluidCellInventory.java new file mode 100644 index 00000000..357a40cc --- /dev/null +++ b/src/main/java/com/glodblock/github/common/storage/FluidCellInventory.java @@ -0,0 +1,486 @@ +package com.glodblock.github.common.storage; + +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.exceptions.AppEngException; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.ISaveProvider; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.util.Platform; +import appeng.util.item.AEFluidStack; +import com.glodblock.github.util.Util; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; + +public class FluidCellInventory implements IFluidCellInventory { + + private static final String FLUID_TYPE_TAG = "ft"; + private static final String FLUID_COUNT_TAG = "fc"; + private static final String FLUID_SLOT = "#"; + private static final String FLUID_SLOT_COUNT = "@"; + private IStorageFluidCell cellType; + private static String[] fluidSlots; + private static String[] fluidSlotCount; + private final ItemStack cellItem; + private final ISaveProvider container; + private final static int MAX_TYPE = 1; + private int storedFluidCount; + private short storedFluids; + private IItemList cellItems; + private final NBTTagCompound tagCompound; + + public FluidCellInventory( final ItemStack o, final ISaveProvider container ) throws AppEngException { + + if( fluidSlots == null ) + { + fluidSlots = new String[MAX_TYPE]; + fluidSlotCount = new String[MAX_TYPE]; + + for( int x = 0; x < MAX_TYPE; x++ ) + { + fluidSlots[x] = FLUID_SLOT + x; + fluidSlotCount[x] = FLUID_SLOT_COUNT + x; + } + } + + if( o == null ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + this.cellType = null; + this.cellItem = o; + + final Item type = this.cellItem.getItem(); + + if( type instanceof IStorageFluidCell) + { + this.cellType = (IStorageFluidCell) this.cellItem.getItem(); + } + + if( this.cellType == null ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + if( !this.cellType.isStorageCell( this.cellItem ) ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + this.container = container; + this.tagCompound = Platform.openNbtData( o ); + this.storedFluids = this.tagCompound.getShort( FLUID_TYPE_TAG ); + this.storedFluidCount = this.tagCompound.getInteger( FLUID_COUNT_TAG ); + this.cellItems = null; + } + + public static IMEInventoryHandler getCell(final ItemStack o, final ISaveProvider container2 ) + { + try + { + return new FluidCellInventoryHandler( new FluidCellInventory( o, container2 ) ); + } + catch( final AppEngException e ) + { + return null; + } + } + + public static boolean isCell( final ItemStack itemStack ) + { + if( itemStack == null ) + { + return false; + } + + final Item type = itemStack.getItem(); + + if( type instanceof IStorageFluidCell) + { + return ( (IStorageFluidCell) type ).isStorageCell( itemStack ); + } + + return false; + } + + @Override + public ItemStack getItemStack() { + return this.cellItem; + } + + @Override + public double getIdleDrain() { + return this.cellType.getIdleDrain(); + } + + @Override + public IInventory getConfigInventory() { + return this.cellType.getConfigInventory( this.cellItem ); + } + + @Override + public int getBytesPerType() { + return this.cellType.getBytesPerType( this.cellItem ); + } + + @Override + public boolean canHoldNewFluid() { + final long bytesFree = this.getFreeBytes(); + + return ( bytesFree > this.getBytesPerType() || ( bytesFree == this.getBytesPerType() && this.getUnusedFluidCount() > 0 ) ) && this.getRemainingFluidTypes() > 0; + } + + @Override + public long getTotalBytes() { + return this.cellType.getBytes( this.cellItem ); + } + + @Override + public long getFreeBytes() { + return this.getTotalBytes() - this.getUsedBytes(); + } + + @Override + public long getUsedBytes() { + final long bytesForItemCount = ( this.getStoredFluidCount() + this.getUnusedFluidCount() ) / 8 / 256; + return this.getStoredFluidTypes() * this.getBytesPerType() + bytesForItemCount; + } + + @Override + public long getTotalFluidTypes() { + return MAX_TYPE; + } + + @Override + public long getStoredFluidCount() { + return this.storedFluidCount; + } + + @Override + public long getStoredFluidTypes() { + return this.storedFluids; + } + + public long getRemainingFluidTypes() { + final long basedOnStorage = this.getFreeBytes() / this.getBytesPerType(); + final long baseOnTotal = this.getTotalFluidTypes() - this.getStoredFluidTypes(); + + return Math.min(basedOnStorage, baseOnTotal); + } + + @Override + public long getRemainingFluidCount() { + final long remaining = this.getFreeBytes() * 8 + this.getUnusedFluidCount(); + + return remaining > 0 ? remaining : 0; + } + + @Override + public int getUnusedFluidCount() { + final int div = (int) ( this.getStoredFluidCount() % 8 ); + + if( div == 0 ) + { + return 0; + } + + return 8 - div; + } + + @Override + public int getStatusForCell() { + if( this.canHoldNewFluid() ) + { + return 1; + } + if( this.getRemainingFluidCount() > 0 ) + { + return 2; + } + return 3; + } + + private void loadCellItems() + { + if( this.cellItems == null ) + { + this.cellItems = AEApi.instance().storage().createFluidList(); + } + + this.cellItems.resetStatus(); // clears totals and stuff. + + final int types = (int) this.getStoredFluidTypes(); + + for( int x = 0; x < types; x++ ) + { + final FluidStack t = FluidStack.loadFluidStackFromNBT( this.tagCompound.getCompoundTag( fluidSlots[x] ) ); + + if( t != null ) + { + t.amount = this.tagCompound.getInteger( fluidSlotCount[x] ); + + if( t.amount > 0 ) + { + this.cellItems.add( AEFluidStack.create( t ) ); + } + } + } + } + + private IItemList getCellItems() + { + if( this.cellItems == null ) + { + this.loadCellItems(); + } + + return this.cellItems; + } + + private void updateFluidCount( final long delta ) + { + this.storedFluidCount += delta; + this.tagCompound.setInteger( FLUID_COUNT_TAG, this.storedFluidCount ); + } + + private void saveChanges() + { + int itemCount = 0; + + int x = 0; + + for( final IAEFluidStack v : this.cellItems ) + { + itemCount += v.getStackSize(); + + final NBTBase c = this.tagCompound.getTag( fluidSlots[x] ); + + if( c instanceof NBTTagCompound ) + { + v.writeToNBT( (NBTTagCompound) c ); + } + else + { + final NBTTagCompound g = new NBTTagCompound(); + v.writeToNBT( g ); + this.tagCompound.setTag( fluidSlots[x], g ); + } + + /* + * NBTBase tagSlotCount = tagCompound.getTag( itemSlotCount[x] ); if ( tagSlotCount instanceof + * NBTTagInt ) ((NBTTagInt) tagSlotCount).data = (int) v.getStackSize(); else + */ + this.tagCompound.setInteger( fluidSlotCount[x], (int) v.getStackSize() ); + + x++; + } + + // NBTBase tagType = tagCompound.getTag( ITEM_TYPE_TAG ); + // NBTBase tagCount = tagCompound.getTag( ITEM_COUNT_TAG ); + final short oldStoredItems = this.storedFluids; + + /* + * if ( tagType instanceof NBTTagShort ) ((NBTTagShort) tagType).data = storedItems = (short) cellItems.size(); + * else + */ + this.storedFluids = (short) this.cellItems.size(); + + if( this.cellItems.isEmpty() ) + { + this.tagCompound.removeTag( FLUID_TYPE_TAG ); + } + else + { + this.tagCompound.setShort( FLUID_TYPE_TAG, this.storedFluids ); + } + + /* + * if ( tagCount instanceof NBTTagInt ) ((NBTTagInt) tagCount).data = storedItemCount = itemCount; else + */ + this.storedFluidCount = itemCount; + + if( itemCount == 0 ) + { + this.tagCompound.removeTag( FLUID_COUNT_TAG ); + } + else + { + this.tagCompound.setInteger( FLUID_COUNT_TAG, itemCount ); + } + + // clean any old crusty stuff... + for( ; x < oldStoredItems && x < MAX_TYPE; x++ ) + { + this.tagCompound.removeTag( fluidSlots[x] ); + this.tagCompound.removeTag( fluidSlotCount[x] ); + } + + if( this.container != null ) + { + this.container.saveChanges( this ); + } + } + + @Override + public IAEFluidStack injectItems(IAEFluidStack input, Actionable mode, BaseActionSource src) { + if( input == null ) + { + return null; + } + + if( input.getStackSize() == 0 ) + { + return null; + } + + if(this.cellType.isBlackListed( this.cellItem, input )) + { + return input; + } + + final FluidStack sharedFluidStack = input.getFluidStack(); + + final IAEFluidStack l = this.getCellItems().findPrecise( input ); + + if( l != null ) + { + final long remainingItemSlots = this.getRemainingFluidCount(); + + if( remainingItemSlots < 0 ) + { + return input; + } + + if( input.getStackSize() > remainingItemSlots ) + { + final IAEFluidStack r = input.copy(); + r.setStackSize( r.getStackSize() - remainingItemSlots ); + + if( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() + remainingItemSlots ); + this.updateFluidCount( remainingItemSlots ); + this.saveChanges(); + } + + return r; + } + else + { + if( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() + input.getStackSize() ); + this.updateFluidCount( input.getStackSize() ); + this.saveChanges(); + } + + return null; + } + } + + if( this.canHoldNewFluid() ) // room for new type, and for at least one item! + { + final int remainingItemCount = (int) this.getRemainingFluidCount() - this.getBytesPerType() * 8; + + if( remainingItemCount > 0 ) + { + if( input.getStackSize() > remainingItemCount ) + { + final FluidStack toReturn = Util.cloneFluidStack(sharedFluidStack); + toReturn.amount = sharedFluidStack.amount - remainingItemCount; + + if( mode == Actionable.MODULATE ) + { + final FluidStack toWrite = Util.cloneFluidStack( sharedFluidStack ); + toWrite.amount = remainingItemCount; + + this.cellItems.add( AEFluidStack.create( toWrite ) ); + this.updateFluidCount( toWrite.amount ); + + this.saveChanges(); + } + + return AEFluidStack.create( toReturn ); + } + + if( mode == Actionable.MODULATE ) + { + this.updateFluidCount( input.getStackSize() ); + this.cellItems.add( input ); + this.saveChanges(); + } + + return null; + } + } + + return input; + } + + @Override + public IAEFluidStack extractItems(IAEFluidStack request, Actionable mode, BaseActionSource src) { + if( request == null ) + { + return null; + } + + final long size = Math.min( Integer.MAX_VALUE, request.getStackSize() ); + + IAEFluidStack results = null; + + final IAEFluidStack l = this.getCellItems().findPrecise( request ); + + if( l != null ) + { + results = l.copy(); + + if( l.getStackSize() <= size ) + { + results.setStackSize( l.getStackSize() ); + + if( mode == Actionable.MODULATE ) + { + this.updateFluidCount( -l.getStackSize() ); + l.setStackSize( 0 ); + this.saveChanges(); + } + } + else + { + results.setStackSize( size ); + + if( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() - size ); + this.updateFluidCount( -size ); + this.saveChanges(); + } + } + } + + return results; + } + + @Override + public IItemList getAvailableItems(IItemList out) { + for( final IAEFluidStack i : this.getCellItems() ) + { + out.add( i ); + } + + return out; + } + + @Override + public StorageChannel getChannel() { + return StorageChannel.FLUIDS; + } +} diff --git a/src/main/java/com/glodblock/github/common/storage/FluidCellInventoryHandler.java b/src/main/java/com/glodblock/github/common/storage/FluidCellInventoryHandler.java new file mode 100644 index 00000000..c1aede92 --- /dev/null +++ b/src/main/java/com/glodblock/github/common/storage/FluidCellInventoryHandler.java @@ -0,0 +1,80 @@ +package com.glodblock.github.common.storage; + +import appeng.api.AEApi; +import appeng.api.config.IncludeExclude; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.me.storage.MEInventoryHandler; +import appeng.me.storage.MEPassThrough; +import appeng.util.item.AEFluidStack; +import appeng.util.prioitylist.PrecisePriorityList; +import com.glodblock.github.util.Ae2Reflect; +import com.glodblock.github.util.Util; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class FluidCellInventoryHandler extends MEInventoryHandler implements IFluidCellInventoryHandler { + + FluidCellInventoryHandler( final IMEInventory c ) + { + super( c, StorageChannel.FLUIDS ); + + final IFluidCellInventory ci = this.getCellInv(); + + if( ci != null ) + { + final IInventory config = ci.getConfigInventory(); + + final IItemList priorityList = AEApi.instance().storage().createFluidList(); + for (int x = 0; x < config.getSizeInventory(); x++) { + final ItemStack is = config.getStackInSlot(x); + if (is != null && Util.getFluidFromItem(is) != null) { + priorityList.add(AEFluidStack.create(Util.getFluidFromItem(is))); + break; + } + } + if (!priorityList.isEmpty()) { + this.setPartitionList(new PrecisePriorityList<>(priorityList)); + } + } + } + + @Override + public IFluidCellInventory getCellInv() + { + Object o = this.getInternal(); + + if( o instanceof MEPassThrough) + { + o = Ae2Reflect.getInternal( (MEPassThrough) o ); + } + + return (IFluidCellInventory) ( o instanceof IFluidCellInventory ? o : null ); + } + + @Override + public boolean isPreformatted() + { + return !Ae2Reflect.getPartitionList(this).isEmpty(); + } + + @Override + public IncludeExclude getIncludeExcludeMode() + { + return IncludeExclude.WHITELIST; + } + + public int getStatusForCell() + { + int val = this.getCellInv().getStatusForCell(); + + if( val == 1 && this.isPreformatted() ) + { + val = 2; + } + + return val; + } +} diff --git a/src/main/java/com/glodblock/github/common/storage/IFluidCellInventory.java b/src/main/java/com/glodblock/github/common/storage/IFluidCellInventory.java new file mode 100644 index 00000000..288504ef --- /dev/null +++ b/src/main/java/com/glodblock/github/common/storage/IFluidCellInventory.java @@ -0,0 +1,74 @@ +package com.glodblock.github.common.storage; + +import appeng.api.storage.IMEInventory; +import appeng.api.storage.data.IAEFluidStack; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public interface IFluidCellInventory extends IMEInventory +{ + + /** + * @return the item stack of this storage cell. + */ + ItemStack getItemStack(); + + /** + * @return idle cost for this Storage Cell + */ + double getIdleDrain(); + + /** + * @return access configured list + */ + IInventory getConfigInventory(); + + /** + * @return How many bytes are used for each type? + */ + int getBytesPerType(); + + /** + * @return true if a new item type can be added. + */ + boolean canHoldNewFluid(); + + /** + * @return total byte storage. + */ + long getTotalBytes(); + + /** + * @return how many bytes are free. + */ + long getFreeBytes(); + + /** + * @return how many bytes are in use. + */ + long getUsedBytes(); + + /** + * @return how many items are stored. + */ + long getStoredFluidCount(); + + /** + * @return how many more items can be stored. + */ + long getRemainingFluidCount(); + + /** + * @return how many items can be added without consuming another byte. + */ + int getUnusedFluidCount(); + + /** + * @return the status number for this drive. + */ + int getStatusForCell(); + + long getStoredFluidTypes(); + + long getTotalFluidTypes(); +} diff --git a/src/main/java/com/glodblock/github/common/storage/IFluidCellInventoryHandler.java b/src/main/java/com/glodblock/github/common/storage/IFluidCellInventoryHandler.java new file mode 100644 index 00000000..aedfb3e3 --- /dev/null +++ b/src/main/java/com/glodblock/github/common/storage/IFluidCellInventoryHandler.java @@ -0,0 +1,13 @@ +package com.glodblock.github.common.storage; + +import appeng.api.config.IncludeExclude; + +public interface IFluidCellInventoryHandler { + + IFluidCellInventory getCellInv(); + + boolean isPreformatted(); + + IncludeExclude getIncludeExcludeMode(); + +} diff --git a/src/main/java/com/glodblock/github/common/storage/IStorageFluidCell.java b/src/main/java/com/glodblock/github/common/storage/IStorageFluidCell.java new file mode 100644 index 00000000..314b1c3b --- /dev/null +++ b/src/main/java/com/glodblock/github/common/storage/IStorageFluidCell.java @@ -0,0 +1,23 @@ +package com.glodblock.github.common.storage; + +import appeng.api.storage.ICellWorkbenchItem; +import appeng.api.storage.data.IAEFluidStack; +import net.minecraft.item.ItemStack; + +public interface IStorageFluidCell extends ICellWorkbenchItem { + + int getBytes( ItemStack cellItem ); + + int getBytesPerType( ItemStack cellItem ); + + boolean isBlackListed( ItemStack cellItem, IAEFluidStack requestedAddition ); + + boolean storableInStorageCell(); + + boolean isStorageCell( ItemStack i ); + + double getIdleDrain(); + + int getTotalTypes( ItemStack cellItem ); + +} diff --git a/src/main/java/com/glodblock/github/loader/ItemAndBlockHolder.java b/src/main/java/com/glodblock/github/loader/ItemAndBlockHolder.java index 67d1d1ba..2b7dcffe 100644 --- a/src/main/java/com/glodblock/github/loader/ItemAndBlockHolder.java +++ b/src/main/java/com/glodblock/github/loader/ItemAndBlockHolder.java @@ -4,10 +4,8 @@ import com.glodblock.github.common.block.BlockFluidDiscretizer; import com.glodblock.github.common.block.BlockFluidInterface; import com.glodblock.github.common.block.BlockFluidPacketDecoder; import com.glodblock.github.common.block.BlockFluidPatternEncoder; -import com.glodblock.github.common.item.ItemFluidDrop; -import com.glodblock.github.common.item.ItemFluidEncodedPattern; -import com.glodblock.github.common.item.ItemFluidPacket; -import com.glodblock.github.common.item.ItemPartFluidPatternTerminal; +import com.glodblock.github.common.item.*; +import com.glodblock.github.common.storage.CellType; public class ItemAndBlockHolder { @@ -15,10 +13,28 @@ public class ItemAndBlockHolder { public static ItemFluidEncodedPattern PATTERN = new ItemFluidEncodedPattern().register(); public static ItemPartFluidPatternTerminal FLUID_TERMINAL = new ItemPartFluidPatternTerminal().register(); public static ItemFluidPacket PACKET = new ItemFluidPacket().register(); + public static ItemBasicFluidStorageCell CELL1K = new ItemBasicFluidStorageCell(CellType.Cell1kPart, 1).register(); + public static ItemBasicFluidStorageCell CELL4K = new ItemBasicFluidStorageCell(CellType.Cell4kPart, 4).register(); + public static ItemBasicFluidStorageCell CELL16K = new ItemBasicFluidStorageCell(CellType.Cell16kPart, 16).register(); + public static ItemBasicFluidStorageCell CELL64K = new ItemBasicFluidStorageCell(CellType.Cell64kPart, 64).register(); + public static ItemBasicFluidStorageCell CELL256K = new ItemBasicFluidStorageCell(CellType.Cell256kPart, 256).register(); + public static ItemBasicFluidStorageCell CELL1024K = new ItemBasicFluidStorageCell(CellType.Cell1024kPart, 1024).register(); + public static ItemBasicFluidStorageCell CELL4096K = new ItemBasicFluidStorageCell(CellType.Cell4096kPart, 4096).register(); + public static ItemBasicFluidStoragePart CELL_PART = new ItemBasicFluidStoragePart().register(); public static BlockFluidDiscretizer DISCRETIZER = new BlockFluidDiscretizer().register(); public static BlockFluidPatternEncoder ENCODER = new BlockFluidPatternEncoder().register(); public static BlockFluidPacketDecoder DECODER = new BlockFluidPacketDecoder().register(); public static BlockFluidInterface INTERFACE = new BlockFluidInterface().register(); + public static void loadSetting() { + CellType.Cell1kPart.setItemInstance(CELL_PART); + CellType.Cell4kPart.setItemInstance(CELL_PART); + CellType.Cell16kPart.setItemInstance(CELL_PART); + CellType.Cell64kPart.setItemInstance(CELL_PART); + CellType.Cell256kPart.setItemInstance(CELL_PART); + CellType.Cell1024kPart.setItemInstance(CELL_PART); + CellType.Cell4096kPart.setItemInstance(CELL_PART); + } + } diff --git a/src/main/java/com/glodblock/github/util/Ae2Reflect.java b/src/main/java/com/glodblock/github/util/Ae2Reflect.java index 1f2d623c..e905f178 100644 --- a/src/main/java/com/glodblock/github/util/Ae2Reflect.java +++ b/src/main/java/com/glodblock/github/util/Ae2Reflect.java @@ -2,6 +2,7 @@ package com.glodblock.github.util; import appeng.api.implementations.IUpgradeableHost; import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.storage.IMEInventory; import appeng.client.gui.AEBaseGui; import appeng.client.gui.implementations.GuiCraftingStatus; import appeng.client.gui.widgets.GuiTabButton; @@ -9,7 +10,10 @@ import appeng.client.render.AppEngRenderItem; import appeng.container.implementations.ContainerUpgradeable; import appeng.container.implementations.CraftingCPURecord; import appeng.helpers.MultiCraftingTracker; +import appeng.me.storage.MEInventoryHandler; +import appeng.me.storage.MEPassThrough; import appeng.util.inv.ItemSlot; +import appeng.util.prioitylist.IPartitionList; import com.glodblock.github.client.gui.GuiBaseFluidPatternTerminal; import com.glodblock.github.client.gui.GuiFCBaseMonitor; import com.glodblock.github.client.gui.container.ContainerFluidPatternTerminal; @@ -31,9 +35,9 @@ public class Ae2Reflect { private static final Field fInventory_width; private static final Field fInventory_stackList; private static final Field fAEContainer_upgradeable; + private static final Field fAEPass_internal; + private static final Field fAEInv_partitionList; private static final Method mItemSlot_setExtractable; - private static final Method mTracker_isBusy; - private static final Method mTracker_cancel; static { try { @@ -41,9 +45,9 @@ public class Ae2Reflect { fInventory_width = reflectField(InventoryCrafting.class, "inventoryWidth", "field_70464_b", "b"); fInventory_stackList = reflectField(InventoryCrafting.class, "stackList", "field_70466_a", "a"); fAEContainer_upgradeable = reflectField(ContainerUpgradeable.class, "upgradeable"); + fAEPass_internal = reflectField(MEPassThrough.class, "internal"); + fAEInv_partitionList = reflectField(MEInventoryHandler.class, "myPartitionList"); mItemSlot_setExtractable = reflectMethod(ItemSlot.class, "setExtractable", boolean.class); - mTracker_isBusy = reflectMethod(MultiCraftingTracker.class, "isBusy", int.class); - mTracker_cancel = reflectMethod(MultiCraftingTracker.class, "cancel"); } catch (Exception e) { throw new IllegalStateException("Failed to initialize AE2 reflection hacks!", e); } @@ -87,20 +91,12 @@ public class Ae2Reflect { } } - public static void doCancel(MultiCraftingTracker mct) { - try { - mTracker_cancel.invoke(mct); - } catch (Exception e) { - throw new IllegalStateException("Failed to invoke method: " + mTracker_cancel, e); - } + public static IPartitionList getPartitionList(MEInventoryHandler me) { + return Ae2Reflect.readField(me, fAEInv_partitionList); } - public static boolean getBusy(MultiCraftingTracker mct, int slot) { - try { - return (boolean) mTracker_isBusy.invoke(mct, slot); - } catch (Exception e) { - throw new IllegalStateException("Failed to invoke method: " + mTracker_isBusy, e); - } + public static IMEInventory getInternal(MEPassThrough me) { + return Ae2Reflect.readField(me, fAEPass_internal); } public static IUpgradeableHost getUpgrade(ContainerUpgradeable container) { diff --git a/src/main/java/com/glodblock/github/util/NameConst.java b/src/main/java/com/glodblock/github/util/NameConst.java index ca588030..f591a9b4 100644 --- a/src/main/java/com/glodblock/github/util/NameConst.java +++ b/src/main/java/com/glodblock/github/util/NameConst.java @@ -13,6 +13,8 @@ public class NameConst { public static final String ITEM_FLUID_ENCODED_PATTERN = "fluid_encoded_pattern"; public static final String ITEM_PART_FLUID_PATTERN_TERMINAL = "part_fluid_pattern_terminal"; public static final String ITEM_FLUID_PACKET = "fluid_packet"; + public static final String ITEM_FLUID_STORAGE = "fluid_storage"; + public static final String ITEM_FLUID_PART = "fluid_part"; public static final String TT_KEY = FluidCraft.MODID + ".tooltip."; public static final String TT_INVALID_FLUID = TT_KEY + "invalid_fluid"; diff --git a/src/main/java/com/glodblock/github/util/Util.java b/src/main/java/com/glodblock/github/util/Util.java index 155f4721..61da63ea 100644 --- a/src/main/java/com/glodblock/github/util/Util.java +++ b/src/main/java/com/glodblock/github/util/Util.java @@ -99,4 +99,9 @@ public final class Util { return stack != null && stack.getItem() instanceof ItemFluidPacket; } + public static FluidStack cloneFluidStack(FluidStack fluidStack) { + if (fluidStack != null) return fluidStack.copy(); + return null; + } + } diff --git a/src/main/resources/assets/ae2fc/lang/en_US.lang b/src/main/resources/assets/ae2fc/lang/en_US.lang index dde8ce6d..17c865f8 100644 --- a/src/main/resources/assets/ae2fc/lang/en_US.lang +++ b/src/main/resources/assets/ae2fc/lang/en_US.lang @@ -2,6 +2,20 @@ item.fluid_drop.name=drop of %s item.fluid_encoded_pattern.name=Encode Pattern item.part_fluid_pattern_terminal.name=ME Fluid Pattern Terminal item.fluid_packet.name=Fluid Packet +item.fluid_storage.1.name=1k ME Fluid Storage Cell +item.fluid_storage.4.name=4k ME Fluid Storage Cell +item.fluid_storage.16.name=16k ME Fluid Storage Cell +item.fluid_storage.64.name=64k ME Fluid Storage Cell +item.fluid_storage.256.name=256k ME Fluid Storage Cell +item.fluid_storage.1024.name=1024k ME Fluid Storage Cell +item.fluid_storage.4096.name=4096k ME Fluid Storage Cell +item.fluid_part.0.name=1k ME Fluid Storage Component +item.fluid_part.1.name=4k ME Fluid Storage Component +item.fluid_part.2.name=16k ME Fluid Storage Component +item.fluid_part.3.name=64k ME Fluid Storage Component +item.fluid_part.4.name=256k ME Fluid Storage Component +item.fluid_part.5.name=1024k ME Fluid Storage Component +item.fluid_part.6.name=4096k ME Fluid Storage Component tile.fluid_discretizer.name=Fluid Discretizer tile.fluid_pattern_encoder.name=Fluid Pattern Encoder diff --git a/src/main/resources/assets/ae2fc/textures/items/fluid_part.0.png b/src/main/resources/assets/ae2fc/textures/items/fluid_part.0.png new file mode 100644 index 0000000000000000000000000000000000000000..ad372d851309fc1160e181b27492c52924343b15 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Q#@T9Lo9leC5|OLJ2UhDS>CG$ zC5{|>8myMn#LLV3f9KAf4{HRZRotd9?htu2DcR*&!yK;7KhMpz=F!s9l6bQ|e!tO@ z<;xF$-KZdKknbixXKr-N>4g1hye+~)hYWUZmt4JiLmQ)JLz2G1qG&d5jR|ZsHap&9 zlw_Lfez93s%z)>pdb_r)LDL*AW(705=60imgaihLXerO5^L11Uf$n4QboFyt=akR{ E0NqST%K!iX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ae2fc/textures/items/fluid_part.1.png b/src/main/resources/assets/ae2fc/textures/items/fluid_part.1.png new file mode 100644 index 0000000000000000000000000000000000000000..5a6724643be9dba735b3f302d05d320aa198f73e GIT binary patch literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`i#=T&Lo9leCFUeNJ2UhDMcFoA z9+rp;tWr`^|B8!?jb})&TAabq+4uw~ATjai%nPQ%TtX$L1(zNCSZ+G;{P^`%+qtUB zO1Xpfi@Lo9le7g)`(EPhsB>|AQV zw(;W67vBsOi>0Kb{uLJ&AO5LeW+lIbZ8hTyp&tyJqTJY4Y)&-0yR*36(bbjp92;Yb zUC-aIufyBEd?|6;z^L&5pwAiIb*UdbeOWheKQoVa*~Fidt7kvVv#$K7rtBp#fm!1l zQ)!IBmctA=3>*i9*gY7}%v5;az+fbwmf`Ho9HC$2)gtZ2p|INZJa>=6@`DT=z30@A fDjjNQY-D6uDAH2uTc%k7bUK5ltDnm{r-UW|zJykJ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ae2fc/textures/items/fluid_part.3.png b/src/main/resources/assets/ae2fc/textures/items/fluid_part.3.png new file mode 100644 index 0000000000000000000000000000000000000000..15b2afa249b6de080e67b05bf175bfa11f621e62 GIT binary patch literal 302 zcmV+}0nz@6P)Nkl;+_JN5{l~*-Mu!K@msx0!l291Hdi-#W9HX^p7Me z7PfC(4rZS`e-jdjFaS~n3vC7*u>cDTlt4_%C_+gvga9bEKw)q)J)QD|1P?@*04$zi z{saLK8#(Tg)uQJGMv&8B0K`V;BWtD{FfcFx04C>~Ohd4T#Q*>R07*qoM6N<$f?@=6 Ac>n+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ae2fc/textures/items/fluid_part.4.png b/src/main/resources/assets/ae2fc/textures/items/fluid_part.4.png new file mode 100644 index 0000000000000000000000000000000000000000..6c23f18951e2240c147a4e30f10d6cc4c2252fdb GIT binary patch literal 382 zcmV-^0fGLBP)g@atTfyJCQ zY+%?I5WrwJX(Gd+ynL`2EDWfVkdOsH02I$4f5M^>#D>K^x?1$SzzA|041n0^d}Pg( c0|o{L0Cmj7XNG9RWdHyG07*qoM6N<$f=O+jO8@`> literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ae2fc/textures/items/fluid_part.5.png b/src/main/resources/assets/ae2fc/textures/items/fluid_part.5.png new file mode 100644 index 0000000000000000000000000000000000000000..a4603ba3ad5d84cf9a0866ee9a2881b3ec3786db GIT binary patch literal 523 zcmV+m0`&cfP)T^bBc%@UU^?Oc3^vt3*qtdMfyCeg&< zHlc+KnVf~I9lEqjRU`z8@s;oQa<3O1^Mx<(`#$e|zCYi?q$2L}ON&MQ=i-v>+Qxfc z_jf<>`sDE=T10r#Gxx1DSt+I0Y7Mi`<#Mcv&{^?iNvAnhnoO(fDU?>q2(E{SqKK7j z!W_>VyK5X!+EPkXTRyZFAe(A?*Xf`d1Z)!q4OCk#wuytJ2gSKr-cS@eq%69dilbvh zc9lX`#aP%581J2)iEO$a%7A^mSeAw9g$3aD z77u1-?!B69dd}4Cp@^Hf+757Vb&09@=U6^$q4D7({`x+u-_P;Jw#FSK@}*KS4WpVV zZHi1}*YivhF>2!2>+^kI|B#ZE?Lut-e6?h-^TPl0WQ<8Jf;=}X6&@@{(SrA%ofkBI z#)JlAqw(?+Fvaw~g$&RLY0gw9l|x##GmKFQBwycdnm;u0XPQg^`~yyI-xGG~-}e9j N002ovPDHLkV1n1A^;7@= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ae2fc/textures/items/fluid_part.6.png b/src/main/resources/assets/ae2fc/textures/items/fluid_part.6.png new file mode 100644 index 0000000000000000000000000000000000000000..f8d153d800c06cd1a97991b1fba43d0841ed2e5c GIT binary patch literal 536 zcmV+z0_XjSP)KdU~GsywB(FIWPVT@jc$>ZByp1ZTkW?y=%jH{n8I8wT^dKMdy?=O8pmNaG(!d9*On6PDkQf_7dVlMa z7ykg{L;|qc`0U=_W}UgX7G?VE&wG2U52mKD5}CtUXFp&v!4;VUCa2N&tsAX_Xf&!2 zSu`)TJYH9e&AMhtv$GH{FL+yA#9%&)RZ)ed#zt7JRul>aghC-9{YY74{k64~gH`)4 zlyH!&toa;aWQ0dJb-1B;y=b4GL0C6JXa4ec4$2)4*1fS9&m1HYcQ-hgNK}d>qL@JA zfYwMq3GJC+u-jp{x+-nj<-%Jw%Vt8Bu^n4M`Y5AuAZTUF9#2Wkg44;ON2IBV*K09X zb8$V1;^y)k$)O>1oTT8nyJfaX$o9l{xH9>yy&JVR#0hkdLr`lfXjLRC=#GMirLS-Q a1Aq^>dA(PWyf5|u0000=8@RS87%ZU`x0Vr`d~p;b0}EE2P|Y>LiC}iiqTv6y3}GUq83aIVm}>|c zfUJ4a&dp$q&k!bjn)BR!!5E(*O!zdPUta*m_zVFX@MK;3e?A@&Y+l3)Kx#pHP+S1A zrDg4WI2&Z6Vc-NXhPem?Kx$xY6a(fTJ_mLlx*_PAL25v1Q4IL>d5JV$~JhJAy?*$mOp!!gfGP)ti;j_Q< zDZ|smi(t*jdf*1ESF8flT8a#eptKKh!Bemp$Yzjckh5Vn!vN0Q2udulv;hh*Y?%pf rZUkwtdNd1c@-ewItT~Z^fq?-4Q6tGnl;vkG00000NkvXXu0mjfEii|~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ae2fc/textures/items/fluid_storage.1024.png b/src/main/resources/assets/ae2fc/textures/items/fluid_storage.1024.png new file mode 100644 index 0000000000000000000000000000000000000000..dcefd928c5630659ea3bd18e595123c569037384 GIT binary patch literal 342 zcmV-c0jd6pP)=8@RS87%ZU`x0Vr`d~p;b0}EE2P|b5D%?Gnn@`C^4GK7hcW)J|eVXh%) z0J7$ys!}i}WC%D6KsebW=>Pv)AHldVB<=tIN58-r%!Z1C)WFoE7=TUl!v6nYjLQ(X z7oMz3|If!Gf-5{R07xxJ4_q8(I4j$)_9pINxcgoJ zB}u~#Sg%+GrnM9q7(r=8@RS87%ZU`x0Vr`d~p;b0}EE2P|b7FO2F)tS;7Bt8Nx(JGYEj#FxLSnj-7zpO3`zU{W7VPm4F5&J7{msN!Q??| zVF3?z!IO3A|M_@Cuz3+H0I3D(LGeOgR02cFtR6VKa@7)sAFJ1bF^CNkV*tlU51fr+ zK-c!eU_YW8g02~)2Ba1R!2I8t+6ng~%)iL~MpuJ15V0A8O%4`_@RV3>Ys{E3tLHz= zi69y|`aoi3p0;3b+=8@RS87%ZU`x0Vr`d~p;b0}EE2P|b5Xrh(Zh6~X^;8Nx(JGYEj#FxL=8@RS87%ZU`x0Vr`d~p;b0}EE2P|dxu*${<`g8$<(go%)5unS|e;jSTQ z0J7%B^((;`pCL^6G}i})gE2lsnDA+4igE^He1?Dxc(N}2KOc_>HZNiYAhjSpC@uim zQoML7oDH(^-?F`64090(fYiX)C2UcuK6cHD)YcJoP`!77&db@-Ul0F1h<& zfKdyo4<#w18-g4@J6j(z+)q3U){LwNZoqoQDlo03$iN6n`w$mA1dD-e25AQ62bj$; zfHOCO5(_MCfC3C#X2P2rK^m+c%>tWzOfC&;PGn$UU;qFs{oMOlT>oMK0000=8@RS87%ZU`x0Vr`d~p;b0~1!AP|b7ZuVnyXm_gV8Rs&#~VE~^Y7zUtd zK64C$@fgB{SF?!~1QRd>9EiytLI3|h{|~{NkAmrrj*kD6CQU*S17VO_SirM@h$rjP z|MT&PU>N-M>sJOwM$8BRsRij_U|@hq7KWt3O-6SGHrqioNDoRFY?!hD?8lVEV2A+B z@3637U;xX3)PU5Y0GO%ktLJ071kGk-HCO`?n<3cbP*N|5bFZ}(!w`@^Vc~=8@RS87%ZU`x0Vr`d~p;b0}EE2P|b5H+rjLV_Tc}x3}GUq83aIVm}>|c zfULP_axWO;GlU7B=DyrwFeYROI1rOPg8u(McoU2ZL(;&s-T(h!j4TGiAhoc72fN_O zy7d2iJR;bIHG`wYFjyg6suk%?{>C@Z^t@l&fux8B^LT!D(T}n(c6L5PMnGHHI^ZhZyd@ z7eGnUa0AvWR)J|PMFvJt+6Ng@H2E4>EF;7dtQnLaw9w)eXKn