-mod = (x, y) ->
-  (x % y + y) % y
+NOTHING = 0
+FLYING_ROCK = 1
+GROUND = 2
+
+
+class GeneratorState
+
+  constructor: (chunkSize) ->
+    @chunkSize = chunkSize
+    @cacheSizeX = @chunkSize
+    @cacheSizeY = @chunkSize + 1
+    @cacheSizeZ = @chunkSize
+    @blockSourceCache = new Uint8Array @cacheSizeX * @cacheSizeY * @cacheSizeZ
+
+  init: (gen, offX, offY, offZ) ->
+    {cacheSizeX, cacheSizeY, cacheSizeZ} = this
+
+    @offX = offX
+    @offY = offY
+    @offZ = offZ
+
+    sc = @blockSourceCache
+    for cz in [0...cacheSizeZ]
+      for cy in [0...cacheSizeY]
+        for cx in [0...cacheSizeX]
+          source = gen.getBlockSource offX + cx, offY + cy, offZ + cz
+          sc[cx + cy * cacheSizeX + cz * cacheSizeX * cacheSizeY] = source
+
+  getBlockSource: (cx, cy, cz) ->
+    @blockSourceCache[cx + cy * @cacheSizeX + cz * @cacheSizeX * @cacheSizeY]
 
 
 class WorldGeneratorProcess extends webglmc.Process
   constructor: (seed) ->
     @perlin = new webglmc.PerlinGenerator seed
+    @cachedState = null
+    @cachedChunk = null
     @waterLevel = 16
 
   isFlyingRock: (x, y, z) ->

    density = noise * centerFalloff * plateauFalloff
    density > 0.1

  isGroundBlock: (x, y, z) ->
    return y < this.getGroundHeight x, z

  getGroundHeight: (x, z) ->
    nx = x * 0.01
    nz = z * 0.01
    noise = @perlin.noise2D(nx, nz, 3) * 0.5 + 0.5
    noise * 30

  isWater: (x, y, z) ->
    y <= @waterLevel

  getGrassVariation: (x, y, z) ->
    nx = x * 1.2

    nz = z * 0.01
    heightOff = @perlin.simpleNoise2D(nx * 3.0, nz * 3.0) * 0.2

    mx = (nx % 1.0 + 1.0) % 1.0
    my = ((ny + heightOff) % 1.4 + 1.4) % 1.4
    mz = (nz % 1.0 + 1.0) % 1.0

    # falloff from the top
    if my > 0.9
