diff --git a/src/minecraft/fluidmech/common/pump/PathfinderCheckerLiquid.java b/src/minecraft/fluidmech/common/pump/PathfinderCheckerLiquid.java new file mode 100644 index 00000000..627d045b --- /dev/null +++ b/src/minecraft/fluidmech/common/pump/PathfinderCheckerLiquid.java @@ -0,0 +1,60 @@ +package fluidmech.common.pump; + +import fluidmech.common.FluidMech; +import hydraulic.helpers.FluidHelper; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.liquids.LiquidStack; +import universalelectricity.core.path.IPathCallBack; +import universalelectricity.core.path.Pathfinder; +import universalelectricity.core.vector.Vector3; + +/** + * Check if a conductor connects with another. + * + * @author Calclavia + * + */ +public class PathfinderCheckerLiquid extends Pathfinder +{ + public PathfinderCheckerLiquid(final World world, final int maxResources, final LiquidStack resource, final Vector3... ignoreList) + { + super(new IPathCallBack() + { + @Override + public Set getConnectedNodes(Pathfinder finder, Vector3 currentNode) + { + Set neighbors = new HashSet(); + + for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) + { + Vector3 pos = currentNode.clone().modifyPositionFromSide(direction); + + if (FluidHelper.isStillLiquid(world,pos) && FluidHelper.getLiquidFromBlockId(pos.getBlockID(world)).equals(resource)) + { + neighbors.add(pos); + } + } + + return neighbors; + } + + @Override + public boolean onSearch(Pathfinder finder, Vector3 node) + { + if (finder.closedSet.size() >= maxResources) + { + return true; + } + + return false; + } + }); + } +} diff --git a/src/minecraft/fluidmech/common/pump/TileEntityConstructionPump.java b/src/minecraft/fluidmech/common/pump/TileEntityConstructionPump.java new file mode 100644 index 00000000..c114d356 --- /dev/null +++ b/src/minecraft/fluidmech/common/pump/TileEntityConstructionPump.java @@ -0,0 +1,101 @@ +package fluidmech.common.pump; + +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.liquids.ILiquidTank; +import net.minecraftforge.liquids.ITankContainer; +import net.minecraftforge.liquids.LiquidContainerRegistry; +import net.minecraftforge.liquids.LiquidStack; +import net.minecraftforge.liquids.LiquidTank; +import universalelectricity.core.electricity.ElectricityPack; +import universalelectricity.core.vector.Vector3; +import universalelectricity.core.vector.VectorHelper; +import universalelectricity.prefab.tile.TileEntityElectricityRunnable; + +public class TileEntityConstructionPump extends TileEntityElectricityRunnable implements ITankContainer +{ + /* ENERGY PER TICK TO TRY TO PUMP */ + public static final double WATTS_PER_TICK = 100; + /* LIQUID FLOW CONNECTION SIDES */ + private ForgeDirection outputSide = ForgeDirection.UNKNOWN; + private ForgeDirection inputSide = ForgeDirection.UNKNOWN; + /* Fake Internal Tank */ + private LiquidTank fakeTank = new LiquidTank(LiquidContainerRegistry.BUCKET_VOLUME); + + @Override + public void updateEntity() + { + + } + + @Override + public ElectricityPack getRequest() + { + return new ElectricityPack(WATTS_PER_TICK / this.getVoltage(), this.getVoltage()); + } + + @Override + public boolean canConnect(ForgeDirection direction) + { + return direction != outputSide && direction != inputSide; + } + + @Override + public int fill(ForgeDirection from, LiquidStack resource, boolean doFill) + { + if (from != inputSide) + { + return 0; + } + return this.fill(0, resource, doFill); + } + + @Override + public int fill(int tankIndex, LiquidStack resource, boolean doFill) + { + if (tankIndex != 0 || resource == null) + { + return 0; + } + TileEntity entity = VectorHelper.getTileEntityFromSide(this.worldObj, new Vector3(this), outputSide); + if (entity instanceof ITankContainer) + { + return ((ITankContainer) entity).fill(outputSide.getOpposite(), resource, doFill); + } + return 0; + } + + @Override + public LiquidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) + { + // TODO maybe have it make a request for liquid if something tries to drain it + return null; + } + + @Override + public LiquidStack drain(int tankIndex, int maxDrain, boolean doDrain) + { + return null; + } + + @Override + public ILiquidTank[] getTanks(ForgeDirection direction) + { + if (direction == this.inputSide) + { + return new ILiquidTank[] { fakeTank }; + } + return null; + } + + @Override + public ILiquidTank getTank(ForgeDirection direction, LiquidStack type) + { + if (direction == this.inputSide) + { + return fakeTank; + } + return null; + } + +} diff --git a/src/minecraft/fluidmech/common/pump/TileEntityDrain.java b/src/minecraft/fluidmech/common/pump/TileEntityDrain.java new file mode 100644 index 00000000..000ed318 --- /dev/null +++ b/src/minecraft/fluidmech/common/pump/TileEntityDrain.java @@ -0,0 +1,154 @@ +package fluidmech.common.pump; + +import hydraulic.helpers.FluidHelper; +import hydraulic.prefab.tile.TileEntityFluidDevice; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.liquids.ITankContainer; +import net.minecraftforge.liquids.LiquidStack; +import universalelectricity.core.vector.Vector3; +import universalelectricity.core.vector.VectorHelper; + +public class TileEntityDrain extends TileEntityFluidDevice +{ + private ForgeDirection face = ForgeDirection.UNKNOWN; + private boolean drainSources = true; + + /* LIST OF PUMPS AND THERE REQUESTS FOR THIS DRAIN */ + private HashMap requestMap = new HashMap(); + + private List targetSources = new ArrayList(); + + @Override + public String getMeterReading(EntityPlayer user, ForgeDirection side) + { + return (drainSources ? "Draining" : ""); + } + + @Override + public void updateEntity() + { + + if (!this.worldObj.isRemote && this.ticks % 10 == 0) + { + /* MAIN LOGIC PATH FOR DRAINING BODIES OF LIQUID */ + if (this.drainSources) + { + TileEntity entity = VectorHelper.getTileEntityFromSide(worldObj, new Vector3(this), this.face.getOpposite()); + if (entity instanceof ITankContainer) + { + if (this.requestMap.size() > 0) + { + this.getNextFluidBlock(); + int blocksDrained = 0; + for (Vector3 loc : targetSources) + { + if (blocksDrained >= 5 && FluidHelper.isStillLiquid(this.worldObj, loc)) + { + LiquidStack stack = FluidHelper.getLiquidFromBlockId(loc.getBlockID(this.worldObj)); + if (stack != null) + { + for (Entry pump : requestMap.entrySet()) + { + if (pump.getValue().isLiquidEqual(stack)) + { + if (((ITankContainer) entity).fill(0, stack, false) >= stack.amount) + { + ((ITankContainer) entity).fill(0, stack, true); + loc.setBlock(this.worldObj, 0); + blocksDrained++; + } + } + } + } + } + } + } + } + }// END OF DRAIN + else + { + // TODO time to have fun finding a place for this block to exist + } + } + } + + /** + * uses the LiquidStack to fill the area bellow the drain + * + * @param stack - liquidStack + * @return amount of liquid consumed + */ + public int fillArea(LiquidStack stack) + { + return 0; + } + + @Override + public boolean canPipeConnect(TileEntity entity, ForgeDirection dir) + { + return dir == face.getOpposite(); + } + + /** + * Requests that this drain give the pump this liquid. The pump will have to decide if it can + * accept, request, and maintain this demand + * + * @param pump - requesting pump + * @param stack - liquid this pump wants for this request + */ + public void requestLiquid(TileEntityConstructionPump pump, LiquidStack stack) + { + this.requestMap.put(pump, stack); + } + + /** + * Request that this drain no longer supply the pump with a volume. By default a request will be + * removed from the request map after being filled. However, this can be used too stop a request + * short if the pump becomes full before the request is filled + * + * @param pump - requesting pump + */ + public void stopRequesting(TileEntityConstructionPump pump) + { + if (this.requestMap.containsKey(pump)) + { + this.requestMap.remove(pump); + } + } + + /** + * Finds at least 10 more liquid possible targets for the pump to pump + */ + public void getNextFluidBlock() + { + int blockID = Block.waterStill.blockID; + int y = this.yCoord + 1; + while (blockID == Block.waterStill.blockID) + { + blockID = worldObj.getBlockId(xCoord, y, zCoord); + if (blockID == Block.waterStill.blockID) + { + y++; + } + + } + PathfinderCheckerLiquid pathFinder = new PathfinderCheckerLiquid(worldObj, 10, null, (Vector3[]) this.targetSources.toArray()); + pathFinder.init(new Vector3(xCoord, y, zCoord)); + for (Vector3 loc : pathFinder.closedSet) + { + if (!this.targetSources.contains(loc)) + { + this.targetSources.add(loc); + } + } + } +} diff --git a/src/minecraft/fluidmech/common/pump/TileEntityStarterPump.java b/src/minecraft/fluidmech/common/pump/TileEntityStarterPump.java new file mode 100644 index 00000000..f11c80c4 --- /dev/null +++ b/src/minecraft/fluidmech/common/pump/TileEntityStarterPump.java @@ -0,0 +1,209 @@ +package fluidmech.common.pump; + +import hydraulic.api.ColorCode; +import hydraulic.api.IColorCoded; +import hydraulic.api.IPipeConnection; +import hydraulic.api.IReadOut; +import hydraulic.helpers.FluidHelper; +import hydraulic.helpers.MetaGroup; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.INetworkManager; +import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.liquids.ITankContainer; +import net.minecraftforge.liquids.LiquidContainerRegistry; +import net.minecraftforge.liquids.LiquidStack; +import universalelectricity.core.electricity.ElectricityPack; +import universalelectricity.core.vector.Vector3; +import universalelectricity.core.vector.VectorHelper; +import universalelectricity.prefab.network.IPacketReceiver; +import universalelectricity.prefab.tile.TileEntityElectricityRunnable; + +import com.google.common.io.ByteArrayDataInput; + +public class TileEntityStarterPump extends TileEntityElectricityRunnable implements IPacketReceiver, IReadOut, IPipeConnection +{ + public final double WATTS_PER_TICK = (400 / 20); + private double percentPumped = 0.0; + + public int pos = 0; + + public ColorCode color = ColorCode.BLUE; + + ForgeDirection wireConnection = ForgeDirection.EAST; + ForgeDirection pipeConnection = ForgeDirection.EAST; + + /** + * gets the side connection for the wire and pipe + */ + public void getConnections() + { + int notchMeta = MetaGroup.getFacingMeta(worldObj.getBlockMetadata(xCoord, yCoord, zCoord)); + + wireConnection = ForgeDirection.getOrientation(notchMeta); + pipeConnection = VectorHelper.getOrientationFromSide(wireConnection, ForgeDirection.WEST); + + if (notchMeta == 2 || notchMeta == 3) + { + pipeConnection = pipeConnection.getOpposite(); + } + } + + @Override + public void initiate() + { + this.getConnections(); + } + + @Override + public void updateEntity() + { + super.updateEntity(); + + this.getConnections(); + + if (!this.worldObj.isRemote && !this.isDisabled()) + { + if (this.canPump(xCoord, yCoord - 1, zCoord) && this.wattsReceived >= this.WATTS_PER_TICK) + { + wattsReceived -= this.WATTS_PER_TICK; + if (percentPumped < 10) + { + percentPumped++; + } + else if (percentPumped >= 10 && this.drainBlock(new Vector3(xCoord, yCoord - 1, zCoord))) + { + percentPumped = 0; + } + + /* DO ANIMATION CHANGE */ + this.pos++; + if (pos >= 8) + { + pos = 0; + } + } + if (this.ticks % 10 == 0) + { + // Packet packet = PacketManager.getPacket(FluidMech.CHANNEL, this, color.ordinal(), + // this.wattsReceived); + // PacketManager.sendPacketToClients(packet, worldObj, new Vector3(this), 60); + } + } + + } + + @Override + public void handlePacketData(INetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput data) + { + try + { + this.color = ColorCode.get(data.readInt()); + this.wattsReceived = data.readDouble(); + } + catch (Exception e) + { + e.printStackTrace(); + } + + } + + /** + * gets the fluidConductor or storageTank to ouput its pumped liquids too if there is not one it + * will not function + */ + public ITankContainer getFillTarget() + { + TileEntity ent = worldObj.getBlockTileEntity(xCoord + pipeConnection.offsetX, yCoord + pipeConnection.offsetY, zCoord + pipeConnection.offsetZ); + + if (ent instanceof ITankContainer) + { + return (ITankContainer) ent; + } + return null; + } + + /** + * gets the search range the pump used to find valid block to pump + */ + public int getPumpRange() + { + int meta = worldObj.getBlockMetadata(xCoord, yCoord, zCoord); + switch (MetaGroup.getGrouping(meta)) + { + case 2: + return 20; + case 3: + return 50; + } + return 1; + } + + @Override + public ElectricityPack getRequest() + { + double amps = (this.WATTS_PER_TICK / this.getVoltage()); + return new ElectricityPack(amps, this.getVoltage()); + } + + /** + * checks to see if this pump can pump the selected target block + * + * @param x y z - location of the block, use the tileEntities world + * @return true if it can pump + */ + boolean canPump(int x, int y, int z) + { + return getFillTarget() != null && FluidHelper.getLiquidId(worldObj.getBlockId(x, y, z)) != -1 && worldObj.getBlockMetadata(x, y, z) == 0 ; + } + + /** + * drains the block(removes) at the location given + * + * @param loc - vector 3 location + * @return true if the block was drained + */ + boolean drainBlock(Vector3 loc) + { + int blockID = worldObj.getBlockId(loc.intX(), loc.intY(), loc.intZ()); + + LiquidStack stack = FluidHelper.getLiquidFromBlockId(blockID); + if (color.isValidLiquid(stack) && getFillTarget() != null) + { + stack.amount = LiquidContainerRegistry.BUCKET_VOLUME; + int fillAmmount = getFillTarget().fill(pipeConnection.getOpposite(), stack, true); + + if (fillAmmount > 0) + { + worldObj.setBlockMetadataWithNotify(xCoord, yCoord - 1, zCoord, 0, 0); + return true; + } + } + + return false; + } + + @Override + public String getMeterReading(EntityPlayer user, ForgeDirection side) + { + return String.format("%.2f/%.2f %f Done", this.wattsReceived,this.WATTS_PER_TICK,this.percentPumped); + } + + @Override + public boolean canConnect(ForgeDirection direction) + { + return direction == wireConnection; + } + + @Override + public boolean canPipeConnect(TileEntity entity, ForgeDirection dir) + { + if (dir == this.pipeConnection.getOpposite()) + { + return entity != null && entity instanceof IColorCoded && (((IColorCoded) entity).getColor() == ColorCode.NONE || ((IColorCoded) entity).getColor() == this.color); + } + return false; + } + +}