local blockData = require(script.BlockData)

local maxWorldHeight = 25
local mapSizeInChunks = 8
local chunkSizeInBlocks = 5
local blockSize = 4

warn("Total Possible Blocks: "..((mapSizeInChunks*mapSizeInChunks)*(chunkSizeInBlocks*chunkSizeInBlocks)*maxWorldHeight))

function deriveBlockPos(chunkX, chunkZ, bY, bX, bZ)
	local nX, nY, nZ
	
	nX = bX*blockSize+(chunkX*(chunkSizeInBlocks*blockSize))
	nY = bY*blockSize
	nZ = bZ*blockSize+(chunkZ*(chunkSizeInBlocks*blockSize))
	
	--print(nX, nY, nZ)
	return Vector3.new(nX, nY, nZ)
end

for chunkX = -mapSizeInChunks/2, mapSizeInChunks/2-1, 1 do
	for chunkZ = -mapSizeInChunks/2, mapSizeInChunks/2-1, 1 do
		for bY = 0, maxWorldHeight do
			for bX = 0, chunkSizeInBlocks do
				for bZ = 0, chunkSizeInBlocks do
					local newBlock
					if bY == 0 then newBlock = blockData:GetBlockFromServer("Stone"):Clone() end
					if bY ~= 0 then newBlock = blockData:GetBlockFromServer("Dirt"):Clone() end
					if bY == maxWorldHeight then newBlock = blockData:GetBlockFromServer("Grass"):Clone() end
					newBlock.Position = deriveBlockPos(chunkX, chunkZ, bY, bX, bZ)
					newBlock.Parent = game.Workspace.WorldHolder
				end
			end
			wait()
		end
	end
end

I want to be able to generate mountains, rivers, caves, etc... How would I go about that, while also keeping it to a fairly quick rate? Right now it's 80-82 seconds to complete.