Hey devs!
I’m working on a “VoxelCraft” kind of game and I made a terrain generation module for the game. After I created the terrain generation I tried to make it so grass can spawn on the surface layer of the world.
Whenever I play the game I recieve this error
> ServerScriptService.Modules.TerrainGenerationModule:51: attempt to iterate over a nil value - Server - TerrainGenerationModule:51
The Module:
local TerrainGenerationModule = {}
--====> Terrain Generation Module <====
--// Services
local RS = game:GetService("ReplicatedStorage")
--// Conditions
local BLOCK_SCALE = 2.8
local SEED = 5000
local MAP_SCALE = 100
local MAX_HEIGHT = 25
local MIN_HEIGHT = -25
local FREQUENCY = 10
local AMPLITUDE = 8
local SCALE = 200
local STONE_LEVEL = -10
--[[ NON-PRIVATES ]]--
function TerrainGenerationModule.grass_generation(blocks: {}, surface_y: {}): ({})
local grass = RS.GAME_ITEMS.BLOCKS.Grass
local tallgrass = RS.GAME_ITEMS.BLOCKS.TallGrass
local GRASS_SIZE = grass.PrimaryPart.Size
local width_difference = (BLOCK_SCALE - GRASS_SIZE.X) / 2 * 100
local y_difference = (BLOCK_SCALE - GRASS_SIZE.Y)
for x, x_blocks in blocks do
for z, z_blocks in x_blocks do
if math.random(100) < 25 then
if math.random(100) < 50 then
local grass = grass:Clone()
grass.Parent = game.Workspace.Game
local y_level = surface_y[x][z] + 1
grass:PivotTo(CFrame.new(
(x * BLOCK_SCALE + math.random(-width_difference, width_difference) / 100),
(y_level * 3 - y_difference / 2),
(z * BLOCK_SCALE + math.random(-width_difference, width_difference) / 100))
)
blocks[x][z][y_level] = "Grass"
else
local grass = tallgrass:Clone()
grass.Parent = game.Workspace.Game
local y_level = surface_y[x][z] + 1
grass:PivotTo(CFrame.new(
(x * BLOCK_SCALE + math.random(-width_difference, width_difference) / 100),
(y_level * 3 - y_difference / 2),
(z * BLOCK_SCALE + math.random(-width_difference, width_difference) / 100))
)
blocks[x][z][y_level] = "Grass"
end
end
end
return x_blocks, surface_y, blocks
end
end
function TerrainGenerationModule.surface_generation(seed): ({}, {})
local blocks = {}
local surface_y = {}
for x = 1, MAP_SCALE, 1 do
blocks[x] = {}
surface_y[x] = {}
for z = 1, MAP_SCALE, 1 do
blocks[x][z] = {}
local y = math.floor(
math.noise((x /SCALE) * FREQUENCY, (z / SCALE) * FREQUENCY, seed) * AMPLITUDE
)
local block = RS:WaitForChild("GAME_ITEMS").BLOCKS.GrassBlock:Clone()
block.Parent = game.Workspace:WaitForChild("Game")
block.Position = Vector3.new(x * BLOCK_SCALE, y * BLOCK_SCALE, z * BLOCK_SCALE)
surface_y[x][z] = y
blocks[x][z][y] = block
end
end
return blocks, surface_y
end
return TerrainGenerationModule
The Server Script
--// Services
local SSS = game:GetService("ServerScriptService")
--// Shortcuts
local MODULE_FOLDER = SSS:WaitForChild("Modules")
--// Modules
local TerrainGeneration = require(MODULE_FOLDER.TerrainGenerationModule)
--[[ RUN FUNCTIONS ]]--
TerrainGeneration.surface_generation()
TerrainGeneration.grass_generation()
Thanks for reading, I hope you are able to help!