Initial Fluid Integration (#3510)

* Added Fluid Storage Cells

* Added Fluid Import Bus

* Added Fluid Export Bus

* Added Fluid Storage Bus

* Added Fluid Terminal.
While holding a item with the FLUID_HANDLER_ITEM_CAPABILITY, such as a tank
Left click on a fluid to extract the fluid
Right click to insert the fluid
This commit is contained in:
Brock
2018-06-12 03:55:33 +10:00
committed by yueh
parent 89bebc4385
commit d16677224a
126 changed files with 8031 additions and 778 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ aebasename=appliedenergistics2
######################################################### #########################################################
minecraft_version=1.12.2 minecraft_version=1.12.2
mcp_mappings=snapshot_20171003 mcp_mappings=snapshot_20171003
forge_version=14.23.1.2554 forge_version=14.23.3.2655
######################################################### #########################################################
# Installable # # Installable #
@@ -88,6 +88,14 @@ public interface IItems
IItemDefinition cell64k(); IItemDefinition cell64k();
IItemDefinition fluidCell1k();
IItemDefinition fluidCell4k();
IItemDefinition fluidCell16k();
IItemDefinition fluidCell64k();
IItemDefinition spatialCell2(); IItemDefinition spatialCell2();
IItemDefinition spatialCell16(); IItemDefinition spatialCell16();
@@ -134,4 +134,12 @@ public interface IMaterials
IItemDefinition qESingularity(); IItemDefinition qESingularity();
IItemDefinition blankPattern(); IItemDefinition blankPattern();
IItemDefinition fluidCell1kPart();
IItemDefinition fluidCell4kPart();
IItemDefinition fluidCell16kPart();
IItemDefinition fluidCell64kPart();
} }
@@ -107,4 +107,12 @@ public interface IParts
IItemDefinition storageMonitor(); IItemDefinition storageMonitor();
IItemDefinition conversionMonitor(); IItemDefinition conversionMonitor();
IItemDefinition fluidTerminal();
IItemDefinition fluidImportBus();
IItemDefinition fluidExportBus();
IItemDefinition fluidStorageBus();
} }
@@ -27,7 +27,8 @@ package appeng.api.implementations.items;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import appeng.api.storage.ICellWorkbenchItem; 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 * The standard AE implementation only provides 1-63 Types
*/ */
public interface IStorageCell extends ICellWorkbenchItem public interface IStorageCell<T extends IAEStack<T>> extends ICellWorkbenchItem
{ {
/** /**
@@ -82,7 +83,7 @@ public interface IStorageCell extends ICellWorkbenchItem
* *
* @return true to preventAdditionOfItem * @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 * 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. * @return drain in ae/t this storage cell will use.
*/ */
double getIdleDrain(); double getIdleDrain();
/**
* @return the type of channel your cell should be part of
*/
IStorageChannel<T> getChannel();
} }
@@ -28,10 +28,10 @@ import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack;
public interface ICellInventory extends IMEInventory<IAEItemStack> public interface ICellInventory<T extends IAEStack<T>> extends IMEInventory<T>
{ {
/** /**
@@ -25,10 +25,10 @@ package appeng.api.storage;
import appeng.api.config.IncludeExclude; import appeng.api.config.IncludeExclude;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack;
public interface ICellInventoryHandler extends IMEInventoryHandler<IAEItemStack> public interface ICellInventoryHandler<T extends IAEStack<T>> extends IMEInventoryHandler<T>
{ {
/** /**
+56 -7
View File
@@ -46,6 +46,8 @@ import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator; 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.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType; import net.minecraft.inventory.ClickType;
@@ -54,6 +56,8 @@ import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.client.gui.widgets.GuiScrollbar; import appeng.client.gui.widgets.GuiScrollbar;
@@ -66,7 +70,8 @@ import appeng.container.AEBaseContainer;
import appeng.container.slot.AppEngCraftingSlot; import appeng.container.slot.AppEngCraftingSlot;
import appeng.container.slot.AppEngSlot; import appeng.container.slot.AppEngSlot;
import appeng.container.slot.AppEngSlot.hasCalculatedValidness; 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.SlotCraftingTerm;
import appeng.container.slot.SlotDisabled; import appeng.container.slot.SlotDisabled;
import appeng.container.slot.SlotFake; import appeng.container.slot.SlotFake;
@@ -208,6 +213,23 @@ public abstract class AEBaseGui extends GuiContainer
this.drawHoveringText( lines, x, y, this.fontRenderer ); 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 @Override
protected final void drawGuiContainerForegroundLayer( final int x, final int y ) protected final void drawGuiContainerForegroundLayer( final int x, final int y )
{ {
@@ -236,21 +258,22 @@ public abstract class AEBaseGui extends GuiContainer
final List<Slot> slots = this.getInventorySlots(); final List<Slot> slots = this.getInventorySlots();
for( final Slot slot : slots ) for( final Slot slot : slots )
{ {
if( slot instanceof OptionalSlotFake ) if( slot instanceof IOptionalSlot )
{ {
final OptionalSlotFake fs = (OptionalSlotFake) slot; final IOptionalSlot optionalSlot = (IOptionalSlot) slot;
if( fs.renderDisabled() ) 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 ); 18 );
} }
else else
{ {
GlStateManager.color( 1.0F, 1.0F, 1.0F, 0.4F ); GlStateManager.color( 1.0F, 1.0F, 1.0F, 0.4F );
GlStateManager.enableBlend(); 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 ); 18 );
GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F ); GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F );
} }
@@ -715,6 +738,32 @@ public abstract class AEBaseGui extends GuiContainer
return; 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 else
{ {
try try
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<SlotFluidME> 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<String> 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<IAEFluidStack> 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<SlotFluidME> getMeFluidSlots()
{
return this.meFluidSlots;
}
@Override
protected boolean isPowered()
{
return this.repo.hasPower();
}
protected String getBackground()
{
return "guis/terminal.png";
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack> list = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
private final ArrayList<IAEFluidStack> view = new ArrayList<>();
private final IScrollSource src;
private final ISortSource sortSrc;
private int rowSize = 9;
private String searchString = "";
private IPartitionList<IAEFluidStack> 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<String> 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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<BakedQuad> quads;
public DummyFluidBakedModel( ImmutableList<BakedQuad> quads )
{
this.quads = quads;
}
@Override
public List<BakedQuad> 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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<ResourceLocation, TextureAtlasSprite> bakedTextureGetter;
public DummyFluidDispatcherBakedModel( IBakedModel baseModel, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
super( baseModel );
this.format = format;
this.bakedTextureGetter = bakedTextureGetter;
}
// This is never used. See the item override list below.
@Override
public List<BakedQuad> 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() ) );
}
};
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<ResourceLocation> getDependencies()
{
return Collections.emptyList();
}
@Override
public Collection<ResourceLocation> getTextures()
{
return Collections.emptyList();
}
@Override
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
IBakedModel bakedBaseModel = this.getBaseModel().bake( state, format, bakedTextureGetter );
return new DummyFluidDispatcherBakedModel( bakedBaseModel, format, bakedTextureGetter );
}
@Override
public IModelState getDefaultState()
{
return getBaseModel().getDefaultState();
}
}
@@ -33,10 +33,12 @@ import appeng.api.AEApi;
import appeng.api.config.CopyMode; import appeng.api.config.CopyMode;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.implementations.items.IStorageCell;
import appeng.api.storage.ICellWorkbenchItem; import appeng.api.storage.ICellWorkbenchItem;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; 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.api.storage.data.IItemList;
import appeng.container.guisync.GuiSync; import appeng.container.guisync.GuiSync;
import appeng.container.slot.OptionalSlotRestrictedInput; import appeng.container.slot.OptionalSlotRestrictedInput;
@@ -219,17 +221,20 @@ public class ContainerCellWorkbench extends ContainerUpgradeable
public void partition() public void partition()
{ {
final IItemHandler inv = this.getUpgradeable().getInventoryByName( "config" ); final IItemHandler inv = this.getUpgradeable().getInventoryByName( "config" );
final IMEInventory<IAEItemStack> cellInv = AEApi.instance().registries().cell().getCellInventory( final ItemStack is = this.getUpgradeable().getInventoryByName( "cell" ).getStackInSlot( 0 );
this.getUpgradeable().getInventoryByName( "cell" ).getStackInSlot( 0 ), null, final IStorageChannel channel = is.getItem() instanceof IStorageCell ? ( (IStorageCell) is.getItem() ).getChannel() : AEApi.instance()
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); .storage()
.getStorageChannel( IItemStorageChannel.class );
Iterator<IAEItemStack> i = new NullIterator<>(); final IMEInventory cellInv = AEApi.instance().registries().cell().getCellInventory( is, null, channel );
Iterator<IAEStack> i = new NullIterator<>();
if( cellInv != null ) if( cellInv != null )
{ {
final IItemList<IAEItemStack> list = cellInv final IItemList list = cellInv.getAvailableItems( channel.createList() );
.getAvailableItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() );
i = list.iterator(); i = list.iterator();
} }
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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 );
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack> cellInv = this.storageBus.getInternalHandler();
Iterator<IAEFluidStack> i = new NullIterator<>();
if( cellInv != null )
{
final IItemList<IAEFluidStack> 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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack>
{
private final IConfigManager clientCM;
private final IMEMonitor<IAEFluidStack> monitor;
private final IItemList<IAEFluidStack> 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<IAEFluidStack> monitor, Iterable<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack> 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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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();
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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;
}
}
@@ -25,7 +25,7 @@ import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
public class OptionalSlotFake extends SlotFake public class OptionalSlotFake extends SlotFake implements IOptionalSlot
{ {
private final int srcX; private final int srcX;
@@ -69,12 +69,8 @@ public class OptionalSlotFake extends SlotFake
return this.host.isSlotEnabled( this.groupNum ); return this.host.isSlotEnabled( this.groupNum );
} }
public boolean renderDisabled() @Override
{ public boolean isRenderDisabled()
return this.isRenderDisabled();
}
private boolean isRenderDisabled()
{ {
return this.renderDisabled; return this.renderDisabled;
} }
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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;
}
}
@@ -22,7 +22,7 @@ package appeng.container.slot;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
public class OptionalSlotNormal extends AppEngSlot public class OptionalSlotNormal extends AppEngSlot implements IOptionalSlot
{ {
private final int groupNum; private final int groupNum;
@@ -45,4 +45,16 @@ public class OptionalSlotNormal extends AppEngSlot
return this.host.isSlotEnabled( this.groupNum ); return this.host.isSlotEnabled( this.groupNum );
} }
@Override
public int getSourceX()
{
return this.xPos;
}
@Override
public int getSourceY()
{
return this.yPos;
}
} }
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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;
}
}
+18 -2
View File
@@ -91,7 +91,7 @@ import appeng.bootstrap.components.IRecipeRegistrationComponent;
import appeng.capabilities.Capabilities; import appeng.capabilities.Capabilities;
import appeng.core.features.AEFeature; import appeng.core.features.AEFeature;
import appeng.core.features.registries.P2PTunnelRegistry; 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.features.registries.cell.CreativeCellHandler;
import appeng.core.localization.GuiText; import appeng.core.localization.GuiText;
import appeng.core.localization.PlayerMessages; import appeng.core.localization.PlayerMessages;
@@ -99,6 +99,7 @@ import appeng.core.stats.AdvancementTriggers;
import appeng.core.stats.PartItemPredicate; import appeng.core.stats.PartItemPredicate;
import appeng.core.stats.Stats; import appeng.core.stats.Stats;
import appeng.core.worlddata.SpatialDimensionManager; import appeng.core.worlddata.SpatialDimensionManager;
import appeng.fluids.registries.BasicFluidCellHandler;
import appeng.hooks.TickHandler; import appeng.hooks.TickHandler;
import appeng.items.materials.ItemMaterial; import appeng.items.materials.ItemMaterial;
import appeng.items.parts.ItemFacade; import appeng.items.parts.ItemFacade;
@@ -286,8 +287,9 @@ final class Registration
gcr.registerGridCache( ISecurityGrid.class, SecurityCache.class ); gcr.registerGridCache( ISecurityGrid.class, SecurityCache.class );
gcr.registerGridCache( ICraftingGrid.class, CraftingGridCache.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 CreativeCellHandler() );
registries.cell().addCellHandler( new BasicFluidCellHandler() );
api.definitions().materials().matterBall().maybeStack( 1 ).ifPresent( ammoStack -> api.definitions().materials().matterBall().maybeStack( 1 ).ifPresent( ammoStack ->
{ {
@@ -423,6 +425,11 @@ final class Registration
Upgrades.CAPACITY.registerItem( parts.importBus(), 2 ); Upgrades.CAPACITY.registerItem( parts.importBus(), 2 );
Upgrades.SPEED.registerItem( parts.importBus(), 4 ); 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 // Export Bus
Upgrades.FUZZY.registerItem( parts.exportBus(), 1 ); Upgrades.FUZZY.registerItem( parts.exportBus(), 1 );
Upgrades.REDSTONE.registerItem( parts.exportBus(), 1 ); Upgrades.REDSTONE.registerItem( parts.exportBus(), 1 );
@@ -430,6 +437,11 @@ final class Registration
Upgrades.SPEED.registerItem( parts.exportBus(), 4 ); Upgrades.SPEED.registerItem( parts.exportBus(), 4 );
Upgrades.CRAFTING.registerItem( parts.exportBus(), 1 ); 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 // Storage Cells
Upgrades.FUZZY.registerItem( items.cell1k(), 1 ); Upgrades.FUZZY.registerItem( items.cell1k(), 1 );
Upgrades.INVERTER.registerItem( items.cell1k(), 1 ); Upgrades.INVERTER.registerItem( items.cell1k(), 1 );
@@ -454,6 +466,10 @@ final class Registration
Upgrades.INVERTER.registerItem( parts.storageBus(), 1 ); Upgrades.INVERTER.registerItem( parts.storageBus(), 1 );
Upgrades.CAPACITY.registerItem( parts.storageBus(), 5 ); Upgrades.CAPACITY.registerItem( parts.storageBus(), 5 );
// Storage Bus Fluids
Upgrades.INVERTER.registerItem( parts.fluidStorageBus(), 1 );
Upgrades.CAPACITY.registerItem( parts.fluidStorageBus(), 5 );
// Formation Plane // Formation Plane
Upgrades.FUZZY.registerItem( parts.formationPlane(), 1 ); Upgrades.FUZZY.registerItem( parts.formationPlane(), 1 );
Upgrades.INVERTER.registerItem( parts.formationPlane(), 1 ); Upgrades.INVERTER.registerItem( parts.formationPlane(), 1 );
@@ -163,7 +163,7 @@ public class ApiStorage implements IStorageHelper
@Override @Override
public int transferFactor() public int transferFactor()
{ {
return 1000; return 125;
} }
@Override @Override
@@ -30,6 +30,9 @@ import appeng.debug.ToolDebugCard;
import appeng.debug.ToolEraser; import appeng.debug.ToolEraser;
import appeng.debug.ToolMeteoritePlacer; import appeng.debug.ToolMeteoritePlacer;
import appeng.debug.ToolReplicatorCard; 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.DispenserBlockTool;
import appeng.hooks.DispenserMatterCannon; import appeng.hooks.DispenserMatterCannon;
import appeng.items.materials.MaterialType; import appeng.items.materials.MaterialType;
@@ -40,7 +43,7 @@ import appeng.items.misc.ItemPaintBall;
import appeng.items.misc.ItemPaintBallRendering; import appeng.items.misc.ItemPaintBallRendering;
import appeng.items.parts.FacadeRendering; import appeng.items.parts.FacadeRendering;
import appeng.items.parts.ItemFacade; import appeng.items.parts.ItemFacade;
import appeng.items.storage.ItemBasicStorageCell; import appeng.items.storage.BasicItemStorageCell;
import appeng.items.storage.ItemCreativeStorageCell; import appeng.items.storage.ItemCreativeStorageCell;
import appeng.items.storage.ItemSpatialStorageCell; import appeng.items.storage.ItemSpatialStorageCell;
import appeng.items.storage.ItemViewCell; import appeng.items.storage.ItemViewCell;
@@ -102,6 +105,11 @@ public final class ApiItems implements IItems
private final IItemDefinition cell16k; private final IItemDefinition cell16k;
private final IItemDefinition cell64k; 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 spatialCell2;
private final IItemDefinition spatialCell16; private final IItemDefinition spatialCell16;
private final IItemDefinition spatialCell128; private final IItemDefinition spatialCell128;
@@ -123,6 +131,8 @@ public final class ApiItems implements IItems
private final IItemDefinition toolDebugCard; private final IItemDefinition toolDebugCard;
private final IItemDefinition toolReplicatorCard; private final IItemDefinition toolReplicatorCard;
private final IItemDefinition dummyFluidItem;
public ApiItems( FeatureFactory registry ) public ApiItems( FeatureFactory registry )
{ {
FeatureFactory certusTools = registry.features( AEFeature.CERTUS_QUARTZ_TOOLS ); 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(); this.viewCell = registry.item( "view_cell", ItemViewCell::new ).features( AEFeature.VIEW_CELL ).build();
FeatureFactory storageCells = registry.features( AEFeature.STORAGE_CELLS ); FeatureFactory storageCells = registry.features( AEFeature.STORAGE_CELLS );
this.cell1k = storageCells.item( "storage_cell_1k", () -> new ItemBasicStorageCell( MaterialType.CELL1K_PART, 1 ) ).build(); this.cell1k = storageCells.item( "storage_cell_1k", () -> new BasicItemStorageCell( MaterialType.CELL1K_PART, 1 ) ).build();
this.cell4k = storageCells.item( "storage_cell_4k", () -> new ItemBasicStorageCell( MaterialType.CELL4K_PART, 4 ) ).build(); this.cell4k = storageCells.item( "storage_cell_4k", () -> new BasicItemStorageCell( MaterialType.CELL4K_PART, 4 ) ).build();
this.cell16k = storageCells.item( "storage_cell_16k", () -> new ItemBasicStorageCell( MaterialType.CELL16K_PART, 16 ) ).build(); this.cell16k = storageCells.item( "storage_cell_16k", () -> new BasicItemStorageCell( MaterialType.CELL16K_PART, 16 ) ).build();
this.cell64k = storageCells.item( "storage_cell_64k", () -> new ItemBasicStorageCell( MaterialType.CELL64K_PART, 64 ) ).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 ); FeatureFactory spatialCells = registry.features( AEFeature.SPATIAL_IO );
this.spatialCell2 = spatialCells.item( "spatial_storage_cell_2_cubed", () -> new ItemSpatialStorageCell( 2 ) ).build(); 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.toolMeteoritePlacer = debugTools.item( "debug_meteorite_placer", ToolMeteoritePlacer::new ).build();
this.toolDebugCard = debugTools.item( "debug_card", ToolDebugCard::new ).build(); this.toolDebugCard = debugTools.item( "debug_card", ToolDebugCard::new ).build();
this.toolReplicatorCard = debugTools.item( "debug_replicator_card", ToolReplicatorCard::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 @Override
@@ -406,6 +423,30 @@ public final class ApiItems implements IItems
return this.cell64k; 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 @Override
public IItemDefinition spatialCell2() public IItemDefinition spatialCell2()
{ {
@@ -484,4 +525,9 @@ public final class ApiItems implements IItems
{ {
return this.toolReplicatorCard; return this.toolReplicatorCard;
} }
public IItemDefinition dummyFluidItem()
{
return this.dummyFluidItem;
}
} }
@@ -111,6 +111,11 @@ public final class ApiMaterials implements IMaterials
private final IItemDefinition qESingularity; private final IItemDefinition qESingularity;
private final IItemDefinition blankPattern; private final IItemDefinition blankPattern;
private final IItemDefinition fluidCell1kPart;
private final IItemDefinition fluidCell4kPart;
private final IItemDefinition fluidCell16kPart;
private final IItemDefinition fluidCell64kPart;
public ApiMaterials( FeatureFactory registry ) public ApiMaterials( FeatureFactory registry )
{ {
final ItemMaterial materials = new ItemMaterial(); final ItemMaterial materials = new ItemMaterial();
@@ -210,6 +215,11 @@ public final class ApiMaterials implements IMaterials
this.qESingularity = new DamagedItemDefinition( "material.singularity.entangled.quantum", materials this.qESingularity = new DamagedItemDefinition( "material.singularity.entangled.quantum", materials
.createMaterial( MaterialType.QUANTUM_ENTANGLED_SINGULARITY ) ); .createMaterial( MaterialType.QUANTUM_ENTANGLED_SINGULARITY ) );
this.blankPattern = new DamagedItemDefinition( "material.pattern.blank", materials.createMaterial( MaterialType.BLANK_PATTERN ) ); 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 @Override
@@ -529,4 +539,28 @@ public final class ApiMaterials implements IMaterials
{ {
return this.blankPattern; 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;
}
} }
@@ -77,6 +77,10 @@ public final class ApiParts implements IParts
private final IItemDefinition terminal; private final IItemDefinition terminal;
private final IItemDefinition storageMonitor; private final IItemDefinition storageMonitor;
private final IItemDefinition conversionMonitor; 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 ) 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.iface = new DamagedItemDefinition( "part.interface", itemPart.createPart( PartType.INTERFACE ) );
this.levelEmitter = new DamagedItemDefinition( "part.level_emitter", itemPart.createPart( PartType.LEVEL_EMITTER ) ); 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.annihilationPlane = new DamagedItemDefinition( "part.plane.annihilation", itemPart.createPart( PartType.ANNIHILATION_PLANE ) );
this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity", itemPart this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity",
.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) ); itemPart.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) );
this.formationPlane = new DamagedItemDefinition( "part.plane.formation", itemPart.createPart( PartType.FORMATION_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.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 ) ); 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.terminal = new DamagedItemDefinition( "part.terminal", itemPart.createPart( PartType.TERMINAL ) );
this.storageMonitor = new DamagedItemDefinition( "part.monitor.storage", itemPart.createPart( PartType.STORAGE_MONITOR ) ); 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.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 ) private static AEColoredItemDefinition constructColoredDefinition( final ItemPart target, final PartType type )
@@ -380,4 +388,28 @@ public final class ApiParts implements IParts
{ {
return this.conversionMonitor; 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;
}
} }
@@ -1,6 +1,6 @@
/* /*
* This file is part of Applied Energistics 2. * 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 * 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 * 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 ), INTERFACE( "Interface", Constants.CATEGORY_NETWORK_BUSES ),
LEVEL_EMITTER( "LevelEmitter", 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 ), CRAFTING_TERMINAL( "CraftingTerminal", Constants.CATEGORY_NETWORK_BUSES ),
TERMINAL( "Terminal", Constants.CATEGORY_NETWORK_BUSES ), TERMINAL( "Terminal", Constants.CATEGORY_NETWORK_BUSES ),
STORAGE_MONITOR( "StorageMonitor", 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 ), ANNIHILATION_PLANE( "AnnihilationPlane", Constants.CATEGORY_NETWORK_BUSES ),
IDENTITY_ANNIHILATION_PLANE( "IdentityAnnihilationPlane", Constants.CATEGORY_NETWORK_BUSES ), IDENTITY_ANNIHILATION_PLANE( "IdentityAnnihilationPlane", Constants.CATEGORY_NETWORK_BUSES ),
IMPORT_BUS( "ImportBus", 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 ), EXPORT_BUS( "ExportBus", Constants.CATEGORY_NETWORK_BUSES ),
FLUID_EXPORT_BUS( "FluidExportBus", Constants.CATEGORY_NETWORK_BUSES ),
STORAGE_BUS( "StorageBus", 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 ), PART_CONVERSION_MONITOR( "PartConversionMonitor", Constants.CATEGORY_NETWORK_BUSES ),
TOGGLE_BUS( "ToggleBus", Constants.CATEGORY_NETWORK_BUSES ), TOGGLE_BUS( "ToggleBus", Constants.CATEGORY_NETWORK_BUSES ),
PANELS( "Panels", Constants.CATEGORY_NETWORK_BUSES ), PANELS( "Panels", Constants.CATEGORY_NETWORK_BUSES ),
@@ -36,18 +36,18 @@ import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IAEStack;
import appeng.api.util.AEPartLocation; import appeng.api.util.AEPartLocation;
import appeng.core.sync.GuiBridge; import appeng.core.sync.GuiBridge;
import appeng.me.storage.CellInventory; import appeng.me.storage.ItemCellInventory;
import appeng.me.storage.CellInventoryHandler; import appeng.me.storage.ItemCellInventoryHandler;
import appeng.util.Platform; import appeng.util.Platform;
public final class BasicCellHandler implements ICellHandler public class BasicItemCellHandler implements ICellHandler
{ {
@Override @Override
public boolean isCell( final ItemStack is ) public boolean isCell( final ItemStack is )
{ {
return CellInventory.isCell( is ); return ItemCellInventory.isCell( is );
} }
@Override @Override
@@ -55,23 +55,27 @@ public final class BasicCellHandler implements ICellHandler
{ {
if( channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) if( channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{ {
return CellInventory.getCell( is, container ); return ItemCellInventory.getCell( is, container );
} }
return null; return null;
} }
@Override @Override
public void openChestGui( final EntityPlayer player, final IChestOrDrive chest, final ICellHandler cellHandler, final IMEInventoryHandler inv, final ItemStack is, final IStorageChannel chan ) 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 @Override
public int getStatusForCell( final ItemStack is, final IMEInventory handler ) 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 ci.getStatusForCell();
} }
return 0; return 0;
@@ -54,7 +54,7 @@ public class CellRegistry implements ICellRegistry
this.handlers.add( handler ); this.handlers.add( handler );
// Verify that the first entry is always our own 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 @Override
@@ -129,6 +129,9 @@ public enum ButtonToolTips
ReportInaccessibleItems, ReportInaccessibleItems,
ReportInaccessibleItemsYes, ReportInaccessibleItemsYes,
ReportInaccessibleItemsNo, ReportInaccessibleItemsNo,
ReportInaccessibleFluids,
ReportInaccessibleFluidsYes,
ReportInaccessibleFluidsNo,
BlockPlacement, BlockPlacement,
BlockPlacementYes, BlockPlacementYes,
@@ -44,12 +44,15 @@ public enum GuiText
StoredItems, StoredItems,
Patterns, Patterns,
ImportBus, ImportBus,
ImportBusFluids,
ExportBus, ExportBus,
ExportBusFluids,
CellWorkbench, CellWorkbench,
NetworkDetails, NetworkDetails,
StorageCells, StorageCells,
IOBuses, IOBuses,
IOBusesFluids,
IOPort, IOPort,
BytesUsed, BytesUsed,
@@ -64,6 +67,7 @@ public enum GuiText
EnergyDrain, EnergyDrain,
StorageBus, StorageBus,
StorageBusFluids,
Priority, Priority,
Security, Security,
Encoded, Encoded,
@@ -29,8 +29,12 @@ public enum TickRates
ImportBus( 5, 40 ), ImportBus( 5, 40 ),
FluidImportBus( 5, 40 ),
ExportBus( 5, 60 ), ExportBus( 5, 60 ),
FluidExportBus( 5, 60 ),
AnnihilationPlane( 2, 120 ), AnnihilationPlane( 2, 120 ),
METunnel( 5, 20 ), METunnel( 5, 20 ),
@@ -45,6 +49,8 @@ public enum TickRates
StorageBus( 5, 60 ), StorageBus( 5, 60 ),
FluidStorageBus( 5, 60 ),
ItemTunnel( 5, 60 ), ItemTunnel( 5, 60 ),
LightTunnel( 5, 60 ), LightTunnel( 5, 60 ),
@@ -36,6 +36,7 @@ import appeng.core.sync.packets.PacketCraftRequest;
import appeng.core.sync.packets.PacketInventoryAction; import appeng.core.sync.packets.PacketInventoryAction;
import appeng.core.sync.packets.PacketJEIRecipe; import appeng.core.sync.packets.PacketJEIRecipe;
import appeng.core.sync.packets.PacketLightning; import appeng.core.sync.packets.PacketLightning;
import appeng.core.sync.packets.PacketMEFluidInventoryUpdate;
import appeng.core.sync.packets.PacketMEInventoryUpdate; import appeng.core.sync.packets.PacketMEInventoryUpdate;
import appeng.core.sync.packets.PacketMatterCannon; import appeng.core.sync.packets.PacketMatterCannon;
import appeng.core.sync.packets.PacketMockExplosion; 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.PacketProgressBar;
import appeng.core.sync.packets.PacketSwapSlots; import appeng.core.sync.packets.PacketSwapSlots;
import appeng.core.sync.packets.PacketSwitchGuis; import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketTargetFluidStack;
import appeng.core.sync.packets.PacketTargetItemStack; import appeng.core.sync.packets.PacketTargetItemStack;
import appeng.core.sync.packets.PacketTransitionEffect; import appeng.core.sync.packets.PacketTransitionEffect;
import appeng.core.sync.packets.PacketValueConfig; import appeng.core.sync.packets.PacketValueConfig;
@@ -64,6 +66,8 @@ public class AppEngPacketHandlerBase
PACKET_ME_INVENTORY_UPDATE( PacketMEInventoryUpdate.class ), PACKET_ME_INVENTORY_UPDATE( PacketMEInventoryUpdate.class ),
PACKET_ME_FLUID_INVENTORY_UPDATE( PacketMEFluidInventoryUpdate.class ),
PACKET_CONFIG_BUTTON( PacketConfigButton.class ), PACKET_CONFIG_BUTTON( PacketConfigButton.class ),
PACKET_PART_PLACEMENT( PacketPartPlacement.class ), PACKET_PART_PLACEMENT( PacketPartPlacement.class ),
@@ -92,6 +96,8 @@ public class AppEngPacketHandlerBase
PACKET_TARGET_ITEM( PacketTargetItemStack.class ), PACKET_TARGET_ITEM( PacketTargetItemStack.class ),
PACKET_TARGET_FLUID( PacketTargetFluidStack.class ),
PACKET_CRAFTING_REQUEST( PacketCraftRequest.class ), PACKET_CRAFTING_REQUEST( PacketCraftRequest.class ),
PACKET_ASSEMBLER_ANIMATION( PacketAssemblerAnimation.class ), PACKET_ASSEMBLER_ANIMATION( PacketAssemblerAnimation.class ),
@@ -62,6 +62,9 @@ import appeng.container.implementations.ContainerCraftingCPU;
import appeng.container.implementations.ContainerCraftingStatus; import appeng.container.implementations.ContainerCraftingStatus;
import appeng.container.implementations.ContainerCraftingTerm; import appeng.container.implementations.ContainerCraftingTerm;
import appeng.container.implementations.ContainerDrive; 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.ContainerFormationPlane;
import appeng.container.implementations.ContainerGrinder; import appeng.container.implementations.ContainerGrinder;
import appeng.container.implementations.ContainerIOPort; import appeng.container.implementations.ContainerIOPort;
@@ -86,6 +89,8 @@ import appeng.container.implementations.ContainerUpgradeable;
import appeng.container.implementations.ContainerVibrationChamber; import appeng.container.implementations.ContainerVibrationChamber;
import appeng.container.implementations.ContainerWireless; import appeng.container.implementations.ContainerWireless;
import appeng.container.implementations.ContainerWirelessTerm; import appeng.container.implementations.ContainerWirelessTerm;
import appeng.fluids.parts.PartFluidStorageBus;
import appeng.fluids.parts.PartSharedFluidBus;
import appeng.helpers.IInterfaceHost; import appeng.helpers.IInterfaceHost;
import appeng.helpers.IPriorityHost; import appeng.helpers.IPriorityHost;
import appeng.helpers.WirelessTerminalGuiObject; import appeng.helpers.WirelessTerminalGuiObject;
@@ -94,6 +99,7 @@ import appeng.parts.automation.PartFormationPlane;
import appeng.parts.automation.PartLevelEmitter; import appeng.parts.automation.PartLevelEmitter;
import appeng.parts.misc.PartStorageBus; import appeng.parts.misc.PartStorageBus;
import appeng.parts.reporting.PartCraftingTerminal; import appeng.parts.reporting.PartCraftingTerminal;
import appeng.parts.reporting.PartFluidTerminal;
import appeng.parts.reporting.PartInterfaceTerminal; import appeng.parts.reporting.PartInterfaceTerminal;
import appeng.parts.reporting.PartPatternTerminal; import appeng.parts.reporting.PartPatternTerminal;
import appeng.tile.crafting.TileCraftingTile; 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( 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_IOPORT( ContainerIOPort.class, TileIOPort.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_STORAGEBUS( ContainerStorageBus.class, PartStorageBus.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_FORMATION_PLANE( ContainerFormationPlane.class, PartFormationPlane.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_PRIORITY( ContainerPriority.class, IPriorityHost.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_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 // extends (Container/Gui) + Bus
GUI_LEVEL_EMITTER( ContainerLevelEmitter.class, PartLevelEmitter.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), GUI_LEVEL_EMITTER( ContainerLevelEmitter.class, PartLevelEmitter.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack> 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;
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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 );
}
}
}
@@ -44,6 +44,7 @@ import appeng.container.implementations.ContainerCellWorkbench;
import appeng.container.implementations.ContainerCraftConfirm; import appeng.container.implementations.ContainerCraftConfirm;
import appeng.container.implementations.ContainerCraftingCPU; import appeng.container.implementations.ContainerCraftingCPU;
import appeng.container.implementations.ContainerCraftingStatus; import appeng.container.implementations.ContainerCraftingStatus;
import appeng.container.implementations.ContainerFluidStorageBus;
import appeng.container.implementations.ContainerLevelEmitter; import appeng.container.implementations.ContainerLevelEmitter;
import appeng.container.implementations.ContainerNetworkTool; import appeng.container.implementations.ContainerNetworkTool;
import appeng.container.implementations.ContainerPatternTerm; import appeng.container.implementations.ContainerPatternTerm;
@@ -179,18 +180,31 @@ public class PacketValueConfig extends AppEngPacket
cpt.getPatternTerminal().setSubstitution( this.Value.equals( "1" ) ); 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.Name.equals( "StorageBus.Action" ) )
{ {
if( this.Value.equals( "Partition" ) ) 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" ) ) else if( this.Value.equals( "Clear" ) )
{ {
ccw.clear(); if( c instanceof ContainerStorageBus )
{
( (ContainerStorageBus) c ).clear();
}
else if( c instanceof ContainerFluidStorageBus )
{
( (ContainerFluidStorageBus) c ).clear();
}
} }
} }
} }
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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 );
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack>
{
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<IAEFluidStack> 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 );
}
} );
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<ItemStack> itemStacks )
{
//Don't show this item in CreativeTabs
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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() );
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack>, IBaseMonitor<IAEFluidStack>, ITickingMonitor
{
private final Map<IMEMonitorHandlerReceiver<IAEFluidStack>, 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<IAEFluidStack> changes = this.cache.update();
if( !changes.isEmpty() )
{
this.postDifference( changes );
return TickRateModulation.URGENT;
}
else
{
return TickRateModulation.SLOWER;
}
}
@Override
public IItemList<IAEFluidStack> getAvailableItems( IItemList<IAEFluidStack> out )
{
return this.cache.getAvailableItems( out );
}
@Override
public IStorageChannel<IAEFluidStack> getChannel()
{
return AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class );
}
@Override
public void setActionSource( IActionSource source )
{
this.source = source;
}
@Override
public void addListener( final IMEMonitorHandlerReceiver<IAEFluidStack> l, final Object verificationToken )
{
this.listeners.put( l, verificationToken );
}
@Override
public void removeListener( final IMEMonitorHandlerReceiver<IAEFluidStack> l )
{
this.listeners.remove( l );
}
private void postDifference( Iterable<IAEFluidStack> a )
{
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object>> i = this.listeners.entrySet().iterator();
while( i.hasNext() )
{
final Map.Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEFluidStack> 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<IAEFluidStack> update()
{
final List<IAEFluidStack> 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<IAEFluidStack> getAvailableItems( IItemList<IAEFluidStack> out )
{
Arrays.stream( this.cachedAeStacks ).forEach( out::add );
return out;
}
private void handlePossibleSlotChanges( int slot, IAEFluidStack oldAeFS, FluidStack newFS, List<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack> 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] );
}
}
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack> 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;
}
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack> 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;
}
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack>
{
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<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack> in = this.getInternalHandler();
IItemList<IAEFluidStack> 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<IAEFluidStack> out = this.getInternalHandler();
if( in != out )
{
IItemList<IAEFluidStack> 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<IAEFluidStack> monitor, final Iterable<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack> 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<IAEFluidStack>( priorityList, (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ) ) );
}
else
{
this.handler.setPartitionList( new PrecisePriorityList<IAEFluidStack>( priorityList ) );
}
if( inv instanceof IBaseMonitor )
{
( (IBaseMonitor<IAEFluidStack>) 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<IMEInventoryHandler> getCellArray( final IStorageChannel channel )
{
if( channel == this.getStorageChannel() )
{
final IMEInventoryHandler<IAEFluidStack> 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;
}
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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();
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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 <T extends IAEStack<T>> IMEInventoryHandler<T> getCellInventory( final ItemStack is, final ISaveProvider container, final IStorageChannel<T> 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();
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack>
{
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;
}
}
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack>
{
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;
}
}
@@ -32,6 +32,10 @@ public enum InventoryAction
CRAFT_ITEM, CRAFT_ITEM,
CRAFT_SHIFT, CRAFT_SHIFT,
// fluid term
FILL_ITEM,
EMPTY_ITEM,
// extra... // extra...
MOVE_REGION, MOVE_REGION,
PICKUP_SINGLE, PICKUP_SINGLE,
@@ -39,7 +39,7 @@ import appeng.api.storage.data.IAEStack;
import appeng.api.util.IConfigManager; import appeng.api.util.IConfigManager;
import appeng.container.interfaces.IInventorySlotAware; import appeng.container.interfaces.IInventorySlotAware;
import appeng.me.helpers.MEMonitorHandler; import appeng.me.helpers.MEMonitorHandler;
import appeng.me.storage.CellInventory; import appeng.me.storage.ItemCellInventory;
import appeng.util.ConfigManager; import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost; import appeng.util.IConfigManagerHost;
import appeng.util.Platform; import appeng.util.Platform;
@@ -54,7 +54,7 @@ public class PortableCellViewer extends MEMonitorHandler<IAEItemStack> implement
public PortableCellViewer( final ItemStack is, final int slot ) public PortableCellViewer( final ItemStack is, final int slot )
{ {
super( CellInventory.getCell( is, null ) ); super( ItemCellInventory.getCell( is, null ) );
this.ips = (IAEItemPowerStorage) is.getItem(); this.ips = (IAEItemPowerStorage) is.getItem();
this.target = is; this.target = is;
this.inventorySlot = slot; this.inventorySlot = slot;
@@ -114,7 +114,12 @@ public enum MaterialType
QUANTUM_ENTANGLED_SINGULARITY( 48, "material_quantum_entangled_singularity", EnumSet.of( AEFeature.QUANTUM_NETWORK_BRIDGE ), EntitySingularity.class ), 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 ) ), 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<AEFeature> features; private final Set<AEFeature> features;
private final ModelResourceLocation model; private final ModelResourceLocation model;
+21 -1
View File
@@ -278,7 +278,9 @@ public final class ItemPart extends AEBaseItem implements IPartItem, IItemGroup
public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is ) public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is )
{ {
boolean importBus = false; boolean importBus = false;
boolean importBusFluids = false;
boolean exportBus = false; boolean exportBus = false;
boolean exportBusFluids = false;
boolean group = false; boolean group = false;
final PartType u = this.getTypeByStack( is ); final PartType u = this.getTypeByStack( is );
@@ -297,6 +299,13 @@ public final class ItemPart extends AEBaseItem implements IPartItem, IItemGroup
group = true; group = true;
} }
break; break;
case FLUID_IMPORT_BUS:
importBusFluids = true;
if( u == pt )
{
group = true;
}
break;
case EXPORT_BUS: case EXPORT_BUS:
exportBus = true; exportBus = true;
if( u == pt ) if( u == pt )
@@ -304,15 +313,26 @@ public final class ItemPart extends AEBaseItem implements IPartItem, IItemGroup
group = true; group = true;
} }
break; break;
case FLUID_EXPORT_BUS:
exportBusFluids = true;
if( u == pt )
{
group = true;
}
break;
default: default:
} }
} }
} }
if( group && importBus && exportBus ) if( group && importBus && exportBus && ( u == PartType.IMPORT_BUS || u == PartType.EXPORT_BUS ) )
{ {
return GuiText.IOBuses.getUnlocalized(); return GuiText.IOBuses.getUnlocalized();
} }
if( group && importBusFluids && exportBusFluids && ( u == PartType.FLUID_IMPORT_BUS || u == PartType.FLUID_EXPORT_BUS ) )
{
return GuiText.IOBusesFluids.getUnlocalized();
}
return null; return null;
} }
+12 -1
View File
@@ -41,6 +41,9 @@ import appeng.core.AEConfig;
import appeng.core.AppEng; import appeng.core.AppEng;
import appeng.core.features.AEFeature; import appeng.core.features.AEFeature;
import appeng.core.localization.GuiText; 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.IntegrationRegistry;
import appeng.integration.IntegrationType; import appeng.integration.IntegrationType;
import appeng.parts.automation.PartAnnihilationPlane; import appeng.parts.automation.PartAnnihilationPlane;
@@ -70,6 +73,7 @@ import appeng.parts.p2p.PartP2PTunnelME;
import appeng.parts.reporting.PartConversionMonitor; import appeng.parts.reporting.PartConversionMonitor;
import appeng.parts.reporting.PartCraftingTerminal; import appeng.parts.reporting.PartCraftingTerminal;
import appeng.parts.reporting.PartDarkPanel; import appeng.parts.reporting.PartDarkPanel;
import appeng.parts.reporting.PartFluidTerminal;
import appeng.parts.reporting.PartInterfaceTerminal; import appeng.parts.reporting.PartInterfaceTerminal;
import appeng.parts.reporting.PartPanel; import appeng.parts.reporting.PartPanel;
import appeng.parts.reporting.PartPatternTerminal; 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 ), 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 ), 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 ), 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 ), 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 ), 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 ANNIHILATION_PLANE( 300, "annihilation_plane", EnumSet.of( AEFeature.ANNIHILATION_PLANE ), EnumSet
@@ -293,7 +302,9 @@ public enum PartType
// IntegrationType.OpenComputers ), PartP2POpenComputers.class, GuiText.OCTunnel ), // IntegrationType.OpenComputers ), PartP2POpenComputers.class, GuiText.OCTunnel ),
INTERFACE_TERMINAL( 480, "interface_terminal", EnumSet.of( AEFeature.INTERFACE_TERMINAL ), EnumSet 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 int baseDamage;
private final Set<AEFeature> features; private final Set<AEFeature> features;
@@ -1,6 +1,6 @@
/* /*
* This file is part of Applied Energistics 2. * 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 * 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 * 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.ICellInventory;
import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.ICellInventoryHandler;
import appeng.api.storage.IMEInventoryHandler; import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.core.AEConfig; import appeng.core.AEConfig;
import appeng.core.features.AEFeature; import appeng.core.features.AEFeature;
@@ -60,49 +60,28 @@ import appeng.util.InventoryAdaptor;
import appeng.util.Platform; 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<T extends IAEStack<T>> extends AEBaseItem implements IStorageCell<T>, IItemGroup
{ {
private final MaterialType component; protected final MaterialType component;
private final int totalBytes; protected final int totalBytes;
private final int perType;
private final double idleDrain;
public ItemBasicStorageCell( final MaterialType whichCell, final int kilobytes ) public AbstractStorageCell( final MaterialType whichCell, final int kilobytes )
{ {
this.setMaxStackSize( 1 ); this.setMaxStackSize( 1 );
this.totalBytes = kilobytes * 1024; this.totalBytes = kilobytes * 1024;
this.component = whichCell; 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 ) @SideOnly( Side.CLIENT )
@Override @Override
public void addCheckedInformation( final ItemStack stack, final World world, final List<String> lines, final ITooltipFlag advancedTooltips ) public void addCheckedInformation( final ItemStack stack, final World world, final List<String> lines, final ITooltipFlag advancedTooltips )
{ {
final IMEInventoryHandler<?> inventory = AEApi.instance().registries().cell().getCellInventory( stack, null, final IMEInventoryHandler<?> inventory = AEApi.instance().registries().cell().getCellInventory( stack, null, getChannel() );
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
if( inventory instanceof ICellInventoryHandler ) if( inventory instanceof ICellInventoryHandler )
{ {
@@ -111,11 +90,9 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe
if( cellInventory != null ) if( cellInventory != null )
{ {
lines.add( lines.add( cellInventory.getUsedBytes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalBytes() + ' ' + GuiText.BytesUsed.getLocal() );
cellInventory.getUsedBytes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalBytes() + ' ' + GuiText.BytesUsed.getLocal() );
lines.add( cellInventory.getStoredItemTypes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalItemTypes() + ' ' + GuiText.Types lines.add( cellInventory.getStoredItemTypes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalItemTypes() + ' ' + GuiText.Types.getLocal() );
.getLocal() );
if( handler.isPreformatted() ) if( handler.isPreformatted() )
{ {
@@ -140,12 +117,6 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe
return this.totalBytes; return this.totalBytes;
} }
@Override
public int getBytesPerType( final ItemStack cellItem )
{
return this.perType;
}
@Override @Override
public int getTotalTypes( final ItemStack cellItem ) public int getTotalTypes( final ItemStack cellItem )
{ {
@@ -153,7 +124,7 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe
} }
@Override @Override
public boolean isBlackListed( final ItemStack cellItem, final IAEItemStack requestedAddition ) public boolean isBlackListed( final ItemStack cellItem, final T requestedAddition )
{ {
return false; return false;
} }
@@ -170,12 +141,6 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe
return true; return true;
} }
@Override
public double getIdleDrain()
{
return this.idleDrain;
}
@Override @Override
public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is ) public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is )
{ {
@@ -237,13 +202,11 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe
} }
final InventoryPlayer playerInventory = player.inventory; final InventoryPlayer playerInventory = player.inventory;
final IMEInventoryHandler inv = AEApi.instance().registries().cell().getCellInventory( stack, null, final IMEInventoryHandler inv = AEApi.instance().registries().cell().getCellInventory( stack, null, getChannel() );
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
if( inv != null && playerInventory.getCurrentItem() == stack ) if( inv != null && playerInventory.getCurrentItem() == stack )
{ {
final InventoryAdaptor ia = InventoryAdaptor.getAdaptor( player ); final InventoryAdaptor ia = InventoryAdaptor.getAdaptor( player );
final IItemList<IAEItemStack> list = inv final IItemList<IAEItemStack> list = inv.getAvailableItems( getChannel().createList() );
.getAvailableItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() );
if( list.isEmpty() && ia != null ) if( list.isEmpty() && ia != null )
{ {
playerInventory.setInventorySlotContents( playerInventory.currentItem, ItemStack.EMPTY ); playerInventory.setInventorySlotContents( playerInventory.currentItem, ItemStack.EMPTY );
@@ -268,14 +231,7 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe
} }
// drop empty storage cell case // drop empty storage cell case
AEApi.instance().definitions().materials().emptyStorageCell().maybeStack( 1 ).ifPresent( is -> dropEmptyStorageCellCase( ia, player );
{
final ItemStack extraA = ia.addItems( is );
if( !extraA.isEmpty() )
{
player.dropItem( extraA, false );
}
} );
if( player.inventoryContainer != null ) if( player.inventoryContainer != null )
{ {
@@ -289,6 +245,8 @@ public final class ItemBasicStorageCell extends AEBaseItem implements IStorageCe
return false; return false;
} }
protected abstract void dropEmptyStorageCellCase( final InventoryAdaptor ia, final EntityPlayer player );
@Override @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 ) 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 @Override
public ItemStack getContainerItem( final ItemStack itemStack ) public ItemStack getContainerItem( final ItemStack itemStack )
{ {
return AEApi.instance() return AEApi.instance().definitions().materials().emptyStorageCell().maybeStack( 1 ).orElseThrow( () -> new MissingDefinitionException( "Tried to use empty storage cells while basic storage cells are defined." ) );
.definitions()
.materials()
.emptyStorageCell()
.maybeStack( 1 )
.orElseThrow( () -> new MissingDefinitionException( "Tried to use empty storage cells while basic storage cells are defined." ) );
} }
@Override @Override
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEItemStack>
{
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<IAEItemStack> 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 );
}
} );
}
}
@@ -61,6 +61,7 @@ import appeng.api.implementations.tiles.IColorableTile;
import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventory;
import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.ICellInventoryHandler;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
@@ -77,13 +78,13 @@ import appeng.items.contents.CellUpgrades;
import appeng.items.misc.ItemPaintBall; import appeng.items.misc.ItemPaintBall;
import appeng.items.tools.powered.powersink.AEBasePoweredItem; import appeng.items.tools.powered.powersink.AEBasePoweredItem;
import appeng.me.helpers.BaseActionSource; import appeng.me.helpers.BaseActionSource;
import appeng.me.storage.CellInventoryHandler; import appeng.me.storage.ItemCellInventoryHandler;
import appeng.tile.misc.TilePaint; import appeng.tile.misc.TilePaint;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCell, IItemGroup, IBlockTool, IMouseWheelItem public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCell<IAEItemStack>, IItemGroup, IBlockTool, IMouseWheelItem
{ {
private static final Map<Integer, AEColor> ORE_TO_COLOR = new HashMap<>(); private static final Map<Integer, AEColor> ORE_TO_COLOR = new HashMap<>();
@@ -434,7 +435,7 @@ public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCe
final IMEInventory<IAEItemStack> cdi = AEApi.instance().registries().cell().getCellInventory( stack, null, final IMEInventory<IAEItemStack> cdi = AEApi.instance().registries().cell().getCellInventory( stack, null,
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
if( cdi instanceof CellInventoryHandler ) if( cdi instanceof ItemCellInventoryHandler )
{ {
final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv(); final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv();
if( cd != null ) if( cd != null )
@@ -506,6 +507,12 @@ public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCe
return 0.5; return 0.5;
} }
@Override
public IStorageChannel<IAEItemStack> getChannel()
{
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
}
@Override @Override
public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is ) public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is )
{ {
@@ -55,6 +55,7 @@ import appeng.api.implementations.items.IStorageCell;
import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventory;
import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.ICellInventoryHandler;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IAEStack;
@@ -76,13 +77,13 @@ import appeng.items.contents.CellUpgrades;
import appeng.items.misc.ItemPaintBall; import appeng.items.misc.ItemPaintBall;
import appeng.items.tools.powered.powersink.AEBasePoweredItem; import appeng.items.tools.powered.powersink.AEBasePoweredItem;
import appeng.me.helpers.PlayerSource; import appeng.me.helpers.PlayerSource;
import appeng.me.storage.CellInventoryHandler; import appeng.me.storage.ItemCellInventoryHandler;
import appeng.tile.misc.TilePaint; import appeng.tile.misc.TilePaint;
import appeng.util.LookDirection; import appeng.util.LookDirection;
import appeng.util.Platform; import appeng.util.Platform;
public class ToolMatterCannon extends AEBasePoweredItem implements IStorageCell public class ToolMatterCannon extends AEBasePoweredItem implements IStorageCell<IAEItemStack>
{ {
public ToolMatterCannon() public ToolMatterCannon()
@@ -99,7 +100,7 @@ public class ToolMatterCannon extends AEBasePoweredItem implements IStorageCell
final IMEInventory<IAEItemStack> cdi = AEApi.instance().registries().cell().getCellInventory( stack, null, final IMEInventory<IAEItemStack> cdi = AEApi.instance().registries().cell().getCellInventory( stack, null,
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
if( cdi instanceof CellInventoryHandler ) if( cdi instanceof ItemCellInventoryHandler )
{ {
final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv(); final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv();
if( cd != null ) if( cd != null )
@@ -529,4 +530,10 @@ public class ToolMatterCannon extends AEBasePoweredItem implements IStorageCell
{ {
return 0.5; return 0.5;
} }
@Override
public IStorageChannel<IAEItemStack> getChannel()
{
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
}
} }
@@ -43,6 +43,7 @@ import appeng.api.implementations.items.IStorageCell;
import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventory;
import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.ICellInventoryHandler;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.util.AEPartLocation; import appeng.api.util.AEPartLocation;
@@ -53,11 +54,11 @@ import appeng.items.contents.CellConfig;
import appeng.items.contents.CellUpgrades; import appeng.items.contents.CellUpgrades;
import appeng.items.contents.PortableCellViewer; import appeng.items.contents.PortableCellViewer;
import appeng.items.tools.powered.powersink.AEBasePoweredItem; import appeng.items.tools.powered.powersink.AEBasePoweredItem;
import appeng.me.storage.CellInventoryHandler; import appeng.me.storage.ItemCellInventoryHandler;
import appeng.util.Platform; import appeng.util.Platform;
public class ToolPortableCell extends AEBasePoweredItem implements IStorageCell, IGuiItem, IItemGroup public class ToolPortableCell extends AEBasePoweredItem implements IStorageCell<IAEItemStack>, IGuiItem, IItemGroup
{ {
public ToolPortableCell() public ToolPortableCell()
{ {
@@ -87,7 +88,7 @@ public class ToolPortableCell extends AEBasePoweredItem implements IStorageCell,
final IMEInventory<IAEItemStack> cdi = AEApi.instance().registries().cell().getCellInventory( stack, null, final IMEInventory<IAEItemStack> cdi = AEApi.instance().registries().cell().getCellInventory( stack, null,
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
if( cdi instanceof CellInventoryHandler ) if( cdi instanceof ItemCellInventoryHandler )
{ {
final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv(); final ICellInventory cd = ( (ICellInventoryHandler) cdi ).getCellInv();
if( cd != null ) if( cd != null )
@@ -140,6 +141,12 @@ public class ToolPortableCell extends AEBasePoweredItem implements IStorageCell,
return 0.5; return 0.5;
} }
@Override
public IStorageChannel<IAEItemStack> getChannel()
{
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
}
@Override @Override
public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is ) public String getUnlocalizedGroupName( final Set<ItemStack> others, final ItemStack is )
{ {
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<T extends IAEStack<T>> implements ICellInventory<T>
{
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<T> 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<T> 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;
}
}
@@ -1,6 +1,6 @@
/* /*
* This file is part of Applied Energistics 2. * 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 * 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 * 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.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import appeng.api.AEApi;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.config.IncludeExclude; import appeng.api.config.IncludeExclude;
import appeng.api.config.Upgrades; import appeng.api.config.Upgrades;
@@ -31,26 +30,29 @@ import appeng.api.implementations.items.IUpgradeModule;
import appeng.api.storage.ICellInventory; import appeng.api.storage.ICellInventory;
import appeng.api.storage.ICellInventoryHandler; import appeng.api.storage.ICellInventoryHandler;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.IStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import appeng.util.prioritylist.FuzzyPriorityList; import appeng.util.prioritylist.FuzzyPriorityList;
import appeng.util.prioritylist.PrecisePriorityList; import appeng.util.prioritylist.PrecisePriorityList;
public class CellInventoryHandler extends MEInventoryHandler<IAEItemStack> implements ICellInventoryHandler /**
* @author DrummerMC
* @version rv6 - 2018-01-23
* @since rv6 2018-01-23
*/
public abstract class AbstractCellInventoryHandler<T extends IAEStack<T>> extends MEInventoryHandler<T> implements ICellInventoryHandler<T>
{ {
public AbstractCellInventoryHandler( final IMEInventory c, final IStorageChannel<T> channel )
CellInventoryHandler( final IMEInventory c )
{ {
super( c, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); super( c, channel );
final ICellInventory ci = this.getCellInv(); final ICellInventory ci = this.getCellInv();
if( ci != null ) if( ci != null )
{ {
final IItemList<IAEItemStack> priorityList = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); final IItemList<T> priorityList = channel.createList();
final IItemHandler upgrades = ci.getUpgradesInventory(); final IItemHandler upgrades = ci.getUpgradesInventory();
final IItemHandler config = ci.getConfigInventory(); final IItemHandler config = ci.getConfigInventory();
@@ -86,7 +88,7 @@ public class CellInventoryHandler extends MEInventoryHandler<IAEItemStack> imple
final ItemStack is = config.getStackInSlot( x ); final ItemStack is = config.getStackInSlot( x );
if( !is.isEmpty() ) if( !is.isEmpty() )
{ {
priorityList.add( AEItemStack.fromItemStack( is ) ); priorityList.add( createConfigStackFromItem( is ) );
} }
} }
@@ -106,6 +108,8 @@ public class CellInventoryHandler extends MEInventoryHandler<IAEItemStack> imple
} }
} }
protected abstract T createConfigStackFromItem( ItemStack is );
@Override @Override
public ICellInventory getCellInv() public ICellInventory getCellInv()
{ {
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<Integer> 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<IAEItemStack> 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<IAEItemStack> 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;
}
}
@@ -55,7 +55,7 @@ public class CreativeCellInventory implements IMEInventoryHandler<IAEItemStack>
public static IMEInventoryHandler getCell( final ItemStack o ) public static IMEInventoryHandler getCell( final ItemStack o )
{ {
return new CellInventoryHandler( new CreativeCellInventory( o ) ); return new ItemCellInventoryHandler( new CreativeCellInventory( o ) );
} }
@Override @Override
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEItemStack>
{
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;
}
}
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEItemStack>
{
public ItemCellInventoryHandler( IMEInventory c )
{
super( c, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
}
@Override
protected IAEItemStack createConfigStackFromItem( ItemStack is )
{
return AEItemStack.fromItemStack( is );
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IMEInventoryHandler> 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;
}
}
}
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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 );
}
}
@@ -192,11 +192,15 @@ public class TileCellWorkbench extends AEBaseTile implements IUpgradeableHost, I
} }
else if( inv == this.config && !this.locked ) else if( inv == this.config && !this.locked )
{ {
this.locked = true;
final IItemHandler c = this.getCellConfigInventory(); final IItemHandler c = this.getCellConfigInventory();
if( c != null ) if( c != null )
{ {
ItemHandlerUtil.copy( this.config, c, false ); 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;
} }
} }
+103
View File
@@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
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<IAEFluidStack> CONFIG_BASED_SORT_BY_NAME = new Comparator<IAEFluidStack>()
{
@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<IAEFluidStack> CONFIG_BASED_SORT_BY_MOD = new Comparator<IAEFluidStack>()
{
@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<IAEFluidStack> CONFIG_BASED_SORT_BY_SIZE = new Comparator<IAEFluidStack>()
{
@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;
}
}
+41
View File
@@ -67,6 +67,8 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldServer; import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.common.util.FakePlayerFactory; 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.FMLCommonHandler;
import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.fml.common.ModContainer;
@@ -121,6 +123,7 @@ import appeng.me.GridNode;
import appeng.me.helpers.AENetworkProxy; import appeng.me.helpers.AENetworkProxy;
import appeng.util.helpers.ItemComparisonHelper; import appeng.util.helpers.ItemComparisonHelper;
import appeng.util.helpers.P2PHelper; import appeng.util.helpers.P2PHelper;
import appeng.util.item.AEFluidStack;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import appeng.util.prioritylist.IPartitionList; import appeng.util.prioritylist.IPartitionList;
@@ -610,6 +613,17 @@ public class Platform
return n == null ? "** Null" : n; 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 ) public static String getItemDisplayName( final Object o )
{ {
if( o == null ) 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 ) public static boolean isWrench( final EntityPlayer player, final ItemStack eq, final BlockPos pos )
{ {
if( !eq.isEmpty() ) if( !eq.isEmpty() )
@@ -131,6 +131,7 @@ gui.appliedenergistics2.SecurityCardEditor=Biometric Card Editor
gui.appliedenergistics2.Encoded=Encoded gui.appliedenergistics2.Encoded=Encoded
gui.appliedenergistics2.Priority=Priority gui.appliedenergistics2.Priority=Priority
gui.appliedenergistics2.StorageBus=Storage Bus gui.appliedenergistics2.StorageBus=Storage Bus
gui.appliedenergistics2.StorageBusFluids=Fluid Storage Bus
gui.appliedenergistics2.EnergyDrain=Passive Drain gui.appliedenergistics2.EnergyDrain=Passive Drain
gui.appliedenergistics2.Installed=Installed gui.appliedenergistics2.Installed=Installed
gui.appliedenergistics2.NetworkTool=Network Tool gui.appliedenergistics2.NetworkTool=Network Tool
@@ -146,8 +147,10 @@ gui.appliedenergistics2.Condenser=Matter Condenser
gui.appliedenergistics2.Config=Config gui.appliedenergistics2.Config=Config
gui.appliedenergistics2.Drive=ME Drive gui.appliedenergistics2.Drive=ME Drive
gui.appliedenergistics2.ExportBus=ME Export Bus gui.appliedenergistics2.ExportBus=ME Export Bus
gui.appliedenergistics2.ExportBusFluids=ME Fluid Export Bus
gui.appliedenergistics2.GrindStone=Grindstone gui.appliedenergistics2.GrindStone=Grindstone
gui.appliedenergistics2.ImportBus=ME Import Bus gui.appliedenergistics2.ImportBus=ME Import Bus
gui.appliedenergistics2.ImportBusFluids=ME Fluid Import Bus
gui.appliedenergistics2.Interface=ME Interface gui.appliedenergistics2.Interface=ME Interface
gui.appliedenergistics2.LevelEmitter=ME Level Emitter gui.appliedenergistics2.LevelEmitter=ME Level Emitter
gui.appliedenergistics2.Of=of gui.appliedenergistics2.Of=of
@@ -163,6 +166,7 @@ gui.appliedenergistics2.VibrationChamber=Vibration Chamber
gui.appliedenergistics2.NetworkDetails=Network Details gui.appliedenergistics2.NetworkDetails=Network Details
gui.appliedenergistics2.StorageCells=ME Storage Cells gui.appliedenergistics2.StorageCells=ME Storage Cells
gui.appliedenergistics2.IOBuses=ME Import/Export Bus gui.appliedenergistics2.IOBuses=ME Import/Export Bus
gui.appliedenergistics2.IOBusesFluids=ME Fluid Import/Export Bus
gui.appliedenergistics2.Stores=Stores gui.appliedenergistics2.Stores=Stores
gui.appliedenergistics2.BytesUsed=Bytes Used gui.appliedenergistics2.BytesUsed=Bytes Used
gui.appliedenergistics2.Types=Types 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.ReportInaccessibleItems=Report Inaccessible Items
gui.tooltips.appliedenergistics2.ReportInaccessibleItemsYes=Yes: Items that cannot be extracted will be visible. 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.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.BlockPlacement=Block Placement
gui.tooltips.appliedenergistics2.BlockPlacementYes=Blocks will be placed as block. gui.tooltips.appliedenergistics2.BlockPlacementYes=Blocks will be placed as block.
gui.tooltips.appliedenergistics2.BlockPlacementNo=Blocks will be dropped as item. 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_4k.name=4k ME Storage Cell
item.appliedenergistics2.storage_cell_16k.name=16k 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.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.creative_storage_cell.name=Creative ME Storage Cell
item.appliedenergistics2.encoded_pattern.name=Encoded Pattern item.appliedenergistics2.encoded_pattern.name=Encoded Pattern
item.appliedenergistics2.view_cell.name=View Cell 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.cell4k_part.name=4k ME Storage Component
item.appliedenergistics2.material.cell16k_part.name=16k 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.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.name=Certus Quartz Crystal
item.appliedenergistics2.material.certus_quartz_crystal_charged.name=Charged 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 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.monitor.name=Bright Illuminated Panel
item.appliedenergistics2.multi_part.dark_monitor.name=Dark 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.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.formation_plane.name=ME Formation Plane
item.appliedenergistics2.multi_part.import_bus.name=ME Import Bus 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.interface.name=ME Interface
item.appliedenergistics2.multi_part.level_emitter.name=ME Level Emitter item.appliedenergistics2.multi_part.level_emitter.name=ME Level Emitter
item.appliedenergistics2.multi_part.p2p_tunnel.name=P2P Tunnel item.appliedenergistics2.multi_part.p2p_tunnel.name=P2P Tunnel
item.appliedenergistics2.multi_part.pattern_terminal.name=ME Pattern Terminal item.appliedenergistics2.multi_part.pattern_terminal.name=ME Pattern Terminal
item.appliedenergistics2.multi_part.quartz_fiber.name=Quartz Fiber item.appliedenergistics2.multi_part.quartz_fiber.name=Quartz Fiber
item.appliedenergistics2.multi_part.storage_bus.name=ME Storage Bus 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.terminal.name=ME Terminal
item.appliedenergistics2.multi_part.inverted_toggle_bus.name=ME Inverted Toggle Bus 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.toggle_bus.name=ME Toggle Bus
item.appliedenergistics2.multi_part.crafting_monitor.name=ME Crafting Monitor item.appliedenergistics2.multi_part.crafting_monitor.name=ME Crafting Monitor
item.appliedenergistics2.multi_part.interface_terminal.name=ME Interface Terminal 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.multi_part.invalid_type.name=Disabled Item
item.appliedenergistics2.spatial_storage_cell_128_cubed.name=128³ Spatial Storage Cell item.appliedenergistics2.spatial_storage_cell_128_cubed.name=128³ Spatial Storage Cell
@@ -0,0 +1,5 @@
{
"parent": "item/generated",
"textures": {
}
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/fluid_storage_cell_16k"
}
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/fluid_storage_cell_1k"
}
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/fluid_storage_cell_4k"
}
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/fluid_storage_cell_64k"
}
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/material_fluid_cell16k_part"
}
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/material_fluid_cell1k_part"
}
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/material_fluid_cell4k_part"
}
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/material_fluid_cell64k_part"
}
}
@@ -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"
}
}
}
]
}
@@ -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"
}
}
}
]
}
@@ -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"
}
}
}
]
}
@@ -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"
}
}
@@ -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"
}
}
}
]
}
@@ -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
}
}
}
}
]
}
@@ -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"
}
}
}
]
}
@@ -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
}
}
}
}
]
}
@@ -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"
}
}
}
]
}
@@ -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
}
}
}
}
]
}
@@ -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"
}
}
}
]
}
@@ -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
}
}
}
}
]
}
@@ -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"
}
}
}
]
}
@@ -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
}
}
}
}
]
}

Some files were not shown because too many files have changed in this diff Show More