diff --git a/gradle.properties b/gradle.properties index b77e19579..98794801b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ aebasename=appliedenergistics2 ######################################################### minecraft_version=1.12.2 mcp_mappings=snapshot_20171003 -forge_version=14.23.1.2554 +forge_version=14.23.3.2655 ######################################################### # Installable # diff --git a/src/api/java/appeng/api/definitions/IItems.java b/src/api/java/appeng/api/definitions/IItems.java index 5ea20f2ad..e7acf2686 100644 --- a/src/api/java/appeng/api/definitions/IItems.java +++ b/src/api/java/appeng/api/definitions/IItems.java @@ -88,6 +88,14 @@ public interface IItems IItemDefinition cell64k(); + IItemDefinition fluidCell1k(); + + IItemDefinition fluidCell4k(); + + IItemDefinition fluidCell16k(); + + IItemDefinition fluidCell64k(); + IItemDefinition spatialCell2(); IItemDefinition spatialCell16(); diff --git a/src/api/java/appeng/api/definitions/IMaterials.java b/src/api/java/appeng/api/definitions/IMaterials.java index 0a4ef10e2..5fcab30dc 100644 --- a/src/api/java/appeng/api/definitions/IMaterials.java +++ b/src/api/java/appeng/api/definitions/IMaterials.java @@ -134,4 +134,12 @@ public interface IMaterials IItemDefinition qESingularity(); IItemDefinition blankPattern(); + + IItemDefinition fluidCell1kPart(); + + IItemDefinition fluidCell4kPart(); + + IItemDefinition fluidCell16kPart(); + + IItemDefinition fluidCell64kPart(); } diff --git a/src/api/java/appeng/api/definitions/IParts.java b/src/api/java/appeng/api/definitions/IParts.java index 324721283..3491500cf 100644 --- a/src/api/java/appeng/api/definitions/IParts.java +++ b/src/api/java/appeng/api/definitions/IParts.java @@ -39,7 +39,7 @@ public interface IParts AEColoredItemDefinition cableGlass(); AEColoredItemDefinition cableDenseCovered(); - + AEColoredItemDefinition cableDenseSmart(); AEColoredItemDefinition lumenCableSmart(); @@ -107,4 +107,12 @@ public interface IParts IItemDefinition storageMonitor(); IItemDefinition conversionMonitor(); + + IItemDefinition fluidTerminal(); + + IItemDefinition fluidImportBus(); + + IItemDefinition fluidExportBus(); + + IItemDefinition fluidStorageBus(); } diff --git a/src/api/java/appeng/api/implementations/items/IStorageCell.java b/src/api/java/appeng/api/implementations/items/IStorageCell.java index b2b35463f..4e50a179b 100644 --- a/src/api/java/appeng/api/implementations/items/IStorageCell.java +++ b/src/api/java/appeng/api/implementations/items/IStorageCell.java @@ -27,7 +27,8 @@ package appeng.api.implementations.items; import net.minecraft.item.ItemStack; import appeng.api.storage.ICellWorkbenchItem; -import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.data.IAEStack; /** @@ -40,7 +41,7 @@ import appeng.api.storage.data.IAEItemStack; * * The standard AE implementation only provides 1-63 Types */ -public interface IStorageCell extends ICellWorkbenchItem +public interface IStorageCell> extends ICellWorkbenchItem { /** @@ -82,7 +83,7 @@ public interface IStorageCell extends ICellWorkbenchItem * * @return true to preventAdditionOfItem */ - boolean isBlackListed( ItemStack cellItem, IAEItemStack requestedAddition ); + boolean isBlackListed( ItemStack cellItem, T requestedAddition ); /** * Allows you to specify if this storage cell can be stored inside other @@ -109,4 +110,9 @@ public interface IStorageCell extends ICellWorkbenchItem * @return drain in ae/t this storage cell will use. */ double getIdleDrain(); + + /** + * @return the type of channel your cell should be part of + */ + IStorageChannel getChannel(); } diff --git a/src/api/java/appeng/api/storage/ICellInventory.java b/src/api/java/appeng/api/storage/ICellInventory.java index 122541c01..36e1cef22 100644 --- a/src/api/java/appeng/api/storage/ICellInventory.java +++ b/src/api/java/appeng/api/storage/ICellInventory.java @@ -28,10 +28,10 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.items.IItemHandler; import appeng.api.config.FuzzyMode; -import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAEStack; -public interface ICellInventory extends IMEInventory +public interface ICellInventory> extends IMEInventory { /** diff --git a/src/api/java/appeng/api/storage/ICellInventoryHandler.java b/src/api/java/appeng/api/storage/ICellInventoryHandler.java index 3f1e77ad9..45716fd9b 100644 --- a/src/api/java/appeng/api/storage/ICellInventoryHandler.java +++ b/src/api/java/appeng/api/storage/ICellInventoryHandler.java @@ -25,10 +25,10 @@ package appeng.api.storage; import appeng.api.config.IncludeExclude; -import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAEStack; -public interface ICellInventoryHandler extends IMEInventoryHandler +public interface ICellInventoryHandler> extends IMEInventoryHandler { /** diff --git a/src/main/java/appeng/client/gui/AEBaseGui.java b/src/main/java/appeng/client/gui/AEBaseGui.java index b399553b9..13e68a87a 100644 --- a/src/main/java/appeng/client/gui/AEBaseGui.java +++ b/src/main/java/appeng/client/gui/AEBaseGui.java @@ -46,6 +46,8 @@ import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.ClickType; @@ -54,6 +56,8 @@ import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; import appeng.api.storage.data.IAEItemStack; import appeng.client.gui.widgets.GuiScrollbar; @@ -66,7 +70,8 @@ import appeng.container.AEBaseContainer; import appeng.container.slot.AppEngCraftingSlot; import appeng.container.slot.AppEngSlot; import appeng.container.slot.AppEngSlot.hasCalculatedValidness; -import appeng.container.slot.OptionalSlotFake; +import appeng.container.slot.IOptionalSlot; +import appeng.container.slot.ISlotFluid; import appeng.container.slot.SlotCraftingTerm; import appeng.container.slot.SlotDisabled; import appeng.container.slot.SlotFake; @@ -208,6 +213,23 @@ public abstract class AEBaseGui extends GuiContainer this.drawHoveringText( lines, x, y, this.fontRenderer ); } + @Override + protected void renderHoveredToolTip( int mouseX, int mouseY ) + { + Slot slot = this.getSlot( mouseX, mouseY ); + if( slot != null && slot.isEnabled() && slot instanceof ISlotFluid ) + { + ISlotFluid fluidSlot = (ISlotFluid) slot; + if( fluidSlot.getFluidInSlot() != null && fluidSlot.shouldRenderAsFluid() ) + { + FluidStack fluidStack = fluidSlot.getFluidInSlot(); + this.drawHoveringText( fluidStack.getLocalizedName(), mouseX, mouseY ); + return; + } + } + super.renderHoveredToolTip( mouseX, mouseY ); + } + @Override protected final void drawGuiContainerForegroundLayer( final int x, final int y ) { @@ -236,21 +258,22 @@ public abstract class AEBaseGui extends GuiContainer final List slots = this.getInventorySlots(); for( final Slot slot : slots ) { - if( slot instanceof OptionalSlotFake ) + if( slot instanceof IOptionalSlot ) { - final OptionalSlotFake fs = (OptionalSlotFake) slot; - if( fs.renderDisabled() ) + final IOptionalSlot optionalSlot = (IOptionalSlot) slot; + if( optionalSlot.isRenderDisabled() ) { - if( fs.isSlotEnabled() ) + final AppEngSlot aeSlot = (AppEngSlot) slot; + if( aeSlot.isSlotEnabled() ) { - this.drawTexturedModalRect( ox + fs.xPos - 1, oy + fs.yPos - 1, fs.getSourceX() - 1, fs.getSourceY() - 1, 18, + this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18 ); } else { GlStateManager.color( 1.0F, 1.0F, 1.0F, 0.4F ); GlStateManager.enableBlend(); - this.drawTexturedModalRect( ox + fs.xPos - 1, oy + fs.yPos - 1, fs.getSourceX() - 1, fs.getSourceY() - 1, 18, + this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18 ); GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F ); } @@ -715,6 +738,32 @@ public abstract class AEBaseGui extends GuiContainer return; } + else if( s instanceof ISlotFluid && ( (ISlotFluid) s ).shouldRenderAsFluid() ) + { + FluidStack fs = ( (ISlotFluid) s ).getFluidInSlot(); + if( fs != null ) + { + GlStateManager.disableLighting(); + Fluid fluid = fs.getFluid(); + Minecraft.getMinecraft().getTextureManager().bindTexture( TextureMap.LOCATION_BLOCKS_TEXTURE ); + TextureAtlasSprite sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite( fluid.getStill().toString() ); + + // Set color for dynamic fluids + // Convert int color to RGB + float red = ( fluid.getColor() >> 16 & 255 ) / 255.0F; + float green = ( fluid.getColor() >> 8 & 255 ) / 255.0F; + float blue = ( fluid.getColor() & 255 ) / 255.0F; + GlStateManager.color( red, green, blue ); + + this.drawTexturedModalRect( s.xPos, s.yPos, sprite, 16, 16 ); + GlStateManager.enableLighting(); + } + if( !this.isPowered() ) + { + drawRect( s.xPos, s.yPos, 16 + s.xPos, 16 + s.yPos, 0x66111111 ); + } + return; + } else { try diff --git a/src/main/java/appeng/client/gui/implementations/GuiFluidIO.java b/src/main/java/appeng/client/gui/implementations/GuiFluidIO.java new file mode 100644 index 000000000..e556f66ef --- /dev/null +++ b/src/main/java/appeng/client/gui/implementations/GuiFluidIO.java @@ -0,0 +1,48 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.client.gui.implementations; + + +import net.minecraft.entity.player.InventoryPlayer; + +import appeng.api.implementations.IUpgradeableHost; +import appeng.container.implementations.ContainerFluidIO; +import appeng.core.localization.GuiText; +import appeng.fluids.parts.PartFluidImportBus; + + +/** + * @author BrockWS + * @version rv5 - 1/05/2018 + * @since rv5 1/05/2018 + */ +public class GuiFluidIO extends GuiUpgradeable +{ + + public GuiFluidIO( InventoryPlayer inventoryPlayer, IUpgradeableHost te ) + { + super( new ContainerFluidIO( inventoryPlayer, te ) ); + } + + @Override + protected GuiText getName() + { + return this.bc instanceof PartFluidImportBus ? GuiText.ImportBusFluids : GuiText.ExportBusFluids; + } +} diff --git a/src/main/java/appeng/client/gui/implementations/GuiFluidStorageBus.java b/src/main/java/appeng/client/gui/implementations/GuiFluidStorageBus.java new file mode 100644 index 000000000..bac27ad10 --- /dev/null +++ b/src/main/java/appeng/client/gui/implementations/GuiFluidStorageBus.java @@ -0,0 +1,153 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.client.gui.implementations; + + +import java.io.IOException; + +import org.lwjgl.input.Mouse; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.InventoryPlayer; + +import appeng.api.config.AccessRestriction; +import appeng.api.config.ActionItems; +import appeng.api.config.FuzzyMode; +import appeng.api.config.Settings; +import appeng.api.config.StorageFilter; +import appeng.client.gui.widgets.GuiImgButton; +import appeng.client.gui.widgets.GuiTabButton; +import appeng.container.implementations.ContainerFluidStorageBus; +import appeng.core.AELog; +import appeng.core.localization.GuiText; +import appeng.core.sync.GuiBridge; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketConfigButton; +import appeng.core.sync.packets.PacketSwitchGuis; +import appeng.core.sync.packets.PacketValueConfig; +import appeng.fluids.parts.PartFluidStorageBus; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class GuiFluidStorageBus extends GuiUpgradeable +{ + private GuiImgButton rwMode; + private GuiImgButton storageFilter; + private GuiTabButton priority; + private GuiImgButton partition; + private GuiImgButton clear; + + public GuiFluidStorageBus( InventoryPlayer inventoryPlayer, PartFluidStorageBus te ) + { + super( new ContainerFluidStorageBus( inventoryPlayer, te ) ); + this.ySize = 251; + } + + @Override + protected void addButtons() + { + this.clear = new GuiImgButton( this.guiLeft - 18, this.guiTop + 8, Settings.ACTIONS, ActionItems.CLOSE ); + this.partition = new GuiImgButton( this.guiLeft - 18, this.guiTop + 28, Settings.ACTIONS, ActionItems.WRENCH ); + this.rwMode = new GuiImgButton( this.guiLeft - 18, this.guiTop + 48, Settings.ACCESS, AccessRestriction.READ_WRITE ); + this.storageFilter = new GuiImgButton( this.guiLeft - 18, this.guiTop + 68, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY ); + this.fuzzyMode = new GuiImgButton( this.guiLeft - 18, this.guiTop + 88, Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL ); + + this.buttonList.add( this.priority = new GuiTabButton( this.guiLeft + 154, this.guiTop, 2 + 4 * 16, GuiText.Priority.getLocal(), this.itemRender ) ); + + this.buttonList.add( this.storageFilter ); + this.buttonList.add( this.fuzzyMode ); + this.buttonList.add( this.rwMode ); + this.buttonList.add( this.partition ); + this.buttonList.add( this.clear ); + } + + @Override + public void drawFG( final int offsetX, final int offsetY, final int mouseX, final int mouseY ) + { + this.fontRenderer.drawString( this.getGuiDisplayName( this.getName().getLocal() ), 8, 6, 4210752 ); + this.fontRenderer.drawString( GuiText.inventory.getLocal(), 8, this.ySize - 96 + 3, 4210752 ); + + if( this.fuzzyMode != null ) + { + this.fuzzyMode.set( this.cvb.getFuzzyMode() ); + } + + if( this.storageFilter != null ) + { + this.storageFilter.set( ( (ContainerFluidStorageBus) this.cvb ).getStorageFilter() ); + } + + if( this.rwMode != null ) + { + this.rwMode.set( ( (ContainerFluidStorageBus) this.cvb ).getReadWriteMode() ); + } + } + + @Override + protected String getBackground() + { + return "guis/storagebus.png"; + } + + @Override + protected void actionPerformed( final GuiButton btn ) throws IOException + { + super.actionPerformed( btn ); + + final boolean backwards = Mouse.isButtonDown( 1 ); + + try + { + if( btn == this.partition ) + { + NetworkHandler.instance().sendToServer( new PacketValueConfig( "StorageBus.Action", "Partition" ) ); + } + else if( btn == this.clear ) + { + NetworkHandler.instance().sendToServer( new PacketValueConfig( "StorageBus.Action", "Clear" ) ); + } + else if( btn == this.priority ) + { + NetworkHandler.instance().sendToServer( new PacketSwitchGuis( GuiBridge.GUI_PRIORITY ) ); + } + else if( btn == this.rwMode ) + { + NetworkHandler.instance().sendToServer( new PacketConfigButton( this.rwMode.getSetting(), backwards ) ); + } + else if( btn == this.storageFilter ) + { + NetworkHandler.instance().sendToServer( new PacketConfigButton( this.storageFilter.getSetting(), backwards ) ); + } + } + catch( final IOException e ) + { + AELog.debug( e ); + } + } + + @Override + protected GuiText getName() + { + return GuiText.StorageBusFluids; + } +} diff --git a/src/main/java/appeng/client/gui/implementations/GuiFluidTerminal.java b/src/main/java/appeng/client/gui/implementations/GuiFluidTerminal.java new file mode 100644 index 000000000..30b3090e5 --- /dev/null +++ b/src/main/java/appeng/client/gui/implementations/GuiFluidTerminal.java @@ -0,0 +1,362 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.client.gui.implementations; + + +import java.io.IOException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.lwjgl.input.Mouse; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.ClickType; +import net.minecraft.inventory.Slot; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fml.common.Loader; + +import appeng.api.config.Settings; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.util.IConfigManager; +import appeng.api.util.IConfigurableObject; +import appeng.client.gui.AEBaseMEGui; +import appeng.client.gui.widgets.GuiImgButton; +import appeng.client.gui.widgets.GuiScrollbar; +import appeng.client.gui.widgets.ISortSource; +import appeng.client.gui.widgets.MEGuiTextField; +import appeng.client.me.FluidRepo; +import appeng.client.me.SlotFluidME; +import appeng.client.me.InternalFluidSlotME; +import appeng.container.implementations.ContainerFluidTerminal; +import appeng.container.slot.ISlotFluid; +import appeng.core.AELog; +import appeng.core.localization.GuiText; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketInventoryAction; +import appeng.core.sync.packets.PacketValueConfig; +import appeng.helpers.InventoryAction; +import appeng.parts.reporting.PartFluidTerminal; +import appeng.util.IConfigManagerHost; +import appeng.util.Platform; +import appeng.util.item.AEFluidStack; + + +/** + * @author BrockWS + * @version rv6 - 12/05/2018 + * @since rv6 12/05/2018 + */ +public class GuiFluidTerminal extends AEBaseMEGui implements ISortSource, IConfigManagerHost +{ + private final List meFluidSlots = new LinkedList<>(); + private final FluidRepo repo; + private final IConfigManager configSrc; + private final ContainerFluidTerminal container; + private final int offsetX = 9; + private int rows = 6; + private int maxRows = Integer.MAX_VALUE; + private int perRow = 9; + + protected PartFluidTerminal terminal; + + private MEGuiTextField searchField; + private GuiImgButton sortByBox; + private GuiImgButton sortDirBox; + + public GuiFluidTerminal( InventoryPlayer inventoryPlayer, PartFluidTerminal terminal ) + { + super( new ContainerFluidTerminal( inventoryPlayer, terminal ) ); + this.terminal = terminal; + this.xSize = 185; + this.ySize = 222; + final GuiScrollbar scrollbar = new GuiScrollbar(); + this.setScrollBar( scrollbar ); + this.repo = new FluidRepo( scrollbar, this ); + this.configSrc = ( (IConfigurableObject) this.inventorySlots ).getConfigManager(); + ( this.container = (ContainerFluidTerminal) this.inventorySlots ).setGui( this ); + } + + @Override + public void initGui() + { + this.mc.player.openContainer = this.inventorySlots; + this.guiLeft = ( this.width - this.xSize ) / 2; + this.guiTop = ( this.height - this.ySize ) / 2; + + this.searchField = new MEGuiTextField( this.fontRenderer, this.guiLeft + Math.max( 80, this.offsetX ), this.guiTop + 4, 90, 12 ); + this.searchField.setEnableBackgroundDrawing( false ); + this.searchField.setMaxStringLength( 25 ); + this.searchField.setTextColor( 0xFFFFFF ); + this.searchField.setSelectionColor( 0xFF99FF99 ); + this.searchField.setVisible( true ); + + int offset = this.guiTop; + + this.buttonList.add( this.sortByBox = new GuiImgButton( this.guiLeft - 18, offset, Settings.SORT_BY, this.configSrc.getSetting( Settings.SORT_BY ) ) ); + offset += 20; + + this.buttonList.add( this.sortDirBox = new GuiImgButton( this.guiLeft - 18, offset, Settings.SORT_DIRECTION, this.configSrc.getSetting( Settings.SORT_DIRECTION ) ) ); + + for( int y = 0; y < this.rows; y++ ) + { + for( int x = 0; x < this.perRow; x++ ) + { + SlotFluidME slot = new SlotFluidME( new InternalFluidSlotME( this.repo, x + y * this.perRow, this.offsetX + x * 18, 18 + y * 18 ) ); + this.getMeFluidSlots().add( slot ); + this.inventorySlots.inventorySlots.add( slot ); + } + } + this.setScrollBar(); + } + + @Override + public void drawFG( int offsetX, int offsetY, int mouseX, int mouseY ) + { + this.fontRenderer.drawString( this.getGuiDisplayName( "Fluid Terminal" ), 8, 6, 4210752 ); + this.fontRenderer.drawString( GuiText.inventory.getLocal(), 8, this.ySize - 96 + 3, 4210752 ); + } + + @Override + public void drawBG( int offsetX, int offsetY, int mouseX, int mouseY ) + { + this.bindTexture( this.getBackground() ); + final int x_width = 197; + this.drawTexturedModalRect( offsetX, offsetY, 0, 0, x_width, 18 ); + + for( int x = 0; x < 6; x++ ) + { + this.drawTexturedModalRect( offsetX, offsetY + 18 + x * 18, 0, 18, x_width, 18 ); + } + + this.drawTexturedModalRect( offsetX, offsetY + 16 + 6 * 18, 0, 106 - 18 - 18, x_width, 99 + 77 ); + + if( this.searchField != null ) + { + this.searchField.drawTextBox(); + } + } + + @Override + public void updateScreen() + { + this.repo.setPower( this.container.isPowered() ); + super.updateScreen(); + } + + @Override + protected void renderHoveredToolTip( int mouseX, int mouseY ) + { + Slot slot = this.getSlot( mouseX, mouseY ); + if( slot != null && slot.isEnabled() && slot instanceof ISlotFluid ) + { + ISlotFluid fluidSlot = (ISlotFluid) slot; + if( fluidSlot.getFluidInSlot() != null && fluidSlot.shouldRenderAsFluid() ) + { + FluidStack fluidStack = fluidSlot.getFluidInSlot(); + List list = new ArrayList<>(); + list.add( fluidStack.getLocalizedName() ); + int amount = fluidStack.amount; + DecimalFormat formatter = new DecimalFormat( "#,###.##" ); + String amountStr = formatter.format( amount ) + "mb"; + if( amount >= 10000 ) + { + amountStr += " ( "; + amountStr += formatter.format( amount / 1000 ) + "B"; + amountStr += " )"; + } + list.add( amountStr ); + String modName = ""; + modName += TextFormatting.BLUE; + modName += TextFormatting.ITALIC; + modName += Loader.instance().getIndexedModList().get( Platform.getModId( AEFluidStack.fromFluidStack( fluidStack ) ) ).getName(); + list.add( modName ); + this.drawHoveringText( list, mouseX, mouseY ); + return; + } + } + super.renderHoveredToolTip( mouseX, mouseY ); + } + + @Override + protected void actionPerformed( GuiButton btn ) throws IOException + { + if( btn instanceof GuiImgButton ) + { + final boolean backwards = Mouse.isButtonDown( 1 ); + + final GuiImgButton iBtn = (GuiImgButton) btn; + if( iBtn.getSetting() != Settings.ACTIONS ) + { + final Enum cv = iBtn.getCurrentValue(); + final Enum next = Platform.rotateEnum( cv, backwards, iBtn.getSetting().getPossibleValues() ); + + try + { + NetworkHandler.instance().sendToServer( new PacketValueConfig( iBtn.getSetting().name(), next.name() ) ); + } + catch( final IOException e ) + { + AELog.debug( e ); + } + + iBtn.set( next ); + } + } + } + + @Override + protected void handleMouseClick( Slot slot, int slotIdx, int mouseButton, ClickType clickType ) + { + if( slot instanceof SlotFluidME ) + { + SlotFluidME meSlot = (SlotFluidME) slot; + if( clickType == ClickType.PICKUP ) + { + // TODO: Allow more options + if( mouseButton == 0 && meSlot.getHasStack() ) + { + this.container.setTargetStack( meSlot.getAEStack() ); + AELog.info( "mouse0 GUI STACK SIZE %s", meSlot.getAEStack().getStackSize() ); + NetworkHandler.instance().sendToServer( new PacketInventoryAction( InventoryAction.FILL_ITEM, slot.slotNumber, 0 ) ); + } + else + { + this.container.setTargetStack( meSlot.getAEStack() ); + if( meSlot.getAEStack() != null ) + { + AELog.info( "mouse1 GUI STACK SIZE %s", meSlot.getAEStack().getStackSize() ); + } + NetworkHandler.instance().sendToServer( new PacketInventoryAction( InventoryAction.EMPTY_ITEM, slot.slotNumber, 0 ) ); + } + } + return; + } + super.handleMouseClick( slot, slotIdx, mouseButton, clickType ); + } + + @Override + protected void keyTyped( final char character, final int key ) throws IOException + { + if( !this.checkHotbarKeys( key ) ) + { + if( character == ' ' && this.searchField.getText().isEmpty() ) + { + return; + } + + if( this.searchField.textboxKeyTyped( character, key ) ) + { + this.repo.setSearchString( this.searchField.getText() ); + this.repo.updateView(); + this.setScrollBar(); + } + else + { + super.keyTyped( character, key ); + } + } + } + + @Override + protected void mouseClicked( final int xCoord, final int yCoord, final int btn ) throws IOException + { + this.searchField.mouseClicked( xCoord, yCoord, btn ); + + if( btn == 1 && this.searchField.isMouseIn( xCoord, yCoord ) ) + { + this.searchField.setText( "" ); + this.repo.setSearchString( "" ); + this.repo.updateView(); + this.setScrollBar(); + } + + super.mouseClicked( xCoord, yCoord, btn ); + } + + public void postUpdate( final List list ) + { + for( final IAEFluidStack is : list ) + { + this.repo.postUpdate( is ); + } + + this.repo.updateView(); + this.setScrollBar(); + } + + private void setScrollBar() + { + this.getScrollBar().setTop( 18 ).setLeft( 175 ).setHeight( this.rows * 18 - 2 ); + this.getScrollBar().setRange( 0, ( this.repo.size() + this.perRow - 1 ) / this.perRow - this.rows, Math.max( 1, this.rows / 6 ) ); + } + + @Override + public Enum getSortBy() + { + return this.configSrc.getSetting( Settings.SORT_BY ); + } + + @Override + public Enum getSortDir() + { + return this.configSrc.getSetting( Settings.SORT_DIRECTION ); + } + + @Override + public Enum getSortDisplay() + { + return this.configSrc.getSetting( Settings.VIEW_MODE ); + } + + @Override + public void updateSetting( IConfigManager manager, Enum settingName, Enum newValue ) + { + if( this.sortByBox != null ) + { + this.sortByBox.set( this.configSrc.getSetting( Settings.SORT_BY ) ); + } + + if( this.sortDirBox != null ) + { + this.sortDirBox.set( this.configSrc.getSetting( Settings.SORT_DIRECTION ) ); + } + + this.repo.updateView(); + } + + protected List getMeFluidSlots() + { + return this.meFluidSlots; + } + + @Override + protected boolean isPowered() + { + return this.repo.hasPower(); + } + + protected String getBackground() + { + return "guis/terminal.png"; + } +} diff --git a/src/main/java/appeng/client/me/FluidRepo.java b/src/main/java/appeng/client/me/FluidRepo.java new file mode 100644 index 000000000..1fb622d3d --- /dev/null +++ b/src/main/java/appeng/client/me/FluidRepo.java @@ -0,0 +1,243 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.client.me; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; + +import javax.annotation.Nonnull; + +import appeng.api.AEApi; +import appeng.api.config.Settings; +import appeng.api.config.SortOrder; +import appeng.api.config.ViewItems; +import appeng.api.config.YesNo; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.client.gui.widgets.IScrollSource; +import appeng.client.gui.widgets.ISortSource; +import appeng.core.AEConfig; +import appeng.util.FluidSorters; +import appeng.util.Platform; +import appeng.util.prioritylist.IPartitionList; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class FluidRepo +{ + private final IItemList list = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); + private final ArrayList view = new ArrayList<>(); + private final IScrollSource src; + private final ISortSource sortSrc; + + private int rowSize = 9; + + private String searchString = ""; + private IPartitionList myPartitionList; + private boolean hasPower; + + public FluidRepo( final IScrollSource src, final ISortSource sortSrc ) + { + this.src = src; + this.sortSrc = sortSrc; + } + + public void updateView() + { + this.view.clear(); + + this.view.ensureCapacity( this.list.size() ); + + String innerSearch = this.searchString; + + boolean searchMod = false; + if( innerSearch.startsWith( "@" ) ) + { + searchMod = true; + innerSearch = innerSearch.substring( 1 ); + } + + Pattern m; + try + { + m = Pattern.compile( innerSearch.toLowerCase(), Pattern.CASE_INSENSITIVE ); + } + catch( final Exception ignore1 ) + { + try + { + m = Pattern.compile( Pattern.quote( innerSearch.toLowerCase() ), Pattern.CASE_INSENSITIVE ); + } + catch( final Exception ignore2 ) + { + return; + } + } + + final Enum viewMode = this.sortSrc.getSortDisplay(); + final boolean needsZeroCopy = viewMode == ViewItems.CRAFTABLE; + final boolean terminalSearchToolTips = AEConfig.instance().getConfigManager().getSetting( Settings.SEARCH_TOOLTIPS ) != YesNo.NO; + + boolean notDone = false; + for( IAEFluidStack fs : this.list ) + { + if( this.myPartitionList != null && !this.myPartitionList.isListed( fs ) ) + { + continue; + } + + if( viewMode == ViewItems.CRAFTABLE && !fs.isCraftable() ) + { + continue; + } + + if( viewMode == ViewItems.STORED && fs.getStackSize() == 0 ) + { + continue; + } + + final String dspName = searchMod ? Platform.getModId( fs ) : Platform.getFluidDisplayName( fs ); + boolean foundMatchingFluidStack = false; + notDone = true; + + if( m.matcher( dspName.toLowerCase() ).find() ) + { + notDone = false; + foundMatchingFluidStack = true; + } + + if( terminalSearchToolTips && notDone && !searchMod ) + { + final List tooltip = Platform.getTooltip( fs ); + + for( final String line : tooltip ) + { + if( m.matcher( line ).find() ) + { + foundMatchingFluidStack = true; + break; + } + } + } + + if( foundMatchingFluidStack ) + { + if( needsZeroCopy ) + { + fs = fs.copy(); + fs.setStackSize( 0 ); + } + + this.view.add( fs ); + } + } + + final Enum sortBy = this.sortSrc.getSortBy(); + final Enum sortDir = this.sortSrc.getSortDir(); + + FluidSorters.setDirection( (appeng.api.config.SortDir) sortDir ); + + if( sortBy == SortOrder.MOD ) + { + Collections.sort( this.view, FluidSorters.CONFIG_BASED_SORT_BY_MOD ); + } + else if( sortBy == SortOrder.AMOUNT ) + { + Collections.sort( this.view, FluidSorters.CONFIG_BASED_SORT_BY_SIZE ); + } + else + { + Collections.sort( this.view, FluidSorters.CONFIG_BASED_SORT_BY_NAME ); + } + } + + public void postUpdate( final IAEFluidStack is ) + { + final IAEFluidStack st = this.list.findPrecise( is ); + + if( st != null ) + { + st.reset(); + st.add( is ); + } + else + { + this.list.add( is ); + } + } + + public IAEFluidStack getReferenceFluid( int idx ) + { + idx += this.src.getCurrentScroll() * this.rowSize; + + if( idx >= this.view.size() ) + { + return null; + } + return this.view.get( idx ); + } + + public int size() + { + return this.view.size(); + } + + public void clear() + { + this.list.resetStatus(); + } + + public boolean hasPower() + { + return this.hasPower; + } + + public void setPower( final boolean hasPower ) + { + this.hasPower = hasPower; + } + + public int getRowSize() + { + return this.rowSize; + } + + public void setRowSize( final int rowSize ) + { + this.rowSize = rowSize; + } + + public String getSearchString() + { + return this.searchString; + } + + public void setSearchString( @Nonnull final String searchString ) + { + this.searchString = searchString; + } +} diff --git a/src/main/java/appeng/client/me/InternalFluidSlotME.java b/src/main/java/appeng/client/me/InternalFluidSlotME.java new file mode 100644 index 000000000..140b85dab --- /dev/null +++ b/src/main/java/appeng/client/me/InternalFluidSlotME.java @@ -0,0 +1,72 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.client.me; + + +import net.minecraftforge.fluids.FluidStack; + +import appeng.api.storage.data.IAEFluidStack; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class InternalFluidSlotME +{ + + private final int offset; + private final int xPos; + private final int yPos; + private final FluidRepo repo; + + public InternalFluidSlotME( final FluidRepo def, final int offset, final int displayX, final int displayY ) + { + this.repo = def; + this.offset = offset; + this.xPos = displayX; + this.yPos = displayY; + } + + FluidStack getStack() + { + return this.getAEStack() == null ? null : this.getAEStack().getFluidStack(); + } + + IAEFluidStack getAEStack() + { + return this.repo.getReferenceFluid( this.offset ); + } + + boolean hasPower() + { + return this.repo.hasPower(); + } + + int getxPosition() + { + return this.xPos; + } + + int getyPosition() + { + return this.yPos; + } +} diff --git a/src/main/java/appeng/client/me/SlotFluidME.java b/src/main/java/appeng/client/me/SlotFluidME.java new file mode 100644 index 000000000..224420dc8 --- /dev/null +++ b/src/main/java/appeng/client/me/SlotFluidME.java @@ -0,0 +1,117 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.client.me; + + +import javax.annotation.Nonnull; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.items.SlotItemHandler; + +import appeng.api.storage.data.IAEFluidStack; +import appeng.container.slot.ISlotFluid; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class SlotFluidME extends SlotItemHandler implements ISlotFluid +{ + private InternalFluidSlotME slot; + + public SlotFluidME( InternalFluidSlotME slot ) + { + super( null, 0, slot.getxPosition(), slot.getyPosition() ); + this.slot = slot; + } + + public IAEFluidStack getAEStack() + { + if( this.slot.hasPower() ) + { + return this.slot.getAEStack(); + } + return null; + } + + @Override + public boolean isItemValid( final ItemStack par1ItemStack ) + { + return false; + } + + @Nonnull + @Override + public ItemStack getStack() + { + return ItemStack.EMPTY; + } + + @Override + public FluidStack getFluidInSlot() + { + return this.slot.getStack(); + } + + @Override + public boolean getHasStack() + { + if( this.slot.hasPower() ) + { + return this.getAEStack() != null; + } + return false; + } + + @Override + public void putStack( final ItemStack par1ItemStack ) + { + + } + + @Override + public int getSlotStackLimit() + { + return 0; + } + + @Nonnull + @Override + public ItemStack decrStackSize( final int par1 ) + { + return ItemStack.EMPTY; + } + + @Override + public boolean isHere( final IInventory inv, final int slotIn ) + { + return false; + } + + @Override + public boolean canTakeStack( final EntityPlayer par1EntityPlayer ) + { + return false; + } +} diff --git a/src/main/java/appeng/client/render/DummyFluidBakedModel.java b/src/main/java/appeng/client/render/DummyFluidBakedModel.java new file mode 100644 index 000000000..4ad226914 --- /dev/null +++ b/src/main/java/appeng/client/render/DummyFluidBakedModel.java @@ -0,0 +1,84 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.client.render; + + +import java.util.List; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemOverrideList; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.util.EnumFacing; + + +/** + * @author DrummerMC + * @version rv6 - 2018-01-22 + * @since rv6 2018-01-22 + */ +public class DummyFluidBakedModel implements IBakedModel +{ + private final ImmutableList quads; + public DummyFluidBakedModel( ImmutableList quads ) + { + this.quads = quads; + } + + @Override + public List getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand ) + { + return quads; + } + + @Override + public boolean isAmbientOcclusion() + { + return false; + } + + @Override + public boolean isGui3d() + { + return false; + } + + @Override + public boolean isBuiltInRenderer() + { + return false; + } + + @Override + public TextureAtlasSprite getParticleTexture() + { + return null; + } + + @Override + public ItemOverrideList getOverrides() + { + return null; + } +} diff --git a/src/main/java/appeng/client/render/DummyFluidDispatcherBakedModel.java b/src/main/java/appeng/client/render/DummyFluidDispatcherBakedModel.java new file mode 100644 index 000000000..573dda52a --- /dev/null +++ b/src/main/java/appeng/client/render/DummyFluidDispatcherBakedModel.java @@ -0,0 +1,117 @@ +/* + * 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.client.render; + + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemOverrideList; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.client.model.ItemLayerModel; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +import appeng.fluids.items.FluidDummyItem; + + +/** + * This baked model class is used as a dispatcher to redirect the renderer to the *real* model that should be used based + * on the item stack. + * A custom Item Override List is used to accomplish this. + */ +public class DummyFluidDispatcherBakedModel extends DelegateBakedModel +{ + private final VertexFormat format; + private final Function bakedTextureGetter; + + public DummyFluidDispatcherBakedModel( IBakedModel baseModel, VertexFormat format, Function bakedTextureGetter ) + { + super( baseModel ); + this.format = format; + this.bakedTextureGetter = bakedTextureGetter; + } + + // This is never used. See the item override list below. + @Override + public List getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand ) + { + return Collections.emptyList(); + } + + @Override + public boolean isGui3d() + { + return this.getBaseModel().isGui3d(); + } + + @Override + public boolean isBuiltInRenderer() + { + return false; + } + + @Override + public ItemOverrideList getOverrides() + { + return new ItemOverrideList( Collections.emptyList() ) + { + @Override + public IBakedModel handleItemState( IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity ) + { + if( !( stack.getItem() instanceof FluidDummyItem ) ) + { + return originalModel; + } + + FluidDummyItem itemFacade = (FluidDummyItem) stack.getItem(); + + FluidStack fluidStack = itemFacade.getFluidStack( stack ); + if( fluidStack == null ) + { + fluidStack = new FluidStack( FluidRegistry.WATER, Fluid.BUCKET_VOLUME ); + } + + TextureAtlasSprite sprite = bakedTextureGetter.apply( fluidStack.getFluid().getStill( fluidStack ) ); + if( sprite == null ) + { + return new DummyFluidBakedModel( ImmutableList.of() ); + } + + return new DummyFluidBakedModel( ItemLayerModel.getQuadsForSprite( 0, sprite, format, Optional.empty() ) ); + } + }; + } +} diff --git a/src/main/java/appeng/client/render/DummyFluidItemModel.java b/src/main/java/appeng/client/render/DummyFluidItemModel.java new file mode 100644 index 000000000..80f952e29 --- /dev/null +++ b/src/main/java/appeng/client/render/DummyFluidItemModel.java @@ -0,0 +1,89 @@ +/* + * 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.client.render; + + +import java.util.Collection; +import java.util.Collections; +import java.util.function.Function; + +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.model.IModel; +import net.minecraftforge.client.model.ModelLoaderRegistry; +import net.minecraftforge.common.model.IModelState; + +import appeng.core.AppEng; + + +/** + * The model class for facades. Since facades wrap existing models, they don't declare any dependencies here other + * than the cable anchor. + */ +public class DummyFluidItemModel implements IModel +{ + // We use this to get the default item transforms and make our lives easier + private static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/dummy_fluid_item_base" ); + + private IModel baseModel = null; + + private IModel getBaseModel() + { + if( this.baseModel == null ) + { + try + { + baseModel = ModelLoaderRegistry.getModel( MODEL_BASE ); + } + catch( Exception e ) + { + throw new RuntimeException( e ); + } + } + return this.baseModel; + } + + @Override + public Collection getDependencies() + { + return Collections.emptyList(); + } + + @Override + public Collection getTextures() + { + return Collections.emptyList(); + } + + @Override + public IBakedModel bake( IModelState state, VertexFormat format, Function bakedTextureGetter ) + { + IBakedModel bakedBaseModel = this.getBaseModel().bake( state, format, bakedTextureGetter ); + + return new DummyFluidDispatcherBakedModel( bakedBaseModel, format, bakedTextureGetter ); + } + + @Override + public IModelState getDefaultState() + { + return getBaseModel().getDefaultState(); + } +} diff --git a/src/main/java/appeng/container/implementations/ContainerCellWorkbench.java b/src/main/java/appeng/container/implementations/ContainerCellWorkbench.java index 76dc341d8..9fe140cce 100644 --- a/src/main/java/appeng/container/implementations/ContainerCellWorkbench.java +++ b/src/main/java/appeng/container/implementations/ContainerCellWorkbench.java @@ -33,10 +33,12 @@ import appeng.api.AEApi; import appeng.api.config.CopyMode; import appeng.api.config.FuzzyMode; import appeng.api.config.Settings; +import appeng.api.implementations.items.IStorageCell; import appeng.api.storage.ICellWorkbenchItem; import appeng.api.storage.IMEInventory; +import appeng.api.storage.IStorageChannel; import appeng.api.storage.channels.IItemStorageChannel; -import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.container.guisync.GuiSync; import appeng.container.slot.OptionalSlotRestrictedInput; @@ -219,17 +221,20 @@ public class ContainerCellWorkbench extends ContainerUpgradeable public void partition() { + final IItemHandler inv = this.getUpgradeable().getInventoryByName( "config" ); - final IMEInventory cellInv = AEApi.instance().registries().cell().getCellInventory( - this.getUpgradeable().getInventoryByName( "cell" ).getStackInSlot( 0 ), null, - AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); + final ItemStack is = this.getUpgradeable().getInventoryByName( "cell" ).getStackInSlot( 0 ); + final IStorageChannel channel = is.getItem() instanceof IStorageCell ? ( (IStorageCell) is.getItem() ).getChannel() : AEApi.instance() + .storage() + .getStorageChannel( IItemStorageChannel.class ); - Iterator i = new NullIterator<>(); + final IMEInventory cellInv = AEApi.instance().registries().cell().getCellInventory( is, null, channel ); + + Iterator i = new NullIterator<>(); if( cellInv != null ) { - final IItemList list = cellInv - .getAvailableItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ); + final IItemList list = cellInv.getAvailableItems( channel.createList() ); i = list.iterator(); } diff --git a/src/main/java/appeng/container/implementations/ContainerFluidIO.java b/src/main/java/appeng/container/implementations/ContainerFluidIO.java new file mode 100644 index 000000000..6e161c979 --- /dev/null +++ b/src/main/java/appeng/container/implementations/ContainerFluidIO.java @@ -0,0 +1,74 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.container.implementations; + + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.items.IItemHandler; + +import appeng.api.implementations.IUpgradeableHost; +import appeng.container.slot.OptionalSlotFakeFluid; +import appeng.container.slot.SlotFakeFluid; + + +/** + * @author BrockWS + * @version rv5 - 1/05/2018 + * @since rv5 1/05/2018 + */ +public class ContainerFluidIO extends ContainerUpgradeable +{ + public ContainerFluidIO( InventoryPlayer ip, IUpgradeableHost te ) + { + super( ip, te ); + } + + @Override + protected void setupConfig() + { + this.setupUpgrades(); + + final IItemHandler inv = this.getUpgradeable().getInventoryByName( "config" ); + final int y = 40; + final int x = 80; + this.addSlotToContainer( new SlotFakeFluid( inv, 0, x, y ) ); + + if( this.supportCapacity() ) + { + this.addSlotToContainer( new OptionalSlotFakeFluid( inv, this, 1, x, y, -1, 0, 1 ) ); + this.addSlotToContainer( new OptionalSlotFakeFluid( inv, this, 2, x, y, 1, 0, 1 ) ); + this.addSlotToContainer( new OptionalSlotFakeFluid( inv, this, 3, x, y, 0, -1, 1 ) ); + this.addSlotToContainer( new OptionalSlotFakeFluid( inv, this, 4, x, y, 0, 1, 1 ) ); + + this.addSlotToContainer( new OptionalSlotFakeFluid( inv, this, 5, x, y, -1, -1, 2 ) ); + this.addSlotToContainer( new OptionalSlotFakeFluid( inv, this, 6, x, y, 1, -1, 2 ) ); + this.addSlotToContainer( new OptionalSlotFakeFluid( inv, this, 7, x, y, -1, 1, 2 ) ); + this.addSlotToContainer( new OptionalSlotFakeFluid( inv, this, 8, x, y, 1, 1, 2 ) ); + } + } + + @Override + public boolean isValidForSlot( Slot s, ItemStack i ) + { + return s instanceof SlotFakeFluid ? i.hasCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null ) : super.isValidForSlot( s, i ); + } +} diff --git a/src/main/java/appeng/container/implementations/ContainerFluidStorageBus.java b/src/main/java/appeng/container/implementations/ContainerFluidStorageBus.java new file mode 100644 index 000000000..ccfa5621a --- /dev/null +++ b/src/main/java/appeng/container/implementations/ContainerFluidStorageBus.java @@ -0,0 +1,196 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.container.implementations; + + +import java.util.Iterator; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +import appeng.api.AEApi; +import appeng.api.config.AccessRestriction; +import appeng.api.config.FuzzyMode; +import appeng.api.config.SecurityPermissions; +import appeng.api.config.Settings; +import appeng.api.config.StorageFilter; +import appeng.api.config.Upgrades; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.container.guisync.GuiSync; +import appeng.container.slot.OptionalSlotFakeFluid; +import appeng.container.slot.SlotFakeFluid; +import appeng.container.slot.SlotRestrictedInput; +import appeng.fluids.parts.PartFluidStorageBus; +import appeng.util.Platform; +import appeng.util.helpers.ItemHandlerUtil; +import appeng.util.iterators.NullIterator; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class ContainerFluidStorageBus extends ContainerUpgradeable +{ + + private final PartFluidStorageBus storageBus; + + @GuiSync( 3 ) + public AccessRestriction rwMode = AccessRestriction.READ_WRITE; + + @GuiSync( 4 ) + public StorageFilter storageFilter = StorageFilter.EXTRACTABLE_ONLY; + + public ContainerFluidStorageBus( InventoryPlayer ip, PartFluidStorageBus te ) + { + super( ip, te ); + this.storageBus = te; + } + + @Override + protected int getHeight() + { + return 251; + } + + @Override + protected void setupConfig() + { + final int xo = 8; + final int yo = 23 + 6; + + final IItemHandler config = this.getUpgradeable().getInventoryByName( "config" ); + for( int y = 0; y < 7; y++ ) + { + for( int x = 0; x < 9; x++ ) + { + if( y < 2 ) + { + this.addSlotToContainer( new SlotFakeFluid( config, y * 9 + x, xo + x * 18, yo + y * 18 ) ); + } + else + { + this.addSlotToContainer( new OptionalSlotFakeFluid( config, this, y * 9 + x, xo, yo, x, y, y - 2 ) ); + } + } + } + + final IItemHandler upgrades = this.getUpgradeable().getInventoryByName( "upgrades" ); + this.addSlotToContainer( ( new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 0, 187, 8, this.getInventoryPlayer() ) ).setNotDraggable() ); + this.addSlotToContainer( ( new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 1, 187, 8 + 18, this.getInventoryPlayer() ) ).setNotDraggable() ); + this.addSlotToContainer( ( new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 2, 187, 8 + 18 * 2, this.getInventoryPlayer() ) ).setNotDraggable() ); + this.addSlotToContainer( ( new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 3, 187, 8 + 18 * 3, this.getInventoryPlayer() ) ).setNotDraggable() ); + this.addSlotToContainer( ( new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.UPGRADES, upgrades, 4, 187, 8 + 18 * 4, this.getInventoryPlayer() ) ).setNotDraggable() ); + } + + @Override + protected boolean supportCapacity() + { + return true; + } + + @Override + public int availableUpgrades() + { + return 5; + } + + @Override + public void detectAndSendChanges() + { + this.verifyPermissions( SecurityPermissions.BUILD, false ); + + if( Platform.isServer() ) + { + this.setFuzzyMode( (FuzzyMode) this.getUpgradeable().getConfigManager().getSetting( Settings.FUZZY_MODE ) ); + this.setReadWriteMode( (AccessRestriction) this.getUpgradeable().getConfigManager().getSetting( Settings.ACCESS ) ); + this.setStorageFilter( (StorageFilter) this.getUpgradeable().getConfigManager().getSetting( Settings.STORAGE_FILTER ) ); + } + + this.standardDetectAndSendChanges(); + } + + @Override + public boolean isSlotEnabled( final int idx ) + { + final int upgrades = this.getUpgradeable().getInstalledUpgrades( Upgrades.CAPACITY ); + + return upgrades > idx; + } + + public void clear() + { + ItemHandlerUtil.clear( this.getUpgradeable().getInventoryByName( "config" ) ); + this.detectAndSendChanges(); + } + + public void partition() + { + final IItemHandler inv = this.getUpgradeable().getInventoryByName( "config" ); + + final IMEInventory cellInv = this.storageBus.getInternalHandler(); + + Iterator i = new NullIterator<>(); + if( cellInv != null ) + { + final IItemList list = cellInv.getAvailableItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList() ); + i = list.iterator(); + } + + for( int x = 0; x < inv.getSlots(); x++ ) + { + if( i.hasNext() && this.isSlotEnabled( ( x / 9 ) - 2 ) ) + { + final ItemStack g = i.next().asItemStackRepresentation(); + ItemHandlerUtil.setStackInSlot( inv, x, g ); + } + else + { + ItemHandlerUtil.setStackInSlot( inv, x, ItemStack.EMPTY ); + } + } + + this.detectAndSendChanges(); + } + + public AccessRestriction getReadWriteMode() + { + return this.rwMode; + } + + private void setReadWriteMode( final AccessRestriction rwMode ) + { + this.rwMode = rwMode; + } + + public StorageFilter getStorageFilter() + { + return this.storageFilter; + } + + private void setStorageFilter( final StorageFilter storageFilter ) + { + this.storageFilter = storageFilter; + } +} diff --git a/src/main/java/appeng/container/implementations/ContainerFluidTerminal.java b/src/main/java/appeng/container/implementations/ContainerFluidTerminal.java new file mode 100644 index 000000000..d5cb3e81c --- /dev/null +++ b/src/main/java/appeng/container/implementations/ContainerFluidTerminal.java @@ -0,0 +1,478 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.container.implementations; + + +import java.io.IOException; +import java.nio.BufferOverflowException; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.init.Items; +import net.minecraft.inventory.IContainerListener; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ForgeModContainer; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidUtil; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; + +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.config.PowerMultiplier; +import appeng.api.config.Settings; +import appeng.api.config.SortDir; +import appeng.api.config.SortOrder; +import appeng.api.config.ViewItems; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridNode; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.networking.security.IActionSource; +import appeng.api.networking.storage.IBaseMonitor; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IMEMonitorHandlerReceiver; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.api.util.AEPartLocation; +import appeng.api.util.IConfigManager; +import appeng.api.util.IConfigurableObject; +import appeng.container.AEBaseContainer; +import appeng.container.guisync.GuiSync; +import appeng.core.AELog; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketMEFluidInventoryUpdate; +import appeng.core.sync.packets.PacketTargetFluidStack; +import appeng.core.sync.packets.PacketValueConfig; +import appeng.helpers.InventoryAction; +import appeng.me.helpers.ChannelPowerSrc; +import appeng.parts.reporting.PartFluidTerminal; +import appeng.util.ConfigManager; +import appeng.util.IConfigManagerHost; +import appeng.util.Platform; +import appeng.util.item.AEFluidStack; + + +/** + * @author BrockWS + * @version rv6 - 12/05/2018 + * @since rv6 12/05/2018 + */ +public class ContainerFluidTerminal extends AEBaseContainer implements IConfigManagerHost, IConfigurableObject, IMEMonitorHandlerReceiver +{ + private final IConfigManager clientCM; + private final IMEMonitor monitor; + private final IItemList fluids = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); + @GuiSync( 99 ) + public boolean hasPower = false; + private PartFluidTerminal terminal; + private IConfigManager serverCM; + private IConfigManagerHost gui; + private IGridNode networkNode; + // Holds the fluid the client wishes to extract, or null for insert + private IAEFluidStack clientRequestedTargetFluid = null; + + public ContainerFluidTerminal( InventoryPlayer ip, PartFluidTerminal terminal ) + { + super( ip, terminal ); + this.terminal = terminal; + this.clientCM = new ConfigManager( this ); + + this.clientCM.registerSetting( Settings.SORT_BY, SortOrder.NAME ); + this.clientCM.registerSetting( Settings.SORT_DIRECTION, SortDir.ASCENDING ); + this.clientCM.registerSetting( Settings.VIEW_MODE, ViewItems.ALL ); + if( Platform.isServer() ) + { + this.serverCM = terminal.getConfigManager(); + this.monitor = terminal.getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ); + if( this.monitor != null ) + { + this.monitor.addListener( this, null ); + final IGridNode node = terminal.getGridNode( AEPartLocation.INTERNAL ); + if( node != null ) + { + this.networkNode = node; + final IGrid g = node.getGrid(); + if( g != null ) + { + this.setPowerSource( new ChannelPowerSrc( this.networkNode, g.getCache( IEnergyGrid.class ) ) ); + } + } + } + } + else + { + this.monitor = null; + } + this.bindPlayerInventory( ip, 0, 222 - 82 ); + } + + @Override + public boolean isValid( Object verificationToken ) + { + return true; + } + + @Override + public void postChange( IBaseMonitor monitor, Iterable change, IActionSource actionSource ) + { + for( final IAEFluidStack is : change ) + { + this.fluids.add( is ); + } + } + + @Override + public void onListUpdate() + { + for( final IContainerListener c : this.listeners ) + { + this.queueInventory( c ); + } + } + + @Override + public void addListener( IContainerListener listener ) + { + super.addListener( listener ); + + this.queueInventory( listener ); + } + + @Override + public void onContainerClosed( final EntityPlayer player ) + { + super.onContainerClosed( player ); + if( this.monitor != null ) + { + this.monitor.removeListener( this ); + } + } + + private void queueInventory( final IContainerListener c ) + { + if( Platform.isServer() && c instanceof EntityPlayer && this.monitor != null ) + { + try + { + PacketMEFluidInventoryUpdate piu = new PacketMEFluidInventoryUpdate(); + final IItemList monitorCache = this.monitor.getStorageList(); + + for( final IAEFluidStack send : monitorCache ) + { + try + { + piu.appendFluid( send ); + } + catch( final BufferOverflowException boe ) + { + NetworkHandler.instance().sendTo( piu, (EntityPlayerMP) c ); + + piu = new PacketMEFluidInventoryUpdate(); + piu.appendFluid( send ); + } + } + + NetworkHandler.instance().sendTo( piu, (EntityPlayerMP) c ); + } + catch( final IOException e ) + { + AELog.debug( e ); + } + } + } + + @Override + public IConfigManager getConfigManager() + { + if( Platform.isServer() ) + { + return this.serverCM; + } + return this.clientCM; + } + + public void setTargetStack( final IAEFluidStack stack ) + { + if( Platform.isClient() ) + { + if( stack == null && this.clientRequestedTargetFluid == null ) + { + return; + } + if( stack != null && this.clientRequestedTargetFluid != null && stack.getFluidStack() + .isFluidEqual( this.clientRequestedTargetFluid.getFluidStack() ) ) + { + return; + } + NetworkHandler.instance().sendToServer( new PacketTargetFluidStack( (AEFluidStack) stack ) ); + } + + this.clientRequestedTargetFluid = stack == null ? null : stack.copy(); + } + + @Override + public void updateSetting( IConfigManager manager, Enum settingName, Enum newValue ) + { + if( this.getGui() != null ) + { + this.getGui().updateSetting( manager, settingName, newValue ); + } + } + + @Override + public void detectAndSendChanges() + { + if( Platform.isServer() ) + { + if( this.monitor != this.terminal.getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) ) + { + this.setValidContainer( false ); + } + + for( final Settings set : this.serverCM.getSettings() ) + { + final Enum sideLocal = this.serverCM.getSetting( set ); + final Enum sideRemote = this.clientCM.getSetting( set ); + + if( sideLocal != sideRemote ) + { + this.clientCM.putSetting( set, sideLocal ); + for( final IContainerListener crafter : this.listeners ) + { + if( crafter instanceof EntityPlayerMP ) + { + try + { + NetworkHandler.instance().sendTo( new PacketValueConfig( set.name(), sideLocal.name() ), (EntityPlayerMP) crafter ); + } + catch( final IOException e ) + { + AELog.debug( e ); + } + } + } + } + } + + if( !this.fluids.isEmpty() ) + { + try + { + final IItemList monitorCache = this.monitor.getStorageList(); + + final PacketMEFluidInventoryUpdate piu = new PacketMEFluidInventoryUpdate(); + + for( final IAEFluidStack is : this.fluids ) + { + final IAEFluidStack send = monitorCache.findPrecise( is ); + if( send == null ) + { + is.setStackSize( 0 ); + piu.appendFluid( is ); + } + else + { + piu.appendFluid( send ); + } + } + + if( !piu.isEmpty() ) + { + this.fluids.resetStatus(); + + for( final Object c : this.listeners ) + { + if( c instanceof EntityPlayer ) + { + NetworkHandler.instance().sendTo( piu, (EntityPlayerMP) c ); + } + } + } + } + catch( final IOException e ) + { + AELog.debug( e ); + } + } + this.updatePowerStatus(); + + super.detectAndSendChanges(); + } + } + + @Override + public void doAction( EntityPlayerMP player, InventoryAction action, int slot, long id ) + { + if( action != InventoryAction.FILL_ITEM && action != InventoryAction.EMPTY_ITEM ) + { + super.doAction( player, action, slot, id ); + return; + } + ItemStack held = player.inventory.getItemStack(); + if( !held.hasCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null ) ) + { // For now only do simple i/o with held tanks + return; + } + IFluidHandlerItem fh = FluidUtil.getFluidHandler( held ); + if( fh == null ) + { + throw new NullPointerException( held.getDisplayName() + " did not give FLUID_HANDLER_ITEM_CAPABILITY" ); + } + boolean isBucket = held.getItem() == Items.BUCKET || + held.getItem() == Items.WATER_BUCKET || + held.getItem() == Items.LAVA_BUCKET || + held.getItem() == Items.MILK_BUCKET || + held.getItem() == ForgeModContainer.getInstance().universalBucket; + + if( action == InventoryAction.FILL_ITEM && this.clientRequestedTargetFluid != null ) + { + AEFluidStack stack = (AEFluidStack) this.clientRequestedTargetFluid.copy(); + + AELog.info( "Filling %s with %s, %s mb", held.getDisplayName(), this.clientRequestedTargetFluid.getFluidStack().getLocalizedName(), + stack.getStackSize() ); + + if( isBucket && stack.getStackSize() < 1000 ) + { // Although buckets support less than a buckets worth of fluid, it does not display how much it holds + return; + } + + // Check how much we can store in the item + stack.setStackSize( Integer.MAX_VALUE ); + int amountAllowed = fh.fill( stack.getFluidStack(), false ); + stack.setStackSize( amountAllowed ); + + // Check if we can pull out of the system + IAEFluidStack canPull = this.monitor.extractItems( stack, Actionable.SIMULATE, this.getActionSource() ); + if( canPull == null || canPull.getStackSize() < 1 || ( isBucket && canPull.getStackSize() < 1000 ) ) + { + // Either we couldn't pull out of the system, + // or we are using a bucket and can only pull out less than a buckets worth of fluid + return; + } + + // Now actually pull out of the system + IAEFluidStack pulled = Platform.poweredExtraction( this.getPowerSource(), this.monitor, stack, this.getActionSource() ); + if( pulled == null || pulled.getStackSize() < 1 ) + { + // Something went wrong + AELog.error( "Unable to pull fluid out of the ME system even though the simulation said yes " ); + return; + } + + if( isBucket ) + { + // We need to handle buckets separately + ItemStack filledBucket = FluidUtil.getFilledBucket( pulled.getFluidStack() ); + player.inventory.setItemStack( filledBucket ); + } + else + { + fh.fill( pulled.getFluidStack(), true ); + } + this.updateHeld( player ); + } + else if( action == InventoryAction.EMPTY_ITEM ) + { + // Empty held item + AELog.info( "Emptying %s", held.getDisplayName() ); + + // See how much we can drain from the item + FluidStack extract = fh.drain( Integer.MAX_VALUE, false ); + if( extract == null || extract.amount < 1 ) + { + return; + } + + // Check if we can push into the system + IAEFluidStack canPush = this.monitor.injectItems( AEFluidStack.fromFluidStack( extract ), Actionable.SIMULATE, this.getActionSource() ); + if( isBucket && canPush != null && canPush.getStackSize() > 0 ) + { + // We can't push enough for the bucket + return; + } + + IAEFluidStack inserted = Platform.poweredInsert( this.getPowerSource(), this.monitor, AEFluidStack.fromFluidStack( extract ), + this.getActionSource() ); + if( inserted != null && inserted.getStackSize() > 0 ) + { + // Only try to extract the amount we DID insert + extract.amount -= Math.toIntExact( inserted.getStackSize() ); + } + + if( isBucket ) + { + // Remove bucket and replace with EmptyBucket + player.inventory.setItemStack( new ItemStack( Items.BUCKET, 1 ) ); + } + else + { + // Actually drain + fh.drain( extract, true ); + } + this.updateHeld( player ); + } + } + + protected void updatePowerStatus() + { + try + { + if( this.networkNode != null ) + { + this.setPowered( this.networkNode.isActive() ); + } + else if( this.getPowerSource() instanceof IEnergyGrid ) + { + this.setPowered( ( (IEnergyGrid) this.getPowerSource() ).isNetworkPowered() ); + } + else + { + this.setPowered( this.getPowerSource().extractAEPower( 1, Actionable.SIMULATE, PowerMultiplier.CONFIG ) > 0.8 ); + } + } + catch( final Exception ignore ) + { + // :P + } + } + + private IConfigManagerHost getGui() + { + return this.gui; + } + + public void setGui( @Nonnull final IConfigManagerHost gui ) + { + this.gui = gui; + } + + public boolean isPowered() + { + return this.hasPower; + } + + private void setPowered( final boolean isPowered ) + { + this.hasPower = isPowered; + } +} diff --git a/src/main/java/appeng/container/slot/IOptionalSlot.java b/src/main/java/appeng/container/slot/IOptionalSlot.java new file mode 100644 index 000000000..727b6a2f2 --- /dev/null +++ b/src/main/java/appeng/container/slot/IOptionalSlot.java @@ -0,0 +1,37 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.container.slot; + + +/** + * @author BrockWS + * @version rv6 - 2/05/2018 + * @since rv6 2/05/2018 + */ +public interface IOptionalSlot +{ + default boolean isRenderDisabled() + { + return false; + } + + int getSourceX(); + + int getSourceY(); +} diff --git a/src/main/java/appeng/container/slot/ISlotFluid.java b/src/main/java/appeng/container/slot/ISlotFluid.java new file mode 100644 index 000000000..864be0a9a --- /dev/null +++ b/src/main/java/appeng/container/slot/ISlotFluid.java @@ -0,0 +1,38 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.container.slot; + + +import net.minecraftforge.fluids.FluidStack; + + +/** + * @author BrockWS + * @version rv6 - 3/05/2018 + * @since rv6 3/05/2018 + */ +public interface ISlotFluid +{ + FluidStack getFluidInSlot(); + + default boolean shouldRenderAsFluid() + { + return true; + } +} diff --git a/src/main/java/appeng/container/slot/OptionalSlotFake.java b/src/main/java/appeng/container/slot/OptionalSlotFake.java index df1af41f2..2ebefa0a9 100644 --- a/src/main/java/appeng/container/slot/OptionalSlotFake.java +++ b/src/main/java/appeng/container/slot/OptionalSlotFake.java @@ -25,7 +25,7 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.items.IItemHandler; -public class OptionalSlotFake extends SlotFake +public class OptionalSlotFake extends SlotFake implements IOptionalSlot { private final int srcX; @@ -69,12 +69,8 @@ public class OptionalSlotFake extends SlotFake return this.host.isSlotEnabled( this.groupNum ); } - public boolean renderDisabled() - { - return this.isRenderDisabled(); - } - - private boolean isRenderDisabled() + @Override + public boolean isRenderDisabled() { return this.renderDisabled; } diff --git a/src/main/java/appeng/container/slot/OptionalSlotFakeFluid.java b/src/main/java/appeng/container/slot/OptionalSlotFakeFluid.java new file mode 100644 index 000000000..336ab3482 --- /dev/null +++ b/src/main/java/appeng/container/slot/OptionalSlotFakeFluid.java @@ -0,0 +1,96 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.container.slot; + + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + + +/** + * @author BrockWS + * @version rv6 - 1/05/2018 + * @since rv6 1/05/2018 + */ +public class OptionalSlotFakeFluid extends SlotFakeFluid implements IOptionalSlot +{ + + private final int srcX; + private final int srcY; + private final int groupNum; + private final IOptionalSlotHost host; + private boolean renderDisabled = true; + + public OptionalSlotFakeFluid( final IItemHandler inv, final IOptionalSlotHost containerBus, final int idx, final int x, final int y, final int offX, final int offY, final int groupNum ) + { + super( inv, idx, x + offX * 18, y + offY * 18 ); + this.srcX = x; + this.srcY = y; + this.groupNum = groupNum; + this.host = containerBus; + } + + @Override + @Nonnull + public ItemStack getStack() + { + if( !this.isSlotEnabled() ) + { + if( !this.getDisplayStack().isEmpty() ) + { + this.clearStack(); + } + } + + return super.getStack(); + } + + @Override + public boolean isSlotEnabled() + { + if( this.host == null ) + { + return false; + } + + return this.host.isSlotEnabled( this.groupNum ); + } + + public boolean isRenderDisabled() + { + return this.renderDisabled; + } + + public void setRenderDisabled( final boolean renderDisabled ) + { + this.renderDisabled = renderDisabled; + } + + public int getSourceX() + { + return this.srcX; + } + + public int getSourceY() + { + return this.srcY; + } +} diff --git a/src/main/java/appeng/container/slot/OptionalSlotNormal.java b/src/main/java/appeng/container/slot/OptionalSlotNormal.java index 426396dbe..44d4edd37 100644 --- a/src/main/java/appeng/container/slot/OptionalSlotNormal.java +++ b/src/main/java/appeng/container/slot/OptionalSlotNormal.java @@ -22,7 +22,7 @@ package appeng.container.slot; import net.minecraftforge.items.IItemHandler; -public class OptionalSlotNormal extends AppEngSlot +public class OptionalSlotNormal extends AppEngSlot implements IOptionalSlot { private final int groupNum; @@ -45,4 +45,16 @@ public class OptionalSlotNormal extends AppEngSlot return this.host.isSlotEnabled( this.groupNum ); } + + @Override + public int getSourceX() + { + return this.xPos; + } + + @Override + public int getSourceY() + { + return this.yPos; + } } diff --git a/src/main/java/appeng/container/slot/SlotFakeFluid.java b/src/main/java/appeng/container/slot/SlotFakeFluid.java new file mode 100644 index 000000000..fcd94ddeb --- /dev/null +++ b/src/main/java/appeng/container/slot/SlotFakeFluid.java @@ -0,0 +1,77 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.container.slot; + + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; +import net.minecraftforge.items.IItemHandler; + + +/** + * @author BrockWS + * @version rv6 - 1/05/2018 + * @since rv6 1/05/2018 + */ +public class SlotFakeFluid extends SlotFake implements ISlotFluid +{ + public SlotFakeFluid( IItemHandler inv, int idx, int x, int y ) + { + super( inv, idx, x, y ); + this.setIIcon( 12 * 16 + 15 ); + } + + @Override + public void putStack( ItemStack is ) + { + if( this.isItemValid( is ) || is.isEmpty() ) + { + super.putStack( is ); + } + } + + @Override + public boolean isItemValid( ItemStack stack ) + { + return stack.hasCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null ) && this.getContainer().isValidForSlot( this, stack ); + } + + @Override + public boolean renderIconWithItem() + { + return true; + } + + @Override + public FluidStack getFluidInSlot() + { + if( !this.getStack().isEmpty() ) + { + IFluidHandlerItem fh = this.getStack().getCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null ); + if( fh == null ) + { + throw new NullPointerException( "Item did not give IFluidHandlerItem: " + this.getStack().getDisplayName() ); + } + return fh.drain( Integer.MAX_VALUE, false ); + } + return null; + } +} diff --git a/src/main/java/appeng/core/Registration.java b/src/main/java/appeng/core/Registration.java index 04b7f9c76..2f95163ca 100644 --- a/src/main/java/appeng/core/Registration.java +++ b/src/main/java/appeng/core/Registration.java @@ -91,7 +91,7 @@ import appeng.bootstrap.components.IRecipeRegistrationComponent; import appeng.capabilities.Capabilities; import appeng.core.features.AEFeature; import appeng.core.features.registries.P2PTunnelRegistry; -import appeng.core.features.registries.cell.BasicCellHandler; +import appeng.core.features.registries.cell.BasicItemCellHandler; import appeng.core.features.registries.cell.CreativeCellHandler; import appeng.core.localization.GuiText; import appeng.core.localization.PlayerMessages; @@ -99,6 +99,7 @@ import appeng.core.stats.AdvancementTriggers; import appeng.core.stats.PartItemPredicate; import appeng.core.stats.Stats; import appeng.core.worlddata.SpatialDimensionManager; +import appeng.fluids.registries.BasicFluidCellHandler; import appeng.hooks.TickHandler; import appeng.items.materials.ItemMaterial; import appeng.items.parts.ItemFacade; @@ -286,8 +287,9 @@ final class Registration gcr.registerGridCache( ISecurityGrid.class, SecurityCache.class ); gcr.registerGridCache( ICraftingGrid.class, CraftingGridCache.class ); - registries.cell().addCellHandler( new BasicCellHandler() ); + registries.cell().addCellHandler( new BasicItemCellHandler() ); registries.cell().addCellHandler( new CreativeCellHandler() ); + registries.cell().addCellHandler( new BasicFluidCellHandler() ); api.definitions().materials().matterBall().maybeStack( 1 ).ifPresent( ammoStack -> { @@ -423,6 +425,11 @@ final class Registration Upgrades.CAPACITY.registerItem( parts.importBus(), 2 ); Upgrades.SPEED.registerItem( parts.importBus(), 4 ); + // Fluid Import Bus + Upgrades.CAPACITY.registerItem( parts.fluidImportBus(), 2 ); + Upgrades.REDSTONE.registerItem( parts.fluidImportBus(), 1 ); + Upgrades.SPEED.registerItem( parts.fluidImportBus(), 4 ); + // Export Bus Upgrades.FUZZY.registerItem( parts.exportBus(), 1 ); Upgrades.REDSTONE.registerItem( parts.exportBus(), 1 ); @@ -430,6 +437,11 @@ final class Registration Upgrades.SPEED.registerItem( parts.exportBus(), 4 ); Upgrades.CRAFTING.registerItem( parts.exportBus(), 1 ); + // Fluid Export Bus + Upgrades.CAPACITY.registerItem( parts.fluidExportBus(), 2 ); + Upgrades.REDSTONE.registerItem( parts.fluidExportBus(), 1 ); + Upgrades.SPEED.registerItem( parts.fluidExportBus(), 4 ); + // Storage Cells Upgrades.FUZZY.registerItem( items.cell1k(), 1 ); Upgrades.INVERTER.registerItem( items.cell1k(), 1 ); @@ -454,6 +466,10 @@ final class Registration Upgrades.INVERTER.registerItem( parts.storageBus(), 1 ); Upgrades.CAPACITY.registerItem( parts.storageBus(), 5 ); + // Storage Bus Fluids + Upgrades.INVERTER.registerItem( parts.fluidStorageBus(), 1 ); + Upgrades.CAPACITY.registerItem( parts.fluidStorageBus(), 5 ); + // Formation Plane Upgrades.FUZZY.registerItem( parts.formationPlane(), 1 ); Upgrades.INVERTER.registerItem( parts.formationPlane(), 1 ); diff --git a/src/main/java/appeng/core/api/ApiStorage.java b/src/main/java/appeng/core/api/ApiStorage.java index b746d41de..b60fd18a7 100644 --- a/src/main/java/appeng/core/api/ApiStorage.java +++ b/src/main/java/appeng/core/api/ApiStorage.java @@ -163,7 +163,7 @@ public class ApiStorage implements IStorageHelper @Override public int transferFactor() { - return 1000; + return 125; } @Override diff --git a/src/main/java/appeng/core/api/definitions/ApiItems.java b/src/main/java/appeng/core/api/definitions/ApiItems.java index b209dda43..abdf8d01f 100644 --- a/src/main/java/appeng/core/api/definitions/ApiItems.java +++ b/src/main/java/appeng/core/api/definitions/ApiItems.java @@ -30,6 +30,9 @@ import appeng.debug.ToolDebugCard; import appeng.debug.ToolEraser; import appeng.debug.ToolMeteoritePlacer; import appeng.debug.ToolReplicatorCard; +import appeng.fluids.items.BasicFluidStorageCell; +import appeng.fluids.items.FluidDummyItem; +import appeng.fluids.items.FluidDummyItemRendering; import appeng.hooks.DispenserBlockTool; import appeng.hooks.DispenserMatterCannon; import appeng.items.materials.MaterialType; @@ -40,7 +43,7 @@ import appeng.items.misc.ItemPaintBall; import appeng.items.misc.ItemPaintBallRendering; import appeng.items.parts.FacadeRendering; import appeng.items.parts.ItemFacade; -import appeng.items.storage.ItemBasicStorageCell; +import appeng.items.storage.BasicItemStorageCell; import appeng.items.storage.ItemCreativeStorageCell; import appeng.items.storage.ItemSpatialStorageCell; import appeng.items.storage.ItemViewCell; @@ -102,6 +105,11 @@ public final class ApiItems implements IItems private final IItemDefinition cell16k; private final IItemDefinition cell64k; + private final IItemDefinition fluidCell1k; + private final IItemDefinition fluidCell4k; + private final IItemDefinition fluidCell16k; + private final IItemDefinition fluidCell64k; + private final IItemDefinition spatialCell2; private final IItemDefinition spatialCell16; private final IItemDefinition spatialCell128; @@ -123,6 +131,8 @@ public final class ApiItems implements IItems private final IItemDefinition toolDebugCard; private final IItemDefinition toolReplicatorCard; + private final IItemDefinition dummyFluidItem; + public ApiItems( FeatureFactory registry ) { FeatureFactory certusTools = registry.features( AEFeature.CERTUS_QUARTZ_TOOLS ); @@ -198,10 +208,15 @@ public final class ApiItems implements IItems this.viewCell = registry.item( "view_cell", ItemViewCell::new ).features( AEFeature.VIEW_CELL ).build(); FeatureFactory storageCells = registry.features( AEFeature.STORAGE_CELLS ); - this.cell1k = storageCells.item( "storage_cell_1k", () -> new ItemBasicStorageCell( MaterialType.CELL1K_PART, 1 ) ).build(); - this.cell4k = storageCells.item( "storage_cell_4k", () -> new ItemBasicStorageCell( MaterialType.CELL4K_PART, 4 ) ).build(); - this.cell16k = storageCells.item( "storage_cell_16k", () -> new ItemBasicStorageCell( MaterialType.CELL16K_PART, 16 ) ).build(); - this.cell64k = storageCells.item( "storage_cell_64k", () -> new ItemBasicStorageCell( MaterialType.CELL64K_PART, 64 ) ).build(); + this.cell1k = storageCells.item( "storage_cell_1k", () -> new BasicItemStorageCell( MaterialType.CELL1K_PART, 1 ) ).build(); + this.cell4k = storageCells.item( "storage_cell_4k", () -> new BasicItemStorageCell( MaterialType.CELL4K_PART, 4 ) ).build(); + this.cell16k = storageCells.item( "storage_cell_16k", () -> new BasicItemStorageCell( MaterialType.CELL16K_PART, 16 ) ).build(); + this.cell64k = storageCells.item( "storage_cell_64k", () -> new BasicItemStorageCell( MaterialType.CELL64K_PART, 64 ) ).build(); + + this.fluidCell1k = storageCells.item( "fluid_storage_cell_1k", () -> new BasicFluidStorageCell( MaterialType.FLUID_CELL1K_PART, 1 ) ).build(); + this.fluidCell4k = storageCells.item( "fluid_storage_cell_4k", () -> new BasicFluidStorageCell( MaterialType.FLUID_CELL4K_PART, 4 ) ).build(); + this.fluidCell16k = storageCells.item( "fluid_storage_cell_16k", () -> new BasicFluidStorageCell( MaterialType.FLUID_CELL16K_PART, 16 ) ).build(); + this.fluidCell64k = storageCells.item( "fluid_storage_cell_64k", () -> new BasicFluidStorageCell( MaterialType.FLUID_CELL64K_PART, 64 ) ).build(); FeatureFactory spatialCells = registry.features( AEFeature.SPATIAL_IO ); this.spatialCell2 = spatialCells.item( "spatial_storage_cell_2_cubed", () -> new ItemSpatialStorageCell( 2 ) ).build(); @@ -236,6 +251,8 @@ public final class ApiItems implements IItems this.toolMeteoritePlacer = debugTools.item( "debug_meteorite_placer", ToolMeteoritePlacer::new ).build(); this.toolDebugCard = debugTools.item( "debug_card", ToolDebugCard::new ).build(); this.toolReplicatorCard = debugTools.item( "debug_replicator_card", ToolReplicatorCard::new ).build(); + + this.dummyFluidItem = registry.item( "dummy_fluid_item", FluidDummyItem::new ).rendering( new FluidDummyItemRendering() ).build(); } @Override @@ -406,6 +423,30 @@ public final class ApiItems implements IItems return this.cell64k; } + @Override + public IItemDefinition fluidCell1k() + { + return this.fluidCell1k; + } + + @Override + public IItemDefinition fluidCell4k() + { + return this.fluidCell4k; + } + + @Override + public IItemDefinition fluidCell16k() + { + return this.fluidCell16k; + } + + @Override + public IItemDefinition fluidCell64k() + { + return this.fluidCell64k; + } + @Override public IItemDefinition spatialCell2() { @@ -484,4 +525,9 @@ public final class ApiItems implements IItems { return this.toolReplicatorCard; } + + public IItemDefinition dummyFluidItem() + { + return this.dummyFluidItem; + } } diff --git a/src/main/java/appeng/core/api/definitions/ApiMaterials.java b/src/main/java/appeng/core/api/definitions/ApiMaterials.java index e5464e1d8..818feda52 100644 --- a/src/main/java/appeng/core/api/definitions/ApiMaterials.java +++ b/src/main/java/appeng/core/api/definitions/ApiMaterials.java @@ -111,6 +111,11 @@ public final class ApiMaterials implements IMaterials private final IItemDefinition qESingularity; private final IItemDefinition blankPattern; + private final IItemDefinition fluidCell1kPart; + private final IItemDefinition fluidCell4kPart; + private final IItemDefinition fluidCell16kPart; + private final IItemDefinition fluidCell64kPart; + public ApiMaterials( FeatureFactory registry ) { final ItemMaterial materials = new ItemMaterial(); @@ -210,6 +215,11 @@ public final class ApiMaterials implements IMaterials this.qESingularity = new DamagedItemDefinition( "material.singularity.entangled.quantum", materials .createMaterial( MaterialType.QUANTUM_ENTANGLED_SINGULARITY ) ); this.blankPattern = new DamagedItemDefinition( "material.pattern.blank", materials.createMaterial( MaterialType.BLANK_PATTERN ) ); + + this.fluidCell1kPart = new DamagedItemDefinition( "material.cell.storage.1k", materials.createMaterial( MaterialType.FLUID_CELL1K_PART ) ); + this.fluidCell4kPart = new DamagedItemDefinition( "material.cell.storage.4k", materials.createMaterial( MaterialType.FLUID_CELL4K_PART ) ); + this.fluidCell16kPart = new DamagedItemDefinition( "material.cell.storage.16k", materials.createMaterial( MaterialType.FLUID_CELL16K_PART ) ); + this.fluidCell64kPart = new DamagedItemDefinition( "material.cell.storage.64k", materials.createMaterial( MaterialType.FLUID_CELL64K_PART ) ); } @Override @@ -529,4 +539,28 @@ public final class ApiMaterials implements IMaterials { return this.blankPattern; } + + @Override + public IItemDefinition fluidCell1kPart() + { + return this.fluidCell1kPart; + } + + @Override + public IItemDefinition fluidCell4kPart() + { + return this.fluidCell4kPart; + } + + @Override + public IItemDefinition fluidCell16kPart() + { + return this.fluidCell16kPart; + } + + @Override + public IItemDefinition fluidCell64kPart() + { + return this.fluidCell64kPart; + } } diff --git a/src/main/java/appeng/core/api/definitions/ApiParts.java b/src/main/java/appeng/core/api/definitions/ApiParts.java index e394a59e1..3f52c438d 100644 --- a/src/main/java/appeng/core/api/definitions/ApiParts.java +++ b/src/main/java/appeng/core/api/definitions/ApiParts.java @@ -77,6 +77,10 @@ public final class ApiParts implements IParts private final IItemDefinition terminal; private final IItemDefinition storageMonitor; private final IItemDefinition conversionMonitor; + private final IItemDefinition fluidImportBus; + private final IItemDefinition fluidExportBus; + private final IItemDefinition fluidTerminal; + private final IItemDefinition fluidStorageBus; public ApiParts( FeatureFactory registry, PartModels partModels ) { @@ -109,8 +113,8 @@ public final class ApiParts implements IParts this.iface = new DamagedItemDefinition( "part.interface", itemPart.createPart( PartType.INTERFACE ) ); this.levelEmitter = new DamagedItemDefinition( "part.level_emitter", itemPart.createPart( PartType.LEVEL_EMITTER ) ); this.annihilationPlane = new DamagedItemDefinition( "part.plane.annihilation", itemPart.createPart( PartType.ANNIHILATION_PLANE ) ); - this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity", itemPart - .createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) ); + this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity", + itemPart.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) ); this.formationPlane = new DamagedItemDefinition( "part.plane.formation", itemPart.createPart( PartType.FORMATION_PLANE ) ); this.p2PTunnelME = new DamagedItemDefinition( "part.tunnel.me", itemPart.createPart( PartType.P2P_TUNNEL_ME ) ); this.p2PTunnelRedstone = new DamagedItemDefinition( "part.tunnel.redstone", itemPart.createPart( PartType.P2P_TUNNEL_REDSTONE ) ); @@ -131,6 +135,10 @@ public final class ApiParts implements IParts this.terminal = new DamagedItemDefinition( "part.terminal", itemPart.createPart( PartType.TERMINAL ) ); this.storageMonitor = new DamagedItemDefinition( "part.monitor.storage", itemPart.createPart( PartType.STORAGE_MONITOR ) ); this.conversionMonitor = new DamagedItemDefinition( "part.monitor.conversion", itemPart.createPart( PartType.CONVERSION_MONITOR ) ); + this.fluidImportBus = new DamagedItemDefinition( "part.bus.import.fluid", itemPart.createPart( PartType.FLUID_IMPORT_BUS ) ); + this.fluidExportBus = new DamagedItemDefinition( "part.bus.export.fluid", itemPart.createPart( PartType.FLUID_EXPORT_BUS ) ); + this.fluidTerminal = new DamagedItemDefinition( "part.terminal.fluid", itemPart.createPart( PartType.FLUID_TERMINAL ) ); + this.fluidStorageBus = new DamagedItemDefinition( "part.bus.storage.fluid", itemPart.createPart( PartType.FLUID_STORAGE_BUS ) ); } private static AEColoredItemDefinition constructColoredDefinition( final ItemPart target, final PartType type ) @@ -380,4 +388,28 @@ public final class ApiParts implements IParts { return this.conversionMonitor; } + + @Override + public IItemDefinition fluidTerminal() + { + return this.fluidTerminal; + } + + @Override + public IItemDefinition fluidImportBus() + { + return this.fluidImportBus; + } + + @Override + public IItemDefinition fluidExportBus() + { + return this.fluidExportBus; + } + + @Override + public IItemDefinition fluidStorageBus() + { + return this.fluidStorageBus; + } } diff --git a/src/main/java/appeng/core/features/AEFeature.java b/src/main/java/appeng/core/features/AEFeature.java index f2795d359..a80f63d45 100644 --- a/src/main/java/appeng/core/features/AEFeature.java +++ b/src/main/java/appeng/core/features/AEFeature.java @@ -1,6 +1,6 @@ /* * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved. + * Copyright (c) 2013 - 2018, 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 @@ -76,6 +76,7 @@ public enum AEFeature INTERFACE( "Interface", Constants.CATEGORY_NETWORK_BUSES ), LEVEL_EMITTER( "LevelEmitter", Constants.CATEGORY_NETWORK_BUSES ), + FLUID_TERMINAL( "FluidTerminal", Constants.CATEGORY_NETWORK_BUSES ), CRAFTING_TERMINAL( "CraftingTerminal", Constants.CATEGORY_NETWORK_BUSES ), TERMINAL( "Terminal", Constants.CATEGORY_NETWORK_BUSES ), STORAGE_MONITOR( "StorageMonitor", Constants.CATEGORY_NETWORK_BUSES ), @@ -84,8 +85,11 @@ public enum AEFeature ANNIHILATION_PLANE( "AnnihilationPlane", Constants.CATEGORY_NETWORK_BUSES ), IDENTITY_ANNIHILATION_PLANE( "IdentityAnnihilationPlane", Constants.CATEGORY_NETWORK_BUSES ), IMPORT_BUS( "ImportBus", Constants.CATEGORY_NETWORK_BUSES ), + FLUID_IMPORT_BUS( "FluidImportBus", Constants.CATEGORY_NETWORK_BUSES ), EXPORT_BUS( "ExportBus", Constants.CATEGORY_NETWORK_BUSES ), + FLUID_EXPORT_BUS( "FluidExportBus", Constants.CATEGORY_NETWORK_BUSES ), STORAGE_BUS( "StorageBus", Constants.CATEGORY_NETWORK_BUSES ), + FLUID_STORAGE_BUS( "FluidStorageBus", Constants.CATEGORY_NETWORK_BUSES ), PART_CONVERSION_MONITOR( "PartConversionMonitor", Constants.CATEGORY_NETWORK_BUSES ), TOGGLE_BUS( "ToggleBus", Constants.CATEGORY_NETWORK_BUSES ), PANELS( "Panels", Constants.CATEGORY_NETWORK_BUSES ), diff --git a/src/main/java/appeng/core/features/registries/cell/BasicCellHandler.java b/src/main/java/appeng/core/features/registries/cell/BasicItemCellHandler.java similarity index 81% rename from src/main/java/appeng/core/features/registries/cell/BasicCellHandler.java rename to src/main/java/appeng/core/features/registries/cell/BasicItemCellHandler.java index 063ba963c..fe9a3a737 100644 --- a/src/main/java/appeng/core/features/registries/cell/BasicCellHandler.java +++ b/src/main/java/appeng/core/features/registries/cell/BasicItemCellHandler.java @@ -36,18 +36,18 @@ import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEStack; import appeng.api.util.AEPartLocation; import appeng.core.sync.GuiBridge; -import appeng.me.storage.CellInventory; -import appeng.me.storage.CellInventoryHandler; +import appeng.me.storage.ItemCellInventory; +import appeng.me.storage.ItemCellInventoryHandler; import appeng.util.Platform; -public final class BasicCellHandler implements ICellHandler +public class BasicItemCellHandler implements ICellHandler { @Override public boolean isCell( final ItemStack is ) { - return CellInventory.isCell( is ); + return ItemCellInventory.isCell( is ); } @Override @@ -55,23 +55,27 @@ public final class BasicCellHandler implements ICellHandler { if( channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) { - return CellInventory.getCell( is, container ); + return ItemCellInventory.getCell( is, container ); } + return null; } @Override public void openChestGui( final EntityPlayer player, final IChestOrDrive chest, final ICellHandler cellHandler, final IMEInventoryHandler inv, final ItemStack is, final IStorageChannel chan ) { - Platform.openGUI( player, (TileEntity) chest, AEPartLocation.fromFacing( chest.getUp() ), GuiBridge.GUI_ME ); + if( chan == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) + { + Platform.openGUI( player, (TileEntity) chest, AEPartLocation.fromFacing( chest.getUp() ), GuiBridge.GUI_ME ); + } } @Override public int getStatusForCell( final ItemStack is, final IMEInventory handler ) { - if( handler instanceof CellInventoryHandler ) + if( handler instanceof ItemCellInventoryHandler ) { - final CellInventoryHandler ci = (CellInventoryHandler) handler; + final ItemCellInventoryHandler ci = (ItemCellInventoryHandler) handler; return ci.getStatusForCell(); } return 0; diff --git a/src/main/java/appeng/core/features/registries/cell/CellRegistry.java b/src/main/java/appeng/core/features/registries/cell/CellRegistry.java index 0bd4f0c1f..bb4c0322f 100644 --- a/src/main/java/appeng/core/features/registries/cell/CellRegistry.java +++ b/src/main/java/appeng/core/features/registries/cell/CellRegistry.java @@ -54,7 +54,7 @@ public class CellRegistry implements ICellRegistry this.handlers.add( handler ); // Verify that the first entry is always our own handler. - Verify.verify( this.handlers.get( 0 ) instanceof BasicCellHandler ); + Verify.verify( this.handlers.get( 0 ) instanceof BasicItemCellHandler ); } @Override diff --git a/src/main/java/appeng/core/localization/ButtonToolTips.java b/src/main/java/appeng/core/localization/ButtonToolTips.java index bbbd25ab9..2ea884d82 100644 --- a/src/main/java/appeng/core/localization/ButtonToolTips.java +++ b/src/main/java/appeng/core/localization/ButtonToolTips.java @@ -129,6 +129,9 @@ public enum ButtonToolTips ReportInaccessibleItems, ReportInaccessibleItemsYes, ReportInaccessibleItemsNo, + ReportInaccessibleFluids, + ReportInaccessibleFluidsYes, + ReportInaccessibleFluidsNo, BlockPlacement, BlockPlacementYes, diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index 014602a84..092eec89c 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -44,12 +44,15 @@ public enum GuiText StoredItems, Patterns, ImportBus, + ImportBusFluids, ExportBus, + ExportBusFluids, CellWorkbench, NetworkDetails, StorageCells, IOBuses, + IOBusesFluids, IOPort, BytesUsed, @@ -64,6 +67,7 @@ public enum GuiText EnergyDrain, StorageBus, + StorageBusFluids, Priority, Security, Encoded, diff --git a/src/main/java/appeng/core/settings/TickRates.java b/src/main/java/appeng/core/settings/TickRates.java index 9a1990ef0..e69edeae3 100644 --- a/src/main/java/appeng/core/settings/TickRates.java +++ b/src/main/java/appeng/core/settings/TickRates.java @@ -29,8 +29,12 @@ public enum TickRates ImportBus( 5, 40 ), + FluidImportBus( 5, 40 ), + ExportBus( 5, 60 ), + FluidExportBus( 5, 60 ), + AnnihilationPlane( 2, 120 ), METunnel( 5, 20 ), @@ -45,6 +49,8 @@ public enum TickRates StorageBus( 5, 60 ), + FluidStorageBus( 5, 60 ), + ItemTunnel( 5, 60 ), LightTunnel( 5, 60 ), diff --git a/src/main/java/appeng/core/sync/AppEngPacketHandlerBase.java b/src/main/java/appeng/core/sync/AppEngPacketHandlerBase.java index 51100cbbf..321fb3776 100644 --- a/src/main/java/appeng/core/sync/AppEngPacketHandlerBase.java +++ b/src/main/java/appeng/core/sync/AppEngPacketHandlerBase.java @@ -36,6 +36,7 @@ import appeng.core.sync.packets.PacketCraftRequest; import appeng.core.sync.packets.PacketInventoryAction; import appeng.core.sync.packets.PacketJEIRecipe; import appeng.core.sync.packets.PacketLightning; +import appeng.core.sync.packets.PacketMEFluidInventoryUpdate; import appeng.core.sync.packets.PacketMEInventoryUpdate; import appeng.core.sync.packets.PacketMatterCannon; import appeng.core.sync.packets.PacketMockExplosion; @@ -45,6 +46,7 @@ import appeng.core.sync.packets.PacketPatternSlot; import appeng.core.sync.packets.PacketProgressBar; import appeng.core.sync.packets.PacketSwapSlots; import appeng.core.sync.packets.PacketSwitchGuis; +import appeng.core.sync.packets.PacketTargetFluidStack; import appeng.core.sync.packets.PacketTargetItemStack; import appeng.core.sync.packets.PacketTransitionEffect; import appeng.core.sync.packets.PacketValueConfig; @@ -64,6 +66,8 @@ public class AppEngPacketHandlerBase PACKET_ME_INVENTORY_UPDATE( PacketMEInventoryUpdate.class ), + PACKET_ME_FLUID_INVENTORY_UPDATE( PacketMEFluidInventoryUpdate.class ), + PACKET_CONFIG_BUTTON( PacketConfigButton.class ), PACKET_PART_PLACEMENT( PacketPartPlacement.class ), @@ -92,6 +96,8 @@ public class AppEngPacketHandlerBase PACKET_TARGET_ITEM( PacketTargetItemStack.class ), + PACKET_TARGET_FLUID( PacketTargetFluidStack.class ), + PACKET_CRAFTING_REQUEST( PacketCraftRequest.class ), PACKET_ASSEMBLER_ANIMATION( PacketAssemblerAnimation.class ), diff --git a/src/main/java/appeng/core/sync/GuiBridge.java b/src/main/java/appeng/core/sync/GuiBridge.java index 954123ca9..252ff1d1d 100644 --- a/src/main/java/appeng/core/sync/GuiBridge.java +++ b/src/main/java/appeng/core/sync/GuiBridge.java @@ -62,6 +62,9 @@ import appeng.container.implementations.ContainerCraftingCPU; import appeng.container.implementations.ContainerCraftingStatus; import appeng.container.implementations.ContainerCraftingTerm; import appeng.container.implementations.ContainerDrive; +import appeng.container.implementations.ContainerFluidIO; +import appeng.container.implementations.ContainerFluidStorageBus; +import appeng.container.implementations.ContainerFluidTerminal; import appeng.container.implementations.ContainerFormationPlane; import appeng.container.implementations.ContainerGrinder; import appeng.container.implementations.ContainerIOPort; @@ -86,6 +89,8 @@ import appeng.container.implementations.ContainerUpgradeable; import appeng.container.implementations.ContainerVibrationChamber; import appeng.container.implementations.ContainerWireless; import appeng.container.implementations.ContainerWirelessTerm; +import appeng.fluids.parts.PartFluidStorageBus; +import appeng.fluids.parts.PartSharedFluidBus; import appeng.helpers.IInterfaceHost; import appeng.helpers.IPriorityHost; import appeng.helpers.WirelessTerminalGuiObject; @@ -94,6 +99,7 @@ import appeng.parts.automation.PartFormationPlane; import appeng.parts.automation.PartLevelEmitter; import appeng.parts.misc.PartStorageBus; import appeng.parts.reporting.PartCraftingTerminal; +import appeng.parts.reporting.PartFluidTerminal; import appeng.parts.reporting.PartInterfaceTerminal; import appeng.parts.reporting.PartPatternTerminal; import appeng.tile.crafting.TileCraftingTile; @@ -152,10 +158,14 @@ public enum GuiBridge implements IGuiHandler GUI_BUS( ContainerUpgradeable.class, IUpgradeableHost.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), + GUI_BUS_FLUID( ContainerFluidIO.class, PartSharedFluidBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), + GUI_IOPORT( ContainerIOPort.class, TileIOPort.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), GUI_STORAGEBUS( ContainerStorageBus.class, PartStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), + GUI_STORAGEBUS_FLUID( ContainerFluidStorageBus.class, PartFluidStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), + GUI_FORMATION_PLANE( ContainerFormationPlane.class, PartFormationPlane.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), GUI_PRIORITY( ContainerPriority.class, IPriorityHost.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), @@ -166,6 +176,8 @@ public enum GuiBridge implements IGuiHandler GUI_PATTERN_TERMINAL( ContainerPatternTerm.class, PartPatternTerminal.class, GuiHostType.WORLD, SecurityPermissions.CRAFT ), + GUI_FLUID_TERMINAL( ContainerFluidTerminal.class, PartFluidTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), + // extends (Container/Gui) + Bus GUI_LEVEL_EMITTER( ContainerLevelEmitter.class, PartLevelEmitter.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), diff --git a/src/main/java/appeng/core/sync/packets/PacketMEFluidInventoryUpdate.java b/src/main/java/appeng/core/sync/packets/PacketMEFluidInventoryUpdate.java new file mode 100644 index 000000000..6182ec3d8 --- /dev/null +++ b/src/main/java/appeng/core/sync/packets/PacketMEFluidInventoryUpdate.java @@ -0,0 +1,207 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.sync.packets; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.BufferOverflowException; +import java.util.LinkedList; +import java.util.List; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; +import javax.annotation.Nullable; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.fml.common.network.internal.FMLProxyPacket; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import appeng.api.storage.data.IAEFluidStack; +import appeng.client.gui.implementations.GuiFluidTerminal; +import appeng.core.AELog; +import appeng.core.sync.AppEngPacket; +import appeng.core.sync.network.INetworkInfo; +import appeng.util.item.AEFluidStack; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class PacketMEFluidInventoryUpdate extends AppEngPacket +{ + private static final int UNCOMPRESSED_PACKET_BYTE_LIMIT = 16 * 1024 * 1024; + private static final int OPERATION_BYTE_LIMIT = 2 * 1024; + private static final int TEMP_BUFFER_SIZE = 1024; + private static final int STREAM_MASK = 0xff; + + // input. + @Nullable + private final List list; + // output... + private final byte ref; + + @Nullable + private final ByteBuf data; + @Nullable + private final GZIPOutputStream compressFrame; + + private int writtenBytes = 0; + private boolean empty = true; + + // automatic. + public PacketMEFluidInventoryUpdate( final ByteBuf stream ) throws IOException + { + this.data = null; + this.compressFrame = null; + this.list = new LinkedList<>(); + this.ref = stream.readByte(); + + // int originalBytes = stream.readableBytes(); + + final GZIPInputStream gzReader = new GZIPInputStream( new InputStream() + { + @Override + public int read() throws IOException + { + if( stream.readableBytes() <= 0 ) + { + return -1; + } + + return stream.readByte() & STREAM_MASK; + } + } ); + + final ByteBuf uncompressed = Unpooled.buffer( stream.readableBytes() ); + final byte[] tmp = new byte[TEMP_BUFFER_SIZE]; + while( gzReader.available() != 0 ) + { + final int bytes = gzReader.read( tmp ); + if( bytes > 0 ) + { + uncompressed.writeBytes( tmp, 0, bytes ); + } + } + gzReader.close(); + + // int uncompressedBytes = uncompressed.readableBytes(); + // AELog.info( "Receiver: " + originalBytes + " -> " + uncompressedBytes ); + + while( uncompressed.readableBytes() > 0 ) + { + this.list.add( AEFluidStack.fromPacket( uncompressed ) ); + } + + this.empty = this.list.isEmpty(); + } + + // api + public PacketMEFluidInventoryUpdate() throws IOException + { + this( (byte) 0 ); + } + + // api + public PacketMEFluidInventoryUpdate( final byte ref ) throws IOException + { + this.ref = ref; + this.data = Unpooled.buffer( OPERATION_BYTE_LIMIT ); + this.data.writeInt( this.getPacketID() ); + this.data.writeByte( this.ref ); + + this.compressFrame = new GZIPOutputStream( new OutputStream() + { + @Override + public void write( final int value ) throws IOException + { + PacketMEFluidInventoryUpdate.this.data.writeByte( value ); + } + } ); + + this.list = null; + } + + @Override + @SideOnly( Side.CLIENT ) + public void clientPacketData( final INetworkInfo network, final AppEngPacket packet, final EntityPlayer player ) + { + final GuiScreen gs = Minecraft.getMinecraft().currentScreen; + + if( gs instanceof GuiFluidTerminal ) + { + ( (GuiFluidTerminal) gs ).postUpdate( this.list ); + } + } + + @Nullable + @Override + public FMLProxyPacket getProxy() + { + try + { + this.compressFrame.close(); + + this.configureWrite( this.data ); + return super.getProxy(); + } + catch( final IOException e ) + { + AELog.debug( e ); + } + + return null; + } + + public void appendFluid( final IAEFluidStack fs ) throws IOException, BufferOverflowException + { + final ByteBuf tmp = Unpooled.buffer( OPERATION_BYTE_LIMIT ); + fs.writeToPacket( tmp ); + + this.compressFrame.flush(); + if( this.writtenBytes + tmp.readableBytes() > UNCOMPRESSED_PACKET_BYTE_LIMIT ) + { + throw new BufferOverflowException(); + } + else + { + this.writtenBytes += tmp.readableBytes(); + this.compressFrame.write( tmp.array(), 0, tmp.readableBytes() ); + this.empty = false; + } + } + + public int getLength() + { + return this.data.readableBytes(); + } + + public boolean isEmpty() + { + return this.empty; + } +} diff --git a/src/main/java/appeng/core/sync/packets/PacketTargetFluidStack.java b/src/main/java/appeng/core/sync/packets/PacketTargetFluidStack.java new file mode 100644 index 000000000..85227ecf3 --- /dev/null +++ b/src/main/java/appeng/core/sync/packets/PacketTargetFluidStack.java @@ -0,0 +1,94 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.sync.packets; + + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import net.minecraft.entity.player.EntityPlayer; + +import appeng.container.implementations.ContainerFluidTerminal; +import appeng.core.AELog; +import appeng.core.sync.AppEngPacket; +import appeng.core.sync.network.INetworkInfo; +import appeng.util.item.AEFluidStack; + + +/** + * @author BrockWS + * @version rv6 - 23/05/2018 + * @since rv6 23/05/2018 + */ +public class PacketTargetFluidStack extends AppEngPacket +{ + private AEFluidStack stack; + + // automatic. + public PacketTargetFluidStack( final ByteBuf stream ) + { + try + { + if( stream.readableBytes() > 0 ) + { + this.stack = (AEFluidStack) AEFluidStack.fromPacket( stream ); + } + else + { + this.stack = null; + } + } + catch( Exception ex ) + { + AELog.debug( ex ); + this.stack = null; + } + } + + // api + public PacketTargetFluidStack( AEFluidStack stack ) + { + + this.stack = stack; + + final ByteBuf data = Unpooled.buffer(); + data.writeInt( this.getPacketID() ); + if( stack != null ) + { + try + { + stack.writeToPacket( data ); + } + catch( Exception ex ) + { + AELog.debug( ex ); + } + } + this.configureWrite( data ); + } + + @Override + public void serverPacketData( final INetworkInfo manager, final AppEngPacket packet, final EntityPlayer player ) + { + if( player.openContainer instanceof ContainerFluidTerminal ) + { + ( (ContainerFluidTerminal) player.openContainer ).setTargetStack( this.stack ); + } + } +} diff --git a/src/main/java/appeng/core/sync/packets/PacketValueConfig.java b/src/main/java/appeng/core/sync/packets/PacketValueConfig.java index c1da35cba..f5020bf97 100644 --- a/src/main/java/appeng/core/sync/packets/PacketValueConfig.java +++ b/src/main/java/appeng/core/sync/packets/PacketValueConfig.java @@ -44,6 +44,7 @@ import appeng.container.implementations.ContainerCellWorkbench; import appeng.container.implementations.ContainerCraftConfirm; import appeng.container.implementations.ContainerCraftingCPU; import appeng.container.implementations.ContainerCraftingStatus; +import appeng.container.implementations.ContainerFluidStorageBus; import appeng.container.implementations.ContainerLevelEmitter; import appeng.container.implementations.ContainerNetworkTool; import appeng.container.implementations.ContainerPatternTerm; @@ -179,18 +180,31 @@ public class PacketValueConfig extends AppEngPacket cpt.getPatternTerminal().setSubstitution( this.Value.equals( "1" ) ); } } - else if( this.Name.startsWith( "StorageBus." ) && c instanceof ContainerStorageBus ) + else if( this.Name.startsWith( "StorageBus." ) ) { - final ContainerStorageBus ccw = (ContainerStorageBus) c; if( this.Name.equals( "StorageBus.Action" ) ) { if( this.Value.equals( "Partition" ) ) { - ccw.partition(); + if( c instanceof ContainerStorageBus ) + { + ( (ContainerStorageBus) c ).partition(); + } + else if( c instanceof ContainerFluidStorageBus ) + { + ( (ContainerFluidStorageBus) c ).partition(); + } } else if( this.Value.equals( "Clear" ) ) { - ccw.clear(); + if( c instanceof ContainerStorageBus ) + { + ( (ContainerStorageBus) c ).clear(); + } + else if( c instanceof ContainerFluidStorageBus ) + { + ( (ContainerFluidStorageBus) c ).clear(); + } } } } diff --git a/src/main/java/appeng/fluids/contents/FluidCellConfig.java b/src/main/java/appeng/fluids/contents/FluidCellConfig.java new file mode 100644 index 000000000..a20279127 --- /dev/null +++ b/src/main/java/appeng/fluids/contents/FluidCellConfig.java @@ -0,0 +1,106 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.contents; + + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidUtil; + +import appeng.core.Api; +import appeng.fluids.items.FluidDummyItem; +import appeng.items.contents.CellConfig; + + +/** + * @author DrummerMC + * @version rv6 - 2018-01-22 + * @since rv6 2018-01-22 + */ +public class FluidCellConfig extends CellConfig +{ + public FluidCellConfig( ItemStack is ) + { + super( is ); + } + + @Override + @Nonnull + public ItemStack insertItem( int slot, @Nonnull ItemStack stack, boolean simulate ) + { + if( stack.isEmpty() || stack.getItem() instanceof FluidDummyItem ) + { + super.insertItem( slot, stack, simulate ); + } + FluidStack fluid = FluidUtil.getFluidContained( stack ); + if( fluid == null || !Api.INSTANCE.definitions().items().dummyFluidItem().maybeStack( 1 ).isPresent() ) + { + return stack; + } + + fluid.amount = Fluid.BUCKET_VOLUME; + ItemStack is = Api.INSTANCE.definitions().items().dummyFluidItem().maybeStack( 1 ).get(); + FluidDummyItem item = (FluidDummyItem) is.getItem(); + item.setFluidStack( is, fluid ); + return super.insertItem( slot, is, simulate ); + } + + @Override + public void setStackInSlot( int slot, @Nonnull ItemStack stack ) + { + if( stack.isEmpty() || stack.getItem() instanceof FluidDummyItem ) + { + super.setStackInSlot( slot, stack ); + } + FluidStack fluid = FluidUtil.getFluidContained( stack ); + if( fluid == null || !Api.INSTANCE.definitions().items().dummyFluidItem().maybeStack( 1 ).isPresent() ) + { + return; + } + + fluid.amount = Fluid.BUCKET_VOLUME; + ItemStack is = Api.INSTANCE.definitions().items().dummyFluidItem().maybeStack( 1 ).get(); + FluidDummyItem item = (FluidDummyItem) is.getItem(); + item.setFluidStack( is, fluid ); + super.setStackInSlot( slot, is ); + } + + @Override + public boolean isItemValidForSlot( int slot, ItemStack stack ) + { + if( stack.isEmpty() || stack.getItem() instanceof FluidDummyItem ) + { + super.isItemValidForSlot( slot, stack ); + } + FluidStack fluid = FluidUtil.getFluidContained( stack ); + if( fluid == null || !Api.INSTANCE.definitions().items().dummyFluidItem().maybeStack( 1 ).isPresent() ) + { + return false; + } + fluid.amount = Fluid.BUCKET_VOLUME; + ItemStack is = Api.INSTANCE.definitions().items().dummyFluidItem().maybeStack( 1 ).get(); + FluidDummyItem item = (FluidDummyItem) is.getItem(); + item.setFluidStack( is, fluid ); + return super.isItemValidForSlot( slot, is ); + } + +} diff --git a/src/main/java/appeng/fluids/items/BasicFluidStorageCell.java b/src/main/java/appeng/fluids/items/BasicFluidStorageCell.java new file mode 100644 index 000000000..021010291 --- /dev/null +++ b/src/main/java/appeng/fluids/items/BasicFluidStorageCell.java @@ -0,0 +1,116 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.items; + + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +import appeng.api.AEApi; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.fluids.contents.FluidCellConfig; +import appeng.items.materials.MaterialType; +import appeng.items.storage.AbstractStorageCell; +import appeng.util.InventoryAdaptor; + + +/** + * @author DrummerMC + * @version rv6 - 2018-01-17 + * @since rv6 2018-01-17 + */ +public final class BasicFluidStorageCell extends AbstractStorageCell +{ + + private final int perType; + private final double idleDrain; + + public BasicFluidStorageCell( final MaterialType whichCell, final int kilobytes ) + { + super( whichCell, kilobytes ); + switch( whichCell ) + { + case FLUID_CELL1K_PART: + this.idleDrain = 0.5; + this.perType = 8; + break; + case FLUID_CELL4K_PART: + this.idleDrain = 1.0; + this.perType = 32; + break; + case FLUID_CELL16K_PART: + this.idleDrain = 1.5; + this.perType = 128; + break; + case FLUID_CELL64K_PART: + this.idleDrain = 2.0; + this.perType = 512; + break; + default: + this.idleDrain = 0.0; + this.perType = 8; + } + + } + + @Override + public int getBytesPerType( ItemStack cellItem ) + { + return this.perType; + } + + @Override + public double getIdleDrain() + { + return this.idleDrain; + } + + @Override + public IStorageChannel getChannel() + { + return AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ); + } + + @Override + public int getTotalTypes( final ItemStack cellItem ) + { + return 5; + } + + @Override + public IItemHandler getConfigInventory( final ItemStack is ) + { + return new FluidCellConfig( is ); + } + + @Override + protected void dropEmptyStorageCellCase( final InventoryAdaptor ia, final EntityPlayer player ) + { + AEApi.instance().definitions().materials().emptyStorageCell().maybeStack( 1 ).ifPresent( is -> { + final ItemStack extraA = ia.addItems( is ); + if( !extraA.isEmpty() ) + { + player.dropItem( extraA, false ); + } + } ); + } +} \ No newline at end of file diff --git a/src/main/java/appeng/fluids/items/FluidDummyItem.java b/src/main/java/appeng/fluids/items/FluidDummyItem.java new file mode 100644 index 000000000..ccba90531 --- /dev/null +++ b/src/main/java/appeng/fluids/items/FluidDummyItem.java @@ -0,0 +1,83 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.items; + + +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.NonNullList; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +import appeng.items.AEBaseItem; + + +/** + * Dummy item to display the fluid Icon + * + * @author DrummerMC + * @version rv6 - 2018-01-22 + * @since rv6 2018-01-22 + */ +public class FluidDummyItem extends AEBaseItem +{ + @Override + public String getItemStackDisplayName( ItemStack stack ) + { + + FluidStack fluidStack = getFluidStack( stack ); + if( fluidStack == null ) + { + fluidStack = new FluidStack( FluidRegistry.WATER, Fluid.BUCKET_VOLUME ); + } + return fluidStack.getLocalizedName(); + } + + public FluidStack getFluidStack( ItemStack is ) + { + if( is.hasTagCompound() ) + { + NBTTagCompound tag = is.getTagCompound(); + return FluidStack.loadFluidStackFromNBT( tag ); + } + return null; + } + + public void setFluidStack( ItemStack is, FluidStack fs ) + { + if( fs == null ) + { + is.setTagCompound( null ); + } + else + { + NBTTagCompound tag = new NBTTagCompound(); + fs.writeToNBT( tag ); + is.setTagCompound( tag ); + } + } + + @Override + protected void getCheckedSubItems( final CreativeTabs creativeTab, final NonNullList itemStacks ) + { + //Don't show this item in CreativeTabs + } +} diff --git a/src/main/java/appeng/fluids/items/FluidDummyItemRendering.java b/src/main/java/appeng/fluids/items/FluidDummyItemRendering.java new file mode 100644 index 000000000..897b9a485 --- /dev/null +++ b/src/main/java/appeng/fluids/items/FluidDummyItemRendering.java @@ -0,0 +1,39 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.items; + + +import appeng.bootstrap.IItemRendering; +import appeng.bootstrap.ItemRenderingCustomizer; +import appeng.client.render.DummyFluidItemModel; + + +/** + * @author DrummerMC + * @version rv6 - 2018-01-22 + * @since rv6 2018-01-22 + */ +public class FluidDummyItemRendering extends ItemRenderingCustomizer +{ + @Override + public void customize( IItemRendering rendering ) + { + rendering.builtInModel( "models/item/dummy_fluid_item", new DummyFluidItemModel() ); + } +} diff --git a/src/main/java/appeng/fluids/parts/FluidHandlerAdapter.java b/src/main/java/appeng/fluids/parts/FluidHandlerAdapter.java new file mode 100644 index 000000000..67de8eba9 --- /dev/null +++ b/src/main/java/appeng/fluids/parts/FluidHandlerAdapter.java @@ -0,0 +1,300 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.parts; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; + +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.networking.security.IActionSource; +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.IStorageChannel; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IItemList; +import appeng.me.GridAccessException; +import appeng.me.helpers.IGridProxyable; +import appeng.me.storage.ITickingMonitor; +import appeng.util.item.AEFluidStack; + + +/** + * Wraps an Fluid Handler in such a way that it can be used as an IMEInventory for fluids. + * + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class FluidHandlerAdapter implements IMEInventory, IBaseMonitor, ITickingMonitor +{ + private final Map, Object> listeners = new HashMap<>(); + private IActionSource source; + private final IFluidHandler fluidHandler; + private final IGridProxyable proxyable; + private final FluidHandlerAdapter.InventoryCache cache; + + FluidHandlerAdapter( IFluidHandler fluidHandler, IGridProxyable proxy ) + { + this.fluidHandler = fluidHandler; + this.proxyable = proxy; + this.cache = new FluidHandlerAdapter.InventoryCache( this.fluidHandler ); + } + + @Override + public IAEFluidStack injectItems( IAEFluidStack input, Actionable type, IActionSource src ) + { + FluidStack fluidStack = input.getFluidStack(); + + // Insert + int wasFillled = this.fluidHandler.fill( fluidStack, type != Actionable.SIMULATE ); + int remaining = fluidStack.amount - wasFillled; + if( fluidStack.amount == remaining ) + { + // The stack was unmodified, target tank is full + return input; + } + + if( type == Actionable.MODULATE ) + { + try + { + this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); + } + catch( GridAccessException ignore ) + { + // meh + } + } + + fluidStack.amount = remaining; + + return AEFluidStack.fromFluidStack( fluidStack ); + } + + @Override + public IAEFluidStack extractItems( IAEFluidStack request, Actionable mode, IActionSource src ) + { + FluidStack requestedFluidStack = request.getFluidStack(); + final boolean doDrain = ( mode == Actionable.MODULATE ); + + // Drain the fluid from the tank + FluidStack gathered = this.fluidHandler.drain( requestedFluidStack, doDrain ); + if( gathered == null ) + { + // If nothing was pulled from the tank, return null + return null; + } + + if( mode == Actionable.MODULATE ) + { + try + { + this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); + } + catch( GridAccessException ignore ) + { + // meh + } + } + return AEFluidStack.fromFluidStack( gathered ); + } + + @Override + public TickRateModulation onTick() + { + List changes = this.cache.update(); + if( !changes.isEmpty() ) + { + this.postDifference( changes ); + return TickRateModulation.URGENT; + } + else + { + return TickRateModulation.SLOWER; + } + } + + @Override + public IItemList getAvailableItems( IItemList out ) + { + return this.cache.getAvailableItems( out ); + } + + @Override + public IStorageChannel getChannel() + { + return AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ); + } + + @Override + public void setActionSource( IActionSource source ) + { + this.source = source; + } + + @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 ); + } + + 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, this.source ); + } + else + { + i.remove(); + } + } + } + + private static class InventoryCache + { + private IAEFluidStack[] cachedAeStacks = new IAEFluidStack[0]; + private final IFluidHandler fluidHandler; + + public InventoryCache( IFluidHandler fluidHandler ) + { + this.fluidHandler = fluidHandler; + } + + public List update() + { + final List changes = new ArrayList<>(); + final IFluidTankProperties[] tankProperties = this.fluidHandler.getTankProperties(); + final int slots = tankProperties.length; + + // Make room for new slots + if( slots > this.cachedAeStacks.length ) + { + this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots ); + } + + for( int slot = 0; slot < slots; slot++ ) + { + // Save the old stuff + final IAEFluidStack oldAEFS = this.cachedAeStacks[slot]; + final FluidStack newFS = tankProperties[slot].getContents(); + + this.handlePossibleSlotChanges( slot, oldAEFS, newFS, changes ); + } + + // Handle cases where the number of slots actually is lower now than before + if( slots < this.cachedAeStacks.length ) + { + for( int slot = slots; slot < this.cachedAeStacks.length; slot++ ) + { + final IAEFluidStack aeStack = this.cachedAeStacks[slot]; + + if( aeStack != null ) + { + final IAEFluidStack a = aeStack.copy(); + a.setStackSize( -a.getStackSize() ); + changes.add( a ); + } + } + + this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots ); + } + return changes; + } + + public IItemList getAvailableItems( IItemList out ) + { + Arrays.stream( this.cachedAeStacks ).forEach( out::add ); + return out; + } + + private void handlePossibleSlotChanges( int slot, IAEFluidStack oldAeFS, FluidStack newFS, List changes ) + { + if( oldAeFS != null && oldAeFS.getFluidStack().isFluidEqual( newFS ) ) + { + this.handleStackSizeChanged( slot, oldAeFS, newFS, changes ); + } + else + { + this.handleFluidChanged( slot, oldAeFS, newFS, changes ); + } + } + + private void handleStackSizeChanged( int slot, IAEFluidStack oldAeFS, FluidStack newFS, List changes ) + { + // Still the same fluid, but amount might have changed + final long diff = newFS.amount - oldAeFS.getStackSize(); + + if( diff != 0 ) + { + final IAEFluidStack stack = oldAeFS.copy(); + stack.setStackSize( newFS.amount ); + + this.cachedAeStacks[slot] = stack; + + final IAEFluidStack a = stack.copy(); + a.setStackSize( diff ); + changes.add( a ); + } + } + + private void handleFluidChanged( int slot, IAEFluidStack oldAeFS, FluidStack newFS, List changes ) + { + // Completely different fluid + this.cachedAeStacks[slot] = AEFluidStack.fromFluidStack( newFS ); + + // If we had a stack previously in this slot, notify the network about its disappearance + if( oldAeFS != null ) + { + oldAeFS.setStackSize( -oldAeFS.getStackSize() ); + changes.add( oldAeFS ); + } + + // Notify the network about the new stack. Note that this is null if newFS was null + if( this.cachedAeStacks[slot] != null ) + { + changes.add( this.cachedAeStacks[slot] ); + } + } + } +} diff --git a/src/main/java/appeng/fluids/parts/PartFluidExportBus.java b/src/main/java/appeng/fluids/parts/PartFluidExportBus.java new file mode 100644 index 000000000..c13670d25 --- /dev/null +++ b/src/main/java/appeng/fluids/parts/PartFluidExportBus.java @@ -0,0 +1,185 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.parts; + + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; + +import appeng.api.config.Actionable; +import appeng.api.config.FuzzyMode; +import appeng.api.config.RedstoneMode; +import appeng.api.config.SchedulingMode; +import appeng.api.config.Settings; +import appeng.api.config.YesNo; +import appeng.api.networking.IGridNode; +import appeng.api.networking.security.IActionSource; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.api.parts.IPartCollisionHelper; +import appeng.api.parts.IPartModel; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.core.AppEng; +import appeng.core.settings.TickRates; +import appeng.items.parts.PartModels; +import appeng.me.GridAccessException; +import appeng.me.helpers.MachineSource; +import appeng.parts.PartModel; +import appeng.util.item.AEFluidStack; + + +/** + * @author BrockWS + * @version rv6 - 30/04/2018 + * @since rv6 30/04/2018 + */ +public class PartFluidExportBus extends PartSharedFluidBus +{ + public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/fluid_export_bus_base" ); + @PartModels + public static final IPartModel MODELS_OFF = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_export_bus_off" ) ); + @PartModels + public static final IPartModel MODELS_ON = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_export_bus_on" ) ); + @PartModels + public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_export_bus_has_channel" ) ); + + private final IActionSource source; + + public PartFluidExportBus( ItemStack is ) + { + super( is ); + this.getConfigManager().registerSetting( Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE ); + this.getConfigManager().registerSetting( Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL ); + this.getConfigManager().registerSetting( Settings.CRAFT_ONLY, YesNo.NO ); + this.getConfigManager().registerSetting( Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT ); + this.source = new MachineSource( this ); + } + + @Override + public TickingRequest getTickingRequest( IGridNode node ) + { + return new TickingRequest( TickRates.FluidExportBus.getMin(), TickRates.FluidExportBus.getMax(), this.isSleeping(), false ); + } + + @Override + public TickRateModulation tickingRequest( IGridNode node, int ticksSinceLastCall ) + { + return this.canDoBusWork() ? this.doBusWork() : TickRateModulation.IDLE; + } + + @Override + protected boolean canDoBusWork() + { + return this.getProxy().isActive(); + } + + @Override + protected TickRateModulation doBusWork() + { + if( !this.canDoBusWork() ) + { + return TickRateModulation.IDLE; + } + + final TileEntity te = this.getConnectedTE(); + if( te != null && te.hasCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, this.getSide().getFacing() ) ) + { + try + { + final IFluidHandler fh = te.getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, this.getSide().getFacing() ); + final IMEMonitor inv = this.getProxy().getStorage().getInventory( this.getChannel() ); + if( fh != null ) + { + for( int i = 0; i < this.getConfig().getSlots(); i++ ) + { + IAEItemStack stack = this.getConfig().getAEStackInSlot( i ); + if( stack != null && stack.getDefinition() != null ) + { + IFluidHandlerItem ifh = stack.getDefinition().getCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null ); + if( ifh == null ) + { + throw new NullPointerException( "IFluidHandlerItem is null" ); + } + AEFluidStack toExtract = AEFluidStack.fromFluidStack( ifh.drain( Integer.MAX_VALUE, false ) ); + toExtract.setStackSize( this.calculateAmountToSend() ); + IAEFluidStack out = inv.extractItems( toExtract, Actionable.SIMULATE, this.source ); + if( out != null ) + { + int wasInserted = fh.fill( out.getFluidStack(), true ); + if( wasInserted > 0 ) + { + inv.extractItems( toExtract, Actionable.MODULATE, this.source ); + return TickRateModulation.FASTER; + } + } + } + } + return TickRateModulation.SLOWER; + } + } + catch( GridAccessException e ) + { + // Ignore + } + } + + return TickRateModulation.SLEEP; + } + + @Override + public void getBoxes( final IPartCollisionHelper bch ) + { + bch.addBox( 4, 4, 12, 12, 12, 14 ); + bch.addBox( 5, 5, 14, 11, 11, 15 ); + bch.addBox( 6, 6, 15, 10, 10, 16 ); + bch.addBox( 6, 6, 11, 10, 10, 12 ); + } + + @Override + public RedstoneMode getRSMode() + { + return (RedstoneMode) this.getConfigManager().getSetting( Settings.REDSTONE_CONTROLLED ); + } + + @Nonnull + @Override + public IPartModel getStaticModels() + { + if( this.isActive() && this.isPowered() ) + { + return MODELS_HAS_CHANNEL; + } + else if( this.isPowered() ) + { + return MODELS_ON; + } + else + { + return MODELS_OFF; + } + } +} diff --git a/src/main/java/appeng/fluids/parts/PartFluidImportBus.java b/src/main/java/appeng/fluids/parts/PartFluidImportBus.java new file mode 100644 index 000000000..00df3d1af --- /dev/null +++ b/src/main/java/appeng/fluids/parts/PartFluidImportBus.java @@ -0,0 +1,202 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.parts; + + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; + +import appeng.api.config.Actionable; +import appeng.api.config.FuzzyMode; +import appeng.api.config.RedstoneMode; +import appeng.api.config.SchedulingMode; +import appeng.api.config.Settings; +import appeng.api.config.YesNo; +import appeng.api.networking.IGridNode; +import appeng.api.networking.security.IActionSource; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.api.parts.IPartModel; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.core.AppEng; +import appeng.core.settings.TickRates; +import appeng.items.parts.PartModels; +import appeng.me.GridAccessException; +import appeng.me.helpers.MachineSource; +import appeng.parts.PartModel; +import appeng.util.item.AEFluidStack; + + +/** + * @author BrockWS + * @version rv6 - 30/04/2018 + * @since rv6 30/04/2018 + */ +public class PartFluidImportBus extends PartSharedFluidBus +{ + public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/fluid_import_bus_base" ); + @PartModels + public static final IPartModel MODELS_OFF = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_import_bus_off" ) ); + @PartModels + public static final IPartModel MODELS_ON = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_import_bus_on" ) ); + @PartModels + public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_import_bus_has_channel" ) ); + + private final IActionSource source; + + public PartFluidImportBus( ItemStack is ) + { + super( is ); + this.getConfigManager().registerSetting( Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE ); + this.getConfigManager().registerSetting( Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL ); + this.getConfigManager().registerSetting( Settings.CRAFT_ONLY, YesNo.NO ); + this.getConfigManager().registerSetting( Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT ); + this.source = new MachineSource( this ); + } + + @Override + public TickingRequest getTickingRequest( IGridNode node ) + { + return new TickingRequest( TickRates.FluidImportBus.getMin(), TickRates.FluidImportBus.getMax(), this.isSleeping(), false ); + } + + @Override + public TickRateModulation tickingRequest( IGridNode node, int ticksSinceLastCall ) + { + return this.canDoBusWork() ? this.doBusWork() : TickRateModulation.IDLE; + } + + @Override + protected TickRateModulation doBusWork() + { + if( !this.canDoBusWork() ) + { + return TickRateModulation.IDLE; + } + + final TileEntity te = this.getConnectedTE(); + if( te != null && te.hasCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, this.getSide().getFacing() ) ) + { + try + { + final IFluidHandler fh = te.getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, this.getSide().getFacing() ); + final IMEMonitor inv = this.getProxy().getStorage().getInventory( this.getChannel() ); + if( fh != null ) + { + FluidStack fluidStack = fh.drain( this.calculateAmountToSend(), false ); + if( this.filterEnabled() && !this.isInFilter( fluidStack ) ) + { + return TickRateModulation.SLOWER; + } + AEFluidStack aeFluidStack = AEFluidStack.fromFluidStack( fluidStack ); + if( aeFluidStack != null ) + { + IAEFluidStack notInserted = inv.injectItems( aeFluidStack, Actionable.MODULATE, this.source ); + if( notInserted != null && notInserted.getStackSize() > 0 ) + { + aeFluidStack.decStackSize( notInserted.getStackSize() ); + } + fh.drain( aeFluidStack.getFluidStack(), true ); + return TickRateModulation.FASTER; + } + } + } + catch( GridAccessException e ) + { + e.printStackTrace(); + } + } + + return TickRateModulation.SLEEP; + } + + @Override + protected boolean canDoBusWork() + { + return this.getProxy().isActive(); + } + + private boolean isInFilter( FluidStack fluid ) + { + for( int i = 0; i < this.getConfig().getSlots(); i++ ) + { + IAEItemStack stack = this.getConfig().getAEStackInSlot( i ); + if( stack != null && stack.getDefinition() != null ) + { + IFluidHandlerItem fh = stack.getDefinition().getCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null ); + if( fh == null ) + { + throw new NullPointerException( "IFluidHandlerItem is null" ); + } + FluidStack filtered = fh.drain( Integer.MAX_VALUE, false ); + if( filtered != null && filtered.isFluidEqual( fluid ) ) + { + return true; + } + } + } + return false; + } + + private boolean filterEnabled() + { + for( int i = 0; i < this.getConfig().getSlots(); i++ ) + { + IAEItemStack stack = this.getConfig().getAEStackInSlot( i ); + if( stack != null ) + { + return true; + } + } + return false; + } + + @Override + public RedstoneMode getRSMode() + { + return (RedstoneMode) this.getConfigManager().getSetting( Settings.REDSTONE_CONTROLLED ); + } + + @Nonnull + @Override + public IPartModel getStaticModels() + { + if( this.isActive() && this.isPowered() ) + { + return MODELS_HAS_CHANNEL; + } + else if( this.isPowered() ) + { + return MODELS_ON; + } + else + { + return MODELS_OFF; + } + } +} diff --git a/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java b/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java new file mode 100644 index 000000000..0a7a6650e --- /dev/null +++ b/src/main/java/appeng/fluids/parts/PartFluidStorageBus.java @@ -0,0 +1,509 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.parts; + + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.player.EntityPlayer; +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.fluids.FluidStack; +import net.minecraftforge.fluids.FluidUtil; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; +import net.minecraftforge.items.IItemHandler; + +import appeng.api.AEApi; +import appeng.api.config.AccessRestriction; +import appeng.api.config.FuzzyMode; +import appeng.api.config.IncludeExclude; +import appeng.api.config.Settings; +import appeng.api.config.StorageFilter; +import appeng.api.config.Upgrades; +import appeng.api.networking.IGridNode; +import appeng.api.networking.events.MENetworkCellArrayUpdate; +import appeng.api.networking.security.IActionSource; +import appeng.api.networking.storage.IBaseMonitor; +import appeng.api.networking.ticking.ITickManager; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.networking.ticking.TickingRequest; +import appeng.api.parts.IPartHost; +import appeng.api.parts.IPartModel; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IMEMonitorHandlerReceiver; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.IStorageMonitorable; +import appeng.api.storage.IStorageMonitorableAccessor; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.api.util.AEPartLocation; +import appeng.capabilities.Capabilities; +import appeng.core.AppEng; +import appeng.core.settings.TickRates; +import appeng.core.sync.GuiBridge; +import appeng.helpers.IInterfaceHost; +import appeng.items.parts.PartModels; +import appeng.me.GridAccessException; +import appeng.me.helpers.MachineSource; +import appeng.me.storage.ITickingMonitor; +import appeng.me.storage.MEInventoryHandler; +import appeng.parts.PartModel; +import appeng.parts.misc.PartSharedStorageBus; +import appeng.tile.inventory.AppEngInternalAEInventory; +import appeng.util.Platform; +import appeng.util.inv.InvOperation; +import appeng.util.item.AEFluidStack; +import appeng.util.prioritylist.FuzzyPriorityList; +import appeng.util.prioritylist.PrecisePriorityList; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class PartFluidStorageBus extends PartSharedStorageBus implements IMEMonitorHandlerReceiver +{ + public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/fluid_storage_bus_base" ); + @PartModels + public static final IPartModel MODELS_OFF = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_storage_bus_off" ) ); + @PartModels + public static final IPartModel MODELS_ON = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_storage_bus_on" ) ); + @PartModels + public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/fluid_storage_bus_has_channel" ) ); + + private final IActionSource source; + private final AppEngInternalAEInventory config = new AppEngInternalAEInventory( this, 63 ); + private boolean cached = false; + private ITickingMonitor monitor = null; + private MEInventoryHandler handler = null; + private int handlerHash = 0; + private byte resetCacheLogic = 0; + + public PartFluidStorageBus( ItemStack is ) + { + super( is ); + this.getConfigManager().registerSetting( Settings.ACCESS, AccessRestriction.READ_WRITE ); + this.getConfigManager().registerSetting( Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL ); + this.getConfigManager().registerSetting( Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY ); + this.source = new MachineSource( this ); + } + + 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( this.source ); + if( inventory != null ) + { + return inventory.getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ); + } + + // 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 + IFluidHandler handlerExt = target.getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, targetSide ); + if( handlerExt != null ) + { + return new FluidHandlerAdapter( handlerExt, this ); + } + + return null; + } + + @Override + public TickRateModulation tickingRequest( IGridNode node, int ticksSinceLastCall ) + { + if( this.resetCacheLogic != 0 ) + { + this.resetCache(); + } + + if( this.monitor != null ) + { + return this.monitor.onTick(); + } + + return TickRateModulation.SLEEP; + } + + protected void resetCache() + { + final boolean fullReset = this.resetCacheLogic == 2; + this.resetCacheLogic = 0; + + final IMEInventory in = this.getInternalHandler(); + IItemList before = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); + if( in != null ) + { + before = in.getAvailableItems( before ); + } + + this.cached = false; + if( fullReset ) + { + this.handlerHash = 0; + } + + final IMEInventory out = this.getInternalHandler(); + + if( in != out ) + { + IItemList after = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); + if( out != null ) + { + after = out.getAvailableItems( after ); + } + Platform.postListChanges( before, after, this, this.source ); + } + } + + protected void resetCache( final boolean fullReset ) + { + if( this.getHost() == null || this.getHost().getTile() == null || this.getHost().getTile().getWorld() == null || this.getHost().getTile().getWorld().isRemote ) + { + return; + } + + if( fullReset ) + { + this.resetCacheLogic = 2; + } + else + { + this.resetCacheLogic = 1; + } + + try + { + this.getProxy().getTick().alertDevice( this.getProxy().getNode() ); + } + catch( final GridAccessException e ) + { + // :P + } + } + + @Override + public boolean onPartActivate( final EntityPlayer player, final EnumHand hand, final Vec3d pos ) + { + if( !player.isSneaking() ) + { + if( Platform.isClient() ) + { + return true; + } + Platform.openGUI( player, this.getHost().getTile(), this.getSide(), GuiBridge.GUI_STORAGEBUS_FLUID ); + return true; + } + + return false; + } + + @Override + public void onChangeInventory( final IItemHandler inv, final int slot, final InvOperation mc, final ItemStack removedStack, final ItemStack newStack ) + { + super.onChangeInventory( inv, slot, mc, removedStack, newStack ); + + if( inv == this.config ) + { + this.resetCache( true ); + } + } + + @Override + public IItemHandler getInventoryByName( final String name ) + { + if( name.equals( "config" ) ) + { + return this.config; + } + + return super.getInventoryByName( name ); + } + + @Override + public void readFromNBT( final NBTTagCompound data ) + { + super.readFromNBT( data ); + this.config.readFromNBT( data, "config" ); + } + + @Override + public void writeToNBT( final NBTTagCompound data ) + { + super.writeToNBT( data ); + this.config.writeToNBT( data, "config" ); + } + + @Override + public boolean isValid( final Object verificationToken ) + { + return this.handler == verificationToken; + } + + @Override + public void postChange( final IBaseMonitor monitor, final Iterable change, final IActionSource source ) + { + try + { + if( this.getProxy().isActive() ) + { + this.getProxy().getStorage().postAlterationOfStoredItems( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ), change, this.source ); + } + } + catch( final GridAccessException e ) + { + // :( + } + } + + public MEInventoryHandler getInternalHandler() + { + if( this.cached ) + { + return this.handler; + } + + final boolean wasSleeping = this.monitor == null; + + this.cached = true; + final TileEntity self = this.getHost().getTile(); + final TileEntity target = self.getWorld().getTileEntity( self.getPos().offset( this.getSide().getFacing() ) ); + final int newHandlerHash = this.createHandlerHash( target ); + + if( newHandlerHash != 0 && newHandlerHash == this.handlerHash ) + { + return this.handler; + } + + this.handlerHash = newHandlerHash; + this.handler = null; + this.monitor = null; + if( target != null ) + { + IMEInventory inv = this.getInventoryWrapper( target ); + 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, AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ); + + 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.getPriority() ); + + final IItemList priorityList = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList(); + + final int slotsToUse = 18 + this.getInstalledUpgrades( Upgrades.CAPACITY ) * 9; + for( int x = 0; x < this.config.getSlots() && x < slotsToUse; x++ ) + { + final IAEItemStack is = this.config.getAEStackInSlot( x ); + if( is != null ) + { + // Because we store filtered fluid as buckets, we need to grab the fluid from the stack + IFluidHandlerItem fh = FluidUtil.getFluidHandler( is.createItemStack() ); + if( fh == null ) + { + continue; + } + FluidStack fluid = fh.drain( Integer.MAX_VALUE, false ); + priorityList.add( AEFluidStack.fromFluidStack( fluid ) ); + } + } + + 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 IBaseMonitor ) + { + ( (IBaseMonitor) inv ).addListener( this, this.handler ); + } + } + } + + // update sleep state... + if( wasSleeping != ( this.monitor == null ) ) + { + try + { + final ITickManager tm = this.getProxy().getTick(); + if( this.monitor == null ) + { + tm.sleepDevice( this.getProxy().getNode() ); + } + else + { + tm.wakeDevice( this.getProxy().getNode() ); + } + } + catch( final GridAccessException ignore ) + { + // :( + } + } + + try + { + // force grid to update handlers... + this.getProxy().getGrid().postEvent( new MENetworkCellArrayUpdate() ); + } + catch( final GridAccessException ignore ) + { + // :3 + } + + return this.handler; + } + + private void checkInterfaceVsStorageBus( final TileEntity target, final AEPartLocation side ) + { + IInterfaceHost achievement = null; + + if( target instanceof IInterfaceHost ) + { + achievement = (IInterfaceHost) target; + } + + if( target instanceof IPartHost ) + { + final Object part = ( (IPartHost) target ).getPart( side ); + if( part instanceof IInterfaceHost ) + { + achievement = (IInterfaceHost) part; + } + } + + if( achievement != null && achievement.getActionableNode() != null ) + { + // Platform.addStat( achievement.getActionableNode().getPlayerID(), Achievements.Recursive.getAchievement() + // ); + // Platform.addStat( getActionableNode().getPlayerID(), Achievements.Recursive.getAchievement() ); + } + } + + @Override + public List getCellArray( final IStorageChannel channel ) + { + if( channel == this.getStorageChannel() ) + { + final IMEInventoryHandler out = this.getProxy().isActive() ? this.getInternalHandler() : null; + if( out != null ) + { + return Collections.singletonList( out ); + } + } + return super.getCellArray( channel ); + } + + private int createHandlerHash( TileEntity target ) + { + if( target == null ) + { + return 0; + } + + final EnumFacing targetSide = this.getSide().getFacing().getOpposite(); + + if( target.hasCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, targetSide ) ) + { + return Objects.hash( target, target.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, targetSide ) ); + } + + final IFluidHandler fluidHandler = target.getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, targetSide ); + + if( fluidHandler != null ) + { + return Objects.hash( target, fluidHandler, fluidHandler.getTankProperties().length ); + } + + return 0; + } + + @Override + public TickingRequest getTickingRequest( IGridNode node ) + { + return new TickingRequest( TickRates.FluidStorageBus.getMin(), TickRates.FluidStorageBus.getMax(), this.isSleeping(), true ); + } + + @Override + public void onListUpdate() + { + // not used here. + } + + @Override + public IStorageChannel getStorageChannel() + { + return AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ); + } + + @SuppressWarnings( "Duplicates" ) + @Nonnull + @Override + public IPartModel getStaticModels() + { + if( this.isActive() && this.isPowered() ) + { + return MODELS_HAS_CHANNEL; + } + else if( this.isPowered() ) + { + return MODELS_ON; + } + else + { + return MODELS_OFF; + } + } +} diff --git a/src/main/java/appeng/fluids/parts/PartSharedFluidBus.java b/src/main/java/appeng/fluids/parts/PartSharedFluidBus.java new file mode 100644 index 000000000..730100eec --- /dev/null +++ b/src/main/java/appeng/fluids/parts/PartSharedFluidBus.java @@ -0,0 +1,209 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.parts; + + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.items.IItemHandler; + +import appeng.api.AEApi; +import appeng.api.config.RedstoneMode; +import appeng.api.config.Upgrades; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.networking.ticking.TickRateModulation; +import appeng.api.parts.IPartCollisionHelper; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.util.AECableType; +import appeng.core.sync.GuiBridge; +import appeng.me.GridAccessException; +import appeng.parts.automation.PartUpgradeable; +import appeng.tile.inventory.AppEngInternalAEInventory; +import appeng.util.Platform; + + +/** + * @author BrockWS + * @version rv6 - 30/04/2018 + * @since rv6 30/04/2018 + */ +public abstract class PartSharedFluidBus extends PartUpgradeable implements IGridTickable +{ + + private final AppEngInternalAEInventory config = new AppEngInternalAEInventory( this, 9 ); + private boolean lastRedstone; + + public PartSharedFluidBus( ItemStack is ) + { + super( is ); + } + + @Override + public void upgradesChanged() + { + this.updateState(); + } + + @Override + public void onNeighborChanged( IBlockAccess w, BlockPos pos, BlockPos neighbor ) + { + this.updateState(); + if( this.lastRedstone != this.getHost().hasRedstone( this.getSide() ) ) + { + this.lastRedstone = !this.lastRedstone; + if( this.lastRedstone && this.getRSMode() == RedstoneMode.SIGNAL_PULSE ) + { + this.doBusWork(); + } + } + } + + private void updateState() + { + try + { + if( !this.isSleeping() ) + { + this.getProxy().getTick().wakeDevice( this.getProxy().getNode() ); + } + else + { + this.getProxy().getTick().sleepDevice( this.getProxy().getNode() ); + } + } + catch( final GridAccessException e ) + { + // :P + } + } + + @Override + public boolean onPartActivate( final EntityPlayer player, final EnumHand hand, final Vec3d pos ) + { + if( !player.isSneaking() ) + { + if( Platform.isClient() ) + { + return true; + } + + Platform.openGUI( player, this.getHost().getTile(), this.getSide(), GuiBridge.GUI_BUS_FLUID ); + return true; + } + + return false; + } + + @Override + public void getBoxes( IPartCollisionHelper bch ) + { + bch.addBox( 6, 6, 11, 10, 10, 13 ); + bch.addBox( 5, 5, 13, 11, 11, 14 ); + bch.addBox( 4, 4, 14, 12, 12, 16 ); + } + + protected TileEntity getConnectedTE() + { + TileEntity self = this.getHost().getTile(); + return this.getTileEntity( self, self.getPos().offset( this.getSide().getFacing() ) ); + } + + private TileEntity getTileEntity( final TileEntity self, final BlockPos pos ) + { + final World w = self.getWorld(); + + if( w.getChunkProvider().getLoadedChunk( pos.getX() >> 4, pos.getZ() >> 4 ) != null ) + { + return w.getTileEntity( pos ); + } + + return null; + } + + @Override + public IItemHandler getInventoryByName( final String name ) + { + if( name.equals( "config" ) ) + { + return this.getConfig(); + } + + return super.getInventoryByName( name ); + } + + protected int calculateAmountToSend() + { + double amount = this.getChannel().transferFactor(); + switch( this.getInstalledUpgrades( Upgrades.SPEED ) ) + { + case 4: + amount = amount * 1.5; + case 3: + amount = amount * 2; + case 2: + amount = amount * 4; + case 1: + amount = amount * 8; + case 0: + default: + return MathHelper.floor( amount ); + } + } + + @Override + public void readFromNBT( NBTTagCompound extra ) + { + super.readFromNBT( extra ); + this.getConfig().readFromNBT( extra, "config" ); + } + + @Override + public void writeToNBT( NBTTagCompound extra ) + { + super.writeToNBT( extra ); + this.getConfig().writeToNBT( extra, "config" ); + } + + public AppEngInternalAEInventory getConfig() + { + return this.config; + } + + protected IFluidStorageChannel getChannel(){ + return AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ); + } + + @Override + public float getCableConnectionLength( AECableType cable ) + { + return 5; + } + + protected abstract TickRateModulation doBusWork(); + + protected abstract boolean canDoBusWork(); +} diff --git a/src/main/java/appeng/fluids/registries/BasicFluidCellHandler.java b/src/main/java/appeng/fluids/registries/BasicFluidCellHandler.java new file mode 100644 index 000000000..1e7d78e9a --- /dev/null +++ b/src/main/java/appeng/fluids/registries/BasicFluidCellHandler.java @@ -0,0 +1,87 @@ +/* + * 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.fluids.registries; + + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +import appeng.api.AEApi; +import appeng.api.implementations.tiles.IChestOrDrive; +import appeng.api.storage.ICellHandler; +import appeng.api.storage.ICellInventory; +import appeng.api.storage.ICellInventoryHandler; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.ISaveProvider; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEStack; +import appeng.fluids.storage.FluidCellInventory; +import appeng.fluids.storage.FluidCellInventoryHandler; + + +public class BasicFluidCellHandler implements ICellHandler +{ + + @Override + public boolean isCell( final ItemStack is ) + { + return FluidCellInventory.isCell( is ); + } + + @Override + public > IMEInventoryHandler getCellInventory( final ItemStack is, final ISaveProvider container, final IStorageChannel channel ) + { + if( channel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) + { + return FluidCellInventory.getCell( is, container ); + } + + return null; + } + + @Override + public void openChestGui( final EntityPlayer player, final IChestOrDrive chest, final ICellHandler cellHandler, final IMEInventoryHandler inv, final ItemStack is, final IStorageChannel chan ) + { + if( chan == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) + { + //TODO: Open Gui + //Platform.openGUI( player, (TileEntity) chest, AEPartLocation.fromFacing( chest.getUp() ), GuiBridge.GUI_ME ); + } + } + + @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 ICellInventory inv = ( (ICellInventoryHandler) handler ).getCellInv(); + return inv.getIdleDrain(); + } +} diff --git a/src/main/java/appeng/fluids/storage/FluidCellInventory.java b/src/main/java/appeng/fluids/storage/FluidCellInventory.java new file mode 100644 index 000000000..2bd514331 --- /dev/null +++ b/src/main/java/appeng/fluids/storage/FluidCellInventory.java @@ -0,0 +1,270 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.fluids.storage; + + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; + +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.exceptions.AppEngException; +import appeng.api.implementations.items.IStorageCell; +import appeng.api.networking.security.IActionSource; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.ISaveProvider; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.core.AEConfig; +import appeng.core.AELog; +import appeng.me.storage.AbstractCellInventory; +import appeng.util.item.AEFluidStack; + + +/** + * @author DrummerMC + * @version rv6 - 2018-01-16 + * @since rv6 2018-01-16 + */ +public class FluidCellInventory extends AbstractCellInventory +{ + protected FluidCellInventory( final NBTTagCompound data, final ISaveProvider container ) + { + super( data, container, 8000 ); + } + + private FluidCellInventory( final ItemStack o, final ISaveProvider container ) throws AppEngException + { + super( o, container, 8000 ); + } + + 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 i ) + { + if( i == null ) + { + return false; + } + + final Item type = i.getItem(); + if( type instanceof IStorageCell ) + { + if( ( (IStorageCell) type ).getChannel() == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) + { + return ( (IStorageCell) type ).isStorageCell( i ); + } + } + + return false; + } + + @Override + public IAEFluidStack injectItems( final IAEFluidStack input, final Actionable mode, final IActionSource src ) + { + if( input == null ) + { + return null; + } + if( input.getStackSize() == 0 ) + { + return null; + } + + if( this.cellType.isBlackListed( this.i, input ) ) + { + return input; + } + + final FluidStack sharedFluidStack = input.getFluidStack(); + + final IAEFluidStack l = this.getCellItems().findPrecise( input ); + if( l != null ) + { + final long remainingItemSlots = this.getRemainingItemCount(); + 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.updateItemCount( remainingItemSlots ); + this.saveChanges(); + } + return r; + } + else + { + if( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() + input.getStackSize() ); + this.updateItemCount( input.getStackSize() ); + this.saveChanges(); + } + return null; + } + } + + if( this.canHoldNewItem() ) // room for new type, and for at least one item! + { + final int remainingItemCount = (int) this.getRemainingItemCount() - this.getBytesPerType() * itemsPerByte; + if( remainingItemCount > 0 ) + { + if( input.getStackSize() > remainingItemCount ) + { + final FluidStack toReturn = sharedFluidStack.copy(); + toReturn.amount = sharedFluidStack.amount - remainingItemCount; + if( mode == Actionable.MODULATE ) + { + final FluidStack toWrite = sharedFluidStack.copy(); + toWrite.amount = remainingItemCount; + + this.cellItems.add( AEFluidStack.fromFluidStack( toWrite ) ); + this.updateItemCount( toWrite.amount ); + + this.saveChanges(); + } + return AEFluidStack.fromFluidStack( toReturn ); + } + + if( mode == Actionable.MODULATE ) + { + this.updateItemCount( input.getStackSize() ); + this.cellItems.add( input ); + this.saveChanges(); + } + + return null; + } + } + + return input; + } + + @Override + public IAEFluidStack extractItems( final IAEFluidStack request, final Actionable mode, final IActionSource 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.updateItemCount( -l.getStackSize() ); + l.setStackSize( 0 ); + this.saveChanges(); + } + } + else + { + results.setStackSize( size ); + if( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() - size ); + this.updateItemCount( -size ); + this.saveChanges(); + } + } + } + + return results; + } + + @Override + public IStorageChannel getChannel() + { + return AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ); + } + + protected void loadCellItem( NBTTagCompound compoundTag, int stackSize ) + { + + // Now load the fluid stack + final FluidStack t; + try + { + t = FluidStack.loadFluidStackFromNBT( compoundTag ); + if( t == null ) + { + AELog.warn( "Removing item " + compoundTag + " from storage cell because the associated item type couldn't be found." ); + return; + } + } + catch( Throwable ex ) + { + if( AEConfig.instance().isRemoveCrashingItemsOnLoad() ) + { + AELog.warn( ex, "Removing item " + compoundTag + " from storage cell because loading the ItemStack crashed." ); + return; + } + throw ex; + } + + t.amount = stackSize; + + if( t.amount > 0 ) + { + try + { + this.cellItems.add( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createStack( t ) ); + } + catch( Throwable ex ) + { + if( AEConfig.instance().isRemoveCrashingItemsOnLoad() ) + { + AELog.warn( ex, "Removing item " + t + " from storage cell because processing the loaded item crashed." ); + return; + } + throw ex; + } + } + } +} diff --git a/src/main/java/appeng/fluids/storage/FluidCellInventoryHandler.java b/src/main/java/appeng/fluids/storage/FluidCellInventoryHandler.java new file mode 100644 index 000000000..a45953c93 --- /dev/null +++ b/src/main/java/appeng/fluids/storage/FluidCellInventoryHandler.java @@ -0,0 +1,52 @@ +/* + * 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.fluids.storage; + + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import appeng.api.AEApi; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.channels.IFluidStorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.fluids.items.FluidDummyItem; +import appeng.me.storage.AbstractCellInventoryHandler; +import appeng.util.item.AEFluidStack; + + +public class FluidCellInventoryHandler extends AbstractCellInventoryHandler +{ + + public FluidCellInventoryHandler( IMEInventory c ) + { + super( c, AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ); + } + + @Override + protected IAEFluidStack createConfigStackFromItem( ItemStack is ) + { + if( is.getItem() instanceof FluidDummyItem ) + { + FluidStack fs = ( (FluidDummyItem) is.getItem() ).getFluidStack( is ); + return fs != null ? AEFluidStack.fromFluidStack( fs ) : null; + } + return null; + } +} diff --git a/src/main/java/appeng/helpers/InventoryAction.java b/src/main/java/appeng/helpers/InventoryAction.java index ec239b222..697ea0b08 100644 --- a/src/main/java/appeng/helpers/InventoryAction.java +++ b/src/main/java/appeng/helpers/InventoryAction.java @@ -32,6 +32,10 @@ public enum InventoryAction CRAFT_ITEM, CRAFT_SHIFT, + // fluid term + FILL_ITEM, + EMPTY_ITEM, + // extra... MOVE_REGION, PICKUP_SINGLE, diff --git a/src/main/java/appeng/items/contents/PortableCellViewer.java b/src/main/java/appeng/items/contents/PortableCellViewer.java index c00a1de2c..07d21a309 100644 --- a/src/main/java/appeng/items/contents/PortableCellViewer.java +++ b/src/main/java/appeng/items/contents/PortableCellViewer.java @@ -39,7 +39,7 @@ import appeng.api.storage.data.IAEStack; import appeng.api.util.IConfigManager; import appeng.container.interfaces.IInventorySlotAware; import appeng.me.helpers.MEMonitorHandler; -import appeng.me.storage.CellInventory; +import appeng.me.storage.ItemCellInventory; import appeng.util.ConfigManager; import appeng.util.IConfigManagerHost; import appeng.util.Platform; @@ -54,7 +54,7 @@ public class PortableCellViewer extends MEMonitorHandler implement public PortableCellViewer( final ItemStack is, final int slot ) { - super( CellInventory.getCell( is, null ) ); + super( ItemCellInventory.getCell( is, null ) ); this.ips = (IAEItemPowerStorage) is.getItem(); this.target = is; this.inventorySlot = slot; diff --git a/src/main/java/appeng/items/materials/MaterialType.java b/src/main/java/appeng/items/materials/MaterialType.java index f55ddd9e8..314493874 100644 --- a/src/main/java/appeng/items/materials/MaterialType.java +++ b/src/main/java/appeng/items/materials/MaterialType.java @@ -114,7 +114,12 @@ public enum MaterialType QUANTUM_ENTANGLED_SINGULARITY( 48, "material_quantum_entangled_singularity", EnumSet.of( AEFeature.QUANTUM_NETWORK_BRIDGE ), EntitySingularity.class ), BLANK_PATTERN( 52, "material_blank_pattern", EnumSet.of( AEFeature.PATTERNS ) ), - CARD_CRAFTING( 53, "material_card_crafting", EnumSet.of( AEFeature.ADVANCED_CARDS, AEFeature.CRAFTING_CPU ) ); + CARD_CRAFTING( 53, "material_card_crafting", EnumSet.of( AEFeature.ADVANCED_CARDS, AEFeature.CRAFTING_CPU ) ), + + FLUID_CELL1K_PART( 54, "material_fluid_cell1k_part", EnumSet.of( AEFeature.STORAGE_CELLS ) ), + FLUID_CELL4K_PART( 55, "material_fluid_cell4k_part", EnumSet.of( AEFeature.STORAGE_CELLS ) ), + FLUID_CELL16K_PART( 56, "material_fluid_cell16k_part", EnumSet.of( AEFeature.STORAGE_CELLS ) ), + FLUID_CELL64K_PART( 57, "material_fluid_cell64k_part", EnumSet.of( AEFeature.STORAGE_CELLS ) ); private final Set features; private final ModelResourceLocation model; diff --git a/src/main/java/appeng/items/parts/ItemPart.java b/src/main/java/appeng/items/parts/ItemPart.java index 0b431257b..de214ecbf 100644 --- a/src/main/java/appeng/items/parts/ItemPart.java +++ b/src/main/java/appeng/items/parts/ItemPart.java @@ -278,7 +278,9 @@ public final class ItemPart extends AEBaseItem implements IPartItem, IItemGroup public String getUnlocalizedGroupName( final Set others, final ItemStack is ) { boolean importBus = false; + boolean importBusFluids = false; boolean exportBus = false; + boolean exportBusFluids = false; boolean group = false; final PartType u = this.getTypeByStack( is ); @@ -297,6 +299,13 @@ public final class ItemPart extends AEBaseItem implements IPartItem, IItemGroup group = true; } break; + case FLUID_IMPORT_BUS: + importBusFluids = true; + if( u == pt ) + { + group = true; + } + break; case EXPORT_BUS: exportBus = true; if( u == pt ) @@ -304,15 +313,26 @@ public final class ItemPart extends AEBaseItem implements IPartItem, IItemGroup group = true; } break; + case FLUID_EXPORT_BUS: + exportBusFluids = true; + if( u == pt ) + { + group = true; + } + break; default: } } } - if( group && importBus && exportBus ) + if( group && importBus && exportBus && ( u == PartType.IMPORT_BUS || u == PartType.EXPORT_BUS ) ) { return GuiText.IOBuses.getUnlocalized(); } + if( group && importBusFluids && exportBusFluids && ( u == PartType.FLUID_IMPORT_BUS || u == PartType.FLUID_EXPORT_BUS ) ) + { + return GuiText.IOBusesFluids.getUnlocalized(); + } return null; } diff --git a/src/main/java/appeng/items/parts/PartType.java b/src/main/java/appeng/items/parts/PartType.java index e72c3925d..1a3d1f467 100644 --- a/src/main/java/appeng/items/parts/PartType.java +++ b/src/main/java/appeng/items/parts/PartType.java @@ -41,6 +41,9 @@ import appeng.core.AEConfig; import appeng.core.AppEng; import appeng.core.features.AEFeature; import appeng.core.localization.GuiText; +import appeng.fluids.parts.PartFluidExportBus; +import appeng.fluids.parts.PartFluidImportBus; +import appeng.fluids.parts.PartFluidStorageBus; import appeng.integration.IntegrationRegistry; import appeng.integration.IntegrationType; import appeng.parts.automation.PartAnnihilationPlane; @@ -70,6 +73,7 @@ import appeng.parts.p2p.PartP2PTunnelME; import appeng.parts.reporting.PartConversionMonitor; import appeng.parts.reporting.PartCraftingTerminal; import appeng.parts.reporting.PartDarkPanel; +import appeng.parts.reporting.PartFluidTerminal; import appeng.parts.reporting.PartInterfaceTerminal; import appeng.parts.reporting.PartPanel; import appeng.parts.reporting.PartPatternTerminal; @@ -190,11 +194,16 @@ public enum PartType DARK_MONITOR( 200, "dark_monitor", EnumSet.of( AEFeature.PANELS ), EnumSet.noneOf( IntegrationType.class ), PartDarkPanel.class ), STORAGE_BUS( 220, "storage_bus", EnumSet.of( AEFeature.STORAGE_BUS ), EnumSet.noneOf( IntegrationType.class ), PartStorageBus.class ), + FLUID_STORAGE_BUS( 221, "fluid_storage_bus", EnumSet.of( AEFeature.FLUID_STORAGE_BUS ), EnumSet.noneOf( IntegrationType.class ), PartFluidStorageBus.class ), IMPORT_BUS( 240, "import_bus", EnumSet.of( AEFeature.IMPORT_BUS ), EnumSet.noneOf( IntegrationType.class ), PartImportBus.class ), + FLUID_IMPORT_BUS( 241, "fluid_import_bus", EnumSet.of( AEFeature.FLUID_IMPORT_BUS ), EnumSet.noneOf( IntegrationType.class ), PartFluidImportBus.class ), + EXPORT_BUS( 260, "export_bus", EnumSet.of( AEFeature.EXPORT_BUS ), EnumSet.noneOf( IntegrationType.class ), PartExportBus.class ), + FLUID_EXPORT_BUS( 261, "fluid_export_bus", EnumSet.of( AEFeature.FLUID_EXPORT_BUS ), EnumSet.noneOf( IntegrationType.class ), PartFluidExportBus.class ), + LEVEL_EMITTER( 280, "level_emitter", EnumSet.of( AEFeature.LEVEL_EMITTER ), EnumSet.noneOf( IntegrationType.class ), PartLevelEmitter.class ), ANNIHILATION_PLANE( 300, "annihilation_plane", EnumSet.of( AEFeature.ANNIHILATION_PLANE ), EnumSet @@ -293,7 +302,9 @@ public enum PartType // IntegrationType.OpenComputers ), PartP2POpenComputers.class, GuiText.OCTunnel ), INTERFACE_TERMINAL( 480, "interface_terminal", EnumSet.of( AEFeature.INTERFACE_TERMINAL ), EnumSet - .noneOf( IntegrationType.class ), PartInterfaceTerminal.class ); + .noneOf( IntegrationType.class ), PartInterfaceTerminal.class ), + + FLUID_TERMINAL( 520, "fluid_terminal", EnumSet.of( AEFeature.FLUID_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartFluidTerminal.class ); private final int baseDamage; private final Set features; diff --git a/src/main/java/appeng/items/storage/ItemBasicStorageCell.java b/src/main/java/appeng/items/storage/AbstractStorageCell.java similarity index 76% rename from src/main/java/appeng/items/storage/ItemBasicStorageCell.java rename to src/main/java/appeng/items/storage/AbstractStorageCell.java index f415098ec..ba5144792 100644 --- a/src/main/java/appeng/items/storage/ItemBasicStorageCell.java +++ b/src/main/java/appeng/items/storage/AbstractStorageCell.java @@ -1,6 +1,6 @@ /* * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * Copyright (c) 2013 - 2018, 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 @@ -46,8 +46,8 @@ import appeng.api.implementations.items.IUpgradeModule; import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.IMEInventoryHandler; -import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.core.AEConfig; import appeng.core.features.AEFeature; @@ -60,49 +60,28 @@ import appeng.util.InventoryAdaptor; import appeng.util.Platform; -public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCell, IItemGroup +/** + * @author DrummerMC + * @version rv6 - 2018-01-17 + * @since rv6 2018-01-17 + */ +public abstract class AbstractStorageCell> extends AEBaseItem implements IStorageCell, IItemGroup { - private final MaterialType component; - private final int totalBytes; - private final int perType; - private final double idleDrain; + protected final MaterialType component; + protected final int totalBytes; - public ItemBasicStorageCell( final MaterialType whichCell, final int kilobytes ) + public AbstractStorageCell( final MaterialType whichCell, final int kilobytes ) { this.setMaxStackSize( 1 ); this.totalBytes = kilobytes * 1024; this.component = whichCell; - - switch( this.component ) - { - case CELL1K_PART: - this.idleDrain = 0.5; - this.perType = 8; - break; - case CELL4K_PART: - this.idleDrain = 1.0; - this.perType = 32; - break; - case CELL16K_PART: - this.idleDrain = 1.5; - this.perType = 128; - break; - case CELL64K_PART: - this.idleDrain = 2.0; - this.perType = 512; - break; - default: - this.idleDrain = 0.0; - this.perType = 8; - } } @SideOnly( Side.CLIENT ) @Override public void addCheckedInformation( final ItemStack stack, final World world, final List lines, final ITooltipFlag advancedTooltips ) { - final IMEInventoryHandler inventory = AEApi.instance().registries().cell().getCellInventory( stack, null, - AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); + final IMEInventoryHandler inventory = AEApi.instance().registries().cell().getCellInventory( stack, null, getChannel() ); if( inventory instanceof ICellInventoryHandler ) { @@ -111,11 +90,9 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe if( cellInventory != null ) { - lines.add( - cellInventory.getUsedBytes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalBytes() + ' ' + GuiText.BytesUsed.getLocal() ); + lines.add( cellInventory.getUsedBytes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalBytes() + ' ' + GuiText.BytesUsed.getLocal() ); - lines.add( cellInventory.getStoredItemTypes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalItemTypes() + ' ' + GuiText.Types - .getLocal() ); + lines.add( cellInventory.getStoredItemTypes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalItemTypes() + ' ' + GuiText.Types.getLocal() ); if( handler.isPreformatted() ) { @@ -140,12 +117,6 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe return this.totalBytes; } - @Override - public int getBytesPerType( final ItemStack cellItem ) - { - return this.perType; - } - @Override public int getTotalTypes( final ItemStack cellItem ) { @@ -153,7 +124,7 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe } @Override - public boolean isBlackListed( final ItemStack cellItem, final IAEItemStack requestedAddition ) + public boolean isBlackListed( final ItemStack cellItem, final T requestedAddition ) { return false; } @@ -170,12 +141,6 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe return true; } - @Override - public double getIdleDrain() - { - return this.idleDrain; - } - @Override public String getUnlocalizedGroupName( final Set others, final ItemStack is ) { @@ -237,13 +202,11 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe } final InventoryPlayer playerInventory = player.inventory; - final IMEInventoryHandler inv = AEApi.instance().registries().cell().getCellInventory( stack, null, - AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); + final IMEInventoryHandler inv = AEApi.instance().registries().cell().getCellInventory( stack, null, getChannel() ); if( inv != null && playerInventory.getCurrentItem() == stack ) { final InventoryAdaptor ia = InventoryAdaptor.getAdaptor( player ); - final IItemList list = inv - .getAvailableItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ); + final IItemList list = inv.getAvailableItems( getChannel().createList() ); if( list.isEmpty() && ia != null ) { playerInventory.setInventorySlotContents( playerInventory.currentItem, ItemStack.EMPTY ); @@ -268,14 +231,7 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe } // drop empty storage cell case - AEApi.instance().definitions().materials().emptyStorageCell().maybeStack( 1 ).ifPresent( is -> - { - final ItemStack extraA = ia.addItems( is ); - if( !extraA.isEmpty() ) - { - player.dropItem( extraA, false ); - } - } ); + dropEmptyStorageCellCase( ia, player ); if( player.inventoryContainer != null ) { @@ -289,6 +245,8 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe return false; } + protected abstract void dropEmptyStorageCellCase( final InventoryAdaptor ia, final EntityPlayer player ); + @Override public EnumActionResult onItemUseFirst( final EntityPlayer player, final World world, final BlockPos pos, final EnumFacing side, final float hitX, final float hitY, final float hitZ, final EnumHand hand ) { @@ -298,12 +256,7 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe @Override public ItemStack getContainerItem( final ItemStack itemStack ) { - return AEApi.instance() - .definitions() - .materials() - .emptyStorageCell() - .maybeStack( 1 ) - .orElseThrow( () -> new MissingDefinitionException( "Tried to use empty storage cells while basic storage cells are defined." ) ); + return AEApi.instance().definitions().materials().emptyStorageCell().maybeStack( 1 ).orElseThrow( () -> new MissingDefinitionException( "Tried to use empty storage cells while basic storage cells are defined." ) ); } @Override diff --git a/src/main/java/appeng/items/storage/BasicItemStorageCell.java b/src/main/java/appeng/items/storage/BasicItemStorageCell.java new file mode 100644 index 000000000..cdf5492b4 --- /dev/null +++ b/src/main/java/appeng/items/storage/BasicItemStorageCell.java @@ -0,0 +1,96 @@ +/* + * 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.items.storage; + + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +import appeng.api.AEApi; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.channels.IItemStorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.items.materials.MaterialType; +import appeng.util.InventoryAdaptor; + + +public final class BasicItemStorageCell extends AbstractStorageCell +{ + + + protected final int perType; + protected final double idleDrain; + public BasicItemStorageCell( final MaterialType whichCell, final int kilobytes ) + { + super(whichCell, kilobytes); + switch( whichCell ) + { + case CELL1K_PART: + this.idleDrain = 0.5; + this.perType = 8; + break; + case CELL4K_PART: + this.idleDrain = 1.0; + this.perType = 32; + break; + case CELL16K_PART: + this.idleDrain = 1.5; + this.perType = 128; + break; + case CELL64K_PART: + this.idleDrain = 2.0; + this.perType = 512; + break; + default: + this.idleDrain = 0.0; + this.perType = 8; + } + + } + + @Override + public int getBytesPerType( ItemStack cellItem ) + { + return this.perType; + } + + @Override + public double getIdleDrain() + { + return this.idleDrain; + } + + @Override + public IStorageChannel getChannel() + { + return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); + } + + @Override + protected void dropEmptyStorageCellCase( final InventoryAdaptor ia, final EntityPlayer player ) + { + AEApi.instance().definitions().materials().emptyStorageCell().maybeStack( 1 ).ifPresent( is -> { + final ItemStack extraA = ia.addItems( is ); + if( !extraA.isEmpty() ) + { + player.dropItem( extraA, false ); + } + } ); + } +} diff --git a/src/main/java/appeng/items/tools/powered/ToolColorApplicator.java b/src/main/java/appeng/items/tools/powered/ToolColorApplicator.java index 63563d06d..49a6e0f70 100644 --- a/src/main/java/appeng/items/tools/powered/ToolColorApplicator.java +++ b/src/main/java/appeng/items/tools/powered/ToolColorApplicator.java @@ -61,6 +61,7 @@ import appeng.api.implementations.tiles.IColorableTile; import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.IMEInventory; +import appeng.api.storage.IStorageChannel; import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; @@ -77,13 +78,13 @@ import appeng.items.contents.CellUpgrades; import appeng.items.misc.ItemPaintBall; import appeng.items.tools.powered.powersink.AEBasePoweredItem; import appeng.me.helpers.BaseActionSource; -import appeng.me.storage.CellInventoryHandler; +import appeng.me.storage.ItemCellInventoryHandler; import appeng.tile.misc.TilePaint; import appeng.util.Platform; import appeng.util.item.AEItemStack; -public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCell, IItemGroup, IBlockTool, IMouseWheelItem +public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCell, IItemGroup, IBlockTool, IMouseWheelItem { private static final Map ORE_TO_COLOR = new HashMap<>(); @@ -434,7 +435,7 @@ public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCe final IMEInventory cdi = AEApi.instance().registries().cell().getCellInventory( stack, null, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); - if( cdi instanceof CellInventoryHandler ) + if( cdi instanceof ItemCellInventoryHandler ) { final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv(); if( cd != null ) @@ -506,6 +507,12 @@ public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCe return 0.5; } + @Override + public IStorageChannel getChannel() + { + return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); + } + @Override public String getUnlocalizedGroupName( final Set others, final ItemStack is ) { diff --git a/src/main/java/appeng/items/tools/powered/ToolMatterCannon.java b/src/main/java/appeng/items/tools/powered/ToolMatterCannon.java index e46bf212b..dcb76ad61 100644 --- a/src/main/java/appeng/items/tools/powered/ToolMatterCannon.java +++ b/src/main/java/appeng/items/tools/powered/ToolMatterCannon.java @@ -55,6 +55,7 @@ import appeng.api.implementations.items.IStorageCell; import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.IMEInventory; +import appeng.api.storage.IStorageChannel; import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack; @@ -76,13 +77,13 @@ import appeng.items.contents.CellUpgrades; import appeng.items.misc.ItemPaintBall; import appeng.items.tools.powered.powersink.AEBasePoweredItem; import appeng.me.helpers.PlayerSource; -import appeng.me.storage.CellInventoryHandler; +import appeng.me.storage.ItemCellInventoryHandler; import appeng.tile.misc.TilePaint; import appeng.util.LookDirection; import appeng.util.Platform; -public class ToolMatterCannon extends AEBasePoweredItem implements IStorageCell +public class ToolMatterCannon extends AEBasePoweredItem implements IStorageCell { public ToolMatterCannon() @@ -99,7 +100,7 @@ public class ToolMatterCannon extends AEBasePoweredItem implements IStorageCell final IMEInventory cdi = AEApi.instance().registries().cell().getCellInventory( stack, null, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); - if( cdi instanceof CellInventoryHandler ) + if( cdi instanceof ItemCellInventoryHandler ) { final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv(); if( cd != null ) @@ -529,4 +530,10 @@ public class ToolMatterCannon extends AEBasePoweredItem implements IStorageCell { return 0.5; } + + @Override + public IStorageChannel getChannel() + { + return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); + } } diff --git a/src/main/java/appeng/items/tools/powered/ToolPortableCell.java b/src/main/java/appeng/items/tools/powered/ToolPortableCell.java index bf7897981..261e8cf96 100644 --- a/src/main/java/appeng/items/tools/powered/ToolPortableCell.java +++ b/src/main/java/appeng/items/tools/powered/ToolPortableCell.java @@ -43,6 +43,7 @@ import appeng.api.implementations.items.IStorageCell; import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.IMEInventory; +import appeng.api.storage.IStorageChannel; import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.data.IAEItemStack; import appeng.api.util.AEPartLocation; @@ -53,11 +54,11 @@ import appeng.items.contents.CellConfig; import appeng.items.contents.CellUpgrades; import appeng.items.contents.PortableCellViewer; import appeng.items.tools.powered.powersink.AEBasePoweredItem; -import appeng.me.storage.CellInventoryHandler; +import appeng.me.storage.ItemCellInventoryHandler; import appeng.util.Platform; -public class ToolPortableCell extends AEBasePoweredItem implements IStorageCell, IGuiItem, IItemGroup +public class ToolPortableCell extends AEBasePoweredItem implements IStorageCell, IGuiItem, IItemGroup { public ToolPortableCell() { @@ -87,7 +88,7 @@ public class ToolPortableCell extends AEBasePoweredItem implements IStorageCell, final IMEInventory cdi = AEApi.instance().registries().cell().getCellInventory( stack, null, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); - if( cdi instanceof CellInventoryHandler ) + if( cdi instanceof ItemCellInventoryHandler ) { final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv(); if( cd != null ) @@ -140,6 +141,12 @@ public class ToolPortableCell extends AEBasePoweredItem implements IStorageCell, return 0.5; } + @Override + public IStorageChannel getChannel() + { + return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); + } + @Override public String getUnlocalizedGroupName( final Set others, final ItemStack is ) { diff --git a/src/main/java/appeng/me/storage/AbstractCellInventory.java b/src/main/java/appeng/me/storage/AbstractCellInventory.java new file mode 100644 index 000000000..5680f2bc1 --- /dev/null +++ b/src/main/java/appeng/me/storage/AbstractCellInventory.java @@ -0,0 +1,362 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.items.IItemHandler; + +import appeng.api.config.FuzzyMode; +import appeng.api.exceptions.AppEngException; +import appeng.api.implementations.items.IStorageCell; +import appeng.api.storage.ICellInventory; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.ISaveProvider; +import appeng.api.storage.data.IAEStack; +import appeng.api.storage.data.IItemList; +import appeng.util.Platform; + + +/** + * @author DrummerMC + * @version rv6 - 2018-01-17 + * @since rv6 2018-01-17 + */ +public abstract class AbstractCellInventory> implements ICellInventory +{ + + private static final String ITEM_TYPE_TAG = "it"; + private static final String ITEM_COUNT_TAG = "ic"; + private static final String ITEM_SLOT = "#"; + private static final String ITEM_SLOT_COUNT = "@"; + protected static final String ITEM_PRE_FORMATTED_COUNT = "PF"; + protected static final String ITEM_PRE_FORMATTED_SLOT = "PF#"; + protected static final String ITEM_PRE_FORMATTED_NAME = "PN"; + protected static final String ITEM_PRE_FORMATTED_FUZZY = "FP"; + private static String[] itemSlots; + private static String[] itemSlotCount; + private final NBTTagCompound tagCompound; + protected final ISaveProvider container; + private int maxItemTypes = 63; + private short storedItems = 0; + private int storedItemCount = 0; + protected IItemList cellItems; + protected ItemStack i; + protected IStorageCell cellType; + protected final int itemsPerByte; + + protected AbstractCellInventory( final NBTTagCompound data, final ISaveProvider container, final int itemsPerByte ) + { + this.tagCompound = data; + this.container = container; + this.itemsPerByte = itemsPerByte; + } + + protected AbstractCellInventory( final ItemStack o, final ISaveProvider container, final int itemsPerByte ) throws AppEngException + { + this.itemsPerByte = itemsPerByte; + if( itemSlots == null ) + { + itemSlots = new String[this.maxItemTypes]; + itemSlotCount = new String[this.maxItemTypes]; + + for( int x = 0; x < this.maxItemTypes; x++ ) + { + itemSlots[x] = ITEM_SLOT + x; + itemSlotCount[x] = ITEM_SLOT_COUNT + x; + } + } + + if( o == null ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + this.cellType = null; + this.i = o; + + final Item type = this.i.getItem(); + if( type instanceof IStorageCell ) + { + this.cellType = (IStorageCell) this.i.getItem(); + this.maxItemTypes = this.cellType.getTotalTypes( this.i ); + } + + if( this.cellType == null ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + if( !this.cellType.isStorageCell( this.i ) ) + { + throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); + } + + if( this.maxItemTypes > 63 ) + { + this.maxItemTypes = 63; + } + if( this.maxItemTypes < 1 ) + { + this.maxItemTypes = 1; + } + + this.container = container; + this.tagCompound = Platform.openNbtData( o ); + this.storedItems = this.tagCompound.getShort( ITEM_TYPE_TAG ); + this.storedItemCount = this.tagCompound.getInteger( ITEM_COUNT_TAG ); + this.cellItems = null; + } + + protected boolean isEmpty( final IMEInventory meInventory ) + { + return meInventory.getAvailableItems( getChannel().createList() ).isEmpty(); + } + + protected IItemList getCellItems() + { + if( this.cellItems == null ) + { + this.cellItems = getChannel().createList(); + this.loadCellItems(); + } + + return this.cellItems; + } + + protected void updateItemCount( final long delta ) + { + this.storedItemCount += delta; + this.tagCompound.setInteger( ITEM_COUNT_TAG, this.storedItemCount ); + } + + protected void saveChanges() + { + int itemCount = 0; + + // add new pretty stuff... + int x = 0; + for( final T v : this.cellItems ) + { + itemCount += v.getStackSize(); + + final NBTTagCompound g = new NBTTagCompound(); + v.writeToNBT( g ); + this.tagCompound.setTag( itemSlots[x], g ); + + this.tagCompound.setInteger( itemSlotCount[x], (int) v.getStackSize() ); + + x++; + } + + final short oldStoredItems = this.storedItems; + + this.storedItems = (short) this.cellItems.size(); + if( this.cellItems.isEmpty() ) + { + this.tagCompound.removeTag( ITEM_TYPE_TAG ); + } + else + { + this.tagCompound.setShort( ITEM_TYPE_TAG, this.storedItems ); + } + + this.storedItemCount = itemCount; + if( itemCount == 0 ) + { + this.tagCompound.removeTag( ITEM_COUNT_TAG ); + } + else + { + this.tagCompound.setInteger( ITEM_COUNT_TAG, itemCount ); + } + + // clean any old crusty stuff... + for( ; x < oldStoredItems && x < this.maxItemTypes; x++ ) + { + this.tagCompound.removeTag( itemSlots[x] ); + this.tagCompound.removeTag( itemSlotCount[x] ); + } + + if( this.container != null ) + { + this.container.saveChanges( this ); + } + } + + private void loadCellItems() + { + if( this.cellItems == null ) + { + this.cellItems = getChannel().createList(); + } + + this.cellItems.resetStatus(); // clears totals and stuff. + + final int types = (int) this.getStoredItemTypes(); + + for( int slot = 0; slot < types; slot++ ) + { + NBTTagCompound compoundTag = this.tagCompound.getCompoundTag( itemSlots[slot] ); + int stackSize = this.tagCompound.getInteger( itemSlotCount[slot] ); + this.loadCellItem( compoundTag, stackSize ); + } + } + + protected abstract void loadCellItem( NBTTagCompound compoundTag, int stackSize ); + + @Override + public IItemList getAvailableItems( final IItemList out ) + { + for( final T item : this.getCellItems() ) + { + out.add( item ); + } + + return out; + } + + + @Override + public ItemStack getItemStack() + { + return this.i; + } + + @Override + public double getIdleDrain() + { + return this.cellType.getIdleDrain(); + } + + @Override + public FuzzyMode getFuzzyMode() + { + return this.cellType.getFuzzyMode( this.i ); + } + + @Override + public IItemHandler getConfigInventory() + { + return this.cellType.getConfigInventory( this.i ); + } + + @Override + public IItemHandler getUpgradesInventory() + { + return this.cellType.getUpgradesInventory( this.i ); + } + + @Override + public int getBytesPerType() + { + return this.cellType.getBytesPerType( this.i ); + } + + @Override + public boolean canHoldNewItem() + { + final long bytesFree = this.getFreeBytes(); + return ( bytesFree > this.getBytesPerType() || ( bytesFree == this.getBytesPerType() && this.getUnusedItemCount() > 0 ) ) && this + .getRemainingItemTypes() > 0; + } + + @Override + public long getTotalBytes() + { + return this.cellType.getBytes( this.i ); + } + + @Override + public long getFreeBytes() + { + return this.getTotalBytes() - this.getUsedBytes(); + } + + @Override + public long getTotalItemTypes() + { + return this.maxItemTypes; + } + + @Override + public long getStoredItemCount() + { + return this.storedItemCount; + } + + @Override + public long getStoredItemTypes() + { + return this.storedItems; + } + + @Override + public long getRemainingItemTypes() + { + final long basedOnStorage = this.getFreeBytes() / this.getBytesPerType(); + final long baseOnTotal = this.getTotalItemTypes() - this.getStoredItemTypes(); + return basedOnStorage > baseOnTotal ? baseOnTotal : basedOnStorage; + } + + + @Override + public long getUsedBytes() + { + final long bytesForItemCount = ( this.getStoredItemCount() + this.getUnusedItemCount() ) / itemsPerByte; + return this.getStoredItemTypes() * this.getBytesPerType() + bytesForItemCount; + } + + @Override + public long getRemainingItemCount() + { + final long remaining = this.getFreeBytes() * itemsPerByte + this.getUnusedItemCount(); + return remaining > 0 ? remaining : 0; + } + + @Override + public int getUnusedItemCount() + { + final int div = (int) ( this.getStoredItemCount() % 8 ); + + if( div == 0 ) + { + return 0; + } + + return itemsPerByte - div; + } + + @Override + public int getStatusForCell() + { + if( this.canHoldNewItem() ) + { + return 1; + } + if( this.getRemainingItemCount() > 0 ) + { + return 2; + } + return 3; + } +} + diff --git a/src/main/java/appeng/me/storage/CellInventoryHandler.java b/src/main/java/appeng/me/storage/AbstractCellInventoryHandler.java similarity index 83% rename from src/main/java/appeng/me/storage/CellInventoryHandler.java rename to src/main/java/appeng/me/storage/AbstractCellInventoryHandler.java index ff0fe7c98..c4baf5407 100644 --- a/src/main/java/appeng/me/storage/CellInventoryHandler.java +++ b/src/main/java/appeng/me/storage/AbstractCellInventoryHandler.java @@ -1,6 +1,6 @@ /* * This file is part of Applied Energistics 2. - * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. + * Copyright (c) 2013 - 2018, 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 @@ -23,7 +23,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.items.IItemHandler; -import appeng.api.AEApi; import appeng.api.config.FuzzyMode; import appeng.api.config.IncludeExclude; import appeng.api.config.Upgrades; @@ -31,26 +30,29 @@ import appeng.api.implementations.items.IUpgradeModule; import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.IMEInventory; -import appeng.api.storage.channels.IItemStorageChannel; -import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import appeng.util.Platform; -import appeng.util.item.AEItemStack; import appeng.util.prioritylist.FuzzyPriorityList; import appeng.util.prioritylist.PrecisePriorityList; -public class CellInventoryHandler extends MEInventoryHandler implements ICellInventoryHandler +/** + * @author DrummerMC + * @version rv6 - 2018-01-23 + * @since rv6 2018-01-23 + */ +public abstract class AbstractCellInventoryHandler> extends MEInventoryHandler implements ICellInventoryHandler { - - CellInventoryHandler( final IMEInventory c ) + public AbstractCellInventoryHandler( final IMEInventory c, final IStorageChannel channel ) { - super( c, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); + super( c, channel ); final ICellInventory ci = this.getCellInv(); if( ci != null ) { - final IItemList priorityList = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); + final IItemList priorityList = channel.createList(); final IItemHandler upgrades = ci.getUpgradesInventory(); final IItemHandler config = ci.getConfigInventory(); @@ -86,7 +88,7 @@ public class CellInventoryHandler extends MEInventoryHandler imple final ItemStack is = config.getStackInSlot( x ); if( !is.isEmpty() ) { - priorityList.add( AEItemStack.fromItemStack( is ) ); + priorityList.add( createConfigStackFromItem( is ) ); } } @@ -106,6 +108,8 @@ public class CellInventoryHandler extends MEInventoryHandler imple } } + protected abstract T createConfigStackFromItem( ItemStack is ); + @Override public ICellInventory getCellInv() { diff --git a/src/main/java/appeng/me/storage/CellInventory.java b/src/main/java/appeng/me/storage/CellInventory.java deleted file mode 100644 index ba651af12..000000000 --- a/src/main/java/appeng/me/storage/CellInventory.java +++ /dev/null @@ -1,629 +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 java.util.HashSet; - -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.oredict.OreDictionary; - -import appeng.api.AEApi; -import appeng.api.config.Actionable; -import appeng.api.config.FuzzyMode; -import appeng.api.exceptions.AppEngException; -import appeng.api.implementations.items.IStorageCell; -import appeng.api.networking.security.IActionSource; -import appeng.api.storage.ICellInventory; -import appeng.api.storage.IMEInventory; -import appeng.api.storage.IMEInventoryHandler; -import appeng.api.storage.ISaveProvider; -import appeng.api.storage.IStorageChannel; -import appeng.api.storage.channels.IItemStorageChannel; -import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IItemList; -import appeng.core.AEConfig; -import appeng.core.AELog; -import appeng.util.Platform; -import appeng.util.item.AEItemStack; - - -public class CellInventory implements ICellInventory -{ - - private static final String ITEM_TYPE_TAG = "it"; - private static final String ITEM_COUNT_TAG = "ic"; - private static final String ITEM_SLOT = "#"; - private static final String ITEM_SLOT_COUNT = "@"; - private static final String ITEM_PRE_FORMATTED_COUNT = "PF"; - private static final String ITEM_PRE_FORMATTED_SLOT = "PF#"; - private static final String ITEM_PRE_FORMATTED_NAME = "PN"; - private static final String ITEM_PRE_FORMATTED_FUZZY = "FP"; - private static final HashSet BLACK_LIST = new HashSet<>(); - private static String[] itemSlots; - private static String[] itemSlotCount; - private final NBTTagCompound tagCompound; - private final ISaveProvider container; - private int maxItemTypes = 63; - private short storedItems = 0; - private int storedItemCount = 0; - private IItemList cellItems; - private ItemStack i; - private IStorageCell cellType; - - protected CellInventory( final NBTTagCompound data, final ISaveProvider container ) - { - this.tagCompound = data; - this.container = container; - } - - private CellInventory( final ItemStack o, final ISaveProvider container ) throws AppEngException - { - if( itemSlots == null ) - { - itemSlots = new String[this.maxItemTypes]; - itemSlotCount = new String[this.maxItemTypes]; - - for( int x = 0; x < this.maxItemTypes; x++ ) - { - itemSlots[x] = ITEM_SLOT + x; - itemSlotCount[x] = ITEM_SLOT_COUNT + x; - } - } - - if( o == null ) - { - throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); - } - - this.cellType = null; - this.i = o; - - final Item type = this.i.getItem(); - if( type instanceof IStorageCell ) - { - this.cellType = (IStorageCell) this.i.getItem(); - this.maxItemTypes = this.cellType.getTotalTypes( this.i ); - } - - if( this.cellType == null ) - { - throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); - } - - if( !this.cellType.isStorageCell( this.i ) ) - { - throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" ); - } - - if( this.maxItemTypes > 63 ) - { - this.maxItemTypes = 63; - } - if( this.maxItemTypes < 1 ) - { - this.maxItemTypes = 1; - } - - this.container = container; - this.tagCompound = Platform.openNbtData( o ); - this.storedItems = this.tagCompound.getShort( ITEM_TYPE_TAG ); - this.storedItemCount = this.tagCompound.getInteger( ITEM_COUNT_TAG ); - this.cellItems = null; - } - - public static IMEInventoryHandler getCell( final ItemStack o, final ISaveProvider container2 ) - { - try - { - return new CellInventoryHandler( new CellInventory( o, container2 ) ); - } - catch( final AppEngException e ) - { - return null; - } - } - - private static boolean isStorageCell( final ItemStack i ) - { - if( i == null ) - { - return false; - } - - try - { - final Item type = i.getItem(); - if( type instanceof IStorageCell ) - { - return !( (IStorageCell) type ).storableInStorageCell(); - } - } - catch( final Throwable err ) - { - return true; - } - - return false; - } - - public static boolean isCell( final ItemStack i ) - { - if( i == null ) - { - return false; - } - - final Item type = i.getItem(); - if( type instanceof IStorageCell ) - { - return ( (IStorageCell) type ).isStorageCell( i ); - } - - return false; - } - - public static void addBasicBlackList( final int itemID, final int meta ) - { - BLACK_LIST.add( ( meta << Platform.DEF_OFFSET ) | itemID ); - } - - private static boolean isBlackListed( final IAEItemStack input ) - { - if( BLACK_LIST.contains( ( OreDictionary.WILDCARD_VALUE << Platform.DEF_OFFSET ) | Item.getIdFromItem( input.getItem() ) ) ) - { - return true; - } - return BLACK_LIST.contains( ( input.getItemDamage() << Platform.DEF_OFFSET ) | Item.getIdFromItem( input.getItem() ) ); - } - - private boolean isEmpty( final IMEInventory meInventory ) - { - return meInventory.getAvailableItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ).isEmpty(); - } - - @Override - public IAEItemStack injectItems( final IAEItemStack input, final Actionable mode, final IActionSource src ) - { - if( input == null ) - { - return null; - } - if( input.getStackSize() == 0 ) - { - return null; - } - - if( isBlackListed( input ) || this.cellType.isBlackListed( this.i, input ) ) - { - return input; - } - - // This is slightly hacky as it expects a read-only access, but fine for now. - // TODO: Guarantee a read-only access. E.g. provide an isEmpty() method and ensure CellInventory does not write - // any NBT data for empty cells instead of relying on an empty IItemContainer - if( CellInventory.isStorageCell( input.getDefinition() ) ) - { - final IMEInventory meInventory = getCell( input.getDefinition(), null ); - if( meInventory != null && !this.isEmpty( meInventory ) ) - { - return input; - } - } - - final IAEItemStack l = this.getCellItems().findPrecise( input ); - if( l != null ) - { - final long remainingItemCount = this.getRemainingItemCount(); - if( remainingItemCount < 0 ) - { - return input; - } - - if( input.getStackSize() > remainingItemCount ) - { - final IAEItemStack r = input.copy(); - r.setStackSize( r.getStackSize() - remainingItemCount ); - if( mode == Actionable.MODULATE ) - { - l.setStackSize( l.getStackSize() + remainingItemCount ); - this.updateItemCount( remainingItemCount ); - this.saveChanges(); - } - return r; - } - else - { - if( mode == Actionable.MODULATE ) - { - l.setStackSize( l.getStackSize() + input.getStackSize() ); - this.updateItemCount( input.getStackSize() ); - this.saveChanges(); - } - return null; - } - } - - if( this.canHoldNewItem() ) // room for new type, and for at least one item! - { - final int remainingItemCount = (int) this.getRemainingItemCount() - this.getBytesPerType() * 8; - if( remainingItemCount > 0 ) - { - if( input.getStackSize() > remainingItemCount ) - { - final IAEItemStack toReturn = input.copy(); - toReturn.setStackSize( input.getStackSize() - remainingItemCount ); - if( mode == Actionable.MODULATE ) - { - final IAEItemStack toWrite = input.copy(); - toWrite.setStackSize( remainingItemCount ); - - this.cellItems.add( toWrite ); - this.updateItemCount( toWrite.getStackSize() ); - - this.saveChanges(); - } - return toReturn; - } - - if( mode == Actionable.MODULATE ) - { - this.updateItemCount( input.getStackSize() ); - this.cellItems.add( input ); - this.saveChanges(); - } - - return null; - } - } - - return input; - } - - @Override - public IAEItemStack extractItems( final IAEItemStack request, final Actionable mode, final IActionSource src ) - { - if( request == null ) - { - return null; - } - - final long size = Math.min( Integer.MAX_VALUE, request.getStackSize() ); - - IAEItemStack Results = null; - - final IAEItemStack l = this.getCellItems().findPrecise( request ); - if( l != null ) - { - Results = l.copy(); - - if( l.getStackSize() <= size ) - { - Results.setStackSize( l.getStackSize() ); - if( mode == Actionable.MODULATE ) - { - this.updateItemCount( -l.getStackSize() ); - l.setStackSize( 0 ); - this.saveChanges(); - } - } - else - { - Results.setStackSize( size ); - if( mode == Actionable.MODULATE ) - { - l.setStackSize( l.getStackSize() - size ); - this.updateItemCount( -size ); - this.saveChanges(); - } - } - } - - return Results; - } - - IItemList getCellItems() - { - if( this.cellItems == null ) - { - this.cellItems = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); - this.loadCellItems(); - } - - return this.cellItems; - } - - private void updateItemCount( final long delta ) - { - this.storedItemCount += delta; - this.tagCompound.setInteger( ITEM_COUNT_TAG, this.storedItemCount ); - } - - void saveChanges() - { - // cellItems.clean(); - int itemCount = 0; - - // add new pretty stuff... - int x = 0; - for( final IAEItemStack v : this.cellItems ) - { - itemCount += v.getStackSize(); - - final NBTTagCompound g = new NBTTagCompound(); - v.writeToNBT( g ); - this.tagCompound.setTag( itemSlots[x], g ); - - this.tagCompound.setInteger( itemSlotCount[x], (int) v.getStackSize() ); - - x++; - } - - // NBTBase tagType = tagCompound.getTag( ITEM_TYPE_TAG ); - // NBTBase tagCount = tagCompound.getTag( ITEM_COUNT_TAG ); - final short oldStoredItems = this.storedItems; - - /* - * if ( tagType instanceof NBTTagShort ) ((NBTTagShort) tagType).data = storedItems = (short) cellItems.size(); - * else - */ - this.storedItems = (short) this.cellItems.size(); - if( this.cellItems.isEmpty() ) - { - this.tagCompound.removeTag( ITEM_TYPE_TAG ); - } - else - { - this.tagCompound.setShort( ITEM_TYPE_TAG, this.storedItems ); - } - - /* - * if ( tagCount instanceof NBTTagInt ) ((NBTTagInt) tagCount).data = storedItemCount = itemCount; else - */ - this.storedItemCount = itemCount; - if( itemCount == 0 ) - { - this.tagCompound.removeTag( ITEM_COUNT_TAG ); - } - else - { - this.tagCompound.setInteger( ITEM_COUNT_TAG, itemCount ); - } - - // clean any old crusty stuff... - for( ; x < oldStoredItems && x < this.maxItemTypes; x++ ) - { - this.tagCompound.removeTag( itemSlots[x] ); - this.tagCompound.removeTag( itemSlotCount[x] ); - } - - if( this.container != null ) - { - this.container.saveChanges( this ); - } - } - - protected void loadCellItems() - { - if( this.cellItems == null ) - { - this.cellItems = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); - } - - this.cellItems.resetStatus(); // clears totals and stuff. - - final int types = (int) this.getStoredItemTypes(); - - for( int slot = 0; slot < types; slot++ ) - { - NBTTagCompound compoundTag = this.tagCompound.getCompoundTag( itemSlots[slot] ); - int stackSize = this.tagCompound.getInteger( itemSlotCount[slot] ); - this.loadCellItem( compoundTag, stackSize ); - } - - // cellItems.clean(); - } - - private void loadCellItem( NBTTagCompound compoundTag, int stackSize ) - { - - // Now load the item stack - final ItemStack t; - try - { - t = new ItemStack( compoundTag ); - if( t.isEmpty() ) - { - AELog.warn( "Removing item " + compoundTag + " from storage cell because the associated item type couldn't be found." ); - return; - } - } - catch( Throwable ex ) - { - if( AEConfig.instance().isRemoveCrashingItemsOnLoad() ) - { - AELog.warn( ex, "Removing item " + compoundTag + " from storage cell because loading the ItemStack crashed." ); - return; - } - throw ex; - } - - t.setCount( stackSize ); - - if( t.getCount() > 0 ) - { - try - { - this.cellItems.add( AEItemStack.fromItemStack( t ) ); - } - catch( Throwable ex ) - { - if( AEConfig.instance().isRemoveCrashingItemsOnLoad() ) - { - AELog.warn( ex, "Removing item " + t + " from storage cell because processing the loaded item crashed." ); - return; - } - throw ex; - } - } - } - - @Override - public IItemList getAvailableItems( final IItemList out ) - { - for( final IAEItemStack i : this.getCellItems() ) - { - out.add( i ); - } - - return out; - } - - @Override - public IStorageChannel getChannel() - { - return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); - } - - @Override - public ItemStack getItemStack() - { - return this.i; - } - - @Override - public double getIdleDrain() - { - return this.cellType.getIdleDrain(); - } - - @Override - public FuzzyMode getFuzzyMode() - { - return this.cellType.getFuzzyMode( this.i ); - } - - @Override - public IItemHandler getConfigInventory() - { - return this.cellType.getConfigInventory( this.i ); - } - - @Override - public IItemHandler getUpgradesInventory() - { - return this.cellType.getUpgradesInventory( this.i ); - } - - @Override - public int getBytesPerType() - { - return this.cellType.getBytesPerType( this.i ); - } - - @Override - public boolean canHoldNewItem() - { - final long bytesFree = this.getFreeBytes(); - return ( bytesFree > this.getBytesPerType() || ( bytesFree == this.getBytesPerType() && this.getUnusedItemCount() > 0 ) ) && this - .getRemainingItemTypes() > 0; - } - - @Override - public long getTotalBytes() - { - return this.cellType.getBytes( this.i ); - } - - @Override - public long getFreeBytes() - { - return this.getTotalBytes() - this.getUsedBytes(); - } - - @Override - public long getUsedBytes() - { - final long bytesForItemCount = ( this.getStoredItemCount() + this.getUnusedItemCount() ) / 8; - return this.getStoredItemTypes() * this.getBytesPerType() + bytesForItemCount; - } - - @Override - public long getTotalItemTypes() - { - return this.maxItemTypes; - } - - @Override - public long getStoredItemCount() - { - return this.storedItemCount; - } - - @Override - public long getStoredItemTypes() - { - return this.storedItems; - } - - @Override - public long getRemainingItemTypes() - { - final long basedOnStorage = this.getFreeBytes() / this.getBytesPerType(); - final long baseOnTotal = this.getTotalItemTypes() - this.getStoredItemTypes(); - return basedOnStorage > baseOnTotal ? baseOnTotal : basedOnStorage; - } - - @Override - public long getRemainingItemCount() - { - final long remaining = this.getFreeBytes() * 8 + this.getUnusedItemCount(); - return remaining > 0 ? remaining : 0; - } - - @Override - public int getUnusedItemCount() - { - final int div = (int) ( this.getStoredItemCount() % 8 ); - - if( div == 0 ) - { - return 0; - } - - return 8 - div; - } - - @Override - public int getStatusForCell() - { - if( this.canHoldNewItem() ) - { - return 1; - } - if( this.getRemainingItemCount() > 0 ) - { - return 2; - } - return 3; - } -} diff --git a/src/main/java/appeng/me/storage/CreativeCellInventory.java b/src/main/java/appeng/me/storage/CreativeCellInventory.java index 47ae748e0..8d59c60e9 100644 --- a/src/main/java/appeng/me/storage/CreativeCellInventory.java +++ b/src/main/java/appeng/me/storage/CreativeCellInventory.java @@ -55,7 +55,7 @@ public class CreativeCellInventory implements IMEInventoryHandler public static IMEInventoryHandler getCell( final ItemStack o ) { - return new CellInventoryHandler( new CreativeCellInventory( o ) ); + return new ItemCellInventoryHandler( new CreativeCellInventory( o ) ); } @Override diff --git a/src/main/java/appeng/me/storage/ItemCellInventory.java b/src/main/java/appeng/me/storage/ItemCellInventory.java new file mode 100644 index 000000000..2fa3742ab --- /dev/null +++ b/src/main/java/appeng/me/storage/ItemCellInventory.java @@ -0,0 +1,295 @@ +/* + * 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.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.exceptions.AppEngException; +import appeng.api.implementations.items.IStorageCell; +import appeng.api.networking.security.IActionSource; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.ISaveProvider; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.channels.IItemStorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.core.AEConfig; +import appeng.core.AELog; + + +public class ItemCellInventory extends AbstractCellInventory +{ + protected ItemCellInventory( final NBTTagCompound data, final ISaveProvider container ) + { + super( data, container, 8 ); + } + + private ItemCellInventory( final ItemStack o, final ISaveProvider container ) throws AppEngException + { + super( o, container, 8 ); + } + + public static IMEInventoryHandler getCell( final ItemStack o, final ISaveProvider container2 ) + { + try + { + return new ItemCellInventoryHandler( new ItemCellInventory( o, container2 ) ); + } + catch( final AppEngException e ) + { + return null; + } + } + + private static boolean isStorageCell( final ItemStack i ) + { + if( i == null ) + { + return false; + } + + try + { + final Item type = i.getItem(); + if( type instanceof IStorageCell ) + { + return !( (IStorageCell) type ).storableInStorageCell(); + } + } + catch( final Throwable err ) + { + return true; + } + + return false; + } + + public static boolean isCell( final ItemStack i ) + { + if( i == null ) + { + return false; + } + + final Item type = i.getItem(); + if( type instanceof IStorageCell ) + { + if ( ( (IStorageCell) type ).getChannel() == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) + { + return ( (IStorageCell) type ).isStorageCell( i ); + } + } + + return false; + } + + @Override + public IAEItemStack injectItems( final IAEItemStack input, final Actionable mode, final IActionSource src ) + { + if( input == null ) + { + return null; + } + if( input.getStackSize() == 0 ) + { + return null; + } + + if( this.cellType.isBlackListed( this.i, input ) ) + { + return input; + } + // This is slightly hacky as it expects a read-only access, but fine for now. + // TODO: Guarantee a read-only access. E.g. provide an isEmpty() method and ensure CellInventory does not write + // any NBT data for empty cells instead of relying on an empty IItemContainer + if( ItemCellInventory.isStorageCell( input.getDefinition() ) ) + { + final IMEInventory meInventory = getCell( input.getDefinition(), null ); + if( meInventory != null && !this.isEmpty( meInventory ) ) + { + return input; + } + } + + final IAEItemStack l = this.getCellItems().findPrecise( input ); + if( l != null ) + { + final long remainingItemCount = this.getRemainingItemCount(); + if( remainingItemCount < 0 ) + { + return input; + } + + if( input.getStackSize() > remainingItemCount ) + { + final IAEItemStack r = input.copy(); + r.setStackSize( r.getStackSize() - remainingItemCount ); + if( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() + remainingItemCount ); + this.updateItemCount( remainingItemCount ); + this.saveChanges(); + } + return r; + } + else + { + if( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() + input.getStackSize() ); + this.updateItemCount( input.getStackSize() ); + this.saveChanges(); + } + return null; + } + } + + if( this.canHoldNewItem() ) // room for new type, and for at least one item! + { + final int remainingItemCount = (int) this.getRemainingItemCount() - this.getBytesPerType() * itemsPerByte; + if( remainingItemCount > 0 ) + { + if( input.getStackSize() > remainingItemCount ) + { + final IAEItemStack toReturn = input.copy(); + toReturn.setStackSize( input.getStackSize() - remainingItemCount ); + if( mode == Actionable.MODULATE ) + { + final IAEItemStack toWrite = input.copy(); + toWrite.setStackSize( remainingItemCount ); + + this.cellItems.add( toWrite ); + this.updateItemCount( toWrite.getStackSize() ); + + this.saveChanges(); + } + return toReturn; + } + + if( mode == Actionable.MODULATE ) + { + this.updateItemCount( input.getStackSize() ); + this.cellItems.add( input ); + this.saveChanges(); + } + + return null; + } + } + + return input; + } + + @Override + public IAEItemStack extractItems( final IAEItemStack request, final Actionable mode, final IActionSource src ) + { + if( request == null ) + { + return null; + } + + final long size = Math.min( Integer.MAX_VALUE, request.getStackSize() ); + + IAEItemStack Results = null; + + final IAEItemStack l = this.getCellItems().findPrecise( request ); + if( l != null ) + { + Results = l.copy(); + + if( l.getStackSize() <= size ) + { + Results.setStackSize( l.getStackSize() ); + if( mode == Actionable.MODULATE ) + { + this.updateItemCount( -l.getStackSize() ); + l.setStackSize( 0 ); + this.saveChanges(); + } + } + else + { + Results.setStackSize( size ); + if( mode == Actionable.MODULATE ) + { + l.setStackSize( l.getStackSize() - size ); + this.updateItemCount( -size ); + this.saveChanges(); + } + } + } + + return Results; + } + + @Override + public IStorageChannel getChannel() + { + return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); + } + + protected void loadCellItem( NBTTagCompound compoundTag, int stackSize ) + { + + // Now load the item stack + final ItemStack t; + try + { + t = new ItemStack( compoundTag ); + if( t.isEmpty() ) + { + AELog.warn( "Removing item " + compoundTag + " from storage cell because the associated item type couldn't be found." ); + return; + } + } + catch( Throwable ex ) + { + if( AEConfig.instance().isRemoveCrashingItemsOnLoad() ) + { + AELog.warn( ex, "Removing item " + compoundTag + " from storage cell because loading the ItemStack crashed." ); + return; + } + throw ex; + } + + t.setCount( stackSize ); + + if( t.getCount() > 0 ) + { + try + { + this.cellItems.add( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( t ) ); + } + catch( Throwable ex ) + { + if( AEConfig.instance().isRemoveCrashingItemsOnLoad() ) + { + AELog.warn( ex, "Removing item " + t + " from storage cell because processing the loaded item crashed." ); + return; + } + throw ex; + } + } + } +} diff --git a/src/main/java/appeng/me/storage/ItemCellInventoryHandler.java b/src/main/java/appeng/me/storage/ItemCellInventoryHandler.java new file mode 100644 index 000000000..c1de58ade --- /dev/null +++ b/src/main/java/appeng/me/storage/ItemCellInventoryHandler.java @@ -0,0 +1,44 @@ +/* + * 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.item.ItemStack; + +import appeng.api.AEApi; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.channels.IItemStorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.util.item.AEItemStack; + + +public class ItemCellInventoryHandler extends AbstractCellInventoryHandler +{ + + public ItemCellInventoryHandler( IMEInventory c ) + { + super( c, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); + } + + @Override + protected IAEItemStack createConfigStackFromItem( ItemStack is ) + { + return AEItemStack.fromItemStack( is ); + } +} diff --git a/src/main/java/appeng/parts/misc/PartSharedStorageBus.java b/src/main/java/appeng/parts/misc/PartSharedStorageBus.java new file mode 100644 index 000000000..9db4888f6 --- /dev/null +++ b/src/main/java/appeng/parts/misc/PartSharedStorageBus.java @@ -0,0 +1,229 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.Collections; +import java.util.List; + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; + +import appeng.api.AEApi; +import appeng.api.networking.events.MENetworkCellArrayUpdate; +import appeng.api.networking.events.MENetworkChannelsChanged; +import appeng.api.networking.events.MENetworkEventSubscribe; +import appeng.api.networking.events.MENetworkPowerStatusChange; +import appeng.api.networking.ticking.IGridTickable; +import appeng.api.parts.IPartCollisionHelper; +import appeng.api.parts.IPartModel; +import appeng.api.storage.ICellContainer; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.IMEInventoryHandler; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.channels.IItemStorageChannel; +import appeng.api.util.AECableType; +import appeng.api.util.IConfigManager; +import appeng.core.AppEng; +import appeng.helpers.IPriorityHost; +import appeng.items.parts.PartModels; +import appeng.me.GridAccessException; +import appeng.parts.PartModel; +import appeng.parts.automation.PartUpgradeable; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public abstract class PartSharedStorageBus extends PartUpgradeable implements IGridTickable, ICellContainer, IPriorityHost +{ + public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/storage_bus_base" ); + @PartModels + public static final IPartModel MODELS_OFF = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/storage_bus_off" ) ); + @PartModels + public static final IPartModel MODELS_ON = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/storage_bus_on" ) ); + @PartModels + public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/storage_bus_has_channel" ) ); + + private boolean wasActive = false; + private int priority = 0; + + public PartSharedStorageBus( ItemStack is ) + { + super( is ); + } + + protected void updateStatus() + { + final boolean currentActive = this.getProxy().isActive(); + if( this.wasActive != currentActive ) + { + this.wasActive = currentActive; + try + { + this.getProxy().getGrid().postEvent( new MENetworkCellArrayUpdate() ); + this.getHost().markForUpdate(); + } + catch( final GridAccessException ignore ) + { + // :P + } + } + } + + @MENetworkEventSubscribe + public void updateChannels( final MENetworkChannelsChanged changedChannels ) + { + this.updateStatus(); + } + + /** + * Helper method to get this parts storage channel + * + * @return Storage channel + */ + public IStorageChannel getStorageChannel() + { + return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); + } + + protected abstract void resetCache(); + + protected abstract void resetCache( boolean fullReset ); + + @Override + public List getCellArray( final IStorageChannel channel ) + { + return Collections.emptyList(); + } + + @Override + public void blinkCell( int slot ) + { + } + + @Override + public void saveChanges( IMEInventory cellInventory ) + { + } + + @Override + public int getPriority() + { + return this.priority; + } + + @Override + public void setPriority( final int newValue ) + { + this.priority = newValue; + this.getHost().markForSave(); + this.resetCache( true ); + } + + @Override + @MENetworkEventSubscribe + public void powerRender( final MENetworkPowerStatusChange c ) + { + this.updateStatus(); + } + + @Override + public void upgradesChanged() + { + super.upgradesChanged(); + this.resetCache( true ); + } + + @Override + public void updateSetting( final IConfigManager manager, final Enum settingName, final Enum newValue ) + { + this.resetCache( true ); + this.getHost().markForSave(); + } + + @Override + public void onNeighborChanged( IBlockAccess w, BlockPos pos, BlockPos neighbor ) + { + if( pos.offset( this.getSide().getFacing() ).equals( neighbor ) ) + { + this.resetCache( false ); + } + } + + @Override + public void readFromNBT( final NBTTagCompound data ) + { + super.readFromNBT( data ); + this.priority = data.getInteger( "priority" ); + } + + @Override + public void writeToNBT( final NBTTagCompound data ) + { + super.writeToNBT( data ); + data.setInteger( "priority", this.priority ); + } + + @Override + public void getBoxes( final IPartCollisionHelper bch ) + { + bch.addBox( 3, 3, 15, 13, 13, 16 ); + bch.addBox( 2, 2, 14, 14, 14, 15 ); + bch.addBox( 5, 5, 12, 11, 11, 14 ); + } + + @Override + protected int getUpgradeSlots() + { + return 5; + } + + @Override + public float getCableConnectionLength( AECableType cable ) + { + return 4; + } + + @SuppressWarnings( "Duplicates" ) + @Nonnull + @Override + public IPartModel getStaticModels() + { + if( this.isActive() && this.isPowered() ) + { + return MODELS_HAS_CHANNEL; + } + else if( this.isPowered() ) + { + return MODELS_ON; + } + else + { + return MODELS_OFF; + } + } +} diff --git a/src/main/java/appeng/parts/reporting/PartFluidTerminal.java b/src/main/java/appeng/parts/reporting/PartFluidTerminal.java new file mode 100644 index 000000000..0b8fe26ad --- /dev/null +++ b/src/main/java/appeng/parts/reporting/PartFluidTerminal.java @@ -0,0 +1,66 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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.reporting; + + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +import appeng.api.parts.IPartModel; +import appeng.core.AppEng; +import appeng.core.sync.GuiBridge; +import appeng.items.parts.PartModels; +import appeng.parts.PartModel; + + +/** + * @author BrockWS + * @version rv6 - 12/05/2018 + * @since rv6 12/05/2018 + */ +public class PartFluidTerminal extends AbstractPartTerminal +{ + + @PartModels + public static final ResourceLocation MODEL_OFF = new ResourceLocation( AppEng.MOD_ID, "part/crafting_terminal_off" ); + @PartModels + public static final ResourceLocation MODEL_ON = new ResourceLocation( AppEng.MOD_ID, "part/crafting_terminal_on" ); + + public static final IPartModel MODELS_OFF = new PartModel( MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF ); + public static final IPartModel MODELS_ON = new PartModel( MODEL_BASE, MODEL_ON, MODEL_STATUS_ON ); + public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL ); + + public PartFluidTerminal( ItemStack is ) + { + super( is ); + } + + @Override + public GuiBridge getGui( EntityPlayer player ) + { + return GuiBridge.GUI_FLUID_TERMINAL; + } + + @Override + public IPartModel getStaticModels() + { + return this.selectModel( MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL ); + } +} diff --git a/src/main/java/appeng/tile/misc/TileCellWorkbench.java b/src/main/java/appeng/tile/misc/TileCellWorkbench.java index e29cbc2da..80c14d516 100644 --- a/src/main/java/appeng/tile/misc/TileCellWorkbench.java +++ b/src/main/java/appeng/tile/misc/TileCellWorkbench.java @@ -192,11 +192,15 @@ public class TileCellWorkbench extends AEBaseTile implements IUpgradeableHost, I } else if( inv == this.config && !this.locked ) { + this.locked = true; final IItemHandler c = this.getCellConfigInventory(); if( c != null ) { ItemHandlerUtil.copy( this.config, c, false ); + //copy items back. The ConfigInventory may changed the items on insert + ItemHandlerUtil.copy( c, this.config, false ); } + this.locked = false; } } diff --git a/src/main/java/appeng/util/FluidSorters.java b/src/main/java/appeng/util/FluidSorters.java new file mode 100644 index 000000000..cb8284859 --- /dev/null +++ b/src/main/java/appeng/util/FluidSorters.java @@ -0,0 +1,103 @@ +/* + * This file is part of Applied Energistics 2. + * Copyright (c) 2013 - 2018, 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; + + +import java.util.Comparator; + +import appeng.api.config.SortDir; +import appeng.api.storage.data.IAEFluidStack; +import appeng.util.item.AEFluidStack; + + +/** + * @author BrockWS + * @version rv6 - 22/05/2018 + * @since rv6 22/05/2018 + */ +public class FluidSorters +{ + private static SortDir Direction = SortDir.ASCENDING; + + public static final Comparator CONFIG_BASED_SORT_BY_NAME = new Comparator() + { + + @Override + public int compare( final IAEFluidStack o1, final IAEFluidStack o2 ) + { + if( getDirection() == SortDir.ASCENDING ) + { + return Platform.getFluidDisplayName( o1 ).compareToIgnoreCase( Platform.getFluidDisplayName( o2 ) ); + } + return Platform.getFluidDisplayName( o2 ).compareToIgnoreCase( Platform.getFluidDisplayName( o1 ) ); + } + }; + + public static final Comparator CONFIG_BASED_SORT_BY_MOD = new Comparator() + { + + @Override + public int compare( final IAEFluidStack o1, final IAEFluidStack o2 ) + { + final AEFluidStack op1 = (AEFluidStack) o1; + final AEFluidStack op2 = (AEFluidStack) o2; + + if( getDirection() == SortDir.ASCENDING ) + { + return this.secondarySort( Platform.getModId( op1 ).compareToIgnoreCase( Platform.getModId( op2 ) ), o2, o1 ); + } + return this.secondarySort( Platform.getModId( op2 ).compareToIgnoreCase( Platform.getModId( op1 ) ), o1, o2 ); + } + + private int secondarySort( final int compareToIgnoreCase, final IAEFluidStack o1, final IAEFluidStack o2 ) + { + if( compareToIgnoreCase == 0 ) + { + return Platform.getFluidDisplayName( o2 ).compareToIgnoreCase( Platform.getFluidDisplayName( o1 ) ); + } + + return compareToIgnoreCase; + } + }; + + public static final Comparator CONFIG_BASED_SORT_BY_SIZE = new Comparator() + { + + @Override + public int compare( final IAEFluidStack o1, final IAEFluidStack o2 ) + { + if( getDirection() == SortDir.ASCENDING ) + { + return Long.compare( o2.getStackSize(), o1.getStackSize() ); + } + return Long.compare( o1.getStackSize(), o2.getStackSize() ); + } + }; + + + private static SortDir getDirection() + { + return Direction; + } + + public static void setDirection( final SortDir direction ) + { + Direction = direction; + } +} diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index cc7f75192..7c45cb179 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -67,6 +67,8 @@ import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.util.FakePlayerFactory; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.ModContainer; @@ -121,6 +123,7 @@ import appeng.me.GridNode; import appeng.me.helpers.AENetworkProxy; import appeng.util.helpers.ItemComparisonHelper; import appeng.util.helpers.P2PHelper; +import appeng.util.item.AEFluidStack; import appeng.util.item.AEItemStack; import appeng.util.prioritylist.IPartitionList; @@ -610,6 +613,17 @@ public class Platform return n == null ? "** Null" : n; } + public static String getModId( final IAEFluidStack fs ) + { + if( fs == null || fs.getFluidStack() == null ) + { + return "** Null"; + } + + final String n = FluidRegistry.getModId( fs.getFluidStack() ); + return n == null ? "** Null" : n; + } + public static String getItemDisplayName( final Object o ) { if( o == null ) @@ -655,6 +669,33 @@ public class Platform } } + public static String getFluidDisplayName( Object o ) + { + if( o == null ) + { + return "** Null"; + } + FluidStack fluidStack = null; + if( o instanceof AEFluidStack ) + { + fluidStack = ( (AEFluidStack) o ).getFluidStack(); + } + else if( o instanceof FluidStack ) + { + fluidStack = (FluidStack) o; + } + else + { + return "**Invalid Object"; + } + String n = fluidStack.getLocalizedName(); + if( n == null || "".equalsIgnoreCase( n ) ) + { + n = fluidStack.getUnlocalizedName(); + } + return n == null ? "** Null" : n; + } + public static boolean isWrench( final EntityPlayer player, final ItemStack eq, final BlockPos pos ) { if( !eq.isEmpty() ) diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_us.lang b/src/main/resources/assets/appliedenergistics2/lang/en_us.lang index 31cd744f5..353c37e05 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_us.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_us.lang @@ -131,6 +131,7 @@ gui.appliedenergistics2.SecurityCardEditor=Biometric Card Editor gui.appliedenergistics2.Encoded=Encoded gui.appliedenergistics2.Priority=Priority gui.appliedenergistics2.StorageBus=Storage Bus +gui.appliedenergistics2.StorageBusFluids=Fluid Storage Bus gui.appliedenergistics2.EnergyDrain=Passive Drain gui.appliedenergistics2.Installed=Installed gui.appliedenergistics2.NetworkTool=Network Tool @@ -146,8 +147,10 @@ gui.appliedenergistics2.Condenser=Matter Condenser gui.appliedenergistics2.Config=Config gui.appliedenergistics2.Drive=ME Drive gui.appliedenergistics2.ExportBus=ME Export Bus +gui.appliedenergistics2.ExportBusFluids=ME Fluid Export Bus gui.appliedenergistics2.GrindStone=Grindstone gui.appliedenergistics2.ImportBus=ME Import Bus +gui.appliedenergistics2.ImportBusFluids=ME Fluid Import Bus gui.appliedenergistics2.Interface=ME Interface gui.appliedenergistics2.LevelEmitter=ME Level Emitter gui.appliedenergistics2.Of=of @@ -163,6 +166,7 @@ gui.appliedenergistics2.VibrationChamber=Vibration Chamber gui.appliedenergistics2.NetworkDetails=Network Details gui.appliedenergistics2.StorageCells=ME Storage Cells gui.appliedenergistics2.IOBuses=ME Import/Export Bus +gui.appliedenergistics2.IOBusesFluids=ME Fluid Import/Export Bus gui.appliedenergistics2.Stores=Stores gui.appliedenergistics2.BytesUsed=Bytes Used gui.appliedenergistics2.Types=Types @@ -323,6 +327,9 @@ gui.tooltips.appliedenergistics2.EmitWhenCrafting=Emit Redstone while item is cr gui.tooltips.appliedenergistics2.ReportInaccessibleItems=Report Inaccessible Items gui.tooltips.appliedenergistics2.ReportInaccessibleItemsYes=Yes: Items that cannot be extracted will be visible. gui.tooltips.appliedenergistics2.ReportInaccessibleItemsNo=No: Only extractable items will be visible. +gui.tooltips.appliedenergistics2.ReportInaccessibleFluids=Report Inaccessible Fluids +gui.tooltips.appliedenergistics2.ReportInaccessibleFluidsYes=Yes: Fluids that cannot be extracted will be visible. +gui.tooltips.appliedenergistics2.ReportInaccessibleFluidsNo=No: Only extractable fluids will be visible. gui.tooltips.appliedenergistics2.BlockPlacement=Block Placement gui.tooltips.appliedenergistics2.BlockPlacementYes=Blocks will be placed as block. gui.tooltips.appliedenergistics2.BlockPlacementNo=Blocks will be dropped as item. @@ -396,6 +403,10 @@ item.appliedenergistics2.storage_cell_1k.name=1k ME Storage Cell item.appliedenergistics2.storage_cell_4k.name=4k ME Storage Cell item.appliedenergistics2.storage_cell_16k.name=16k ME Storage Cell item.appliedenergistics2.storage_cell_64k.name=64k ME Storage Cell +item.appliedenergistics2.fluid_storage_cell_1k.name=1k ME Fluid Storage Cell +item.appliedenergistics2.fluid_storage_cell_4k.name=4k ME Fluid Storage Cell +item.appliedenergistics2.fluid_storage_cell_16k.name=16k ME Fluid Storage Cell +item.appliedenergistics2.fluid_storage_cell_64k.name=64k ME Fluid Storage Cell item.appliedenergistics2.creative_storage_cell.name=Creative ME Storage Cell item.appliedenergistics2.encoded_pattern.name=Encoded Pattern item.appliedenergistics2.view_cell.name=View Cell @@ -422,6 +433,10 @@ item.appliedenergistics2.material.cell1k_part.name=1k ME Storage Component item.appliedenergistics2.material.cell4k_part.name=4k ME Storage Component item.appliedenergistics2.material.cell16k_part.name=16k ME Storage Component item.appliedenergistics2.material.cell64k_part.name=64k ME Storage Component +item.appliedenergistics2.material.fluid_cell1k_part.name=1k ME Fluid Storage Component +item.appliedenergistics2.material.fluid_cell4k_part.name=4k ME Fluid Storage Component +item.appliedenergistics2.material.fluid_cell16k_part.name=16k ME Fluid Storage Component +item.appliedenergistics2.material.fluid_cell64k_part.name=64k ME Fluid Storage Component item.appliedenergistics2.material.certus_quartz_crystal.name=Certus Quartz Crystal item.appliedenergistics2.material.certus_quartz_crystal_charged.name=Charged Certus Quartz Crystal item.appliedenergistics2.material.certus_quartz_dust.name=Certus Quartz Dust @@ -475,19 +490,23 @@ item.appliedenergistics2.multi_part.semi_dark_monitor.name=Illuminated Panel item.appliedenergistics2.multi_part.monitor.name=Bright Illuminated Panel item.appliedenergistics2.multi_part.dark_monitor.name=Dark Illuminated Panel item.appliedenergistics2.multi_part.export_bus.name=ME Export Bus +item.appliedenergistics2.multi_part.fluid_export_bus.name=ME Fluid Export Bus item.appliedenergistics2.multi_part.formation_plane.name=ME Formation Plane item.appliedenergistics2.multi_part.import_bus.name=ME Import Bus +item.appliedenergistics2.multi_part.fluid_import_bus.name=ME Fluid Import Bus item.appliedenergistics2.multi_part.interface.name=ME Interface item.appliedenergistics2.multi_part.level_emitter.name=ME Level Emitter item.appliedenergistics2.multi_part.p2p_tunnel.name=P2P Tunnel item.appliedenergistics2.multi_part.pattern_terminal.name=ME Pattern Terminal item.appliedenergistics2.multi_part.quartz_fiber.name=Quartz Fiber item.appliedenergistics2.multi_part.storage_bus.name=ME Storage Bus +item.appliedenergistics2.multi_part.fluid_storage_bus.name=ME Fluid Storage Bus item.appliedenergistics2.multi_part.terminal.name=ME Terminal item.appliedenergistics2.multi_part.inverted_toggle_bus.name=ME Inverted Toggle Bus item.appliedenergistics2.multi_part.toggle_bus.name=ME Toggle Bus item.appliedenergistics2.multi_part.crafting_monitor.name=ME Crafting Monitor item.appliedenergistics2.multi_part.interface_terminal.name=ME Interface Terminal +item.appliedenergistics2.multi_part.fluid_terminal.name=ME Fluid Terminal item.appliedenergistics2.multi_part.invalid_type.name=Disabled Item item.appliedenergistics2.spatial_storage_cell_128_cubed.name=128³ Spatial Storage Cell diff --git a/src/main/resources/assets/appliedenergistics2/models/item/dummy_fluid_item_base.json b/src/main/resources/assets/appliedenergistics2/models/item/dummy_fluid_item_base.json new file mode 100644 index 000000000..b68686041 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/dummy_fluid_item_base.json @@ -0,0 +1,5 @@ +{ + "parent": "item/generated", + "textures": { + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_16k.json b/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_16k.json new file mode 100644 index 000000000..39712683e --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_16k.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "appliedenergistics2:items/fluid_storage_cell_16k" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_1k.json b/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_1k.json new file mode 100644 index 000000000..41e170829 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_1k.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "appliedenergistics2:items/fluid_storage_cell_1k" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_4k.json b/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_4k.json new file mode 100644 index 000000000..cb8a78ece --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_4k.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "appliedenergistics2:items/fluid_storage_cell_4k" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_64k.json b/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_64k.json new file mode 100644 index 000000000..fa0b49a16 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/fluid_storage_cell_64k.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "appliedenergistics2:items/fluid_storage_cell_64k" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell16k_part.json b/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell16k_part.json new file mode 100644 index 000000000..e01489e83 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell16k_part.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "appliedenergistics2:items/material_fluid_cell16k_part" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell1k_part.json b/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell1k_part.json new file mode 100644 index 000000000..d74932ef5 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell1k_part.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "appliedenergistics2:items/material_fluid_cell1k_part" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell4k_part.json b/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell4k_part.json new file mode 100644 index 000000000..fb7088dba --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell4k_part.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "appliedenergistics2:items/material_fluid_cell4k_part" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell64k_part.json b/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell64k_part.json new file mode 100644 index 000000000..ebda1c38f --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/material_fluid_cell64k_part.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "appliedenergistics2:items/material_fluid_cell64k_part" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_export_bus.json b/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_export_bus.json new file mode 100644 index 000000000..3b3c94b24 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_export_bus.json @@ -0,0 +1,106 @@ +{ + "parent": "appliedenergistics2:item/part/part", + "textures": { + "sides": "appliedenergistics2:parts/export_bus_sides", + "back": "appliedenergistics2:parts/monitor_back", + "front": "appliedenergistics2:items/part/export_bus" + }, + "elements": [ + { + "from": [ + 4, + 4, + 8 + ], + "to": [ + 12, + 12, + 10 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + }, + { + "from": [ + 5, + 5, + 7 + ], + "to": [ + 11, + 11, + 8 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + }, + { + "from": [ + 6, + 6, + 6 + ], + "to": [ + 10, + 10, + 7 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_import_bus.json b/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_import_bus.json new file mode 100644 index 000000000..cd019540e --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_import_bus.json @@ -0,0 +1,106 @@ +{ + "parent": "appliedenergistics2:item/part/part", + "textures": { + "sides": "appliedenergistics2:parts/import_bus_sides", + "back": "appliedenergistics2:parts/monitor_back", + "front": "appliedenergistics2:items/part/import_bus" + }, + "elements": [ + { + "from": [ + 3, + 3, + 8 + ], + "to": [ + 13, + 13, + 9 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + }, + { + "from": [ + 4, + 4, + 9 + ], + "to": [ + 12, + 12, + 10 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + }, + { + "from": [ + 5, + 5, + 10 + ], + "to": [ + 11, + 11, + 11 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_storage_bus.json b/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_storage_bus.json new file mode 100644 index 000000000..464df4cea --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_storage_bus.json @@ -0,0 +1,106 @@ +{ + "parent": "appliedenergistics2:item/part/part", + "textures": { + "sides": "appliedenergistics2:parts/storage_bus_sides", + "back": "appliedenergistics2:parts/storage_bus_back", + "front": "appliedenergistics2:items/part/storage_bus" + }, + "elements": [ + { + "from": [ + 3, + 3, + 6 + ], + "to": [ + 13, + 13, + 7 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + }, + { + "from": [ + 2, + 2, + 7 + ], + "to": [ + 14, + 14, + 8 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + }, + { + "from": [ + 5, + 5, + 8 + ], + "to": [ + 11, + 11, + 10 + ], + "faces": { + "north": { + "texture": "#front" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "down": { + "texture": "#sides" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_terminal.json b/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_terminal.json new file mode 100644 index 000000000..d61fef4ae --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/item/part/fluid_terminal.json @@ -0,0 +1,9 @@ +{ + "parent": "appliedenergistics2:item/part/display", + "textures": { + "front": "appliedenergistics2:items/part/terminal", + "front_bright": "appliedenergistics2:parts/terminal_bright", + "front_medium": "appliedenergistics2:parts/terminal_medium", + "front_dark": "appliedenergistics2:parts/terminal_dark" + } +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_base.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_base.json new file mode 100644 index 000000000..9d036d085 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_base.json @@ -0,0 +1,136 @@ +{ + "textures": { + "sides": "appliedenergistics2:parts/export_bus_sides", + "sidesStatus": "appliedenergistics2:parts/monitor_sides_status", + "back": "appliedenergistics2:parts/monitor_back", + "front": "appliedenergistics2:items/part/export_bus", + "particle": "appliedenergistics2:parts/monitor_back" + }, + "elements": [ + { + "from": [ + 4, + 4, + 2 + ], + "to": [ + 12, + 12, + 4 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "north": { + "texture": "#front" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 5, + 5, + 1 + ], + "to": [ + 11, + 11, + 2 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "north": { + "texture": "#front" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 6, + 6, + 0 + ], + "to": [ + 10, + 10, + 1 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "north": { + "texture": "#front" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 6, + 6, + 4 + ], + "to": [ + 10, + 10, + 5 + ], + "faces": { + "down": { + "texture": "#sidesStatus" + }, + "up": { + "texture": "#sidesStatus" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sidesStatus" + }, + "west": { + "texture": "#sidesStatus" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_has_channel.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_has_channel.json new file mode 100644 index 000000000..9ed52e0e9 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_has_channel.json @@ -0,0 +1,54 @@ +{ + "ae2_uvl_marker": true, + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_has_channel" + }, + "elements": [ + { + "from": [ + 6, + 6, + 4 + ], + "to": [ + 10, + 10, + 5 + ], + "faces": { + "down": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "up": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "east": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "west": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_off.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_off.json new file mode 100644 index 000000000..7ab36af58 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_off.json @@ -0,0 +1,33 @@ +{ + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_off" + }, + "elements": [ + { + "from": [ + 6, + 6, + 4 + ], + "to": [ + 10, + 10, + 5 + ], + "faces": { + "down": { + "texture": "#indicator" + }, + "up": { + "texture": "#indicator" + }, + "east": { + "texture": "#indicator" + }, + "west": { + "texture": "#indicator" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_on.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_on.json new file mode 100644 index 000000000..c1596db34 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_export_bus_on.json @@ -0,0 +1,54 @@ +{ + "ae2_uvl_marker": true, + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_on" + }, + "elements": [ + { + "from": [ + 6, + 6, + 4 + ], + "to": [ + 10, + 10, + 5 + ], + "faces": { + "down": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "up": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "east": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "west": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_base.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_base.json new file mode 100644 index 000000000..98f994ded --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_base.json @@ -0,0 +1,136 @@ +{ + "textures": { + "sides": "appliedenergistics2:parts/import_bus_sides", + "sidesStatus": "appliedenergistics2:parts/monitor_sides_status", + "back": "appliedenergistics2:parts/monitor_back", + "front": "appliedenergistics2:items/part/import_bus", + "particle": "appliedenergistics2:parts/monitor_back" + }, + "elements": [ + { + "from": [ + 4, + 4, + 0 + ], + "to": [ + 12, + 12, + 2 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "north": { + "texture": "#front" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 5, + 5, + 2 + ], + "to": [ + 11, + 11, + 3 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "north": { + "texture": "#front" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 6, + 6, + 3 + ], + "to": [ + 10, + 10, + 4 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "north": { + "texture": "#front" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 6, + 6, + 4 + ], + "to": [ + 10, + 10, + 5 + ], + "faces": { + "down": { + "texture": "#sidesStatus" + }, + "up": { + "texture": "#sidesStatus" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sidesStatus" + }, + "west": { + "texture": "#sidesStatus" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_has_channel.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_has_channel.json new file mode 100644 index 000000000..9ed52e0e9 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_has_channel.json @@ -0,0 +1,54 @@ +{ + "ae2_uvl_marker": true, + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_has_channel" + }, + "elements": [ + { + "from": [ + 6, + 6, + 4 + ], + "to": [ + 10, + 10, + 5 + ], + "faces": { + "down": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "up": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "east": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "west": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_off.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_off.json new file mode 100644 index 000000000..7ab36af58 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_off.json @@ -0,0 +1,33 @@ +{ + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_off" + }, + "elements": [ + { + "from": [ + 6, + 6, + 4 + ], + "to": [ + 10, + 10, + 5 + ], + "faces": { + "down": { + "texture": "#indicator" + }, + "up": { + "texture": "#indicator" + }, + "east": { + "texture": "#indicator" + }, + "west": { + "texture": "#indicator" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_on.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_on.json new file mode 100644 index 000000000..c1596db34 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_import_bus_on.json @@ -0,0 +1,54 @@ +{ + "ae2_uvl_marker": true, + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_on" + }, + "elements": [ + { + "from": [ + 6, + 6, + 4 + ], + "to": [ + 10, + 10, + 5 + ], + "faces": { + "down": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "up": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "east": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "west": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_base.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_base.json new file mode 100644 index 000000000..7e1a4dd55 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_base.json @@ -0,0 +1,130 @@ +{ + "textures": { + "sides": "appliedenergistics2:parts/storage_bus_sides", + "sidesStatus": "appliedenergistics2:parts/monitor_sides_status", + "back": "appliedenergistics2:parts/storage_bus_back", + "front": "appliedenergistics2:items/part/storage_bus", + "particle": "appliedenergistics2:parts/storage_bus_back" + }, + "elements": [ + { + "from": [ + 3, + 3, + 0 + ], + "to": [ + 13, + 13, + 1 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "north": { + "texture": "#front" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 2, + 2, + 1 + ], + "to": [ + 14, + 14, + 2 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "north": { + "texture": "#front" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 5, + 5, + 3 + ], + "to": [ + 11, + 11, + 4 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "south": { + "texture": "#back" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + } + } + }, + { + "from": [ + 5, + 5, + 2 + ], + "to": [ + 11, + 11, + 3 + ], + "faces": { + "down": { + "texture": "#sides" + }, + "up": { + "texture": "#sides" + }, + "east": { + "texture": "#sides" + }, + "west": { + "texture": "#sides" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_has_channel.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_has_channel.json new file mode 100644 index 000000000..f47216bf2 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_has_channel.json @@ -0,0 +1,54 @@ +{ + "ae2_uvl_marker": true, + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_has_channel" + }, + "elements": [ + { + "from": [ + 5, + 5, + 2 + ], + "to": [ + 11, + 11, + 3 + ], + "faces": { + "down": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "up": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "east": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "west": { + "texture": "#indicator", + "tintindex": 1, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_off.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_off.json new file mode 100644 index 000000000..3ab8507fa --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_off.json @@ -0,0 +1,33 @@ +{ + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_off" + }, + "elements": [ + { + "from": [ + 5, + 5, + 2 + ], + "to": [ + 11, + 11, + 3 + ], + "faces": { + "down": { + "texture": "#indicator" + }, + "up": { + "texture": "#indicator" + }, + "east": { + "texture": "#indicator" + }, + "west": { + "texture": "#indicator" + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_on.json b/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_on.json new file mode 100644 index 000000000..cd41b8f73 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/models/part/fluid_storage_bus_on.json @@ -0,0 +1,54 @@ +{ + "ae2_uvl_marker": true, + "textures": { + "indicator": "appliedenergistics2:parts/monitor_sides_status_on" + }, + "elements": [ + { + "from": [ + 5, + 5, + 2 + ], + "to": [ + 11, + 11, + 3 + ], + "faces": { + "down": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "up": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "east": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + }, + "west": { + "texture": "#indicator", + "tintindex": 3, + "uvlightmap": { + "sky": 0.007, + "block": 0.007 + } + } + } + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_16k.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_16k.json new file mode 100644 index 000000000..d99ee13ac --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_16k.json @@ -0,0 +1,28 @@ +{ + "result": { + "item": "appliedenergistics2:fluid_storage_cell_16k" + }, + "type": "forge:ore_shaped", + "pattern": [ + "aba", + "bcb", + "ddd" + ], + "key": { + "a": { + "item": "appliedenergistics2:quartz_glass" + }, + "d": { + "type": "forge:ore_dict", + "ore": "ingotIron" + }, + "b": { + "type": "forge:ore_dict", + "ore": "dustRedstone" + }, + "c": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell16k_part" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_16k_storage.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_16k_storage.json new file mode 100644 index 000000000..bd6d51602 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_16k_storage.json @@ -0,0 +1,16 @@ +{ + "result": { + "item": "appliedenergistics2:fluid_storage_cell_16k" + }, + "type": "forge:ore_shapeless", + "ingredients": [ + { + "type": "appliedenergistics2:part", + "part": "material.empty_storage_cell" + }, + { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell16k_part" + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_1k.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_1k.json new file mode 100644 index 000000000..537923a61 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_1k.json @@ -0,0 +1,28 @@ +{ + "result": { + "item": "appliedenergistics2:fluid_storage_cell_1k" + }, + "type": "forge:ore_shaped", + "pattern": [ + "aba", + "bcb", + "ddd" + ], + "key": { + "a": { + "item": "appliedenergistics2:quartz_glass" + }, + "d": { + "type": "forge:ore_dict", + "ore": "ingotIron" + }, + "b": { + "type": "forge:ore_dict", + "ore": "dustRedstone" + }, + "c": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell1k_part" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_1k_storage.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_1k_storage.json new file mode 100644 index 000000000..f69e8ec07 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_1k_storage.json @@ -0,0 +1,16 @@ +{ + "result": { + "item": "appliedenergistics2:fluid_storage_cell_1k" + }, + "type": "forge:ore_shapeless", + "ingredients": [ + { + "type": "appliedenergistics2:part", + "part": "material.empty_storage_cell" + }, + { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell1k_part" + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_4k.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_4k.json new file mode 100644 index 000000000..11de55ede --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_4k.json @@ -0,0 +1,28 @@ +{ + "result": { + "item": "appliedenergistics2:fluid_storage_cell_4k" + }, + "type": "forge:ore_shaped", + "pattern": [ + "aba", + "bcb", + "ddd" + ], + "key": { + "a": { + "item": "appliedenergistics2:quartz_glass" + }, + "d": { + "type": "forge:ore_dict", + "ore": "ingotIron" + }, + "b": { + "type": "forge:ore_dict", + "ore": "dustRedstone" + }, + "c": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell4k_part" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_4k_storage.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_4k_storage.json new file mode 100644 index 000000000..b6d5b2967 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_4k_storage.json @@ -0,0 +1,16 @@ +{ + "result": { + "item": "appliedenergistics2:fluid_storage_cell_4k" + }, + "type": "forge:ore_shapeless", + "ingredients": [ + { + "type": "appliedenergistics2:part", + "part": "material.empty_storage_cell" + }, + { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell4k_part" + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_64k.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_64k.json new file mode 100644 index 000000000..cd2fa2a26 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_64k.json @@ -0,0 +1,28 @@ +{ + "result": { + "item": "appliedenergistics2:fluid_storage_cell_64k" + }, + "type": "forge:ore_shaped", + "pattern": [ + "aba", + "bcb", + "ddd" + ], + "key": { + "a": { + "item": "appliedenergistics2:quartz_glass" + }, + "d": { + "type": "forge:ore_dict", + "ore": "ingotIron" + }, + "b": { + "type": "forge:ore_dict", + "ore": "dustRedstone" + }, + "c": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell64k_part" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_64k_storage.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_64k_storage.json new file mode 100644 index 000000000..b25ff52c5 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_cell_64k_storage.json @@ -0,0 +1,16 @@ +{ + "result": { + "item": "appliedenergistics2:fluid_storage_cell_64k" + }, + "type": "forge:ore_shapeless", + "ingredients": [ + { + "type": "appliedenergistics2:part", + "part": "material.empty_storage_cell" + }, + { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell64k_part" + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_16k_part.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_16k_part.json new file mode 100644 index 000000000..03083f302 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_16k_part.json @@ -0,0 +1,29 @@ +{ + "result": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell16k_part" + }, + "type": "appliedenergistics2:part_shaped", + "pattern": [ + "aba", + "cdc", + "aca" + ], + "key": { + "d": { + "item": "appliedenergistics2:quartz_glass" + }, + "a": { + "item": "minecraft:dye", + "data": 4 + }, + "c": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell4k_part" + }, + "b": { + "type": "appliedenergistics2:part", + "part": "material.calculation_processor" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_1k_part.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_1k_part.json new file mode 100644 index 000000000..2bfd62acc --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_1k_part.json @@ -0,0 +1,25 @@ +{ + "result": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell1k_part" + }, + "type": "appliedenergistics2:part_shaped", + "pattern": [ + "aba", + "bcb", + "aba" + ], + "key": { + "a": { + "item": "minecraft:dye", + "data": 4 + }, + "b": { + "item": "#appliedenergistics2:certusCrystal" + }, + "c": { + "type": "appliedenergistics2:part", + "part": "material.logic_processor" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_4k_part.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_4k_part.json new file mode 100644 index 000000000..e636726dc --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_4k_part.json @@ -0,0 +1,29 @@ +{ + "result": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell4k_part" + }, + "type": "appliedenergistics2:part_shaped", + "pattern": [ + "aba", + "cdc", + "aca" + ], + "key": { + "d": { + "item": "appliedenergistics2:quartz_glass" + }, + "a": { + "item": "minecraft:dye", + "data": 4 + }, + "c": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell1k_part" + }, + "b": { + "type": "appliedenergistics2:part", + "part": "material.calculation_processor" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_64k_part.json b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_64k_part.json new file mode 100644 index 000000000..ba9211c5f --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/cells/fluid_storage_components_cell_64k_part.json @@ -0,0 +1,29 @@ +{ + "result": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell64k_part" + }, + "type": "appliedenergistics2:part_shaped", + "pattern": [ + "aba", + "cdc", + "aca" + ], + "key": { + "d": { + "item": "appliedenergistics2:quartz_glass" + }, + "a": { + "item": "minecraft:dye", + "data": 4 + }, + "c": { + "type": "appliedenergistics2:part", + "part": "material.fluid_cell16k_part" + }, + "b": { + "type": "appliedenergistics2:part", + "part": "material.calculation_processor" + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/parts/export_bus_fluid.json b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/export_bus_fluid.json new file mode 100644 index 000000000..2a6d97c59 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/export_bus_fluid.json @@ -0,0 +1,28 @@ +{ + "result": { + "type": "appliedenergistics2:part", + "part": "part.export_bus_fluid" + }, + "type": "appliedenergistics2:part_shaped", + "pattern": [ + "aba", + "lcl" + ], + "key": { + "b": { + "type": "appliedenergistics2:part", + "part": "material.formation_core" + }, + "a": { + "type": "forge:ore_dict", + "ore": "ingotIron" + }, + "c": { + "item": "minecraft:piston" + }, + "l": { + "item": "minecraft:dye", + "data": 4 + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/parts/import_bus_fluid.json b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/import_bus_fluid.json new file mode 100644 index 000000000..4275142a9 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/import_bus_fluid.json @@ -0,0 +1,28 @@ +{ + "result": { + "type": "appliedenergistics2:part", + "part": "part.import_bus_fluid" + }, + "type": "appliedenergistics2:part_shaped", + "pattern": [ + "lal", + "bcb" + ], + "key": { + "c": { + "item": "minecraft:sticky_piston" + }, + "b": { + "type": "forge:ore_dict", + "ore": "ingotIron" + }, + "a": { + "type": "appliedenergistics2:part", + "part": "material.annihilation_core" + }, + "l": { + "item": "minecraft:dye", + "data": 4 + } + } +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/parts/storage_bus_fluid.json b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/storage_bus_fluid.json new file mode 100644 index 000000000..10dc4a50c --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/storage_bus_fluid.json @@ -0,0 +1,22 @@ +{ + "result": { + "type": "appliedenergistics2:part", + "part": "part.storage_bus_fluid" + }, + "type": "appliedenergistics2:part_shapeless", + "ingredients": [ + { + "item": "minecraft:sticky_piston" + }, + { + "item": "#appliedenergistics2:interface" + }, + { + "item": "minecraft:piston" + }, + { + "item": "minecraft:dye", + "data": 4 + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/parts/terminals_fluid.json b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/terminals_fluid.json new file mode 100644 index 000000000..38fb67c29 --- /dev/null +++ b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/terminals_fluid.json @@ -0,0 +1,21 @@ +{ + "result": { + "type": "appliedenergistics2:part", + "part": "part.fluid_terminal" + }, + "type": "appliedenergistics2:part_shapeless", + "ingredients": [ + { + "type": "appliedenergistics2:part", + "part": "part.terminal" + }, + { + "item": "minecraft:dye", + "data": 4 + }, + { + "type": "appliedenergistics2:part", + "part": "material.logic_processor" + } + ] +} diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_16k.png b/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_16k.png new file mode 100644 index 000000000..3c0c367da Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_16k.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_1k.png b/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_1k.png new file mode 100644 index 000000000..99a0009dd Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_1k.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_4k.png b/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_4k.png new file mode 100644 index 000000000..d37d66cbc Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_4k.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_64k.png b/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_64k.png new file mode 100644 index 000000000..8171533f9 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/fluid_storage_cell_64k.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell16k_part.png b/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell16k_part.png new file mode 100644 index 000000000..38ecf24fe Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell16k_part.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell1k_part.png b/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell1k_part.png new file mode 100644 index 000000000..f27413bd8 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell1k_part.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell4k_part.png b/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell4k_part.png new file mode 100644 index 000000000..fc6e4f282 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell4k_part.png differ diff --git a/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell64k_part.png b/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell64k_part.png new file mode 100644 index 000000000..59536b207 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/items/material_fluid_cell64k_part.png differ