@Override
    public void generateTerrain(Chunk chunk) {
        if (chunk.isGenerated()) {
            chunk.getWorld().getLogger().logWarning("Attempted to generate a chunk twice at " + chunk.asCoords());
        } else {
            Vec3i cLoc = chunk.getLocation();
            int chunkY = cLoc.y * chunkSize;
            int chunkX = cLoc.x * chunkSize;
            int chunkZ = cLoc.z * chunkSize;
            for (int x = 0; x < chunkSize; x++) {
                for (int z = 0; z < chunkSize; z++) {
                    for (int y = 0; y < chunkSize; y++) {
                        int currX = x + chunkX;
                        int currY = y + chunkY;
                        int currZ = z + chunkZ;
                        double val = getSimplex(currX, currY, currZ);
                        if (val < TERRAIN_PERCENTAGE) {
                            chunk.setBlockAt(x, y, z, Blocks.air);
                        } else if (val < TERRAIN_PERCENTAGE + DIRT_THICKNESS) {
                            if (getSimplex(currX, currY + 1, currZ) < TERRAIN_PERCENTAGE) {
                                chunk.setBlockAt(x, y, z, Blocks.grass);
                            } else {
                                chunk.setBlockAt(x, y, z, Blocks.dirt);
                            }
                        } else {
                            chunk.setBlockAt(x, y, z, Blocks.stone);
                        }
                    }
                }
            }
        }
        chunk.markGenerated();
        chunk.setNeedsRebuild(true);
    }