package crazypants.enderio.conduit.liquid;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import crazypants.enderio.EnderIO;
import crazypants.enderio.conduit.AbstractConduitNetwork;
import crazypants.enderio.conduit.ConduitUtil;
import crazypants.enderio.conduit.ConnectionMode;
import crazypants.enderio.conduit.IConduit;
import crazypants.enderio.conduit.RaytraceResult;
import crazypants.enderio.conduit.geom.CollidableComponent;
import crazypants.render.IconUtil;
import crazypants.util.BlockCoord;
public class EnderLiquidConduit extends AbstractLiquidConduit {
public static final String ICON_KEY = "enderio:liquidConduitEnder";
public static final String ICON_CORE_KEY = "enderio:liquidConduitCoreEnder";
public static final String ICON_EXTRACT_KEY = "enderio:liquidConduitAdvancedInput";
public static final String ICON_INSERT_KEY = "enderio:liquidConduitAdvancedOutput";
static final Map<String, IIcon> ICONS = new HashMap<String, IIcon>();
@SideOnly(Side.CLIENT)
public static void initIcons() {
IconUtil.addIconProvider(new IconUtil.IIconProvider() {
@Override
public void registerIcons(IIconRegister register) {
ICONS.put(ICON_KEY, register.registerIcon(ICON_KEY));
ICONS.put(ICON_CORE_KEY, register.registerIcon(ICON_CORE_KEY));
ICONS.put(ICON_EXTRACT_KEY, register.registerIcon(ICON_EXTRACT_KEY));
ICONS.put(ICON_INSERT_KEY, register.registerIcon(ICON_INSERT_KEY));
}
@Override
public int getTextureType() {
return 0;
}
});
}
private EnderLiquidConduitNetwork network;
private int ticksSinceFailedExtract;
private final EnumMap<ForgeDirection, FluidFilter> outputFilters = new EnumMap<ForgeDirection, FluidFilter>(ForgeDirection.class);
private final EnumMap<ForgeDirection, FluidFilter> inputFilters = new EnumMap<ForgeDirection, FluidFilter>(ForgeDirection.class);
@Override
public ItemStack createItem() {
return new ItemStack(EnderIO.itemLiquidConduit, 1, 2);
}
@Override
public boolean onBlockActivated(EntityPlayer player, RaytraceResult res, List<RaytraceResult> all) {
if(player.getCurrentEquippedItem() == null) {
return false;
}
if(ConduitUtil.isToolEquipped(player)) {
if(!getBundle().getEntity().getWorldObj().isRemote) {
if(res != null && res.component != null) {
ForgeDirection connDir = res.component.dir;
ForgeDirection faceHit = ForgeDirection.getOrientation(res.movingObjectPosition.sideHit);
if(connDir == ForgeDirection.UNKNOWN || connDir == faceHit) {
if(getConnectionMode(faceHit) == ConnectionMode.DISABLED) {
setConnectionMode(faceHit, getNextConnectionMode(faceHit));
return true;
}
BlockCoord loc = getLocation().getLocation(faceHit);
ILiquidConduit n = ConduitUtil.getConduit(getBundle().getEntity().getWorldObj(), loc.x, loc.y, loc.z, ILiquidConduit.class);
if(n == null) {
return false;
}
if(!(n instanceof EnderLiquidConduit)) {
return false;
}
return ConduitUtil.joinConduits(this, faceHit);
} else if(containsExternalConnection(connDir)) {
// Toggle extraction mode
setConnectionMode(connDir, getNextConnectionMode(connDir));
} else if(containsConduitConnection(connDir)) {
ConduitUtil.disconectConduits(this, connDir);
}
}
}
return true;
}
return false;
}
@Override
public AbstractConduitNetwork<?, ?> getNetwork() {
return network;
}
public FluidFilter getFilter(ForgeDirection dir, boolean isInput) {
if(isInput) {
return inputFilters.get(dir);
}
return outputFilters.get(dir);
}
public void setFilter(ForgeDirection dir, FluidFilter filter, boolean isInput) {
if(isInput) {
inputFilters.put(dir, filter);
} else {
outputFilters.put(dir, filter);
}
}
@Override
public boolean setNetwork(AbstractConduitNetwork<?, ?> network) {
if(network == null) {
this.network = null;
return true;
}
if(!(network instanceof EnderLiquidConduitNetwork)) {
return false;
}
this.network = (EnderLiquidConduitNetwork) network;
for (ForgeDirection dir : externalConnections) {
this.network.connectionChanged(this, dir);
}
return true;
}
@Override
public IIcon getTextureForState(CollidableComponent component) {
if(component.dir == ForgeDirection.UNKNOWN) {
return ICONS.get(ICON_CORE_KEY);
}
return ICONS.get(ICON_KEY);
}
public IIcon getTextureForInputMode() {
return ICONS.get(ICON_EXTRACT_KEY);
}
public IIcon getTextureForOutputMode() {
return ICONS.get(ICON_INSERT_KEY);
}
@Override
public IIcon getTransmitionTextureForState(CollidableComponent component) {
return null;
}
@Override
public boolean canConnectToConduit(ForgeDirection direction, IConduit con) {
if(!super.canConnectToConduit(direction, con)) {
return false;
}
if(!(con instanceof EnderLiquidConduit)) {
return false;
}
return true;
}
@Override
public void setConnectionMode(ForgeDirection dir, ConnectionMode mode) {
super.setConnectionMode(dir, mode);
refreshConnections(dir);
}
private void refreshConnections(ForgeDirection dir) {
if(network == null) {
return;
}
network.connectionChanged(this, dir);
}
@Override
public void externalConnectionAdded(ForgeDirection fromDirection) {
super.externalConnectionAdded(fromDirection);
refreshConnections(fromDirection);
}
@Override
public void externalConnectionRemoved(ForgeDirection fromDirection) {
super.externalConnectionRemoved(fromDirection);
refreshConnections(fromDirection);
}
@Override
public void updateEntity(World world) {
super.updateEntity(world);
if(world.isRemote) {
return;
}
doExtract();
}
private void doExtract() {
BlockCoord loc = getLocation();
if(!hasConnectionMode(ConnectionMode.INPUT)) {
return;
}
if(network == null) {
return;
}
// assume failure, reset to 0 if we do extract
ticksSinceFailedExtract++;
if(ticksSinceFailedExtract > 25 && ticksSinceFailedExtract % 10 != 0) {
// after 25 ticks of failing, only check every 10 ticks
return;
}
for (ForgeDirection dir : externalConnections) {
if(autoExtractForDir(dir)) {
if(network.extractFrom(this, dir)) {
ticksSinceFailedExtract = 0;
}
}
}
}
//Fluid API
@Override
public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
if(network == null || !getConnectionMode(from).acceptsInput()) {
return 0;
}
return network.fillFrom(this, from, resource, doFill);
}
@Override
public boolean canFill(ForgeDirection from, Fluid fluid) {
if(network == null) {
return false;
}
return getConnectionMode(from).acceptsInput();
}
@Override
public boolean canDrain(ForgeDirection from, Fluid fluid) {
return false;
}
@Override
public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
return null;
}
@Override
public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
return null;
}
@Override
public FluidTankInfo[] getTankInfo(ForgeDirection from) {
if(network == null) {
return new FluidTankInfo[0];
}
return network.getTankInfo(this, from);
}
@Override
public void writeToNBT(NBTTagCompound nbtRoot) {
super.writeToNBT(nbtRoot);
for (Entry<ForgeDirection, FluidFilter> entry : inputFilters.entrySet()) {
if(entry.getValue() != null) {
FluidFilter f = entry.getValue();
if(f != null && !f.isEmpty()) {
NBTTagCompound itemRoot = new NBTTagCompound();
f.writeToNBT(itemRoot);
nbtRoot.setTag("inFilts." + entry.getKey().name(), itemRoot);
}
}
}
for (Entry<ForgeDirection, FluidFilter> entry : outputFilters.entrySet()) {
if(entry.getValue() != null) {
FluidFilter f = entry.getValue();
if(f != null && !f.isEmpty()) {
NBTTagCompound itemRoot = new NBTTagCompound();
f.writeToNBT(itemRoot);
nbtRoot.setTag("outFilts." + entry.getKey().name(), itemRoot);
}
}
}
}
@Override
public void readFromNBT(NBTTagCompound nbtRoot, short nbtVersion) {
super.readFromNBT(nbtRoot, nbtVersion);
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
String key = "inFilts." + dir.name();
if(nbtRoot.hasKey(key)) {
NBTTagCompound filterTag = (NBTTagCompound) nbtRoot.getTag(key);
FluidFilter f = new FluidFilter();
f.readFromNBT(filterTag);
if(!f.isEmpty()) {
inputFilters.put(dir, f);
}
}
key = "outFilts." + dir.name();
if(nbtRoot.hasKey(key)) {
NBTTagCompound filterTag = (NBTTagCompound) nbtRoot.getTag(key);
FluidFilter f = new FluidFilter();
f.readFromNBT(filterTag);
if(!f.isEmpty()) {
outputFilters.put(dir, f);
}
}
}
}
}