/// <summary> /// Update a specific voxel (Called from world update thread) /// </summary> public override bool UpdateVoxel(uint Tick, Point LocalPosition, VoxelInstance Voxel, VoxelChunk Chunk) { // Perform cleanup, if liquid too small if (Tick % mCleanRate == 0 && mRandom.Next(0, 100) < mCleanPercent) { // Replace with air, if no fill if (Voxel.mMetaFlags <= 1) { Voxel.SetNew(0); return(true); } } // Attempt to settle liquids other than puddles (Put at multiple of 2) if (Tick % mSettleRate == 0 && Voxel.mMetaFlags > 1) { if (Voxel.mMetaFlags % 2 != 0) { Voxel.mMetaFlags--; return(true); } if (Voxel.mMetaFlags == 0) { Voxel.SetNew(0); return(true); } } // Only update at given tick rate if (Tick % mUpdateRate != 0) { return(false); } // Clamp liquid to max height if (Voxel.mMetaFlags > VoxelData_Liquid.MaxHeight) { Voxel.mMetaFlags = (ushort)VoxelData_Liquid.MaxHeight; } ushort startHeight = Voxel.mMetaFlags; VoxelInstance above = Chunk.Get(LocalPosition.x, LocalPosition.y + 1, LocalPosition.z); VoxelInstance below = Chunk.Get(LocalPosition.x, LocalPosition.y - 1, LocalPosition.z); VoxelInstance left = Chunk.Get(LocalPosition.x - 1, LocalPosition.y, LocalPosition.z); VoxelInstance right = Chunk.Get(LocalPosition.x + 1, LocalPosition.y, LocalPosition.z); VoxelInstance front = Chunk.Get(LocalPosition.x, LocalPosition.y, LocalPosition.z - 1); VoxelInstance back = Chunk.Get(LocalPosition.x, LocalPosition.y, LocalPosition.z + 1); // Move liquid down and then out AttemptLiquidDisperse(Voxel, below, true); AttemptAirDisperse(Voxel, below, true); if (Voxel.mMetaFlags > 1) { // Shuffle order everytime to prevent any flattening issues uint order = (uint)mRandom.Next(0, 4); switch (order) { case 0: AttemptAirDisperse(Voxel, left); AttemptAirDisperse(Voxel, right); AttemptAirDisperse(Voxel, front); AttemptAirDisperse(Voxel, back); AttemptLiquidDisperse(Voxel, left); AttemptLiquidDisperse(Voxel, right); AttemptLiquidDisperse(Voxel, front); AttemptLiquidDisperse(Voxel, back); break; case 1: AttemptAirDisperse(Voxel, back); AttemptAirDisperse(Voxel, left); AttemptAirDisperse(Voxel, right); AttemptAirDisperse(Voxel, front); AttemptLiquidDisperse(Voxel, back); AttemptLiquidDisperse(Voxel, left); AttemptLiquidDisperse(Voxel, right); AttemptLiquidDisperse(Voxel, front); break; case 2: AttemptAirDisperse(Voxel, front); AttemptAirDisperse(Voxel, back); AttemptAirDisperse(Voxel, left); AttemptAirDisperse(Voxel, right); AttemptLiquidDisperse(Voxel, front); AttemptLiquidDisperse(Voxel, back); AttemptLiquidDisperse(Voxel, left); AttemptLiquidDisperse(Voxel, right); break; case 3: AttemptAirDisperse(Voxel, right); AttemptAirDisperse(Voxel, front); AttemptAirDisperse(Voxel, back); AttemptAirDisperse(Voxel, left); AttemptLiquidDisperse(Voxel, right); AttemptLiquidDisperse(Voxel, front); AttemptLiquidDisperse(Voxel, back); AttemptLiquidDisperse(Voxel, left); break; } } // Replace with air, if no fill if (Voxel.mMetaFlags == 0) { Voxel.SetNew(0); return(true); } return(Voxel.mMetaFlags != startHeight); }