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
@@ -36,6 +36,7 @@ import appeng.core.sync.packets.PacketCraftRequest;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.core.sync.packets.PacketJEIRecipe;
import appeng.core.sync.packets.PacketLightning;
import appeng.core.sync.packets.PacketMEFluidInventoryUpdate;
import appeng.core.sync.packets.PacketMEInventoryUpdate;
import appeng.core.sync.packets.PacketMatterCannon;
import appeng.core.sync.packets.PacketMockExplosion;
@@ -45,6 +46,7 @@ import appeng.core.sync.packets.PacketPatternSlot;
import appeng.core.sync.packets.PacketProgressBar;
import appeng.core.sync.packets.PacketSwapSlots;
import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketTargetFluidStack;
import appeng.core.sync.packets.PacketTargetItemStack;
import appeng.core.sync.packets.PacketTransitionEffect;
import appeng.core.sync.packets.PacketValueConfig;
@@ -64,6 +66,8 @@ public class AppEngPacketHandlerBase
PACKET_ME_INVENTORY_UPDATE( PacketMEInventoryUpdate.class ),
PACKET_ME_FLUID_INVENTORY_UPDATE( PacketMEFluidInventoryUpdate.class ),
PACKET_CONFIG_BUTTON( PacketConfigButton.class ),
PACKET_PART_PLACEMENT( PacketPartPlacement.class ),
@@ -92,6 +96,8 @@ public class AppEngPacketHandlerBase
PACKET_TARGET_ITEM( PacketTargetItemStack.class ),
PACKET_TARGET_FLUID( PacketTargetFluidStack.class ),
PACKET_CRAFTING_REQUEST( PacketCraftRequest.class ),
PACKET_ASSEMBLER_ANIMATION( PacketAssemblerAnimation.class ),
@@ -62,6 +62,9 @@ import appeng.container.implementations.ContainerCraftingCPU;
import appeng.container.implementations.ContainerCraftingStatus;
import appeng.container.implementations.ContainerCraftingTerm;
import appeng.container.implementations.ContainerDrive;
import appeng.container.implementations.ContainerFluidIO;
import appeng.container.implementations.ContainerFluidStorageBus;
import appeng.container.implementations.ContainerFluidTerminal;
import appeng.container.implementations.ContainerFormationPlane;
import appeng.container.implementations.ContainerGrinder;
import appeng.container.implementations.ContainerIOPort;
@@ -86,6 +89,8 @@ import appeng.container.implementations.ContainerUpgradeable;
import appeng.container.implementations.ContainerVibrationChamber;
import appeng.container.implementations.ContainerWireless;
import appeng.container.implementations.ContainerWirelessTerm;
import appeng.fluids.parts.PartFluidStorageBus;
import appeng.fluids.parts.PartSharedFluidBus;
import appeng.helpers.IInterfaceHost;
import appeng.helpers.IPriorityHost;
import appeng.helpers.WirelessTerminalGuiObject;
@@ -94,6 +99,7 @@ import appeng.parts.automation.PartFormationPlane;
import appeng.parts.automation.PartLevelEmitter;
import appeng.parts.misc.PartStorageBus;
import appeng.parts.reporting.PartCraftingTerminal;
import appeng.parts.reporting.PartFluidTerminal;
import appeng.parts.reporting.PartInterfaceTerminal;
import appeng.parts.reporting.PartPatternTerminal;
import appeng.tile.crafting.TileCraftingTile;
@@ -152,10 +158,14 @@ public enum GuiBridge implements IGuiHandler
GUI_BUS( ContainerUpgradeable.class, IUpgradeableHost.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_BUS_FLUID( ContainerFluidIO.class, PartSharedFluidBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_IOPORT( ContainerIOPort.class, TileIOPort.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_STORAGEBUS( ContainerStorageBus.class, PartStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_STORAGEBUS_FLUID( ContainerFluidStorageBus.class, PartFluidStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_FORMATION_PLANE( ContainerFormationPlane.class, PartFormationPlane.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_PRIORITY( ContainerPriority.class, IPriorityHost.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
@@ -166,6 +176,8 @@ public enum GuiBridge implements IGuiHandler
GUI_PATTERN_TERMINAL( ContainerPatternTerm.class, PartPatternTerminal.class, GuiHostType.WORLD, SecurityPermissions.CRAFT ),
GUI_FLUID_TERMINAL( ContainerFluidTerminal.class, PartFluidTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
// extends (Container/Gui) + Bus
GUI_LEVEL_EMITTER( ContainerLevelEmitter.class, PartLevelEmitter.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
@@ -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.ContainerCraftingCPU;
import appeng.container.implementations.ContainerCraftingStatus;
import appeng.container.implementations.ContainerFluidStorageBus;
import appeng.container.implementations.ContainerLevelEmitter;
import appeng.container.implementations.ContainerNetworkTool;
import appeng.container.implementations.ContainerPatternTerm;
@@ -179,18 +180,31 @@ public class PacketValueConfig extends AppEngPacket
cpt.getPatternTerminal().setSubstitution( this.Value.equals( "1" ) );
}
}
else if( this.Name.startsWith( "StorageBus." ) && c instanceof ContainerStorageBus )
else if( this.Name.startsWith( "StorageBus." ) )
{
final ContainerStorageBus ccw = (ContainerStorageBus) c;
if( this.Name.equals( "StorageBus.Action" ) )
{
if( this.Value.equals( "Partition" ) )
{
ccw.partition();
if( c instanceof ContainerStorageBus )
{
( (ContainerStorageBus) c ).partition();
}
else if( c instanceof ContainerFluidStorageBus )
{
( (ContainerFluidStorageBus) c ).partition();
}
}
else if( this.Value.equals( "Clear" ) )
{
ccw.clear();
if( c instanceof ContainerStorageBus )
{
( (ContainerStorageBus) c ).clear();
}
else if( c instanceof ContainerFluidStorageBus )
{
( (ContainerFluidStorageBus) c ).clear();
}
}
}
}