(DO NOT USE THIS CODE, THIS CODE LOOPS THROUGH EVERY BLOCK OF A CHUNK WHICH IS 98304 BLOCKS FOR 1 CHUNK. I AM CURRENTLY MAKING A NEW ONE)
I made a really basic Minecraft Terrain Generation ModuleScript so that anyone could use it.
Note that it doesn’t include any biomes, structures or trees… Just ground and water.
Preparation
Create 4 main blocks in the workspace: GRASS_BLOCK, DIRT, STONE and WATER
Their names have to be like that.
Create a folder in ServerStorage and rename it “Blocks”.
Select the 4 blocks you created and parent them to that new folder.
Create a new ModuleScript in ServerScriptService and call it “TerrainGenerator”.
Create a new ModuleScript inside that one and call it “Blocks”.
Copy this script and paste it in the “Blocks” ModuleScript:
local folder = game.ServerStorage.Blocks
local blocks = {
AIR = {
transparent = true,
noClip = true
},
DIRT = {
transparent = false,
noClip = false,
block = folder.DIRT
},
GRASS_BLOCK = {
transparent = false,
noClip = false,
block = folder.GRASS_BLOCK
},
STONE = {
transparent = false,
noClip = false,
block = folder.STONE
},
WATER = {
transparent = true,
noClip = true,
block = folder.WATER
},
}
return blocks
And now copy this script and paste it in the “TerrainGenerator” ModuleScript:
local TerrainGenerator = {}
function TerrainGenerator.generate(SEED: number, octaves: number, amplitude: number, frequency: number, sizex: number, sizey: number, sizez: number, startx: number, starty: number, startz: number, blocksize: number, surfacelevel: number, sealevel: number): number
SEED = SEED or Random.new():NextNumber(1, 100000)
octaves = octaves or 4
amplitude = amplitude or 20
frequency = frequency or 50
local startX = startx or 100
local startY = starty or 100
local startZ = startz or 100
startx = startx or 100
starty = starty or 100
startz = startz or 100
sizex = sizex or 16
sizey = sizey or 384
sizez = sizez or 16
blocksize = blocksize or 3
surfacelevel = surfacelevel or 112
sealevel = sealevel or 109
local surfaceY = surfacelevel
local seaY = sealevel
local blocks = require(script.Blocks)
local lowestY = starty
local highestY = starty + sizey * blocksize
local function getBlock(x: number, y: number, z: number): table
surfacelevel = surfaceY
for i = 1, octaves do
surfacelevel += math.noise(x / (frequency / i), z / (frequency / i), SEED) * (amplitude / i)
end
sealevel = seaY
if y-blocksize < surfacelevel and y+blocksize > surfacelevel and y >= surfacelevel then
return blocks.GRASS_BLOCK
elseif y-blocksize < sealevel and y+blocksize > sealevel and y >= sealevel and y > surfacelevel then
blocks.WATER.block.Size = Vector3.new(blocksize, (blocksize / 16) * 14, blocksize)
return blocks.WATER
end
return blocks.AIR
end
local function placeBlock(x: number, y: number, z: number, block: table): Instance
local clone = block.block:Clone()
clone.Position = Vector3.new(x, y, z)
clone.Parent = workspace
return clone
end
local function checkBlocksAround(x: number, y: number, z: number): bool
return getBlock(x + blocksize, y, z).transparent or getBlock(x - blocksize, y, z).transparent or getBlock(x, y, z + blocksize).transparent or getBlock(x, y, z - blocksize).transparent
end
local fillerBlocks = {}
local function fillAir(x: number, y: number, z: number, block: table): nil
if y + blocksize <= highestY then
if not getBlock(x, y + blocksize, z).transparent then
table.insert(fillerBlocks, {x, y, z, blocks.DIRT})
for i, v in fillerBlocks do
placeBlock(v[1], v[2], v[3], v[4])
end
table.clear(fillerBlocks)
else
if (not getBlock(x, y + (blocksize * 3), z).transparent) or (not getBlock(x, y + (blocksize * 2), z).transparent) then
table.insert(fillerBlocks, {x, y, z, blocks.DIRT})
fillAir(x, y + blocksize, z, blocks.DIRT)
return
end
table.insert(fillerBlocks, {x, y, z, blocks.STONE})
fillAir(x, y + blocksize, z, blocks.STONE)
end
else
table.clear(fillerBlocks)
end
end
local function fillWater(x: number, y: number, z: number): nil
if y - blocksize >= lowestY then
if getBlock(x, y - blocksize, z) == blocks.AIR then
placeBlock(x, y - blocksize, z, blocks.WATER)
fillWater(x, y - blocksize, z)
end
end
end
for x = 1, sizex do
for z = 1, sizez do
for y = 1, sizey do
local block = getBlock(startx, starty, startz)
if block == blocks.AIR then
starty += blocksize
continue
end
placeBlock(startx, starty, startz, block)
blocks.WATER.block.Size = Vector3.new(blocksize, blocksize, blocksize)
if block == blocks.GRASS_BLOCK then
fillAir(startx + blocksize, starty + blocksize, startz, blocks.DIRT)
fillAir(startx - blocksize, starty + blocksize, startz, blocks.DIRT)
fillAir(startx, starty + blocksize, startz + blocksize, blocks.DIRT)
fillAir(startx, starty + blocksize, startz - blocksize, blocks.DIRT)
elseif block == blocks.WATER then
fillWater(startx, starty, startz)
end
starty += blocksize
end
starty = startY
startz += blocksize
end
startz = startZ
startx += blocksize
end
return SEED
end
return TerrainGenerator
To use this generator, create a new script in ServerScriptService, and paste this in it:
local terrainGenerator = require(script.Parent.TerrainGenerator)
terrainGenerator.generate()
The terrainGenerator.generate()
function wants 13 arguments:
SEED: number, octaves: number, amplitude: number, frequency: number, sizex: number, sizey: number, sizez: number, startx: number, starty: number, startz: number, blocksize: number, surfacelevel: number, sealevel: number
And returns the SEED: number
If one of these arguments is nil, it defaults to:
SEED: Random.new():NextNumber(1, 100000)
octaves: 4
amplitude: 20
frequency: 50
startx: 100
starty: 100
startz: 100
sizex: 16
sizey: 384
sizez: 16
blocksize: 3
surfacelevel: 112
sealevel: 109