Advertisement
Guest User

Untitled

a guest
Jan 15th, 2016
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 31.16 KB | None | 0 0
  1. Block:
  2.  
  3. package com.lordmau5.ffs.blocks;
  4.  
  5. import com.lordmau5.ffs.FancyFluidStorage;
  6. import com.lordmau5.ffs.tile.TileEntityValve;
  7. import com.lordmau5.ffs.util.FFSStateProps;
  8. import com.lordmau5.ffs.util.GenericUtil;
  9. import net.minecraft.block.Block;
  10. import net.minecraft.block.material.Material;
  11. import net.minecraft.block.state.BlockState;
  12. import net.minecraft.block.state.IBlockState;
  13. import net.minecraft.creativetab.CreativeTabs;
  14. import net.minecraft.entity.EntityLiving;
  15. import net.minecraft.entity.player.EntityPlayer;
  16. import net.minecraft.item.Item;
  17. import net.minecraft.tileentity.TileEntity;
  18. import net.minecraft.util.BlockPos;
  19. import net.minecraft.util.EnumFacing;
  20. import net.minecraft.util.EnumWorldBlockLayer;
  21. import net.minecraft.world.Explosion;
  22. import net.minecraft.world.IBlockAccess;
  23. import net.minecraft.world.World;
  24. import net.minecraftforge.fml.relauncher.Side;
  25. import net.minecraftforge.fml.relauncher.SideOnly;
  26.  
  27. import java.util.Random;
  28.  
  29. /**
  30.  * Created by Dustin on 28.06.2015.
  31.  */
  32. public class BlockValve extends Block {
  33.  
  34.     public BlockValve() {
  35.         super(Material.iron);
  36.         setUnlocalizedName("blockValve");
  37.         setRegistryName("blockValve");
  38.         setCreativeTab(CreativeTabs.tabRedstone);
  39.         setHardness(5.0F); // Same hardness as an iron block
  40.         setResistance(10.0F); // Same as hardness
  41.  
  42.         setDefaultState((blockState.getBaseState())
  43.                 .withProperty(FFSStateProps.VALVE_VALID, false)
  44.                 .withProperty(FFSStateProps.VALVE_MASTER, false)
  45.                 .withProperty(FFSStateProps.VALVE_INSIDE, EnumFacing.Axis.X));
  46.     }
  47.  
  48.     @Override
  49.     public boolean hasTileEntity(IBlockState state) {
  50.         return true;
  51.     }
  52.  
  53.     @Override
  54.     public TileEntity createTileEntity(World world, IBlockState state) {
  55.         return new TileEntityValve();
  56.     }
  57.  
  58.     @Override
  59.     public void onBlockExploded(World world, BlockPos pos, Explosion explosion) {
  60.         TileEntity tile = world.getTileEntity(pos);
  61.         if(tile != null && tile instanceof TileEntityValve) {
  62.             TileEntityValve valve = (TileEntityValve) world.getTileEntity(pos);
  63.             valve.breakTank(null);
  64.         }
  65.         super.onBlockDestroyedByExplosion(world, pos, explosion);
  66.     }
  67.  
  68.     @Override
  69.     public void breakBlock(World world, BlockPos pos, IBlockState state) {
  70.         if(!world.isRemote) {
  71.             TileEntityValve valve = (TileEntityValve) world.getTileEntity(pos);
  72.             valve.breakTank(null);
  73.         }
  74.  
  75.         super.breakBlock(world, pos, state);
  76.     }
  77.  
  78.     @Override
  79.     public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ) {
  80.         if (super.onBlockActivated(world, pos, state, player, side, hitX, hitY, hitZ)) {
  81.             return true;
  82.         }
  83.         if (player.isSneaking()) return false;
  84.  
  85.         TileEntityValve valve = (TileEntityValve) world.getTileEntity(pos);
  86.  
  87.         if(valve.isValid()) {
  88.             if(GenericUtil.isFluidContainer(player.getHeldItem()))
  89.                 return GenericUtil.fluidContainerHandler(world, pos, valve, player, side);
  90.  
  91.             player.openGui(FancyFluidStorage.instance, 0, world, pos.getX(), pos.getY(), pos.getZ());
  92.             return true;
  93.         }
  94.         else {
  95.             valve.buildTank(side.getOpposite());
  96.         }
  97.         return true;
  98.     }
  99.  
  100.     @Override
  101.     public Item getItemDropped(IBlockState state, Random rand, int fortune) {
  102.         return Item.getItemFromBlock(FancyFluidStorage.blockValve);
  103.     }
  104.  
  105.     @Override
  106.     public boolean canRenderInLayer(EnumWorldBlockLayer layer) {
  107.         return layer == EnumWorldBlockLayer.SOLID || layer == EnumWorldBlockLayer.TRANSLUCENT;
  108.     }
  109.  
  110.     @Override
  111.     protected BlockState createBlockState() {
  112.         return new BlockState(this, FFSStateProps.VALVE_VALID, FFSStateProps.VALVE_MASTER, FFSStateProps.VALVE_INSIDE);
  113.     }
  114.  
  115.     @Override
  116.     public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos) {
  117.         TileEntity tile = world.getTileEntity(pos);
  118.         if(tile != null && tile instanceof TileEntityValve) {
  119.             TileEntityValve valve = (TileEntityValve) tile;
  120.  
  121.             state = state.withProperty(FFSStateProps.VALVE_VALID, valve.isValid())
  122.                     .withProperty(FFSStateProps.VALVE_MASTER, valve.isMaster())
  123.                     .withProperty(FFSStateProps.VALVE_INSIDE, (valve.getInside() == null) ? EnumFacing.Axis.X : valve.getInside().getAxis());
  124.         }
  125.         return state;
  126.     }
  127.  
  128.     @Override
  129.     public IBlockState getStateFromMeta(int meta) {
  130.         return getDefaultState();
  131.     }
  132.  
  133.     @Override
  134.     public int getMetaFromState(IBlockState state) {
  135.         return 0;
  136.     }
  137.  
  138.     @SideOnly(Side.CLIENT)
  139.     @Override
  140.     public int getRenderType() {
  141.         return 3;
  142.     }
  143.  
  144.     @Override
  145.     public boolean isOpaqueCube() {
  146.         return false;
  147.     }
  148.  
  149.     @Override
  150.     public boolean isNormalCube(IBlockAccess world, BlockPos pos) {
  151.         return true;
  152.     }
  153.  
  154.     @Override
  155.     public boolean isNormalCube() {
  156.         return true;
  157.     }
  158.  
  159.     @Override
  160.     public boolean hasComparatorInputOverride() {
  161.         return true;
  162.     }
  163.  
  164.     @Override
  165.     public boolean canCreatureSpawn(IBlockAccess world, BlockPos pos, EntityLiving.SpawnPlacementType type) {
  166.         return false;
  167.     }
  168. }
  169.  
  170. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  171. Tile:
  172.  
  173. package com.lordmau5.ffs.tile;
  174.  
  175. import com.lordmau5.ffs.FancyFluidStorage;
  176. import com.lordmau5.ffs.util.GenericUtil;
  177. import net.minecraft.block.state.IBlockState;
  178. import net.minecraft.nbt.NBTTagCompound;
  179. import net.minecraft.network.NetworkManager;
  180. import net.minecraft.network.Packet;
  181. import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
  182. import net.minecraft.tileentity.TileEntity;
  183. import net.minecraft.util.BlockPos;
  184. import net.minecraft.util.EnumFacing;
  185. import net.minecraft.util.ITickable;
  186. import net.minecraft.world.ChunkCoordIntPair;
  187. import net.minecraft.world.chunk.Chunk;
  188. import net.minecraftforge.common.ForgeChunkManager;
  189. import net.minecraftforge.fluids.*;
  190.  
  191. import java.util.ArrayList;
  192. import java.util.List;
  193. import java.util.Map;
  194.  
  195. /**
  196.  * Created by Dustin on 28.06.2015.
  197.  */
  198.  
  199. public class TileEntityValve extends TileEntity implements IFluidTank, IFluidHandler, ITickable {
  200.  
  201.     private final int maxSize = FancyFluidStorage.instance.MAX_SIZE;
  202.     protected int mbPerVirtualTank = FancyFluidStorage.instance.MB_PER_TANK_BLOCK;
  203.  
  204.     private boolean wantsUpdate;
  205.     private String valveName = "";
  206.     private boolean isValid;
  207.     private boolean isMaster;
  208.     private BlockPos masterValvePos;
  209.     public boolean initiated;
  210.  
  211.     public int tankHeight = 0;
  212.     public int valveHeightPosition = 0;
  213.     private boolean autoOutput;
  214.  
  215.     private EnumFacing inside = EnumFacing.UP;
  216.  
  217.     private TileEntityValve master;
  218.     public List<TileEntityTankFrame> tankFrames;
  219.     public List<TileEntityValve> otherValves;
  220.  
  221.     private Map<BlockPos, IBlockState>[] maps;
  222.  
  223.     /**
  224.      * Length of the inside
  225.      *
  226.      * 0 = Down
  227.      * 1 = Up
  228.      * 2 = North
  229.      * 3 = South
  230.      * 4 = West
  231.      * 5 = East
  232.      */
  233.     private int[] length = new int[6];
  234.     public BlockPos bottomDiagFrame, topDiagFrame;
  235.     public int initialWaitTick = 20;
  236.  
  237.     // TANK LOGIC
  238.     private FluidStack fluidStack;
  239.     private int fluidCapacity = 0;
  240.     // ---------------
  241.  
  242.     public TileEntityValve() {
  243.         tankFrames = new ArrayList<>();
  244.         otherValves = new ArrayList<>();
  245.     }
  246.  
  247.     @Override
  248.     public void validate() {
  249.         super.validate();
  250.         initiated = true;
  251.         initialWaitTick = 20;
  252.     }
  253.  
  254.     @Override
  255.     public void update() {
  256.         if(getWorld().isRemote)
  257.             return;
  258.  
  259.         if(wantsUpdate && getWorld() != null) {
  260.             if(initiated) {
  261.                 if (isMaster()) {
  262.                     if (bottomDiagFrame != null && topDiagFrame != null) { // Potential fix for huge-ass tanks not loading properly on master-valve chunk load.
  263.                         Chunk chunkBottom = worldObj.getChunkFromBlockCoords(bottomDiagFrame);
  264.                         Chunk chunkTop = worldObj.getChunkFromBlockCoords(topDiagFrame);
  265.  
  266.                         BlockPos pos_chunkBottom = new BlockPos(chunkBottom.xPosition, 0, chunkBottom.zPosition);
  267.                         BlockPos pos_chunkTop = new BlockPos(chunkTop.xPosition, 0, chunkTop.zPosition);
  268.  
  269.                         BlockPos diff = pos_chunkTop.subtract(pos_chunkBottom);
  270.                         for (int x = 0; x <= diff.getX(); x++) {
  271.                             for (int z = 0; z <= diff.getZ(); z++) {
  272.                                 ForgeChunkManager.forceChunk(ForgeChunkManager.requestTicket(FancyFluidStorage.instance, worldObj, ForgeChunkManager.Type.NORMAL), new ChunkCoordIntPair(pos_chunkTop.getX() + x, pos_chunkTop.getZ() + z));
  273.                             }
  274.                         }
  275.  
  276.                         updateBlockAndNeighbors();
  277.                     }
  278.                     if (initialWaitTick-- <= 0) {
  279.                         initiated = false;
  280.                         buildTank(getInside());
  281.                         return;
  282.                     }
  283.                 }
  284.             }
  285.         }
  286.  
  287.         if(!isValid())
  288.             return;
  289.  
  290.         if(!isMaster() && getMaster() == null) {
  291.             setValid(false);
  292.             updateBlockAndNeighbors();
  293.         }
  294.     }
  295.  
  296.     private List<TileEntityValve> getAllValves() {
  297.         if(!isMaster() && getMaster() != this)
  298.             return getMaster().getAllValves();
  299.  
  300.         List<TileEntityValve> valves = new ArrayList<>();
  301.         valves.add(this);
  302.  
  303.         if(otherValves.isEmpty())
  304.             return valves;
  305.  
  306.         for(TileEntityValve valve : otherValves)
  307.             valves.add(valve);
  308.  
  309.         return valves;
  310.     }
  311.  
  312.     public String getValveName() {
  313.         if(this.valveName.isEmpty())
  314.             setValveName(GenericUtil.getUniqueValveName(this));
  315.  
  316.         return this.valveName;
  317.     }
  318.  
  319.     public void setValveName(String valveName) {
  320.         this.valveName = valveName;
  321.     }
  322.  
  323.     public void setNeedsUpdate() {
  324.         wantsUpdate = true;
  325.     }
  326.  
  327.     public int getTankHeight() {
  328.         return isMaster() ? tankHeight : getMaster().tankHeight;
  329.     }
  330.  
  331.     public void setInside(EnumFacing inside) {
  332.         this.inside = inside;
  333.     }
  334.  
  335.     public EnumFacing getInside() {
  336.         return this.inside;
  337.     }
  338.  
  339.     /**
  340.      * Let's build a tank!
  341.      * @param inside - The direction of the inside of the tank
  342.      */
  343.     public void buildTank(EnumFacing inside) {
  344.         /**
  345.          * Don't build if it's on the client!
  346.          */
  347.         if (getWorld().isRemote)
  348.             return;
  349.  
  350.         /**
  351.          * Let's first set the tank to be invalid,
  352.          * since it should stay like that if the building fails.
  353.          * Also, let's reset variables.
  354.          */
  355.         setValid(false);
  356.  
  357.         fluidCapacity = 0;
  358.         tankFrames.clear();
  359.         otherValves.clear();
  360.  
  361.         /**
  362.          * Now, set the inside direction according to the variable,
  363.          * *IF* our current inside is null.
  364.          */
  365.         if(inside != null)
  366.             setInside(inside);
  367.  
  368.         if(!calculateInside())
  369.             return;
  370.  
  371.         /**
  372.          * Actually setup the tank here
  373.          */
  374.         if(!setupTank())
  375.             return;
  376.  
  377.         /**
  378.          * Just in case, set *initiated* to false again.
  379.          * Also, update our neighbor blocks, e.g. pipes or similar.
  380.          */
  381.         initiated = false;
  382.         updateBlockAndNeighbors();
  383.     }
  384.  
  385.     /**
  386.      * Over here, let's calculate the inside length,
  387.      * which is required to get the corner points later on.
  388.      * Also, to know if the inside of the tank is completely air.
  389.      */
  390.     public boolean calculateInside() {
  391.         BlockPos insidePos = getPos().offset(getInside());
  392.  
  393.         for(EnumFacing dr : EnumFacing.VALUES) {
  394.             for(int i=0; i<maxSize; i++) {
  395.                 BlockPos offsetPos = insidePos.offset(dr, i);
  396.                 if(!worldObj.isAirBlock(offsetPos)) {
  397.                     length[dr.ordinal()] = i - 1;
  398.                     break;
  399.                 }
  400.             }
  401.         }
  402.  
  403.         for(int i=0; i<6; i += 2) {
  404.             if(length[i] + length[i + 1] > maxSize)
  405.                 return false;
  406.         }
  407.         return length[0] != -1;
  408.     }
  409.  
  410.     private void setSlaveValveInside(Map<BlockPos, IBlockState> airBlocks, TileEntityValve slave) {
  411.         List<BlockPos> possibleAirBlocks = new ArrayList<>();
  412.         for(EnumFacing dr : EnumFacing.VALUES) {
  413.             if(worldObj.isAirBlock(slave.getPos().offset(dr)))
  414.                 possibleAirBlocks.add(slave.getPos().offset(dr));
  415.         }
  416.  
  417.         BlockPos insideAir = null;
  418.         for(BlockPos pos : possibleAirBlocks) {
  419.             if (airBlocks.containsKey(pos)) {
  420.                 insideAir = pos;
  421.                 break;
  422.             }
  423.         }
  424.  
  425.         if(insideAir == null)
  426.             return;
  427.  
  428.         BlockPos dist = insideAir.subtract(slave.getPos());
  429.         for(EnumFacing dr : EnumFacing.VALUES) {
  430.             if(dist.equals(new BlockPos(dr.getFrontOffsetX(), dr.getFrontOffsetY(), dr.getFrontOffsetZ()))) {
  431.                 slave.setInside(dr);
  432.                 break;
  433.             }
  434.         }
  435.     }
  436.  
  437.     /**
  438.      * Let's get the corner frames based on the inside position and length,
  439.      * so we can set the BlockPos according to the corners.
  440.      */
  441.     public void updateCornerFrames() {
  442.         bottomDiagFrame = getPos().add(inside.getDirectionVec()).add(length[EnumFacing.WEST.ordinal()] * EnumFacing.WEST.getFrontOffsetX() + EnumFacing.WEST.getFrontOffsetX(),
  443.                 length[EnumFacing.DOWN.ordinal()] * EnumFacing.DOWN.getFrontOffsetY() + EnumFacing.DOWN.getFrontOffsetY(),
  444.                 length[EnumFacing.NORTH.ordinal()] * EnumFacing.NORTH.getFrontOffsetZ() + EnumFacing.NORTH.getFrontOffsetZ());
  445.  
  446.         topDiagFrame = getPos().add(inside.getDirectionVec()).add(length[EnumFacing.EAST.ordinal()] * EnumFacing.EAST.getFrontOffsetX() + EnumFacing.EAST.getFrontOffsetX(),
  447.                 length[EnumFacing.UP.ordinal()] * EnumFacing.UP.getFrontOffsetY() + EnumFacing.UP.getFrontOffsetY(),
  448.                 length[EnumFacing.SOUTH.ordinal()] * EnumFacing.SOUTH.getFrontOffsetZ() + EnumFacing.SOUTH.getFrontOffsetZ());
  449.     }
  450.  
  451.     /**
  452.      * The maps contain the blocks on the:
  453.      * inside,
  454.      * outter frame,
  455.      * inner frame
  456.      */
  457.     private void fetchMaps() {
  458.         maps = GenericUtil.getTankFrame(worldObj, bottomDiagFrame, topDiagFrame);
  459.     }
  460.  
  461.     private boolean setupTank() {
  462.         updateCornerFrames();
  463.         fetchMaps();
  464.  
  465.         otherValves = new ArrayList<>();
  466.         tankFrames = new ArrayList<>();
  467.  
  468.         valveHeightPosition = Math.abs(bottomDiagFrame.subtract(getPos()).getY());
  469.         tankHeight = topDiagFrame.subtract(bottomDiagFrame).getY() - 1;
  470.  
  471.         IBlockState bottomDiagBlock = worldObj.getBlockState(bottomDiagFrame);
  472.         IBlockState topDiagBlock = worldObj.getBlockState(topDiagFrame);
  473.  
  474.         if(!GenericUtil.isValidTankBlock(worldObj, bottomDiagFrame, bottomDiagBlock))
  475.             return false;
  476.  
  477.         if (!GenericUtil.areTankBlocksValid(bottomDiagBlock, topDiagBlock, worldObj, bottomDiagFrame))
  478.             return false;
  479.  
  480.         BlockPos pos;
  481.  
  482.         if (FancyFluidStorage.instance.INSIDE_CAPACITY) {
  483.             fluidCapacity = (maps[2].size()) * mbPerVirtualTank;
  484.         } else {
  485.             fluidCapacity = (maps[0].size() + maps[1].size() + maps[2].size()) * mbPerVirtualTank;
  486.         }
  487.  
  488.         for (Map.Entry<BlockPos, IBlockState> frameCheck : maps[0].entrySet()) {
  489.             pos = frameCheck.getKey();
  490.             IBlockState fBlock = frameCheck.getValue();
  491.  
  492.             if (!GenericUtil.areTankBlocksValid(fBlock, bottomDiagBlock, worldObj, pos))
  493.                 return false;
  494.         }
  495.  
  496.         List<TileEntityValve> valves = new ArrayList<>();
  497.         for (Map.Entry<BlockPos, IBlockState> insideFrameCheck : maps[1].entrySet()) {
  498.             pos = insideFrameCheck.getKey();
  499.             IBlockState check = insideFrameCheck.getValue();
  500.  
  501.             if (GenericUtil.areTankBlocksValid(check, bottomDiagBlock, worldObj, pos) || GenericUtil.isBlockGlass(check.getBlock(), check.getBlock().getMetaFromState(check)))
  502.                 continue;
  503.  
  504.             TileEntity tile = worldObj.getTileEntity(pos);
  505.             if (tile != null) {
  506.                 if (tile instanceof TileEntityValve) {
  507.                     TileEntityValve valve = (TileEntityValve) tile;
  508.                     if (valve == this)
  509.                         continue;
  510.  
  511.                     if (valve.fluidStack != null) {
  512.                         this.fluidStack = valve.fluidStack;
  513.                     }
  514.                     valves.add(valve);
  515.                     continue;
  516.                 }
  517.                 else if (tile instanceof TileEntityTankFrame) {
  518.                     continue;
  519.                 }
  520.                 return false;
  521.             }
  522.  
  523.             return false;
  524.         }
  525.  
  526.         // Make sure we don't overfill a tank. If the new tank is smaller than the old one, excess liquid disappear.
  527.         if (this.fluidStack != null)
  528.             this.fluidStack.amount = Math.min(this.fluidStack.amount, this.fluidCapacity);
  529.  
  530.         for (TileEntityValve valve : valves) {
  531.             pos = valve.getPos();
  532.             valve.valveHeightPosition = Math.abs(bottomDiagFrame.subtract(pos).getY());
  533.  
  534.             valve.isMaster = false;
  535.             valve.setMasterPos(getPos());
  536.             setSlaveValveInside(maps[2], valve);
  537.         }
  538.         isMaster = true;
  539.  
  540.         for (Map.Entry<BlockPos, IBlockState> setTiles : maps[0].entrySet()) {
  541.             pos = setTiles.getKey();
  542.             TileEntityTankFrame tankFrame;
  543.             if (setTiles.getValue().getBlock() != FancyFluidStorage.blockTankFrame) {
  544.                 getWorld().setBlockState(pos, FancyFluidStorage.blockTankFrame.getDefaultState());
  545.             }
  546.             tankFrame = (TileEntityTankFrame) getWorld().getTileEntity(pos);
  547.             tankFrame.initialize(getPos(), setTiles.getValue());
  548.             tankFrames.add(tankFrame);
  549.         }
  550.  
  551.         for (Map.Entry<BlockPos, IBlockState> setTiles : maps[1].entrySet()) {
  552.             pos = setTiles.getKey();
  553.             TileEntity tile = getWorld().getTileEntity(pos);
  554.             if (tile != null) {
  555.                 if (tile instanceof TileEntityValve && tile != this)
  556.                     otherValves.add((TileEntityValve) tile);
  557.  
  558.                 else if (tile instanceof TileEntityTankFrame) {
  559.                     ((TileEntityTankFrame) tile).setValvePos(getPos());
  560.                     tankFrames.add((TileEntityTankFrame) tile);
  561.                 }
  562.                 else if (GenericUtil.isTileEntityAcceptable(setTiles.getValue().getBlock(), tile)) {
  563.                     getWorld().setBlockState(pos, FancyFluidStorage.blockTankFrame.getDefaultState());
  564.                     TileEntityTankFrame tankFrame = (TileEntityTankFrame) getWorld().getTileEntity(pos);
  565.                     tankFrame.initialize(getPos(), setTiles.getValue());
  566.                     tankFrames.add(tankFrame);
  567.                 }
  568.             } else {
  569.                 getWorld().setBlockState(pos, FancyFluidStorage.blockTankFrame.getDefaultState());
  570.                 TileEntityTankFrame tankFrame = (TileEntityTankFrame) getWorld().getTileEntity(pos);
  571.                 tankFrame.initialize(getPos(), setTiles.getValue());
  572.                 tankFrames.add(tankFrame);
  573.             }
  574.         }
  575.  
  576.         setValid(true);
  577.         return true;
  578.     }
  579.  
  580.     public void breakTank(TileEntity frame) {
  581.         if (getWorld().isRemote)
  582.             return;
  583.  
  584.         if(!isMaster() && getMaster() != null) {
  585.             if(getMaster() != this)
  586.                 getMaster().breakTank(frame);
  587.  
  588.             return;
  589.         }
  590.  
  591.         for(TileEntityValve valve : otherValves) {
  592.             valve.fluidStack = getFluid();
  593.             valve.master = null;
  594.             valve.setValid(false);
  595.             valve.updateBlockAndNeighbors();
  596.         }
  597.  
  598.         for(TileEntityTankFrame tankFrame : tankFrames) {
  599.             if(frame == tankFrame)
  600.                 continue;
  601.  
  602.             tankFrame.breakFrame();
  603.         }
  604.         tankFrames.clear();
  605.         otherValves.clear();
  606.  
  607.         setValid(false);
  608.  
  609.         this.updateBlockAndNeighbors();
  610.     }
  611.  
  612.     public void setValid(boolean isValid) {
  613.         this.isValid = isValid;
  614.     }
  615.  
  616.     public boolean isValid() {
  617.         return getMaster() != null && getMaster().isValid;
  618.  
  619.     }
  620.  
  621.     public void updateBlockAndNeighbors() {
  622.         updateBlockAndNeighbors(false);
  623.     }
  624.  
  625.     public void updateBlockAndNeighbors(boolean onlyThis) {
  626.         if(getWorld().isRemote)
  627.             return;
  628.  
  629.         this.markForUpdate(onlyThis);
  630.  
  631.         if(otherValves != null) {
  632.             for(TileEntityValve otherValve : otherValves) {
  633.                 otherValve.markForUpdate(true);
  634.             }
  635.         }
  636.     }
  637.  
  638.     private void markForUpdate(boolean onlyThis) {
  639.         if (!onlyThis) {
  640.             for (TileEntityTankFrame frame : tankFrames) {
  641.                 frame.markForUpdate();
  642.             }
  643.         }
  644.         wantsUpdate = true;
  645.     }
  646.  
  647.     public boolean isMaster() {
  648.         return isMaster;
  649.     }
  650.  
  651.     public TileEntityValve getMaster() {
  652.         if(isMaster())
  653.             return this;
  654.  
  655.         if(masterValvePos != null) {
  656.             TileEntity tile = worldObj.getTileEntity(masterValvePos);
  657.             master = tile instanceof TileEntityValve ? (TileEntityValve) tile : null;
  658.         }
  659.  
  660.         return master;
  661.     }
  662.  
  663.     public void setMasterPos(BlockPos masterValvePos) {
  664.         this.masterValvePos = masterValvePos;
  665.         this.master = null;
  666.     }
  667.  
  668.     public boolean getAutoOutput() {
  669.         return isValid() && this.autoOutput;
  670.     }
  671.  
  672.     public void setAutoOutput(boolean autoOutput) {
  673.         this.autoOutput = autoOutput;
  674.         updateBlockAndNeighbors(true);
  675.     }
  676.  
  677.     @Override
  678.     public void readFromNBT(NBTTagCompound tag) {
  679.         super.readFromNBT(tag);
  680.  
  681.         setInside(EnumFacing.getFront(tag.getInteger("inside")));
  682.  
  683.         isMaster = tag.getBoolean("master");
  684.         if(isMaster()) {
  685.             setValid(tag.getBoolean("isValid"));
  686.  
  687.             if(tag.getBoolean("hasFluid")) {
  688.                 if(tag.hasKey("fluidName"))
  689.                     fluidStack = new FluidStack(FluidRegistry.getFluid(tag.getString("fluidName")), tag.getInteger("fluidAmount"));
  690.             }
  691.             else {
  692.                 fluidStack = null;
  693.             }
  694.  
  695.             tankHeight = tag.getInteger("tankHeight");
  696.             fluidCapacity = tag.getInteger("fluidCapacity");
  697.         }
  698.         else {
  699.             if(getMaster() == null && tag.hasKey("masterValve")) {
  700.                 int[] masterValveP = tag.getIntArray("masterValve");
  701.                 setMasterPos(new BlockPos(masterValveP[0], masterValveP[1], masterValveP[2]));
  702.             }
  703.         }
  704.  
  705.         autoOutput = tag.getBoolean("autoOutput");
  706.         if(tag.hasKey("valveName"))
  707.             setValveName(tag.getString("valveName"));
  708.         else
  709.             setValveName(GenericUtil.getUniqueValveName(this));
  710.  
  711.         if(tag.hasKey("bottomDiagF") && tag.hasKey("topDiagF")) {
  712.             int[] bottomDiagF = tag.getIntArray("bottomDiagF");
  713.             int[] topDiagF = tag.getIntArray("topDiagF");
  714.             bottomDiagFrame = new BlockPos(bottomDiagF[0], bottomDiagF[1], bottomDiagF[2]);
  715.             topDiagFrame = new BlockPos(topDiagF[0], topDiagF[1], topDiagF[2]);
  716.         }
  717.  
  718.         markForUpdate(true);
  719.     }
  720.  
  721.     @Override
  722.     public void writeToNBT(NBTTagCompound tag) {
  723.         tag.setInteger("inside", getInside().ordinal());
  724.  
  725.         tag.setBoolean("master", isMaster());
  726.         if(isMaster()) {
  727.             tag.setBoolean("isValid", isValid());
  728.             tag.setBoolean("hasFluid", fluidStack != null);
  729.             if(fluidStack != null) {
  730.                 tag.setString("fluidName", FluidRegistry.getFluidName(fluidStack));
  731.                 tag.setInteger("fluidAmount", fluidStack.amount);
  732.             }
  733.  
  734.             tag.setInteger("tankHeight", tankHeight);
  735.             tag.setInteger("fluidCapacity", fluidCapacity);
  736.         }
  737.         else {
  738.             if(getMaster() != null) {
  739.                 BlockPos pos = getMaster().getPos();
  740.                 int[] masterPos = new int[]{pos.getX(), pos.getY(), pos.getZ()};
  741.                 tag.setIntArray("masterValve", masterPos);
  742.             }
  743.         }
  744.  
  745.         tag.setBoolean("autoOutput", autoOutput);
  746.         if(!getValveName().isEmpty())
  747.             tag.setString("valveName", getValveName());
  748.  
  749.         if(bottomDiagFrame != null && topDiagFrame != null) {
  750.             tag.setIntArray("bottomDiagF", new int[]{bottomDiagFrame.getX(), bottomDiagFrame.getY(), bottomDiagFrame.getZ()});
  751.             tag.setIntArray("topDiagF", new int[]{topDiagFrame.getX(), topDiagFrame.getY(), topDiagFrame.getZ()});
  752.         }
  753.  
  754.         super.writeToNBT(tag);
  755.     }
  756.  
  757.     @Override
  758.     public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
  759.         readFromNBT(pkt.getNbtCompound());
  760.     }
  761.  
  762.     @Override
  763.     public Packet getDescriptionPacket() {
  764.         NBTTagCompound tag = new NBTTagCompound();
  765.         writeToNBT(tag);
  766.         return new S35PacketUpdateTileEntity(getPos(), 0, tag);
  767.     }
  768.  
  769.     // Tank logic!
  770.  
  771.     @Override
  772.     public FluidStack getFluid() {
  773.         if(!isValid())
  774.             return null;
  775.  
  776.         return getMaster() == this ? fluidStack : getMaster().fluidStack;
  777.     }
  778.  
  779.     @Override
  780.     public int getFluidAmount() {
  781.         if(!isValid() || getFluid() == null)
  782.             return 0;
  783.  
  784.         return getFluid().amount;
  785.     }
  786.  
  787.     @Override
  788.     public int getCapacity() {
  789.         if(!isValid())
  790.             return 0;
  791.            
  792.         return getMaster() == this ? fluidCapacity : getMaster().fluidCapacity;
  793.     }
  794.  
  795.     @Override
  796.     public FluidTankInfo getInfo() {
  797.         if(!isValid())
  798.             return null;
  799.  
  800.         return new FluidTankInfo(getMaster());
  801.     }
  802.  
  803.     @Override
  804.     public int fill(FluidStack resource, boolean doFill) {
  805.         if(getMaster() == this) {
  806.             if (!isValid() || fluidStack != null && !fluidStack.isFluidEqual(resource))
  807.                 return 0;
  808.  
  809.             if (getFluidAmount() >= getCapacity()) {
  810.                 for(TileEntityValve valve : getAllValves()) {
  811.                     if (valve == this)
  812.                         continue;
  813.  
  814.                     EnumFacing outside = valve.getInside().getOpposite();
  815.                     TileEntity tile = worldObj.getTileEntity(valve.getPos().offset(outside));
  816.                     if (tile != null && tile instanceof TileEntityValve) {
  817.                         return ((TileEntityValve) tile).fill(getInside(), resource, doFill);
  818.                     }
  819.                 }
  820.             }
  821.  
  822.             if (!doFill)
  823.             {
  824.                 if (fluidStack == null) {
  825.                     return Math.min(fluidCapacity, resource.amount);
  826.                 }
  827.  
  828.                 return Math.min(fluidCapacity - fluidStack.amount, resource.amount);
  829.             }
  830.  
  831.             if (fluidStack == null)
  832.             {
  833.                 fluidStack = new FluidStack(resource, Math.min(fluidCapacity, resource.amount));
  834.                 setNeedsUpdate();
  835.                 return fluidStack.amount;
  836.             }
  837.  
  838.             int filled = fluidCapacity - fluidStack.amount;
  839.             if (resource.amount < filled) {
  840.                 fluidStack.amount += resource.amount;
  841.                 filled = resource.amount;
  842.             }
  843.             else {
  844.                 fluidStack.amount = fluidCapacity;
  845.             }
  846.  
  847.             getMaster().setNeedsUpdate();
  848.             return filled;
  849.         }
  850.         else
  851.             return getMaster().fill(resource, doFill);
  852.     }
  853.  
  854.     @Override
  855.     public FluidStack drain(int maxDrain, boolean doDrain) {
  856.         if(getMaster() == this) {
  857.             if(!isValid() || fluidStack == null)
  858.                 return null;
  859.  
  860.             int drained = maxDrain;
  861.             if (fluidStack.amount < drained) {
  862.                 drained = fluidStack.amount;
  863.             }
  864.  
  865.             FluidStack stack = new FluidStack(fluidStack, drained);
  866.             if (doDrain) {
  867.                 fluidStack.amount -= drained;
  868.                 if (fluidStack.amount <= 0) {
  869.                     fluidStack = null;
  870.                 }
  871.                 getMaster().setNeedsUpdate();
  872.             }
  873.             return stack;
  874.         }
  875.         else
  876.             return getMaster().drain(maxDrain, doDrain);
  877.     }
  878.  
  879.     // IFluidHandler
  880.  
  881.     /**
  882.      * @return 0-100 in % of how much is filled
  883.      */
  884.     public double getFillPercentage() {
  885.         if(!isValid() || getFluid() == null)
  886.             return 0;
  887.  
  888.         return Math.floor((double) getFluidAmount() / (double) getCapacity() * 100);
  889.     }
  890.  
  891.     @Override
  892.     public int fill(EnumFacing from, FluidStack resource, boolean doFill) {
  893.         if(!canFill(from, resource.getFluid()))
  894.             return 0;
  895.  
  896.         return getMaster() == this ? fill(resource, doFill) : getMaster().fill(resource, doFill);
  897.     }
  898.  
  899.     @Override
  900.     public FluidStack drain(EnumFacing from, FluidStack resource, boolean doDrain) {
  901.         return getMaster() == this ? drain(resource.amount, doDrain) : getMaster().drain(resource.amount, doDrain);
  902.     }
  903.  
  904.     @Override
  905.     public FluidStack drain(EnumFacing from, int maxDrain, boolean doDrain) {
  906.         return getMaster() == this ? drain(maxDrain, doDrain) : getMaster().drain(maxDrain, doDrain);
  907.     }
  908.  
  909.     @Override
  910.     public boolean canFill(EnumFacing from, Fluid fluid) {
  911.         if (!isValid())
  912.             return false;
  913.  
  914.         if (getFluid() != null && getFluid().getFluid() != fluid)
  915.             return false;
  916.  
  917.         if (getFluidAmount() >= getCapacity()) {
  918.             for (TileEntityValve valve : getAllValves()) {
  919.                 if (valve == this)
  920.                     continue;
  921.  
  922.                 if (valve.valveHeightPosition > getTankHeight()) {
  923.                     EnumFacing outside = valve.getInside().getOpposite();
  924.                     TileEntity tile = worldObj.getTileEntity(valve.getPos().offset(outside));
  925.                     if (tile != null && tile instanceof TileEntityValve) {
  926.                         return ((TileEntityValve) tile).canFill(valve.getInside(), fluid);
  927.                     }
  928.                 }
  929.             }
  930.             return false;
  931.         }
  932.  
  933.         return !getAutoOutput() || valveHeightPosition > getTankHeight() || valveHeightPosition + 0.5f >= getTankHeight() * getFillPercentage();
  934.     }
  935.  
  936.     @Override
  937.     public boolean canDrain(EnumFacing from, Fluid fluid) {
  938.         return isValid() && getFluid() != null && getFluid().getFluid() == fluid && getFluidAmount() > 0;
  939.  
  940.     }
  941.  
  942.     @Override
  943.     public FluidTankInfo[] getTankInfo(EnumFacing from) {
  944.         if(!isValid())
  945.             return null;
  946.  
  947.         return getMaster() == this ? new FluidTankInfo[]{ getInfo() } : getMaster().getTankInfo(from);
  948.     }
  949. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement