Added ME Fluid Interface (#3564)
* Fixed fluid storage bus json recipe * Added part version and recipes * Added rudimentary gui
This commit is contained in:
@@ -751,6 +751,7 @@ public abstract class AEBaseGui extends GuiContainer
|
||||
if( fs != null && this.isPowered() )
|
||||
{
|
||||
GlStateManager.disableLighting();
|
||||
GlStateManager.disableBlend();
|
||||
Fluid fluid = fs.getFluid();
|
||||
Minecraft.getMinecraft().getTextureManager().bindTexture( TextureMap.LOCATION_BLOCKS_TEXTURE );
|
||||
TextureAtlasSprite sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite( fluid.getStill().toString() );
|
||||
@@ -764,6 +765,7 @@ public abstract class AEBaseGui extends GuiContainer
|
||||
|
||||
this.drawTexturedModalRect( s.xPos, s.yPos, sprite, 16, 16 );
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.enableBlend();
|
||||
|
||||
if( s instanceof IMEFluidSlot )
|
||||
{
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.widgets;
|
||||
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.IFluidTank;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import appeng.api.util.AEColor;
|
||||
|
||||
|
||||
@SideOnly( Side.CLIENT )
|
||||
public class GuiFluidTank extends GuiButton implements ITooltip
|
||||
{
|
||||
private final IFluidTank tank;
|
||||
|
||||
public GuiFluidTank( int buttonId, IFluidTank tank, int x, int y, int w, int h )
|
||||
{
|
||||
super( buttonId, x, y, w, h, "" );
|
||||
this.tank = tank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawButton( final Minecraft mc, final int mouseX, final int mouseY, final float partialTicks )
|
||||
{
|
||||
if( this.visible )
|
||||
{
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
|
||||
drawRect( this.x, this.y, this.x + this.width, this.y + this.height, AEColor.GRAY.blackVariant | 0xFF000000 );
|
||||
|
||||
if( this.tank != null )
|
||||
{
|
||||
final FluidStack fluid = this.tank.getFluid();
|
||||
if( fluid != null && fluid.amount > 0 )
|
||||
{
|
||||
mc.getTextureManager().bindTexture( TextureMap.LOCATION_BLOCKS_TEXTURE );
|
||||
|
||||
float red = ( fluid.getFluid().getColor() >> 16 & 255 ) / 255.0F;
|
||||
float green = ( fluid.getFluid().getColor() >> 8 & 255 ) / 255.0F;
|
||||
float blue = ( fluid.getFluid().getColor() & 255 ) / 255.0F;
|
||||
GlStateManager.color( red, green, blue );
|
||||
|
||||
TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite( fluid.getFluid().getStill().toString() );
|
||||
final int scaledHeight = (int) ( this.height * ( (float) fluid.amount / this.tank.getCapacity() ) );
|
||||
|
||||
int iconHeightRemainder = scaledHeight % 16;
|
||||
if( iconHeightRemainder > 0 )
|
||||
{
|
||||
drawTexturedModalRect( this.x, this.y + this.height - iconHeightRemainder, sprite, 16, iconHeightRemainder );
|
||||
}
|
||||
for( int i = 0; i < scaledHeight / 16; i++ )
|
||||
{
|
||||
drawTexturedModalRect( this.x, this.y + this.height - iconHeightRemainder - ( i + 1 ) * 16, sprite, 16, 16 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
if( this.tank != null && this.tank.getFluid() != null && this.tank.getFluid().amount > 0 )
|
||||
{
|
||||
String desc = this.tank.getFluid().getFluid().getLocalizedName( this.tank.getFluid() );
|
||||
String amountToText = this.tank.getFluid().amount + "mB";
|
||||
|
||||
return desc + "\n" + amountToText;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int xPos()
|
||||
{
|
||||
return this.x - 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int yPos()
|
||||
{
|
||||
return this.y - 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth()
|
||||
{
|
||||
return this.width + 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return this.height + 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -126,6 +126,8 @@ import appeng.decorative.solid.BlockQuartzPillar;
|
||||
import appeng.decorative.solid.BlockSkyStone;
|
||||
import appeng.decorative.solid.BlockSkyStone.SkystoneType;
|
||||
import appeng.decorative.stair.BlockStairCommon;
|
||||
import appeng.fluids.block.BlockFluidInterface;
|
||||
import appeng.fluids.tile.TileFluidInterface;
|
||||
import appeng.hooks.DispenserBehaviorTinyTNT;
|
||||
import appeng.tile.crafting.TileCraftingMonitorTile;
|
||||
import appeng.tile.crafting.TileCraftingStorageTile;
|
||||
@@ -197,6 +199,7 @@ public final class ApiBlocks implements IBlocks
|
||||
private final ITileDefinition drive;
|
||||
private final ITileDefinition chest;
|
||||
private final ITileDefinition iface;
|
||||
private final ITileDefinition fluidIface;
|
||||
private final ITileDefinition cellWorkbench;
|
||||
private final ITileDefinition iOPort;
|
||||
private final ITileDefinition condenser;
|
||||
@@ -390,6 +393,10 @@ public final class ApiBlocks implements IBlocks
|
||||
.features( AEFeature.INTERFACE )
|
||||
.tileEntity( new TileEntityDefinition( TileInterface.class ) )
|
||||
.build();
|
||||
this.fluidIface = registry.block( "fluid_interface", BlockFluidInterface::new )
|
||||
.features( AEFeature.FLUID_INTERFACE )
|
||||
.tileEntity( new TileEntityDefinition( TileFluidInterface.class ) )
|
||||
.build();
|
||||
this.cellWorkbench = registry.block( "cell_workbench", BlockCellWorkbench::new )
|
||||
.features( AEFeature.STORAGE_CELLS )
|
||||
.tileEntity( new TileEntityDefinition( TileCellWorkbench.class ) )
|
||||
@@ -893,6 +900,12 @@ public final class ApiBlocks implements IBlocks
|
||||
return this.iface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITileDefinition fluidIface()
|
||||
{
|
||||
return this.fluidIface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITileDefinition cellWorkbench()
|
||||
{
|
||||
|
||||
@@ -55,6 +55,7 @@ public final class ApiParts implements IParts
|
||||
private final IItemDefinition importBus;
|
||||
private final IItemDefinition exportBus;
|
||||
private final IItemDefinition iface;
|
||||
private final IItemDefinition fluidIface;
|
||||
private final IItemDefinition levelEmitter;
|
||||
private final IItemDefinition annihilationPlane;
|
||||
private final IItemDefinition identityAnnihilationPlane;
|
||||
@@ -111,10 +112,11 @@ public final class ApiParts implements IParts
|
||||
this.importBus = new DamagedItemDefinition( "part.bus.import", itemPart.createPart( PartType.IMPORT_BUS ) );
|
||||
this.exportBus = new DamagedItemDefinition( "part.bus.export", itemPart.createPart( PartType.EXPORT_BUS ) );
|
||||
this.iface = new DamagedItemDefinition( "part.interface", itemPart.createPart( PartType.INTERFACE ) );
|
||||
this.fluidIface = new DamagedItemDefinition( "part.fluid_interface", itemPart.createPart( PartType.FLUID_INTERFACE ) );
|
||||
this.levelEmitter = new DamagedItemDefinition( "part.level_emitter", itemPart.createPart( PartType.LEVEL_EMITTER ) );
|
||||
this.annihilationPlane = new DamagedItemDefinition( "part.plane.annihilation", itemPart.createPart( PartType.ANNIHILATION_PLANE ) );
|
||||
this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity",
|
||||
itemPart.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) );
|
||||
this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity", itemPart
|
||||
.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) );
|
||||
this.formationPlane = new DamagedItemDefinition( "part.plane.formation", itemPart.createPart( PartType.FORMATION_PLANE ) );
|
||||
this.p2PTunnelME = new DamagedItemDefinition( "part.tunnel.me", itemPart.createPart( PartType.P2P_TUNNEL_ME ) );
|
||||
this.p2PTunnelRedstone = new DamagedItemDefinition( "part.tunnel.redstone", itemPart.createPart( PartType.P2P_TUNNEL_REDSTONE ) );
|
||||
@@ -255,6 +257,12 @@ public final class ApiParts implements IParts
|
||||
return this.iface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemDefinition fluidIface()
|
||||
{
|
||||
return this.fluidIface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemDefinition levelEmitter()
|
||||
{
|
||||
|
||||
@@ -75,6 +75,7 @@ public enum AEFeature
|
||||
CHANNELS( "Channels", Constants.CATEGORY_NETWORK_FEATURES ),
|
||||
|
||||
INTERFACE( "Interface", Constants.CATEGORY_NETWORK_BUSES ),
|
||||
FLUID_INTERFACE( "FluidInterface", 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 ),
|
||||
|
||||
@@ -40,6 +40,7 @@ public enum GuiText
|
||||
Terminal,
|
||||
|
||||
Interface,
|
||||
FluidInterface,
|
||||
Config,
|
||||
StoredItems,
|
||||
Patterns,
|
||||
|
||||
@@ -39,8 +39,6 @@ import appeng.core.sync.network.NetworkHandler;
|
||||
|
||||
public abstract class AppEngPacket implements Packet
|
||||
{
|
||||
|
||||
private AppEngPacketHandlerBase.PacketTypes id;
|
||||
private PacketBuffer p;
|
||||
private PacketCallState caller;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import appeng.core.sync.packets.PacketCompassResponse;
|
||||
import appeng.core.sync.packets.PacketCompressedNBT;
|
||||
import appeng.core.sync.packets.PacketConfigButton;
|
||||
import appeng.core.sync.packets.PacketCraftRequest;
|
||||
import appeng.core.sync.packets.PacketFluidTank;
|
||||
import appeng.core.sync.packets.PacketInventoryAction;
|
||||
import appeng.core.sync.packets.PacketJEIRecipe;
|
||||
import appeng.core.sync.packets.PacketLightning;
|
||||
@@ -104,7 +105,9 @@ public class AppEngPacketHandlerBase
|
||||
|
||||
PACKET_COMPRESSED_NBT( PacketCompressedNBT.class ),
|
||||
|
||||
PACKET_PAINTED_ENTITY( PacketPaintedEntity.class );
|
||||
PACKET_PAINTED_ENTITY( PacketPaintedEntity.class ),
|
||||
|
||||
PACKET_FLUID_TANK( PacketFluidTank.class );
|
||||
|
||||
private final Class<? extends AppEngPacket> packetClass;
|
||||
private final Constructor<? extends AppEngPacket> packetConstructor;
|
||||
|
||||
@@ -87,8 +87,10 @@ import appeng.container.implementations.ContainerVibrationChamber;
|
||||
import appeng.container.implementations.ContainerWireless;
|
||||
import appeng.container.implementations.ContainerWirelessTerm;
|
||||
import appeng.fluids.container.ContainerFluidIO;
|
||||
import appeng.fluids.container.ContainerFluidInterface;
|
||||
import appeng.fluids.container.ContainerFluidStorageBus;
|
||||
import appeng.fluids.container.ContainerFluidTerminal;
|
||||
import appeng.fluids.helper.IFluidInterfaceHost;
|
||||
import appeng.fluids.parts.PartFluidStorageBus;
|
||||
import appeng.fluids.parts.PartFluidTerminal;
|
||||
import appeng.fluids.parts.PartSharedFluidBus;
|
||||
@@ -156,6 +158,8 @@ public enum GuiBridge implements IGuiHandler
|
||||
|
||||
GUI_INTERFACE( ContainerInterface.class, IInterfaceHost.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
|
||||
|
||||
GUI_FLUID_INTERFACE( ContainerFluidInterface.class, IFluidInterfaceHost.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 ),
|
||||
|
||||
@@ -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.core.sync.packets;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fml.common.network.ByteBufUtils;
|
||||
|
||||
import appeng.core.sync.AppEngPacket;
|
||||
import appeng.core.sync.network.INetworkInfo;
|
||||
import appeng.fluids.container.ContainerFluidInterface;
|
||||
|
||||
|
||||
public class PacketFluidTank extends AppEngPacket
|
||||
{
|
||||
private final Map<Integer, NBTTagCompound> updateMap;
|
||||
|
||||
public PacketFluidTank( final ByteBuf stream )
|
||||
{
|
||||
this.updateMap = new HashMap<>();
|
||||
NBTTagCompound tags = ByteBufUtils.readTag( stream );
|
||||
|
||||
for( final String key : tags.getKeySet() )
|
||||
{
|
||||
updateMap.put( Integer.parseInt( key ), tags.getCompoundTag( key ) );
|
||||
}
|
||||
}
|
||||
|
||||
// api
|
||||
public PacketFluidTank( final Map<Integer, NBTTagCompound> updateMap )
|
||||
{
|
||||
this.updateMap = updateMap;
|
||||
|
||||
final NBTTagCompound tag = new NBTTagCompound();
|
||||
for( Map.Entry<Integer, NBTTagCompound> e : updateMap.entrySet() )
|
||||
{
|
||||
tag.setTag( e.getKey().toString(), e.getValue() );
|
||||
}
|
||||
final ByteBuf data = Unpooled.buffer();
|
||||
data.writeInt( this.getPacketID() );
|
||||
ByteBufUtils.writeTag( data, tag );
|
||||
this.configureWrite( data );
|
||||
}
|
||||
|
||||
public Map<Integer, NBTTagCompound> getUpdateMap()
|
||||
{
|
||||
return this.updateMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clientPacketData( final INetworkInfo manager, final AppEngPacket packet, final EntityPlayer player )
|
||||
{
|
||||
final Container c = player.openContainer;
|
||||
if( c instanceof ContainerFluidInterface )
|
||||
{
|
||||
( (ContainerFluidInterface) c ).receiveTankInfo( this.updateMap );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.fluids.block;
|
||||
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.block.AEBaseTileBlock;
|
||||
import appeng.core.sync.GuiBridge;
|
||||
import appeng.fluids.tile.TileFluidInterface;
|
||||
import appeng.util.Platform;
|
||||
|
||||
|
||||
public class BlockFluidInterface extends AEBaseTileBlock
|
||||
{
|
||||
public BlockFluidInterface()
|
||||
{
|
||||
super( Material.IRON );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivated( final World w, final BlockPos pos, final EntityPlayer p, final EnumHand hand, final @Nullable ItemStack heldItem, final EnumFacing side, final float hitX, final float hitY, final float hitZ )
|
||||
{
|
||||
if( p.isSneaking() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final TileEntity tg = this.getTileEntity( w, pos );
|
||||
if( tg instanceof TileFluidInterface )
|
||||
{
|
||||
if( Platform.isServer() )
|
||||
{
|
||||
Platform.openGUI( p, tg, AEPartLocation.fromFacing( side ), GuiBridge.GUI_FLUID_INTERFACE );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.client.gui;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
|
||||
import appeng.client.gui.AEBaseGui;
|
||||
import appeng.client.gui.widgets.GuiFluidTank;
|
||||
import appeng.client.gui.widgets.GuiTabButton;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.core.sync.GuiBridge;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.packets.PacketSwitchGuis;
|
||||
import appeng.fluids.container.ContainerFluidInterface;
|
||||
import appeng.fluids.helper.DualityFluidInterface;
|
||||
import appeng.fluids.helper.IFluidInterfaceHost;
|
||||
|
||||
|
||||
public class GuiFluidInterface extends AEBaseGui
|
||||
{
|
||||
public final static int ID_BUTTON_TANK = 222;
|
||||
|
||||
private final IFluidInterfaceHost host;
|
||||
private GuiTabButton priority;
|
||||
|
||||
public GuiFluidInterface( final InventoryPlayer ip, final IFluidInterfaceHost te )
|
||||
{
|
||||
super( new ContainerFluidInterface( ip, te ) );
|
||||
this.ySize = 231;
|
||||
this.host = te;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui()
|
||||
{
|
||||
super.initGui();
|
||||
|
||||
for( int i = 0; i < DualityFluidInterface.NUMBER_OF_TANKS; ++i )
|
||||
{
|
||||
this.buttonList.add( new GuiFluidTank( ID_BUTTON_TANK + i, this.host.getDualityFluidInterface()
|
||||
.getTank( i ), this.getGuiLeft() + 7 + 18 * i, this.getGuiTop() + 16 + 8, 16, 80 ) );
|
||||
}
|
||||
|
||||
this.priority = new GuiTabButton( this.getGuiLeft() + 154, this.getGuiTop(), 2 + 4 * 16, GuiText.Priority.getLocal(), this.itemRender );
|
||||
this.buttonList.add( this.priority );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawFG( int offsetX, int offsetY, int mouseX, int mouseY )
|
||||
{
|
||||
this.fontRenderer.drawString( this.getGuiDisplayName( GuiText.FluidInterface.getLocal() ), 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( "guis/interfacefluid.png" );
|
||||
this.drawTexturedModalRect( offsetX, offsetY, 0, 0, this.xSize, this.ySize );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed( final GuiButton btn ) throws IOException
|
||||
{
|
||||
super.actionPerformed( btn );
|
||||
|
||||
if( btn == this.priority )
|
||||
{
|
||||
NetworkHandler.instance().sendToServer( new PacketSwitchGuis( GuiBridge.GUI_PRIORITY ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.container;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.IContainerListener;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.container.AEBaseContainer;
|
||||
import appeng.core.sync.network.NetworkHandler;
|
||||
import appeng.core.sync.packets.PacketFluidTank;
|
||||
import appeng.fluids.container.slots.SlotFakeFluid;
|
||||
import appeng.fluids.helper.DualityFluidInterface;
|
||||
import appeng.fluids.helper.IFluidInterfaceHost;
|
||||
import appeng.util.Platform;
|
||||
|
||||
|
||||
public class ContainerFluidInterface extends AEBaseContainer
|
||||
{
|
||||
private final DualityFluidInterface myDuality;
|
||||
|
||||
public ContainerFluidInterface( final InventoryPlayer ip, final IFluidInterfaceHost te )
|
||||
{
|
||||
super( ip, (TileEntity) ( te instanceof TileEntity ? te : null ), (IPart) ( te instanceof IPart ? te : null ) );
|
||||
|
||||
this.myDuality = te.getDualityFluidInterface();
|
||||
|
||||
for( int x = 0; x < DualityFluidInterface.NUMBER_OF_TANKS; x++ )
|
||||
{
|
||||
this.addSlotToContainer( new SlotFakeFluid( this.myDuality.getConfig(), x, 8 + 18 * x, 115 ) );
|
||||
}
|
||||
|
||||
this.bindPlayerInventory( ip, 0, 231 - /* height of player inventory */82 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detectAndSendChanges()
|
||||
{
|
||||
this.verifyPermissions( SecurityPermissions.BUILD, false );
|
||||
|
||||
if( Platform.isServer() )
|
||||
{
|
||||
this.sendTankUpdate();
|
||||
}
|
||||
|
||||
super.detectAndSendChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener( IContainerListener listener )
|
||||
{
|
||||
super.addListener( listener );
|
||||
this.sendTankInfo( listener );
|
||||
}
|
||||
|
||||
private void sendTankUpdate( final IContainerListener l, final HashMap<Integer, NBTTagCompound> updateMap )
|
||||
{
|
||||
if( l instanceof EntityPlayerMP )
|
||||
{
|
||||
NetworkHandler.instance().sendTo( new PacketFluidTank( updateMap ), (EntityPlayerMP) l );
|
||||
}
|
||||
}
|
||||
|
||||
private void sendTankUpdate()
|
||||
{
|
||||
final HashMap<Integer, NBTTagCompound> updateMap = new HashMap<>();
|
||||
if( this.myDuality.writeTankInfo( updateMap, false ) )
|
||||
{
|
||||
for( final IContainerListener listener : this.listeners )
|
||||
{
|
||||
this.sendTankUpdate( listener, updateMap );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendTankInfo( final IContainerListener l )
|
||||
{
|
||||
final HashMap<Integer, NBTTagCompound> updateMap = new HashMap<>();
|
||||
if( this.myDuality.writeTankInfo( updateMap, true ) )
|
||||
{
|
||||
this.sendTankUpdate( l, updateMap );
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveTankInfo( final Map<Integer, NBTTagCompound> tankTags )
|
||||
{
|
||||
this.myDuality.readTankInfo( tankTags );
|
||||
}
|
||||
|
||||
@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,45 @@
|
||||
/*
|
||||
* 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.helper;
|
||||
|
||||
|
||||
import net.minecraftforge.fluids.FluidTank;
|
||||
|
||||
|
||||
public class AEFluidTank extends FluidTank
|
||||
{
|
||||
private final IAEFluidInventory host;
|
||||
|
||||
public AEFluidTank( IAEFluidInventory host, int capacity )
|
||||
{
|
||||
super( capacity );
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onContentsChanged()
|
||||
{
|
||||
if( host != null )
|
||||
{
|
||||
host.onFluidInventoryChanged( this );
|
||||
}
|
||||
super.onContentsChanged();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,662 @@
|
||||
/*
|
||||
* 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.helper;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
|
||||
import net.minecraftforge.fluids.capability.templates.FluidHandlerConcatenate;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergySource;
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.storage.IMEInventory;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
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.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.capabilities.Capabilities;
|
||||
import appeng.core.settings.TickRates;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.me.helpers.AENetworkProxy;
|
||||
import appeng.me.helpers.MachineSource;
|
||||
import appeng.me.storage.MEMonitorIFluidHandler;
|
||||
import appeng.me.storage.MEMonitorPassThrough;
|
||||
import appeng.me.storage.NullInventory;
|
||||
import appeng.tile.inventory.AppEngInternalAEInventory;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.IAEAppEngInventory;
|
||||
import appeng.util.inv.InvOperation;
|
||||
|
||||
|
||||
public class DualityFluidInterface implements IGridTickable, IStorageMonitorable, IAEFluidInventory, IAEAppEngInventory, IPriorityHost
|
||||
{
|
||||
public static final int NUMBER_OF_TANKS = 9;
|
||||
public static final int TANK_CAPACITY = Fluid.BUCKET_VOLUME * 4;
|
||||
|
||||
private final AENetworkProxy gridProxy;
|
||||
private final IFluidInterfaceHost iHost;
|
||||
private final IActionSource mySource;
|
||||
private final IActionSource interfaceRequestSource;
|
||||
private boolean hasConfig = false;
|
||||
private final IStorageMonitorableAccessor accessor = this::getMonitorable;
|
||||
private final AEFluidTank[] tanks;
|
||||
private final IFluidHandler storage;
|
||||
private final AppEngInternalAEInventory config = new AppEngInternalAEInventory( this, NUMBER_OF_TANKS );
|
||||
private final IAEFluidStack[] configStacks;
|
||||
private final IAEFluidStack[] requireWork;
|
||||
private final boolean[] tankChanged;
|
||||
private int isWorking = -1;
|
||||
private int priority;
|
||||
|
||||
private final MEMonitorPassThrough<IAEItemStack> items = new MEMonitorPassThrough<>( new NullInventory<IAEItemStack>(), AEApi.instance()
|
||||
.storage()
|
||||
.getStorageChannel( IItemStorageChannel.class ) );
|
||||
private final MEMonitorPassThrough<IAEFluidStack> fluids = new MEMonitorPassThrough<>( new NullInventory<IAEFluidStack>(), AEApi.instance()
|
||||
.storage()
|
||||
.getStorageChannel( IFluidStorageChannel.class ) );
|
||||
|
||||
public DualityFluidInterface( final AENetworkProxy networkProxy, final IFluidInterfaceHost ih )
|
||||
{
|
||||
this.gridProxy = networkProxy;
|
||||
this.gridProxy.setFlags( GridFlags.REQUIRE_CHANNEL );
|
||||
this.iHost = ih;
|
||||
|
||||
this.mySource = new MachineSource( this.iHost );
|
||||
this.interfaceRequestSource = new InterfaceRequestSource( this.iHost );
|
||||
|
||||
this.fluids.setChangeSource( this.mySource );
|
||||
this.items.setChangeSource( this.mySource );
|
||||
|
||||
this.tanks = new AEFluidTank[NUMBER_OF_TANKS];
|
||||
this.requireWork = new IAEFluidStack[NUMBER_OF_TANKS];
|
||||
this.configStacks = new IAEFluidStack[NUMBER_OF_TANKS];
|
||||
this.tankChanged = new boolean[NUMBER_OF_TANKS];
|
||||
for( int i = 0; i < NUMBER_OF_TANKS; ++i )
|
||||
{
|
||||
this.tanks[i] = new AEFluidTank( this, TANK_CAPACITY );
|
||||
this.requireWork[i] = null;
|
||||
this.configStacks[i] = null;
|
||||
this.tankChanged[i] = false;
|
||||
}
|
||||
this.storage = new FluidHandlerConcatenate( this.tanks );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IAEStack<T>> IMEMonitor<T> getInventory( IStorageChannel<T> channel )
|
||||
{
|
||||
if( channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
|
||||
{
|
||||
if( this.hasConfig() )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return (IMEMonitor<T>) this.items;
|
||||
}
|
||||
else if( channel == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) )
|
||||
{
|
||||
if( this.hasConfig() )
|
||||
{
|
||||
return (IMEMonitor<T>) new InterfaceInventory( this );
|
||||
}
|
||||
|
||||
return (IMEMonitor<T>) this.fluids;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IStorageMonitorable getMonitorable( final IActionSource src )
|
||||
{
|
||||
if( Platform.canAccess( this.gridProxy, src ) )
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest( final IGridNode node )
|
||||
{
|
||||
return new TickingRequest( TickRates.Interface.getMin(), TickRates.Interface.getMax(), !this.hasWorkToDo(), true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest( final IGridNode node, final int ticksSinceLastCall )
|
||||
{
|
||||
if( !this.gridProxy.isActive() )
|
||||
{
|
||||
return TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
final boolean couldDoWork = this.updateStorage();
|
||||
return this.hasWorkToDo() ? ( couldDoWork ? TickRateModulation.URGENT : TickRateModulation.SLOWER ) : TickRateModulation.SLEEP;
|
||||
}
|
||||
|
||||
public void notifyNeighbors()
|
||||
{
|
||||
if( this.gridProxy.isActive() )
|
||||
{
|
||||
try
|
||||
{
|
||||
this.gridProxy.getTick().wakeDevice( this.gridProxy.getNode() );
|
||||
}
|
||||
catch( final GridAccessException e )
|
||||
{
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
final TileEntity te = this.iHost.getTileEntity();
|
||||
if( te != null && te.getWorld() != null )
|
||||
{
|
||||
Platform.notifyBlocksOfNeighbors( te.getWorld(), te.getPos() );
|
||||
}
|
||||
}
|
||||
|
||||
public void gridChanged()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.items.setInternal( this.gridProxy.getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) );
|
||||
this.fluids.setInternal( this.gridProxy.getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) );
|
||||
}
|
||||
catch( final GridAccessException gae )
|
||||
{
|
||||
this.items.setInternal( new NullInventory<IAEItemStack>() );
|
||||
this.fluids.setInternal( new NullInventory<IAEFluidStack>() );
|
||||
}
|
||||
|
||||
this.notifyNeighbors();
|
||||
}
|
||||
|
||||
public AECableType getCableConnectionType( final AEPartLocation dir )
|
||||
{
|
||||
return AECableType.SMART;
|
||||
}
|
||||
|
||||
public DimensionalCoord getLocation()
|
||||
{
|
||||
return new DimensionalCoord( this.iHost.getTileEntity() );
|
||||
}
|
||||
|
||||
public boolean hasCapability( Capability<?> capabilityClass, EnumFacing facing )
|
||||
{
|
||||
return capabilityClass == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY || capabilityClass == Capabilities.STORAGE_MONITORABLE_ACCESSOR;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public <T> T getCapability( Capability<T> capabilityClass, EnumFacing facing )
|
||||
{
|
||||
if( capabilityClass == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY )
|
||||
{
|
||||
return (T) this.storage;
|
||||
}
|
||||
else if( capabilityClass == Capabilities.STORAGE_MONITORABLE_ACCESSOR )
|
||||
{
|
||||
return (T) this.accessor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean hasConfig()
|
||||
{
|
||||
return this.hasConfig;
|
||||
}
|
||||
|
||||
private void readConfig()
|
||||
{
|
||||
final boolean had = this.hasWorkToDo();
|
||||
|
||||
for( int x = 0; x < NUMBER_OF_TANKS; x++ )
|
||||
{
|
||||
this.configStacks[x] = null;
|
||||
ItemStack is = this.config.getStackInSlot( x );
|
||||
if( !is.isEmpty() )
|
||||
{
|
||||
IFluidHandlerItem fh = is.getCapability( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null );
|
||||
if( fh != null )
|
||||
{
|
||||
FluidStack fs = fh.drain( Fluid.BUCKET_VOLUME, false );
|
||||
if( fs != null && fs.amount > 0 )
|
||||
{
|
||||
this.configStacks[x] = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createStack( fs );
|
||||
}
|
||||
}
|
||||
}
|
||||
this.updatePlan( x );
|
||||
}
|
||||
|
||||
final boolean has = this.hasWorkToDo();
|
||||
|
||||
if( had != has )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( has )
|
||||
{
|
||||
this.gridProxy.getTick().alertDevice( this.gridProxy.getNode() );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.gridProxy.getTick().sleepDevice( this.gridProxy.getNode() );
|
||||
}
|
||||
}
|
||||
catch( final GridAccessException e )
|
||||
{
|
||||
// :P
|
||||
}
|
||||
}
|
||||
|
||||
this.notifyNeighbors();
|
||||
}
|
||||
|
||||
private boolean updateStorage()
|
||||
{
|
||||
boolean didSomething = false;
|
||||
for( int x = 0; x < NUMBER_OF_TANKS; x++ )
|
||||
{
|
||||
if( this.requireWork[x] != null )
|
||||
{
|
||||
didSomething = this.usePlan( x ) || didSomething;
|
||||
}
|
||||
}
|
||||
return didSomething;
|
||||
}
|
||||
|
||||
private boolean hasWorkToDo()
|
||||
{
|
||||
for( final IAEFluidStack requiredWork : this.requireWork )
|
||||
{
|
||||
if( requiredWork != null )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getTankSlot( final IFluidHandler inventory )
|
||||
{
|
||||
for( int i = 0; i < NUMBER_OF_TANKS; ++i )
|
||||
{
|
||||
if( this.tanks[i] == inventory )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
private void updatePlan( final int slot )
|
||||
{
|
||||
final IAEFluidStack req = this.configStacks[slot];
|
||||
final FluidStack stored = this.tanks[slot].drain( TANK_CAPACITY, false );
|
||||
|
||||
if( req == null && ( stored != null && stored.amount > 0 ) )
|
||||
{
|
||||
final IAEFluidStack work = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createStack( stored );
|
||||
this.requireWork[slot] = work.setStackSize( -work.getStackSize() );
|
||||
return;
|
||||
}
|
||||
else if( req != null )
|
||||
{
|
||||
if( stored == null || stored.amount == 0 ) // need to add stuff!
|
||||
{
|
||||
this.requireWork[slot] = req.copy();
|
||||
return;
|
||||
}
|
||||
else if( req.getFluid().equals( stored.getFluid() ) ) // same type ( qty different? )!
|
||||
{
|
||||
if( stored.amount < TANK_CAPACITY )
|
||||
{
|
||||
this.requireWork[slot] = req.copy();
|
||||
this.requireWork[slot].setStackSize( TANK_CAPACITY - stored.amount );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
// Stored != null; dispose!
|
||||
{
|
||||
final IAEFluidStack work = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createStack( stored );
|
||||
this.requireWork[slot] = work.setStackSize( -work.getStackSize() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.requireWork[slot] = null;
|
||||
}
|
||||
|
||||
private boolean usePlan( final int slot )
|
||||
{
|
||||
IFluidHandler tank = this.tanks[slot];
|
||||
IAEFluidStack work = this.requireWork[slot];
|
||||
this.isWorking = slot;
|
||||
|
||||
boolean changed = false;
|
||||
try
|
||||
{
|
||||
final IMEInventory<IAEFluidStack> dest = this.gridProxy.getStorage()
|
||||
.getInventory( AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
|
||||
final IEnergySource src = this.gridProxy.getEnergy();
|
||||
|
||||
if( work.getStackSize() > 0 )
|
||||
{
|
||||
// make sure strange things didn't happen...
|
||||
if( tank.fill( work.getFluidStack(), false ) != work.getStackSize() )
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
final IAEFluidStack acquired = Platform.poweredExtraction( src, dest, work, this.interfaceRequestSource );
|
||||
if( acquired != null )
|
||||
{
|
||||
changed = true;
|
||||
final int filled = tank.fill( acquired.getFluidStack(), true );
|
||||
if( filled != acquired.getStackSize() )
|
||||
{
|
||||
throw new IllegalStateException( "bad attempt at managing tanks. ( fill )" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( work.getStackSize() < 0 )
|
||||
{
|
||||
IAEFluidStack toStore = work.copy();
|
||||
toStore.setStackSize( -toStore.getStackSize() );
|
||||
|
||||
// make sure strange things didn't happen...
|
||||
final FluidStack canExtract = tank.drain( toStore.getFluidStack(), false );
|
||||
if( canExtract == null || canExtract.amount != toStore.getStackSize() )
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IAEFluidStack notStored = Platform.poweredInsert( src, dest, toStore, this.interfaceRequestSource );
|
||||
toStore.setStackSize( toStore.getStackSize() - ( notStored == null ? 0 : notStored.getStackSize() ) );
|
||||
|
||||
if( toStore.getStackSize() > 0 )
|
||||
{
|
||||
// extract items!
|
||||
changed = true;
|
||||
final FluidStack removed = tank.drain( toStore.getFluidStack(), true );
|
||||
if( removed == null || toStore.getStackSize() != removed.amount )
|
||||
{
|
||||
throw new IllegalStateException( "bad attempt at managing tanks. ( drain )" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( final GridAccessException e )
|
||||
{
|
||||
// :P
|
||||
}
|
||||
|
||||
if( changed )
|
||||
{
|
||||
this.updatePlan( slot );
|
||||
}
|
||||
|
||||
this.isWorking = -1;
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFluidInventoryChanged( final IFluidHandler inventory )
|
||||
{
|
||||
final int slot = getTankSlot( inventory );
|
||||
|
||||
this.tankChanged[slot] = true;
|
||||
this.saveChanges();
|
||||
|
||||
if( this.isWorking == slot )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean had = this.hasWorkToDo();
|
||||
|
||||
this.updatePlan( slot );
|
||||
|
||||
final boolean now = this.hasWorkToDo();
|
||||
|
||||
if( had != now )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( now )
|
||||
{
|
||||
this.gridProxy.getTick().alertDevice( this.gridProxy.getNode() );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.gridProxy.getTick().sleepDevice( this.gridProxy.getNode() );
|
||||
}
|
||||
}
|
||||
catch( final GridAccessException e )
|
||||
{
|
||||
// :P
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeInventory( IItemHandler inv, int slot, InvOperation mc, ItemStack removedStack, ItemStack newStack )
|
||||
{
|
||||
if( this.isWorking == slot )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( inv == this.config )
|
||||
{
|
||||
this.readConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority( final int newValue )
|
||||
{
|
||||
this.priority = newValue;
|
||||
}
|
||||
|
||||
public void writeToNBT( final NBTTagCompound data )
|
||||
{
|
||||
final NBTTagList tankContents = new NBTTagList();
|
||||
for( int i = 0; i < NUMBER_OF_TANKS; ++i )
|
||||
{
|
||||
tankContents.appendTag( this.tanks[i].writeToNBT( new NBTTagCompound() ) );
|
||||
}
|
||||
|
||||
data.setInteger( "priority", this.priority );
|
||||
data.setTag( "storage", tankContents );
|
||||
this.config.writeToNBT( data, "config" );
|
||||
}
|
||||
|
||||
public void readFromNBT( final NBTTagCompound data )
|
||||
{
|
||||
this.config.readFromNBT( data, "config" );
|
||||
final NBTTagList tankContents = data.getTagList( "storage", 10 );
|
||||
if( tankContents != null )
|
||||
{
|
||||
for( int i = 0; i < Math.min( NUMBER_OF_TANKS, tankContents.tagCount() ); ++i )
|
||||
{
|
||||
this.tanks[i].readFromNBT( tankContents.getCompoundTagAt( i ) );
|
||||
}
|
||||
}
|
||||
this.priority = data.getInteger( "priority" );
|
||||
this.readConfig();
|
||||
}
|
||||
|
||||
public IItemHandler getConfig()
|
||||
{
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public AEFluidTank getTank( final int i )
|
||||
{
|
||||
return this.tanks[i];
|
||||
}
|
||||
|
||||
public boolean writeTankInfo( final Map<Integer, NBTTagCompound> tagMap, boolean all )
|
||||
{
|
||||
boolean empty = true;
|
||||
for( int i = 0; i < NUMBER_OF_TANKS; ++i )
|
||||
{
|
||||
if( all || this.tankChanged[i] )
|
||||
{
|
||||
tagMap.put( i, this.tanks[i].writeToNBT( new NBTTagCompound() ) );
|
||||
this.tankChanged[i] = !all;
|
||||
empty = false;
|
||||
}
|
||||
}
|
||||
return !empty;
|
||||
}
|
||||
|
||||
public boolean readTankInfo( final Map<Integer, NBTTagCompound> tagMap )
|
||||
{
|
||||
boolean changed = false;
|
||||
for( int i = 0; i < NUMBER_OF_TANKS; ++i )
|
||||
{
|
||||
if( tagMap.containsKey( i ) )
|
||||
{
|
||||
this.tanks[i].readFromNBT( tagMap.get( i ) );
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
private class InterfaceRequestSource extends MachineSource
|
||||
{
|
||||
private final InterfaceRequestContext context;
|
||||
|
||||
InterfaceRequestSource( IActionHost v )
|
||||
{
|
||||
super( v );
|
||||
this.context = new InterfaceRequestContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Optional<T> context( Class<T> key )
|
||||
{
|
||||
if( key == InterfaceRequestContext.class )
|
||||
{
|
||||
return (Optional<T>) Optional.of( this.context );
|
||||
}
|
||||
|
||||
return super.context( key );
|
||||
}
|
||||
}
|
||||
|
||||
private class InterfaceRequestContext implements Comparable<Integer>
|
||||
{
|
||||
@Override
|
||||
public int compareTo( Integer o )
|
||||
{
|
||||
return Integer.compare( DualityFluidInterface.this.priority, o );
|
||||
}
|
||||
}
|
||||
|
||||
private class InterfaceInventory extends MEMonitorIFluidHandler
|
||||
{
|
||||
|
||||
InterfaceInventory( final DualityFluidInterface tileInterface )
|
||||
{
|
||||
super( tileInterface.storage );
|
||||
this.setActionSource( new MachineSource( tileInterface.iHost ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEFluidStack injectItems( final IAEFluidStack input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
final Optional<InterfaceRequestContext> context = src.context( InterfaceRequestContext.class );
|
||||
final boolean isInterface = context.isPresent();
|
||||
|
||||
if( isInterface )
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
return super.injectItems( input, type, src );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEFluidStack extractItems( final IAEFluidStack request, final Actionable type, final IActionSource src )
|
||||
{
|
||||
final Optional<InterfaceRequestContext> context = src.context( InterfaceRequestContext.class );
|
||||
final boolean hasLowerOrEqualPriority = context.map( c -> c.compareTo( DualityFluidInterface.this.priority ) <= 0 ).orElse( false );
|
||||
|
||||
if( hasLowerOrEqualPriority )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return super.extractItems( request, type, src );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChanges()
|
||||
{
|
||||
this.iHost.getTileEntity().markDirty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.helper;
|
||||
|
||||
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IAEFluidInventory
|
||||
{
|
||||
void onFluidInventoryChanged( IFluidHandler inventory );
|
||||
}
|
||||
@@ -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.fluids.helper;
|
||||
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.me.helpers.IGridProxyable;
|
||||
|
||||
|
||||
public interface IFluidInterfaceHost extends IActionHost, IGridProxyable
|
||||
{
|
||||
DualityFluidInterface getDualityFluidInterface();
|
||||
|
||||
EnumSet<EnumFacing> getTargets();
|
||||
|
||||
TileEntity getTileEntity();
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* 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.EnumSet;
|
||||
|
||||
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.common.capabilities.Capability;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
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.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.IStorageChannel;
|
||||
import appeng.api.storage.IStorageMonitorable;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.sync.GuiBridge;
|
||||
import appeng.fluids.helper.DualityFluidInterface;
|
||||
import appeng.fluids.helper.IFluidInterfaceHost;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.helpers.Reflected;
|
||||
import appeng.items.parts.PartModels;
|
||||
import appeng.parts.PartBasicState;
|
||||
import appeng.parts.PartModel;
|
||||
import appeng.util.Platform;
|
||||
|
||||
|
||||
public class PartFluidInterface extends PartBasicState implements IGridTickable, IStorageMonitorable, IFluidInterfaceHost, IPriorityHost
|
||||
{
|
||||
public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/interface_base" );
|
||||
|
||||
@PartModels
|
||||
public static final PartModel MODELS_OFF = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/interface_off" ) );
|
||||
|
||||
@PartModels
|
||||
public static final PartModel MODELS_ON = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/interface_on" ) );
|
||||
|
||||
@PartModels
|
||||
public static final PartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/interface_has_channel" ) );
|
||||
|
||||
private final DualityFluidInterface duality = new DualityFluidInterface( this.getProxy(), this );
|
||||
|
||||
@Reflected
|
||||
public PartFluidInterface( final ItemStack is )
|
||||
{
|
||||
super( is );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DualityFluidInterface getDualityFluidInterface()
|
||||
{
|
||||
return duality;
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange( final MENetworkChannelsChanged c )
|
||||
{
|
||||
this.duality.notifyNeighbors();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange( final MENetworkPowerStatusChange c )
|
||||
{
|
||||
this.duality.notifyNeighbors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes( final IPartCollisionHelper bch )
|
||||
{
|
||||
bch.addBox( 2, 2, 14, 14, 14, 16 );
|
||||
bch.addBox( 5, 5, 12, 11, 11, 14 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gridChanged()
|
||||
{
|
||||
this.duality.gridChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT( final NBTTagCompound data )
|
||||
{
|
||||
super.readFromNBT( data );
|
||||
this.duality.readFromNBT( data );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT( final NBTTagCompound data )
|
||||
{
|
||||
super.writeToNBT( data );
|
||||
this.duality.writeToNBT( data );
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCableConnectionLength( AECableType cable )
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPartActivate( final EntityPlayer p, final EnumHand hand, final Vec3d pos )
|
||||
{
|
||||
if( p.isSneaking() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( Platform.isServer() )
|
||||
{
|
||||
Platform.openGUI( p, this.getTileEntity(), this.getSide(), GuiBridge.GUI_FLUID_INTERFACE );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IAEStack<T>> IMEMonitor<T> getInventory( IStorageChannel<T> channel )
|
||||
{
|
||||
return this.duality.getInventory( channel );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest( final IGridNode node )
|
||||
{
|
||||
return this.duality.getTickingRequest( node );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest( final IGridNode node, final int ticksSinceLastCall )
|
||||
{
|
||||
return this.duality.tickingRequest( node, ticksSinceLastCall );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EnumFacing> getTargets()
|
||||
{
|
||||
return EnumSet.of( this.getSide().getFacing() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTileEntity()
|
||||
{
|
||||
return super.getHost().getTile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModel getStaticModels()
|
||||
{
|
||||
if( this.isActive() && this.isPowered() )
|
||||
{
|
||||
return MODELS_HAS_CHANNEL;
|
||||
}
|
||||
else if( this.isPowered() )
|
||||
{
|
||||
return MODELS_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MODELS_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return this.duality.getPriority();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority( final int newValue )
|
||||
{
|
||||
this.duality.setPriority( newValue );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCapability( Capability<?> capabilityClass )
|
||||
{
|
||||
return this.duality.hasCapability( capabilityClass, this.getSide().getFacing() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getCapability( Capability<T> capabilityClass )
|
||||
{
|
||||
return this.duality.getCapability( capabilityClass, this.getSide().getFacing() );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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.tile;
|
||||
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
|
||||
import appeng.api.networking.IGridNode;
|
||||
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.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.api.util.DimensionalCoord;
|
||||
import appeng.fluids.helper.DualityFluidInterface;
|
||||
import appeng.fluids.helper.IFluidInterfaceHost;
|
||||
import appeng.helpers.IPriorityHost;
|
||||
import appeng.tile.grid.AENetworkTile;
|
||||
|
||||
|
||||
public class TileFluidInterface extends AENetworkTile implements IGridTickable, IFluidInterfaceHost, IPriorityHost
|
||||
{
|
||||
private final DualityFluidInterface duality = new DualityFluidInterface( this.getProxy(), this );
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange( final MENetworkChannelsChanged c )
|
||||
{
|
||||
this.duality.notifyNeighbors();
|
||||
}
|
||||
|
||||
@MENetworkEventSubscribe
|
||||
public void stateChange( final MENetworkPowerStatusChange c )
|
||||
{
|
||||
this.duality.notifyNeighbors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickingRequest getTickingRequest( IGridNode node )
|
||||
{
|
||||
return this.duality.getTickingRequest( node );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation tickingRequest( IGridNode node, int ticksSinceLastCall )
|
||||
{
|
||||
return this.duality.tickingRequest( node, ticksSinceLastCall );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DualityFluidInterface getDualityFluidInterface()
|
||||
{
|
||||
return this.duality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTileEntity()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gridChanged()
|
||||
{
|
||||
this.duality.gridChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound writeToNBT( final NBTTagCompound data )
|
||||
{
|
||||
super.writeToNBT( data );
|
||||
this.duality.writeToNBT( data );
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT( final NBTTagCompound data )
|
||||
{
|
||||
super.readFromNBT( data );
|
||||
this.duality.readFromNBT( data );
|
||||
}
|
||||
|
||||
@Override
|
||||
public AECableType getCableConnectionType( final AEPartLocation dir )
|
||||
{
|
||||
return this.duality.getCableConnectionType( dir );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionalCoord getLocation()
|
||||
{
|
||||
return this.duality.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EnumFacing> getTargets()
|
||||
{
|
||||
return EnumSet.allOf( EnumFacing.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return this.duality.getPriority();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority( final int newValue )
|
||||
{
|
||||
this.duality.setPriority( newValue );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCapability( Capability<?> capability, @Nullable EnumFacing facing )
|
||||
{
|
||||
return this.duality.hasCapability( capability, facing ) || super.hasCapability( capability, facing );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getCapability( Capability<T> capability, @Nullable EnumFacing facing )
|
||||
{
|
||||
T result = this.duality.getCapability( capability, facing );
|
||||
if( result != null )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return super.getCapability( capability, facing );
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import appeng.core.features.AEFeature;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.fluids.parts.PartFluidExportBus;
|
||||
import appeng.fluids.parts.PartFluidImportBus;
|
||||
import appeng.fluids.parts.PartFluidInterface;
|
||||
import appeng.fluids.parts.PartFluidStorageBus;
|
||||
import appeng.fluids.parts.PartFluidTerminal;
|
||||
import appeng.integration.IntegrationRegistry;
|
||||
@@ -195,7 +196,8 @@ public enum PartType
|
||||
DARK_MONITOR( 200, "dark_monitor", EnumSet.of( AEFeature.PANELS ), EnumSet.noneOf( IntegrationType.class ), PartDarkPanel.class, "itemIlluminatedPanel" ),
|
||||
|
||||
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 ),
|
||||
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 ),
|
||||
|
||||
@@ -228,6 +230,7 @@ public enum PartType
|
||||
.noneOf( IntegrationType.class ), PartConversionMonitor.class ),
|
||||
|
||||
INTERFACE( 440, "interface", EnumSet.of( AEFeature.INTERFACE ), EnumSet.noneOf( IntegrationType.class ), PartInterface.class ),
|
||||
FLUID_INTERFACE( 441, "fluid_interface", EnumSet.of( AEFeature.FLUID_INTERFACE ), EnumSet.noneOf( IntegrationType.class ), PartFluidInterface.class ),
|
||||
|
||||
P2P_TUNNEL_ME( 460, "p2p_tunnel_me", EnumSet.of( AEFeature.P2P_TUNNEL, AEFeature.P2P_TUNNEL_ME ), EnumSet
|
||||
.noneOf( IntegrationType.class ), PartP2PTunnelME.class, GuiText.METunnel )
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
|
||||
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.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.StorageFilter;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
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;
|
||||
|
||||
|
||||
public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITickingMonitor
|
||||
{
|
||||
private final IFluidHandler handler;
|
||||
private final IItemList<IAEFluidStack> list = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
|
||||
private final HashMap<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> listeners = new HashMap<>();
|
||||
private final NavigableMap<Integer, CachedFluidStack> memory;
|
||||
private IActionSource mySource;
|
||||
private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY;
|
||||
|
||||
public MEMonitorIFluidHandler( final IFluidHandler handler )
|
||||
{
|
||||
this.handler = handler;
|
||||
this.memory = new ConcurrentSkipListMap<>();
|
||||
}
|
||||
|
||||
@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 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEFluidStack injectItems( final IAEFluidStack input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
final int filled = this.handler.fill( input.getFluidStack(), type == Actionable.MODULATE );
|
||||
|
||||
if( filled == 0 )
|
||||
{
|
||||
return input.copy();
|
||||
}
|
||||
|
||||
if( type == Actionable.MODULATE )
|
||||
{
|
||||
this.onTick();
|
||||
}
|
||||
|
||||
if( filled == input.getStackSize() )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final IAEFluidStack o = input.copy();
|
||||
o.setStackSize( input.getStackSize() - filled );
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEFluidStack extractItems( final IAEFluidStack request, final Actionable type, final IActionSource src )
|
||||
{
|
||||
final FluidStack removed = this.handler.drain( request.getFluidStack(), type == Actionable.MODULATE );
|
||||
|
||||
if( removed == null || removed.amount == 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if( type == Actionable.MODULATE )
|
||||
{
|
||||
this.onTick();
|
||||
}
|
||||
|
||||
final IAEFluidStack o = request.copy();
|
||||
o.setStackSize( removed.amount );
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel getChannel()
|
||||
{
|
||||
return AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TickRateModulation onTick()
|
||||
{
|
||||
final List<IAEFluidStack> changes = new ArrayList<>();
|
||||
|
||||
this.list.resetStatus();
|
||||
int high = 0;
|
||||
boolean changed = false;
|
||||
|
||||
final IFluidTankProperties[] props = this.handler.getTankProperties();
|
||||
for( int slot = 0; slot < this.handler.getTankProperties().length; ++slot )
|
||||
{
|
||||
final CachedFluidStack old = this.memory.get( slot );
|
||||
high = Math.max( high, slot );
|
||||
|
||||
final FluidStack newIS = !props[slot].canDrain() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? null : props[slot].getContents();
|
||||
final FluidStack oldIS = old == null ? null : old.fluidStack;
|
||||
|
||||
if( isDifferent( newIS, oldIS ) )
|
||||
{
|
||||
final CachedFluidStack cis = new CachedFluidStack( newIS );
|
||||
this.memory.put( slot, cis );
|
||||
|
||||
if( old != null && old.aeStack != null )
|
||||
{
|
||||
old.aeStack.setStackSize( -old.aeStack.getStackSize() );
|
||||
changes.add( old.aeStack );
|
||||
}
|
||||
|
||||
if( cis.aeStack != null )
|
||||
{
|
||||
changes.add( cis.aeStack );
|
||||
this.list.add( cis.aeStack );
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
final int newSize = newIS == null ? 0 : newIS.amount;
|
||||
final int diff = newSize - ( oldIS == null ? 0 : oldIS.amount );
|
||||
|
||||
IAEFluidStack stack = null;
|
||||
|
||||
if( newIS != null )
|
||||
{
|
||||
stack = ( old == null || old.aeStack == null ? AEApi.instance()
|
||||
.storage()
|
||||
.getStorageChannel( IFluidStorageChannel.class )
|
||||
.createStack( newIS ) : old.aeStack.copy() );
|
||||
}
|
||||
if( stack != null )
|
||||
{
|
||||
stack.setStackSize( newSize );
|
||||
this.list.add( stack );
|
||||
}
|
||||
|
||||
if( diff != 0 && stack != null )
|
||||
{
|
||||
final CachedFluidStack cis = new CachedFluidStack( newIS );
|
||||
this.memory.put( slot, cis );
|
||||
|
||||
final IAEFluidStack a = stack.copy();
|
||||
a.setStackSize( diff );
|
||||
changes.add( a );
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// detect dropped items; should fix non IISided Inventory Changes.
|
||||
final NavigableMap<Integer, CachedFluidStack> end = this.memory.tailMap( high, false );
|
||||
if( !end.isEmpty() )
|
||||
{
|
||||
for( final CachedFluidStack cis : end.values() )
|
||||
{
|
||||
if( cis != null && cis.aeStack != null )
|
||||
{
|
||||
final IAEFluidStack a = cis.aeStack.copy();
|
||||
a.setStackSize( -a.getStackSize() );
|
||||
changes.add( a );
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
end.clear();
|
||||
}
|
||||
|
||||
if( !changes.isEmpty() )
|
||||
{
|
||||
this.postDifference( changes );
|
||||
}
|
||||
|
||||
return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
|
||||
}
|
||||
|
||||
private static boolean isDifferent( FluidStack a, FluidStack b )
|
||||
{
|
||||
if( a == b )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( a == null || b == null )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return !a.getFluid().equals( b.getFluid() );
|
||||
}
|
||||
|
||||
private void postDifference( final Iterable<IAEFluidStack> a )
|
||||
{
|
||||
if( a != null )
|
||||
{
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object>> i = this.listeners.entrySet().iterator();
|
||||
while( i.hasNext() )
|
||||
{
|
||||
final Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> l = i.next();
|
||||
final IMEMonitorHandlerReceiver<IAEFluidStack> key = l.getKey();
|
||||
if( key.isValid( l.getValue() ) )
|
||||
{
|
||||
key.postChange( this, a, this.getActionSource() );
|
||||
}
|
||||
else
|
||||
{
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final IAEFluidStack input )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final IAEFluidStack input )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEFluidStack> getAvailableItems( final IItemList out )
|
||||
{
|
||||
for( final CachedFluidStack is : this.memory.values() )
|
||||
{
|
||||
out.addStorage( is.aeStack );
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEFluidStack> getStorageList()
|
||||
{
|
||||
return this.list;
|
||||
}
|
||||
|
||||
private StorageFilter getMode()
|
||||
{
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
public void setMode( final StorageFilter mode )
|
||||
{
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
private IActionSource getActionSource()
|
||||
{
|
||||
return this.mySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionSource( final IActionSource mySource )
|
||||
{
|
||||
this.mySource = mySource;
|
||||
}
|
||||
|
||||
private static class CachedFluidStack
|
||||
{
|
||||
|
||||
private final FluidStack fluidStack;
|
||||
private final IAEFluidStack aeStack;
|
||||
|
||||
CachedFluidStack( final FluidStack is )
|
||||
{
|
||||
if( is == null )
|
||||
{
|
||||
this.fluidStack = null;
|
||||
this.aeStack = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fluidStack = is.copy();
|
||||
this.aeStack = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createStack( is );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user