Posted May 18, 201312 yr Hi there i am OwnAgePau and i am working on my mod called the Soul Forest mod. I have been making some nice custom blocks even managed to easily make a custom fire properly working, after that i wanted to make a custom liquid although this seemed as easy as fire but yet i can't get it to work. I have made 3 new classes one is SoulFluid which is basically BlockFluid but then for my custom fluid, i thought to have to add this if i wanted to pick it up with my custom bucket. Also i made a custom stationary and custom still water class. But somehow it manages to get into BlockFluid into the getFlowDirection which SoulFluid also uses, but it throws a nullPointer Exception. I just hoped you guys know what to do with the custom liquids. So here are my files : SoulFluid package Mod_Ores.Blocks.Special; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.BlockFluid; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IconRegister; import net.minecraft.entity.Entity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.Icon; import net.minecraft.util.Vec3; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import Mod_Ores.mod_Ores; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public abstract class SoulFluid extends BlockFluid { @SideOnly(Side.CLIENT) protected Icon[] theIcon; protected SoulFluid(int par1, Material par2Material) { super(par1, par2Material); float f = 0.0F; float f1 = 0.0F; this.setBlockBounds(0.0F + f1, 0.0F + f, 0.0F + f1, 1.0F + f1, 1.0F + f, 1.0F + f1); this.setTickRandomly(true); } public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) { return this.blockMaterial != mod_Ores.soulWater; } @SideOnly(Side.CLIENT) public int getBlockColor() { return 16777215; } @SideOnly(Side.CLIENT) /** * Returns a integer with hex for 0xrrggbb with this color multiplied against the blocks color. Note only called * when first determining what to render. */ public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) { if (this.blockMaterial != mod_Ores.soulWater) { return 16777215; } else { int l = 0; int i1 = 0; int j1 = 0; for (int k1 = -1; k1 <= 1; ++k1) { for (int l1 = -1; l1 <= 1; ++l1) { int i2 = par1IBlockAccess.getBiomeGenForCoords(par2 + l1, par4 + k1).getWaterColorMultiplier(); l += (i2 & 16711680) >> 16; i1 += (i2 & 65280) >> 8; j1 += i2 & 255; } } return (l / 9 & 255) << 16 | (i1 / 9 & 255) << 8 | j1 / 9 & 255; } } /** * Returns the percentage of the fluid block that is air, based on the given flow decay of the fluid. */ public static float getFluidHeightPercent(int par0) { if (par0 >= { par0 = 0; } return (float)(par0 + 1) / 9.0F; } @SideOnly(Side.CLIENT) /** * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata */ public Icon getIcon(int par1, int par2) { return par1 != 0 && par1 != 1 ? this.theIcon[1] : this.theIcon[0]; } /** * Returns the amount of fluid decay at the coordinates, or -1 if the block at the coordinates is not the same * material as the fluid. */ protected int getFlowDecay(World par1World, int par2, int par3, int par4) { return par1World.getBlockMaterial(par2, par3, par4) == this.blockMaterial ? par1World.getBlockMetadata(par2, par3, par4) : -1; } /** * Returns the flow decay but converts values indicating falling liquid (values >= to their effective source block * value of zero. */ protected int getEffectiveFlowDecay(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) { if (par1IBlockAccess.getBlockMaterial(par2, par3, par4) != this.blockMaterial) { return -1; } else { int l = par1IBlockAccess.getBlockMetadata(par2, par3, par4); if (l >= { l = 0; } return l; } } /** * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) */ public boolean renderAsNormalBlock() { return false; } /** * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. */ public boolean isOpaqueCube() { return false; } /** * Returns whether this block is collideable based on the arguments passed in Args: blockMetaData, unknownFlag */ public boolean canCollideCheck(int par1, boolean par2) { return par2 && par1 == 0; } /** * Returns Returns true if the given side of this block type should be rendered (if it's solid or not), if the * adjacent block is at the given coordinates. Args: blockAccess, x, y, z, side */ public boolean isBlockSolid(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) { Material material = par1IBlockAccess.getBlockMaterial(par2, par3, par4); return material == this.blockMaterial ? false : (par5 == 1 ? true : (material == Material.ice ? false : super.isBlockSolid(par1IBlockAccess, par2, par3, par4, par5))); } @SideOnly(Side.CLIENT) /** * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given * coordinates. Args: blockAccess, x, y, z, side */ public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) { Material material = par1IBlockAccess.getBlockMaterial(par2, par3, par4); return material == this.blockMaterial ? false : (par5 == 1 ? true : (material == Material.ice ? false : super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5))); } /** * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been * cleared to be reused) */ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) { return null; } /** * The type of render function that is called for this block */ public int getRenderType() { return 4; } /** * Returns the ID of the items to drop on destruction. */ public int idDropped(int par1, Random par2Random, int par3) { return 0; } /** * Returns the quantity of items to drop on block destruction. */ public int quantityDropped(Random par1Random) { return 0; } /** * Returns a vector indicating the direction and intensity of fluid flow. */ public Vec3 getFlowVector(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) { Vec3 vec3 = par1IBlockAccess.getWorldVec3Pool().getVecFromPool(0.0D, 0.0D, 0.0D); int l = this.getEffectiveFlowDecay(par1IBlockAccess, par2, par3, par4); for (int i1 = 0; i1 < 4; ++i1) { int j1 = par2; int k1 = par4; if (i1 == 0) { j1 = par2 - 1; } if (i1 == 1) { k1 = par4 - 1; } if (i1 == 2) { ++j1; } if (i1 == 3) { ++k1; } int l1 = this.getEffectiveFlowDecay(par1IBlockAccess, j1, par3, k1); int i2; if (l1 < 0) { if (!par1IBlockAccess.getBlockMaterial(j1, par3, k1).blocksMovement()) { l1 = this.getEffectiveFlowDecay(par1IBlockAccess, j1, par3 - 1, k1); if (l1 >= 0) { i2 = l1 - (l - ; vec3 = vec3.addVector((double)((j1 - par2) * i2), (double)((par3 - par3) * i2), (double)((k1 - par4) * i2)); } } } else if (l1 >= 0) { i2 = l1 - l; vec3 = vec3.addVector((double)((j1 - par2) * i2), (double)((par3 - par3) * i2), (double)((k1 - par4) * i2)); } } if (par1IBlockAccess.getBlockMetadata(par2, par3, par4) >= { boolean flag = false; if (flag || this.isBlockSolid(par1IBlockAccess, par2, par3, par4 - 1, 2)) { flag = true; } if (flag || this.isBlockSolid(par1IBlockAccess, par2, par3, par4 + 1, 3)) { flag = true; } if (flag || this.isBlockSolid(par1IBlockAccess, par2 - 1, par3, par4, 4)) { flag = true; } if (flag || this.isBlockSolid(par1IBlockAccess, par2 + 1, par3, par4, 5)) { flag = true; } if (flag || this.isBlockSolid(par1IBlockAccess, par2, par3 + 1, par4 - 1, 2)) { flag = true; } if (flag || this.isBlockSolid(par1IBlockAccess, par2, par3 + 1, par4 + 1, 3)) { flag = true; } if (flag || this.isBlockSolid(par1IBlockAccess, par2 - 1, par3 + 1, par4, 4)) { flag = true; } if (flag || this.isBlockSolid(par1IBlockAccess, par2 + 1, par3 + 1, par4, 5)) { flag = true; } if (flag) { vec3 = vec3.normalize().addVector(0.0D, -6.0D, 0.0D); } } vec3 = vec3.normalize(); return vec3; } /** * Can add to the passed in vector for a movement vector to be applied to the entity. Args: x, y, z, entity, vec3d */ public void velocityToAddToEntity(World par1World, int par2, int par3, int par4, Entity par5Entity, Vec3 par6Vec3) { Vec3 vec31 = this.getFlowVector(par1World, par2, par3, par4); par6Vec3.xCoord += vec31.xCoord; par6Vec3.yCoord += vec31.yCoord; par6Vec3.zCoord += vec31.zCoord; } /** * How many world ticks before ticking */ public int tickRate(World par1World) { return this.blockMaterial == mod_Ores.soulWater ? 5 : (this.blockMaterial == Material.lava ? (par1World.provider.hasNoSky ? 10 : 30) : 0); } /** * Called whenever the block is added into the world. Args: world, x, y, z */ public void onBlockAdded(World par1World, int par2, int par3, int par4) { this.checkForHarden(par1World, par2, par3, par4); } /** * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are * their own) Args: x, y, z, neighbor blockID */ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) { this.checkForHarden(par1World, par2, par3, par4); } @SideOnly(Side.CLIENT) /** * Goes straight to getLightBrightnessForSkyBlocks for Blocks, does some fancy computing for Fluids */ public int getMixedBrightnessForBlock(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) { int l = par1IBlockAccess.getLightBrightnessForSkyBlocks(par2, par3, par4, 0); int i1 = par1IBlockAccess.getLightBrightnessForSkyBlocks(par2, par3 + 1, par4, 0); int j1 = l & 255; int k1 = i1 & 255; int l1 = l >> 16 & 255; int i2 = i1 >> 16 & 255; return (j1 > k1 ? j1 : k1) | (l1 > i2 ? l1 : i2) << 16; } @SideOnly(Side.CLIENT) /** * How bright to render this block based on the light its receiving. Args: iBlockAccess, x, y, z */ public float getBlockBrightness(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) { float f = par1IBlockAccess.getLightBrightness(par2, par3, par4); float f1 = par1IBlockAccess.getLightBrightness(par2, par3 + 1, par4); return f > f1 ? f : f1; } @SideOnly(Side.CLIENT) /** * Returns which pass should this block be rendered on. 0 for solids and 1 for alpha */ public int getRenderBlockPass() { return this.blockMaterial == mod_Ores.soulWater ? 1 : 0; } @SideOnly(Side.CLIENT) /** * A randomly called display update to be able to add particles or other items for display */ public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random) { int l; if (this.blockMaterial == mod_Ores.soulWater) { if (par5Random.nextInt(10) == 0) { l = par1World.getBlockMetadata(par2, par3, par4); if (l <= 0 || l >= { par1World.spawnParticle("suspended", (double)((float)par2 + par5Random.nextFloat()), (double)((float)par3 + par5Random.nextFloat()), (double)((float)par4 + par5Random.nextFloat()), 0.0D, 0.0D, 0.0D); } } for (l = 0; l < 0; ++l) { int i1 = par5Random.nextInt(4); int j1 = par2; int k1 = par4; if (i1 == 0) { j1 = par2 - 1; } if (i1 == 1) { ++j1; } if (i1 == 2) { k1 = par4 - 1; } if (i1 == 3) { ++k1; } if (par1World.getBlockMaterial(j1, par3, k1) == Material.air && (par1World.getBlockMaterial(j1, par3 - 1, k1).blocksMovement() || par1World.getBlockMaterial(j1, par3 - 1, k1).isLiquid())) { float f = 0.0625F; double d0 = (double)((float)par2 + par5Random.nextFloat()); double d1 = (double)((float)par3 + par5Random.nextFloat()); double d2 = (double)((float)par4 + par5Random.nextFloat()); if (i1 == 0) { d0 = (double)((float)par2 - f); } if (i1 == 1) { d0 = (double)((float)(par2 + 1) + f); } if (i1 == 2) { d2 = (double)((float)par4 - f); } if (i1 == 3) { d2 = (double)((float)(par4 + 1) + f); } double d3 = 0.0D; double d4 = 0.0D; if (i1 == 0) { d3 = (double)(-f); } if (i1 == 1) { d3 = (double)f; } if (i1 == 2) { d4 = (double)(-f); } if (i1 == 3) { d4 = (double)f; } par1World.spawnParticle("splash", d0, d1, d2, d3, 0.0D, d4); } } } if (this.blockMaterial ==mod_Ores.soulWater && par5Random.nextInt(64) == 0) { l = par1World.getBlockMetadata(par2, par3, par4); if (l > 0 && l < { par1World.playSound((double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), "liquid.water", par5Random.nextFloat() * 0.25F + 0.75F, par5Random.nextFloat() * 1.0F + 0.5F, false); } } double d5; double d6; double d7; if (this.blockMaterial == Material.lava && par1World.getBlockMaterial(par2, par3 + 1, par4) == Material.air && !par1World.isBlockOpaqueCube(par2, par3 + 1, par4)) { if (par5Random.nextInt(100) == 0) { d5 = (double)((float)par2 + par5Random.nextFloat()); d7 = (double)par3 + this.maxY; d6 = (double)((float)par4 + par5Random.nextFloat()); par1World.spawnParticle("lava", d5, d7, d6, 0.0D, 0.0D, 0.0D); par1World.playSound(d5, d7, d6, "liquid.lavapop", 0.2F + par5Random.nextFloat() * 0.2F, 0.9F + par5Random.nextFloat() * 0.15F, false); } if (par5Random.nextInt(200) == 0) { par1World.playSound((double)par2, (double)par3, (double)par4, "liquid.lava", 0.2F + par5Random.nextFloat() * 0.2F, 0.9F + par5Random.nextFloat() * 0.15F, false); } } if (par5Random.nextInt(10) == 0 && par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && !par1World.getBlockMaterial(par2, par3 - 2, par4).blocksMovement()) { d5 = (double)((float)par2 + par5Random.nextFloat()); d7 = (double)par3 - 1.05D; d6 = (double)((float)par4 + par5Random.nextFloat()); if (this.blockMaterial == mod_Ores.soulWater) { par1World.spawnParticle("dripWater", d5, d7, d6, 0.0D, 0.0D, 0.0D); } else if(this.blockMaterial == Material.lava) { par1World.spawnParticle("dripLava", d5, d7, d6, 0.0D, 0.0D, 0.0D); } else { par1World.spawnParticle("dripWater", d5, d7, d6, 0.0D, 0.0D, 0.0D); } } } @SideOnly(Side.CLIENT) /** * the sin and cos of this number determine the surface gradient of the flowing block. */ public static double getFlowDirection(IBlockAccess par0IBlockAccess, int par1, int par2, int par3, Material par4Material) { Vec3 vec3 = null; if (par4Material == mod_Ores.soulWater) { vec3 = mod_Ores.SoulWaterMoving.getFlowVector(par0IBlockAccess, par1, par2, par3); } if (par4Material == Material.water) { vec3 = Block.waterMoving.getFlowVector(par0IBlockAccess, par1, par2, par3); } if (par4Material == Material.lava) { vec3 = Block.lavaMoving.getFlowVector(par0IBlockAccess, par1, par2, par3); } return vec3.xCoord == 0.0D && vec3.zCoord == 0.0D ? -1000.0D : Math.atan2(vec3.zCoord, vec3.xCoord) - (Math.PI / 2D); } /** * Forces lava to check to see if it is colliding with water, and then decide what it should harden to. */ private void checkForHarden(World par1World, int par2, int par3, int par4) { if (par1World.getBlockId(par2, par3, par4) == this.blockID) { if (this.blockMaterial == Material.lava) { boolean flag = false; if (flag || par1World.getBlockMaterial(par2, par3, par4 - 1) == mod_Ores.soulWater) { flag = true; } if (flag || par1World.getBlockMaterial(par2, par3, par4 + 1) == mod_Ores.soulWater) { flag = true; } if (flag || par1World.getBlockMaterial(par2 - 1, par3, par4) == mod_Ores.soulWater) { flag = true; } if (flag || par1World.getBlockMaterial(par2 + 1, par3, par4) == mod_Ores.soulWater) { flag = true; } if (flag || par1World.getBlockMaterial(par2, par3 + 1, par4) == mod_Ores.soulWater) { flag = true; } if (flag) { int l = par1World.getBlockMetadata(par2, par3, par4); if (l == 0) { par1World.setBlock(par2, par3, par4, Block.obsidian.blockID); } else if (l <= 4) { par1World.setBlock(par2, par3, par4, Block.cobblestone.blockID); } this.triggerLavaMixEffects(par1World, par2, par3, par4); } } } } /** * Creates fizzing sound and smoke. Used when lava flows over block or mixes with water. */ protected void triggerLavaMixEffects(World par1World, int par2, int par3, int par4) { par1World.playSoundEffect((double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), "random.fizz", 0.5F, 2.6F + (par1World.rand.nextFloat() - par1World.rand.nextFloat()) * 0.8F); for (int l = 0; l < 8; ++l) { par1World.spawnParticle("largesmoke", (double)par2 + Math.random(), (double)par3 + 1.2D, (double)par4 + Math.random(), 0.0D, 0.0D, 0.0D); } } @SideOnly(Side.CLIENT) /** * When this method is called, your block should register all the icons it needs with the given IconRegister. This * is the only chance you get to register icons. */ public void registerIcons(IconRegister par1IconRegister) { if (this.blockMaterial == mod_Ores.soulWater) { this.theIcon = new Icon[] {par1IconRegister.registerIcon("Soul_Water"), par1IconRegister.registerIcon("Soul_Water_FLow")}; } } @SideOnly(Side.CLIENT) public static Icon func_94424_b(String par0Str) { return par0Str == "Soul_Water" ? mod_Ores.SoulWater.theIcon[0] : (par0Str == "Soul_Water_Flow" ? mod_Ores.SoulWaterMoving.theIcon[1] : null); } } SoulWaterFlowing package Mod_Ores.Blocks.Special; import java.util.Random; import Mod_Ores.mod_Ores; import net.minecraft.block.Block; import net.minecraft.block.BlockFlowing; import net.minecraft.block.material.Material; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.liquids.ILiquid; public class SoulWaterFlowing extends SoulFluid { public SoulWaterFlowing(int par1) { super(par1, mod_Ores.soulWater); this.blockHardness = 100F; this.setLightOpacity(3); this.disableStats(); this.setCreativeTab(CreativeTabs.tabMisc); this.setUnlocalizedName("Soul_Water_Flow"); } /** * Number of horizontally adjacent liquid source blocks. Diagonal doesn't count. Only source blocks of the same * liquid as the block using the field are counted. */ int numAdjacentSources = 0; /** * Indicates whether the flow direction is optimal. Each array index corresponds to one of the four cardinal * directions. */ boolean[] isOptimalFlowDirection = new boolean[4]; /** * The estimated cost to flow in a given direction from the current point. Each array index corresponds to one of * the four cardinal directions. */ int[] flowCost = new int[4]; /** * Updates the flow for the BlockFlowing object. */ private void updateFlow(World par1World, int par2, int par3, int par4) { int l = par1World.getBlockMetadata(par2, par3, par4); par1World.setBlock(par2, par3, par4, this.blockID + 1, l, 2); } public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) { return this.blockMaterial != Material.lava; } /** * Ticks the block if it's been scheduled */ public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) { int l = this.getFlowDecay(par1World, par2, par3, par4); byte b0 = 1; if (this.blockMaterial == Material.lava && !par1World.provider.isHellWorld) { b0 = 2; } boolean flag = true; int i1; if (l > 0) { byte b1 = -100; this.numAdjacentSources = 0; int j1 = this.getSmallestFlowDecay(par1World, par2 - 1, par3, par4, b1); j1 = this.getSmallestFlowDecay(par1World, par2 + 1, par3, par4, j1); j1 = this.getSmallestFlowDecay(par1World, par2, par3, par4 - 1, j1); j1 = this.getSmallestFlowDecay(par1World, par2, par3, par4 + 1, j1); i1 = j1 + b0; if (i1 >= 8 || j1 < 0) { i1 = -1; } if (this.getFlowDecay(par1World, par2, par3 + 1, par4) >= 0) { int k1 = this.getFlowDecay(par1World, par2, par3 + 1, par4); if (k1 >= { i1 = k1; } else { i1 = k1 + 8; } } if (this.numAdjacentSources >= 2 && this.blockMaterial == mod_Ores.soulWater) { if (par1World.getBlockMaterial(par2, par3 - 1, par4).isSolid()) { i1 = 0; } else if (par1World.getBlockMaterial(par2, par3 - 1, par4) == this.blockMaterial && par1World.getBlockMetadata(par2, par3 - 1, par4) == 0) { i1 = 0; } } if (this.blockMaterial == Material.lava && l < 8 && i1 < 8 && i1 > l && par5Random.nextInt(4) != 0) { i1 = l; flag = false; } if (i1 == l) { if (flag) { this.updateFlow(par1World, par2, par3, par4); } } else { l = i1; if (i1 < 0) { par1World.setBlockToAir(par2, par3, par4); } else { par1World.setBlockMetadataWithNotify(par2, par3, par4, i1, 2); par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World)); par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); } } } else { this.updateFlow(par1World, par2, par3, par4); } if (this.liquidCanDisplaceBlock(par1World, par2, par3 - 1, par4)) { if (this.blockMaterial == Material.lava && par1World.getBlockMaterial(par2, par3 - 1, par4) == mod_Ores.soulWater) { par1World.setBlock(par2, par3 - 1, par4, Block.stone.blockID); this.triggerLavaMixEffects(par1World, par2, par3 - 1, par4); return; } if (l >= { this.flowIntoBlock(par1World, par2, par3 - 1, par4, l); } else { this.flowIntoBlock(par1World, par2, par3 - 1, par4, l + ; } } else if (l >= 0 && (l == 0 || this.blockBlocksFlow(par1World, par2, par3 - 1, par4))) { boolean[] aboolean = this.getOptimalFlowDirections(par1World, par2, par3, par4); i1 = l + b0; if (l >= { i1 = 1; } if (i1 >= { return; } if (aboolean[0]) { this.flowIntoBlock(par1World, par2 - 1, par3, par4, i1); } if (aboolean[1]) { this.flowIntoBlock(par1World, par2 + 1, par3, par4, i1); } if (aboolean[2]) { this.flowIntoBlock(par1World, par2, par3, par4 - 1, i1); } if (aboolean[3]) { this.flowIntoBlock(par1World, par2, par3, par4 + 1, i1); } } } /** * flowIntoBlock(World world, int x, int y, int z, int newFlowDecay) - Flows into the block at the coordinates and * changes the block type to the liquid. */ private void flowIntoBlock(World par1World, int par2, int par3, int par4, int par5) { if (this.liquidCanDisplaceBlock(par1World, par2, par3, par4)) { int i1 = par1World.getBlockId(par2, par3, par4); if (i1 > 0) { if (this.blockMaterial == Material.lava) { this.triggerLavaMixEffects(par1World, par2, par3, par4); } else { Block.blocksList[i1].dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); } } par1World.setBlock(par2, par3, par4, this.blockID, par5, 3); } } /** * calculateFlowCost(World world, int x, int y, int z, int accumulatedCost, int previousDirectionOfFlow) - Used to * determine the path of least resistance, this method returns the lowest possible flow cost for the direction of * flow indicated. Each necessary horizontal flow adds to the flow cost. */ private int calculateFlowCost(World par1World, int par2, int par3, int par4, int par5, int par6) { int j1 = 1000; for (int k1 = 0; k1 < 4; ++k1) { if ((k1 != 0 || par6 != 1) && (k1 != 1 || par6 != 0) && (k1 != 2 || par6 != 3) && (k1 != 3 || par6 != 2)) { int l1 = par2; int i2 = par4; if (k1 == 0) { l1 = par2 - 1; } if (k1 == 1) { ++l1; } if (k1 == 2) { i2 = par4 - 1; } if (k1 == 3) { ++i2; } if (!this.blockBlocksFlow(par1World, l1, par3, i2) && (par1World.getBlockMaterial(l1, par3, i2) != this.blockMaterial || par1World.getBlockMetadata(l1, par3, i2) != 0)) { if (!this.blockBlocksFlow(par1World, l1, par3 - 1, i2)) { return par5; } if (par5 < 4) { int j2 = this.calculateFlowCost(par1World, l1, par3, i2, par5 + 1, k1); if (j2 < j1) { j1 = j2; } } } } } return j1; } /** * Returns a boolean array indicating which flow directions are optimal based on each direction's calculated flow * cost. Each array index corresponds to one of the four cardinal directions. A value of true indicates the * direction is optimal. */ private boolean[] getOptimalFlowDirections(World par1World, int par2, int par3, int par4) { int l; int i1; for (l = 0; l < 4; ++l) { this.flowCost[l] = 1000; i1 = par2; int j1 = par4; if (l == 0) { i1 = par2 - 1; } if (l == 1) { ++i1; } if (l == 2) { j1 = par4 - 1; } if (l == 3) { ++j1; } if (!this.blockBlocksFlow(par1World, i1, par3, j1) && (par1World.getBlockMaterial(i1, par3, j1) != this.blockMaterial || par1World.getBlockMetadata(i1, par3, j1) != 0)) { if (this.blockBlocksFlow(par1World, i1, par3 - 1, j1)) { this.flowCost[l] = this.calculateFlowCost(par1World, i1, par3, j1, 1, l); } else { this.flowCost[l] = 0; } } } l = this.flowCost[0]; for (i1 = 1; i1 < 4; ++i1) { if (this.flowCost[i1] < l) { l = this.flowCost[i1]; } } for (i1 = 0; i1 < 4; ++i1) { this.isOptimalFlowDirection[i1] = this.flowCost[i1] == l; } return this.isOptimalFlowDirection; } /** * Returns true if block at coords blocks fluids */ private boolean blockBlocksFlow(World par1World, int par2, int par3, int par4) { int l = par1World.getBlockId(par2, par3, par4); if (l != Block.doorWood.blockID && l != Block.doorIron.blockID && l != Block.signPost.blockID && l != Block.ladder.blockID && l != Block.reed.blockID) { if (l == 0) { return false; } else { Material material = Block.blocksList[l].blockMaterial; return material == Material.portal ? true : material.blocksMovement(); } } else { return true; } } /** * getSmallestFlowDecay(World world, intx, int y, int z, int currentSmallestFlowDecay) - Looks up the flow decay at * the coordinates given and returns the smaller of this value or the provided currentSmallestFlowDecay. If one * value is valid and the other isn't, the valid value will be returned. Valid values are >= 0. Flow decay is the * amount that a liquid has dissipated. 0 indicates a source block. */ protected int getSmallestFlowDecay(World par1World, int par2, int par3, int par4, int par5) { int i1 = this.getFlowDecay(par1World, par2, par3, par4); if (i1 < 0) { return par5; } else { if (i1 == 0) { ++this.numAdjacentSources; } if (i1 >= { i1 = 0; } return par5 >= 0 && i1 >= par5 ? par5 : i1; } } /** * Returns true if the block at the coordinates can be displaced by the liquid. */ private boolean liquidCanDisplaceBlock(World par1World, int par2, int par3, int par4) { Material material = par1World.getBlockMaterial(par2, par3, par4); return material == this.blockMaterial ? false : (material == Material.lava ? false : !this.blockBlocksFlow(par1World, par2, par3, par4)); } /** * Called whenever the block is added into the world. Args: world, x, y, z */ public void onBlockAdded(World par1World, int par2, int par3, int par4) { super.onBlockAdded(par1World, par2, par3, par4); if (par1World.getBlockId(par2, par3, par4) == this.blockID) { par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World)); } } public boolean func_82506_l() { return false; } } SoulWaterStationary package Mod_Ores.Blocks.Special; import java.util.Random; import Mod_Ores.mod_Ores; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.liquids.ILiquid; public class SoulWaterStationary extends SoulFluid { public SoulWaterStationary(int par1) { super(par1, mod_Ores.soulWater); this.setTickRandomly(false); this.blockHardness = 100F; this.setLightOpacity(3); this.disableStats(); this.setCreativeTab(CreativeTabs.tabMisc); this.setUnlocalizedName("Soul_Water"); } public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) { return this.blockMaterial != mod_Ores.soulWater; } /** * Ticks the block if it's been scheduled */ @Override public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) { if (this.blockMaterial == mod_Ores.soulWater) { int l = par5Random.nextInt(3); int i1; int j1; for (i1 = 0; i1 < l; ++i1) { par2 += par5Random.nextInt(3) - 1; ++par3; par4 += par5Random.nextInt(3) - 1; j1 = par1World.getBlockId(par2, par3, par4); if (j1 == 0) { if (this.isFlammable(par1World, par2 - 1, par3, par4) || this.isFlammable(par1World, par2 + 1, par3, par4) || this.isFlammable(par1World, par2, par3, par4 - 1) || this.isFlammable(par1World, par2, par3, par4 + 1) || this.isFlammable(par1World, par2, par3 - 1, par4) || this.isFlammable(par1World, par2, par3 + 1, par4)) { par1World.setBlock(par2, par3, par4, mod_Ores.SoulFire.blockID); return; } } else if (Block.blocksList[j1].blockMaterial.blocksMovement()) { return; } } if (l == 0) { i1 = par2; j1 = par4; for (int k1 = 0; k1 < 3; ++k1) { par2 = i1 + par5Random.nextInt(3) - 1; par4 = j1 + par5Random.nextInt(3) - 1; if (par1World.isAirBlock(par2, par3 + 1, par4) && this.isFlammable(par1World, par2, par3, par4)) { par1World.setBlock(par2, par3 + 1, par4, mod_Ores.SoulFire.blockID); } } } } } /** * Checks to see if the block is flammable. */ private boolean isFlammable(World par1World, int par2, int par3, int par4) { return par1World.getBlockMaterial(par2, par3, par4).getCanBurn(); } } I also made a custom bucket and a filled bucket but i haven't gotten to test those yet because i can not yet place my water. Thanks for your time and effort! I am the creator of the Soul Forest Mod : http://www.planetminecraft.com/mod/151-soul-forest-10-ores-vines-dimension-mobs-and-more/
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.