001 package net.minecraft.src; 002 003 import java.util.Random; 004 005 public class BlockFlowing extends BlockFluid 006 { 007 /** 008 * Number of horizontally adjacent liquid source blocks. Diagonal doesn't count. Only source blocks of the same 009 * liquid as the block using the field are counted. 010 */ 011 int numAdjacentSources = 0; 012 013 /** 014 * Indicates whether the flow direction is optimal. Each array index corresponds to one of the four cardinal 015 * directions. 016 */ 017 boolean[] isOptimalFlowDirection = new boolean[4]; 018 019 /** 020 * The estimated cost to flow in a given direction from the current point. Each array index corresponds to one of 021 * the four cardinal directions. 022 */ 023 int[] flowCost = new int[4]; 024 025 protected BlockFlowing(int par1, Material par2Material) 026 { 027 super(par1, par2Material); 028 } 029 030 /** 031 * Updates the flow for the BlockFlowing object. 032 */ 033 private void updateFlow(World par1World, int par2, int par3, int par4) 034 { 035 int var5 = par1World.getBlockMetadata(par2, par3, par4); 036 par1World.setBlockAndMetadata(par2, par3, par4, this.blockID + 1, var5); 037 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4); 038 } 039 040 public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 041 { 042 return this.blockMaterial != Material.lava; 043 } 044 045 /** 046 * Ticks the block if it's been scheduled 047 */ 048 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 049 { 050 int var6 = this.getFlowDecay(par1World, par2, par3, par4); 051 byte var7 = 1; 052 053 if (this.blockMaterial == Material.lava && !par1World.provider.isHellWorld) 054 { 055 var7 = 2; 056 } 057 058 boolean var8 = true; 059 int var10; 060 061 if (var6 > 0) 062 { 063 byte var9 = -100; 064 this.numAdjacentSources = 0; 065 int var12 = this.getSmallestFlowDecay(par1World, par2 - 1, par3, par4, var9); 066 var12 = this.getSmallestFlowDecay(par1World, par2 + 1, par3, par4, var12); 067 var12 = this.getSmallestFlowDecay(par1World, par2, par3, par4 - 1, var12); 068 var12 = this.getSmallestFlowDecay(par1World, par2, par3, par4 + 1, var12); 069 var10 = var12 + var7; 070 071 if (var10 >= 8 || var12 < 0) 072 { 073 var10 = -1; 074 } 075 076 if (this.getFlowDecay(par1World, par2, par3 + 1, par4) >= 0) 077 { 078 int var11 = this.getFlowDecay(par1World, par2, par3 + 1, par4); 079 080 if (var11 >= 8) 081 { 082 var10 = var11; 083 } 084 else 085 { 086 var10 = var11 + 8; 087 } 088 } 089 090 if (this.numAdjacentSources >= 2 && this.blockMaterial == Material.water) 091 { 092 if (par1World.getBlockMaterial(par2, par3 - 1, par4).isSolid()) 093 { 094 var10 = 0; 095 } 096 else if (par1World.getBlockMaterial(par2, par3 - 1, par4) == this.blockMaterial && par1World.getBlockMetadata(par2, par3, par4) == 0) 097 { 098 var10 = 0; 099 } 100 } 101 102 if (this.blockMaterial == Material.lava && var6 < 8 && var10 < 8 && var10 > var6 && par5Random.nextInt(4) != 0) 103 { 104 var10 = var6; 105 var8 = false; 106 } 107 108 if (var10 == var6) 109 { 110 if (var8) 111 { 112 this.updateFlow(par1World, par2, par3, par4); 113 } 114 } 115 else 116 { 117 var6 = var10; 118 119 if (var10 < 0) 120 { 121 par1World.setBlockWithNotify(par2, par3, par4, 0); 122 } 123 else 124 { 125 par1World.setBlockMetadataWithNotify(par2, par3, par4, var10); 126 par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate()); 127 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); 128 } 129 } 130 } 131 else 132 { 133 this.updateFlow(par1World, par2, par3, par4); 134 } 135 136 if (this.liquidCanDisplaceBlock(par1World, par2, par3 - 1, par4)) 137 { 138 if (this.blockMaterial == Material.lava && par1World.getBlockMaterial(par2, par3 - 1, par4) == Material.water) 139 { 140 par1World.setBlockWithNotify(par2, par3 - 1, par4, Block.stone.blockID); 141 this.triggerLavaMixEffects(par1World, par2, par3 - 1, par4); 142 return; 143 } 144 145 if (var6 >= 8) 146 { 147 this.flowIntoBlock(par1World, par2, par3 - 1, par4, var6); 148 } 149 else 150 { 151 this.flowIntoBlock(par1World, par2, par3 - 1, par4, var6 + 8); 152 } 153 } 154 else if (var6 >= 0 && (var6 == 0 || this.blockBlocksFlow(par1World, par2, par3 - 1, par4))) 155 { 156 boolean[] var13 = this.getOptimalFlowDirections(par1World, par2, par3, par4); 157 var10 = var6 + var7; 158 159 if (var6 >= 8) 160 { 161 var10 = 1; 162 } 163 164 if (var10 >= 8) 165 { 166 return; 167 } 168 169 if (var13[0]) 170 { 171 this.flowIntoBlock(par1World, par2 - 1, par3, par4, var10); 172 } 173 174 if (var13[1]) 175 { 176 this.flowIntoBlock(par1World, par2 + 1, par3, par4, var10); 177 } 178 179 if (var13[2]) 180 { 181 this.flowIntoBlock(par1World, par2, par3, par4 - 1, var10); 182 } 183 184 if (var13[3]) 185 { 186 this.flowIntoBlock(par1World, par2, par3, par4 + 1, var10); 187 } 188 } 189 } 190 191 /** 192 * flowIntoBlock(World world, int x, int y, int z, int newFlowDecay) - Flows into the block at the coordinates and 193 * changes the block type to the liquid. 194 */ 195 private void flowIntoBlock(World par1World, int par2, int par3, int par4, int par5) 196 { 197 if (this.liquidCanDisplaceBlock(par1World, par2, par3, par4)) 198 { 199 int var6 = par1World.getBlockId(par2, par3, par4); 200 201 if (var6 > 0) 202 { 203 if (this.blockMaterial == Material.lava) 204 { 205 this.triggerLavaMixEffects(par1World, par2, par3, par4); 206 } 207 else 208 { 209 Block.blocksList[var6].dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); 210 } 211 } 212 213 par1World.setBlockAndMetadataWithNotify(par2, par3, par4, this.blockID, par5); 214 } 215 } 216 217 /** 218 * calculateFlowCost(World world, int x, int y, int z, int accumulatedCost, int previousDirectionOfFlow) - Used to 219 * determine the path of least resistance, this method returns the lowest possible flow cost for the direction of 220 * flow indicated. Each necessary horizontal flow adds to the flow cost. 221 */ 222 private int calculateFlowCost(World par1World, int par2, int par3, int par4, int par5, int par6) 223 { 224 int var7 = 1000; 225 226 for (int var8 = 0; var8 < 4; ++var8) 227 { 228 if ((var8 != 0 || par6 != 1) && (var8 != 1 || par6 != 0) && (var8 != 2 || par6 != 3) && (var8 != 3 || par6 != 2)) 229 { 230 int var9 = par2; 231 int var11 = par4; 232 233 if (var8 == 0) 234 { 235 var9 = par2 - 1; 236 } 237 238 if (var8 == 1) 239 { 240 ++var9; 241 } 242 243 if (var8 == 2) 244 { 245 var11 = par4 - 1; 246 } 247 248 if (var8 == 3) 249 { 250 ++var11; 251 } 252 253 if (!this.blockBlocksFlow(par1World, var9, par3, var11) && (par1World.getBlockMaterial(var9, par3, var11) != this.blockMaterial || par1World.getBlockMetadata(var9, par3, var11) != 0)) 254 { 255 if (!this.blockBlocksFlow(par1World, var9, par3 - 1, var11)) 256 { 257 return par5; 258 } 259 260 if (par5 < 4) 261 { 262 int var12 = this.calculateFlowCost(par1World, var9, par3, var11, par5 + 1, var8); 263 264 if (var12 < var7) 265 { 266 var7 = var12; 267 } 268 } 269 } 270 } 271 } 272 273 return var7; 274 } 275 276 /** 277 * Returns a boolean array indicating which flow directions are optimal based on each direction's calculated flow 278 * cost. Each array index corresponds to one of the four cardinal directions. A value of true indicates the 279 * direction is optimal. 280 */ 281 private boolean[] getOptimalFlowDirections(World par1World, int par2, int par3, int par4) 282 { 283 int var5; 284 int var6; 285 286 for (var5 = 0; var5 < 4; ++var5) 287 { 288 this.flowCost[var5] = 1000; 289 var6 = par2; 290 int var8 = par4; 291 292 if (var5 == 0) 293 { 294 var6 = par2 - 1; 295 } 296 297 if (var5 == 1) 298 { 299 ++var6; 300 } 301 302 if (var5 == 2) 303 { 304 var8 = par4 - 1; 305 } 306 307 if (var5 == 3) 308 { 309 ++var8; 310 } 311 312 if (!this.blockBlocksFlow(par1World, var6, par3, var8) && (par1World.getBlockMaterial(var6, par3, var8) != this.blockMaterial || par1World.getBlockMetadata(var6, par3, var8) != 0)) 313 { 314 if (this.blockBlocksFlow(par1World, var6, par3 - 1, var8)) 315 { 316 this.flowCost[var5] = this.calculateFlowCost(par1World, var6, par3, var8, 1, var5); 317 } 318 else 319 { 320 this.flowCost[var5] = 0; 321 } 322 } 323 } 324 325 var5 = this.flowCost[0]; 326 327 for (var6 = 1; var6 < 4; ++var6) 328 { 329 if (this.flowCost[var6] < var5) 330 { 331 var5 = this.flowCost[var6]; 332 } 333 } 334 335 for (var6 = 0; var6 < 4; ++var6) 336 { 337 this.isOptimalFlowDirection[var6] = this.flowCost[var6] == var5; 338 } 339 340 return this.isOptimalFlowDirection; 341 } 342 343 /** 344 * Returns true if block at coords blocks fluids 345 */ 346 private boolean blockBlocksFlow(World par1World, int par2, int par3, int par4) 347 { 348 int var5 = par1World.getBlockId(par2, par3, par4); 349 350 if (var5 != Block.doorWood.blockID && var5 != Block.doorSteel.blockID && var5 != Block.signPost.blockID && var5 != Block.ladder.blockID && var5 != Block.reed.blockID) 351 { 352 if (var5 == 0) 353 { 354 return false; 355 } 356 else 357 { 358 Material var6 = Block.blocksList[var5].blockMaterial; 359 return var6 == Material.portal ? true : var6.blocksMovement(); 360 } 361 } 362 else 363 { 364 return true; 365 } 366 } 367 368 /** 369 * getSmallestFlowDecay(World world, intx, int y, int z, int currentSmallestFlowDecay) - Looks up the flow decay at 370 * the coordinates given and returns the smaller of this value or the provided currentSmallestFlowDecay. If one 371 * value is valid and the other isn't, the valid value will be returned. Valid values are >= 0. Flow decay is the 372 * amount that a liquid has dissipated. 0 indicates a source block. 373 */ 374 protected int getSmallestFlowDecay(World par1World, int par2, int par3, int par4, int par5) 375 { 376 int var6 = this.getFlowDecay(par1World, par2, par3, par4); 377 378 if (var6 < 0) 379 { 380 return par5; 381 } 382 else 383 { 384 if (var6 == 0) 385 { 386 ++this.numAdjacentSources; 387 } 388 389 if (var6 >= 8) 390 { 391 var6 = 0; 392 } 393 394 return par5 >= 0 && var6 >= par5 ? par5 : var6; 395 } 396 } 397 398 /** 399 * Returns true if the block at the coordinates can be displaced by the liquid. 400 */ 401 private boolean liquidCanDisplaceBlock(World par1World, int par2, int par3, int par4) 402 { 403 Material var5 = par1World.getBlockMaterial(par2, par3, par4); 404 return var5 == this.blockMaterial ? false : (var5 == Material.lava ? false : !this.blockBlocksFlow(par1World, par2, par3, par4)); 405 } 406 407 /** 408 * Called whenever the block is added into the world. Args: world, x, y, z 409 */ 410 public void onBlockAdded(World par1World, int par2, int par3, int par4) 411 { 412 super.onBlockAdded(par1World, par2, par3, par4); 413 414 if (par1World.getBlockId(par2, par3, par4) == this.blockID) 415 { 416 par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate()); 417 } 418 } 419 420 public boolean func_82506_l() 421 { 422 return false; 423 } 424 }