package mekanism.common.tile.component; import io.netty.buffer.ByteBuf; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import mekanism.api.Coord4D; import mekanism.api.EnumColor; import mekanism.api.gas.GasStack; import mekanism.api.gas.GasTank; import mekanism.api.gas.GasTransmission; import mekanism.api.transmitters.TransmissionType; import mekanism.api.util.CapabilityUtils; import mekanism.common.SideData; import mekanism.common.base.ISideConfiguration; import mekanism.common.base.ITankManager; import mekanism.common.base.ITileComponent; import mekanism.common.capabilities.Capabilities; import mekanism.common.content.transporter.TransporterManager; import mekanism.common.tile.TileEntityContainerBlock; import mekanism.common.util.InventoryUtils; import mekanism.common.util.MekanismUtils; import mekanism.common.util.PipeUtils; import mekanism.common.util.TransporterUtils; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; public class TileComponentEjector implements ITileComponent { public TileEntityContainerBlock tileEntity; public boolean strictInput; public EnumColor outputColor; public EnumColor[] inputColors = new EnumColor[] {null, null, null, null, null, null}; public int tickDelay = 0; public Map<TransmissionType, SideData> sideData = new HashMap<TransmissionType, SideData>(); public Map<TransmissionType, int[]> trackers = new HashMap<TransmissionType, int[]>(); public static final int GAS_OUTPUT = 256; public static final int FLUID_OUTPUT = 256; public TileComponentEjector(TileEntityContainerBlock tile) { tileEntity = tile; tile.components.add(this); } public TileComponentEjector setOutputData(TransmissionType type, SideData data) { sideData.put(type, data); trackers.put(type, new int[data.availableSlots.length]); return this; } public void readFrom(TileComponentEjector ejector) { strictInput = ejector.strictInput; outputColor = ejector.outputColor; inputColors = ejector.inputColors; tickDelay = ejector.tickDelay; sideData = ejector.sideData; } private List<EnumFacing> getTrackedOutputs(TransmissionType type, int index, List<EnumFacing> dirs) { List<EnumFacing> sides = new ArrayList<EnumFacing>(); for(int i = trackers.get(type)[index]+1; i <= trackers.get(type)[index]+6; i++) { for(EnumFacing side : dirs) { if(EnumFacing.getFront(i%6) == side) { sides.add(side); } } } return sides; } @Override public void tick() { if(tickDelay == 0) { if(sideData.get(TransmissionType.ITEM) != null) { outputItems(); } } else { tickDelay--; } if(!tileEntity.getWorld().isRemote) { if(sideData.get(TransmissionType.GAS) != null && getEjecting(TransmissionType.GAS)) { SideData data = sideData.get(TransmissionType.GAS); List<EnumFacing> outputSides = getOutputSides(TransmissionType.GAS, data); if(((ITankManager)tileEntity).getTanks() != null) { GasTank tank = (GasTank)((ITankManager)tileEntity).getTanks()[data.availableSlots[0]]; if(tank.getStored() > 0) { GasStack toEmit = tank.getGas().copy().withAmount(Math.min(GAS_OUTPUT, tank.getStored())); int emit = GasTransmission.emit(toEmit, tileEntity, outputSides); tank.draw(emit, true); } } } if(sideData.get(TransmissionType.FLUID) != null && getEjecting(TransmissionType.FLUID)) { SideData data = sideData.get(TransmissionType.FLUID); List<EnumFacing> outputSides = getOutputSides(TransmissionType.FLUID, data); if(((ITankManager)tileEntity).getTanks() != null) { FluidTank tank = (FluidTank)((ITankManager)tileEntity).getTanks()[data.availableSlots[0]]; if(tank.getFluidAmount() > 0) { FluidStack toEmit = PipeUtils.copy(tank.getFluid(), Math.min(FLUID_OUTPUT, tank.getFluidAmount())); int emit = PipeUtils.emit(outputSides, toEmit, tileEntity); tank.drain(emit, true); } } } } } public List<EnumFacing> getOutputSides(TransmissionType type, SideData data) { List<EnumFacing> outputSides = new ArrayList<EnumFacing>(); ISideConfiguration configurable = (ISideConfiguration)tileEntity; for(int i = 0; i < configurable.getConfig().getConfig(type).length; i++) { EnumFacing side = MekanismUtils.getBaseOrientation(EnumFacing.getFront(i), tileEntity.facing); if(configurable.getConfig().getConfig(type)[side.ordinal()] == configurable.getConfig().getOutputs(type).indexOf(data)) { outputSides.add(EnumFacing.getFront(i)); } } return outputSides; } public void outputItems() { if(!getEjecting(TransmissionType.ITEM) || tileEntity.getWorld().isRemote) { return; } SideData data = sideData.get(TransmissionType.ITEM); List<EnumFacing> outputSides = getOutputSides(TransmissionType.ITEM, data); for(int index = 0; index < sideData.get(TransmissionType.ITEM).availableSlots.length; index++) { int slotID = sideData.get(TransmissionType.ITEM).availableSlots[index]; if(tileEntity.getStackInSlot(slotID) == null) { continue; } ItemStack stack = tileEntity.getStackInSlot(slotID); List<EnumFacing> outputs = getTrackedOutputs(TransmissionType.ITEM, index, outputSides); for(EnumFacing side : outputs) { TileEntity tile = Coord4D.get(tileEntity).offset(side).getTileEntity(tileEntity.getWorld()); ItemStack prev = stack.copy(); if(tile instanceof IInventory && !(CapabilityUtils.hasCapability(tile, Capabilities.LOGISTICAL_TRANSPORTER_CAPABILITY, side.getOpposite()))) { stack = InventoryUtils.putStackInInventory((IInventory)tile, stack, side, false); } else if(CapabilityUtils.hasCapability(tile, Capabilities.LOGISTICAL_TRANSPORTER_CAPABILITY, side.getOpposite())) { ItemStack rejects = TransporterUtils.insert(tileEntity, CapabilityUtils.getCapability(tile, Capabilities.LOGISTICAL_TRANSPORTER_CAPABILITY, side.getOpposite()), stack, outputColor, true, 0); if(TransporterManager.didEmit(stack, rejects)) { stack = rejects; } } if(stack == null || prev.stackSize != stack.stackSize) { trackers.get(TransmissionType.ITEM)[index] = side.ordinal(); } if(stack == null) { break; } } tileEntity.setInventorySlotContents(slotID, stack); tileEntity.markDirty(); } tickDelay = 20; } public boolean hasStrictInput() { return strictInput; } public void setStrictInput(boolean strict) { strictInput = strict; MekanismUtils.saveChunk(tileEntity); } public void setOutputColor(EnumColor color) { outputColor = color; MekanismUtils.saveChunk(tileEntity); } public EnumColor getOutputColor() { return outputColor; } public void setInputColor(EnumFacing side, EnumColor color) { inputColors[side.ordinal()] = color; MekanismUtils.saveChunk(tileEntity); } public EnumColor getInputColor(EnumFacing side) { return inputColors[side.ordinal()]; } @Override public void read(NBTTagCompound nbtTags) { strictInput = nbtTags.getBoolean("strictInput"); if(nbtTags.hasKey("ejectColor")) { outputColor = TransporterUtils.colors.get(nbtTags.getInteger("ejectColor")); } for(TransmissionType type : sideData.keySet()) { for(int i = 0; i < sideData.get(type).availableSlots.length; i++) { trackers.get(type)[i] = nbtTags.getInteger("tracker" + type.getTransmission() + i); } } for(int i = 0; i < 6; i++) { if(nbtTags.hasKey("inputColors" + i)) { int inC = nbtTags.getInteger("inputColors" + i); if(inC != -1) { inputColors[i] = TransporterUtils.colors.get(inC); } else { inputColors[i] = null; } } } } @Override public void read(ByteBuf dataStream) { strictInput = dataStream.readBoolean(); int c = dataStream.readInt(); if(c != -1) { outputColor = TransporterUtils.colors.get(c); } else { outputColor = null; } for(int i = 0; i < 6; i++) { int inC = dataStream.readInt(); if(inC != -1) { inputColors[i] = TransporterUtils.colors.get(inC); } else { inputColors[i] = null; } } } @Override public void write(NBTTagCompound nbtTags) { nbtTags.setBoolean("strictInput", strictInput); if(outputColor != null) { nbtTags.setInteger("ejectColor", TransporterUtils.colors.indexOf(outputColor)); } for(TransmissionType type : sideData.keySet()) { for(int i = 0; i < sideData.get(type).availableSlots.length; i++) { nbtTags.setInteger("tracker" + type.getTransmission() + i, trackers.get(type)[i]); } } for(int i = 0; i < 6; i++) { if(inputColors[i] == null) { nbtTags.setInteger("inputColors" + i, -1); } else { nbtTags.setInteger("inputColors" + i, TransporterUtils.colors.indexOf(inputColors[i])); } } } @Override public void write(ArrayList<Object> data) { data.add(strictInput); if(outputColor != null) { data.add(TransporterUtils.colors.indexOf(outputColor)); } else { data.add(-1); } for(int i = 0; i < 6; i++) { if(inputColors[i] == null) { data.add(-1); } else { data.add(TransporterUtils.colors.indexOf(inputColors[i])); } } } @Override public void invalidate() {} private boolean getEjecting(TransmissionType type) { return ((ISideConfiguration)tileEntity).getConfig().isEjecting(type); } }