From 4ef06dc48a92925beade7985262072ebb3f55e68 Mon Sep 17 00:00:00 2001 From: Rseifert Date: Thu, 4 Apr 2013 00:27:46 -0400 Subject: [PATCH] added construction pump working on rewriting this from scratch based off of a demo pump i've been working of out of project. The demo pump was limited though it functioned very well. This new pump will be designed to drain lakes, and even oceans if the area can stay loaded. As well it works like the redpower one and will drain water threw a drain rather than an actual block pump. The pump will request the drain to find it liquid and fill the pump(Not how it works in real life but best way to simulate it). --- .../common/pump/PathfinderCheckerLiquid.java | 60 +++++ .../pump/TileEntityConstructionPump.java | 101 +++++++++ .../common/pump/TileEntityDrain.java | 154 +++++++++++++ .../common/pump/TileEntityStarterPump.java | 209 ++++++++++++++++++ 4 files changed, 524 insertions(+) create mode 100644 src/minecraft/fluidmech/common/pump/PathfinderCheckerLiquid.java create mode 100644 src/minecraft/fluidmech/common/pump/TileEntityConstructionPump.java create mode 100644 src/minecraft/fluidmech/common/pump/TileEntityDrain.java create mode 100644 src/minecraft/fluidmech/common/pump/TileEntityStarterPump.java 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; + } + +}