I need help with my game

Hi,

I am currently working on a minecraft clone and I wanna know how to make it so water that you can swim in will generate in certain places in the world with the rest of it.

Here are my world generation scripts:

Main Script:


local WorldGenerator = require(script:GetCustomProperty('WorldGenerator'))

_G.Blocks = {}

WorldGenerator.Generate(0,50,0,50)

Block Table Script


local blocks = {}

blocks['Dirt'] = {template = script:GetCustomProperty('Dirt')}
blocks['Grass'] = {template = script:GetCustomProperty('Grass')}
blocks['Stone'] = {template = script:GetCustomProperty('Stone')}

blocks['Air'] = {template = nil}

return blocks

Perlin Noise Script:

perlin = {}

perlin.p = {}
perlin.permutation = { 151,160,137,91,90,15,
   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
}

function shuffle(tbl)
    for i = #tbl, 2, -1 do
      local j = math.random(i)
      tbl[i], tbl[j] = tbl[j], tbl[i]
    end
    return tbl
end

perlin.permutation = shuffle(perlin.permutation)
perlin.size = 256
perlin.gx = {}
perlin.gy = {}
perlin.randMax = 256

function perlin:load(  )
    for i=1,self.size do
        self.p[i] = self.permutation[i]
        self.p[256+i] = self.p[i]
    end
end

function perlin:noise( x, y, z, s )
    x = (x / (100*s))  + 0.001
    y = (y / (100*s)) + 0.001
    z = (z / (100*s)) + 0.001
    local X = math.floor(x) % 256
    local Y = math.floor(y) % 256
    local Z = math.floor(z) % 256
    x = x - math.floor(x)
    y = y - math.floor(y)
    z = z - math.floor(z)
    local u = fade(x)
    local v = fade(y)
    local w = fade(z)
    local A  = self.p[X+1]+Y
    local AA = self.p[A+1]+Z
    local AB = self.p[A+2]+Z
    local B  = self.p[X+2]+Y
    local BA = self.p[B+1]+Z
    local BB = self.p[B+2]+Z

    return lerp(w, lerp(v, lerp(u, grad(self.p[AA+1], x  , y  , z  ),
                                   grad(self.p[BA+1], x-1, y  , z  )),
                           lerp(u, grad(self.p[AB+1], x  , y-1, z  ),
                                   grad(self.p[BB+1], x-1, y-1, z  ))),
                   lerp(v, lerp(u, grad(self.p[AB+2], x  , y  , z-1),
                                   grad(self.p[BA+2], x-1, y  , z-1)),
                           lerp(u, grad(self.p[AB+2], x  , y-1, z-1),
                                   grad(self.p[BB+2], x-1, y-1, z-1))))
end

function fade( t )
    return t * t * t * (t * (t * 6 - 15) + 10)
end

function lerp( t, a, b )
    return a + t * (b - a)
end

function grad( hash, x, y, z )
    local h = hash % 16
    local u = h < 8 and x or y
    local v = h < 4 and y or ((h == 12 or h == 14) and x or z)
    return ((h % 2) == 0 and u or -u) + ((h % 3) == 0 and v or -v)
end

perlin:load()  

return perlin

World Generator Script:

local perlinNoise = require(script:GetCustomProperty('PerlinLIB'))
local blockTable = require(script:GetCustomProperty('BlockTable'))

local WorldGenerator = {}

local xStart = 0
local xEnd = 0
local yStart = 0
local yEnd = 0

local maxHeight = 32
local maxDown = -16

local caveScale = 0.08
local caveSpawnRate = -0.3
local entranceSpawnRate = -0.7

function WorldGenerator.Generate(xStartP, xEndP, yStartP, yEndP)

    xStart = xStartP
    xEnd = xEndP
    yStart = yStartP
    yEnd = yEndP

    for x = xStart - 1, xEnd + 1 do
        _G.Blocks[x] = {}
        for y = yStart - 1, yEnd + 1 do
            _G.Blocks[x][y] = {}
            if x < xStart or x > xEnd or y < yStart or y > yEnd then
                for z = maxDown - 1, maxHeight + 1 do
                    if not _G.Blocks[x][y][z] then
                        _G.Blocks[x][y][z] = {blockInfo = blockTable['Air'], isSpawned = true}
                    end
                end
            else
                local height = math.floor(perlinNoise:noise(x,y,0,0.1) * 10)


                for z = maxDown, height do
                    local shouldSpawn = (perlinNoise:noise((x + 999) / 2, (y + 999) / 4, z, caveScale) > caveSpawnRate) and (perlinNoise:noise((x + 999) / 4, (y + 999) / 2, z, caveScale) > caveSpawnRate) and  (perlinNoise:noise((x + 999) / 2, (y + 999) / 2, z / 4, caveScale) > caveSpawnRate)                
                    local shouldSpawnEntrance = (perlinNoise:noise((x + 999) / 2, (y + 999) / 4, z, caveScale) > entranceSpawnRate) and (perlinNoise:noise((x + 999) / 4, (y + 999) / 2, z, caveScale) > entranceSpawnRate) and  (perlinNoise:noise((x + 999) / 2, (y + 999) / 2, z / 4, caveScale) > entranceSpawnRate)

                    if z == height - 1 then
                        if shouldSpawnEntrance then
                            _G.Blocks[x][y][z] = {blockInfo = blockTable['Grass'], isSpawned = false}
                        else
                            _G.Blocks[x][y][z] = {blockInfo = blockTable['Air'], isSpawned = true}
                        end
                    elseif z >= height - 3 then 
                        if shouldSpawnEntrance then
                            _G.Blocks[x][y][z] = {blockInfo = blockTable['Dirt'], isSpawned = false}
                        else
                            _G.Blocks[x][y][z] = {blockInfo = blockTable['Air'], isSpawned = true}
                        end
                
                    elseif z == maxDown then
                        _G.Blocks[x][y][z] = {blockInfo = blockTable['Stone'], isSpawned = false}
                    else
                        if shouldSpawn then
                            _G.Blocks[x][y][z] = {blockInfo = blockTable['Stone'], isSpawned = false}
                        else
                            _G.Blocks[x][y][z] = {blockInfo = blockTable['Air'], isSpawned = true}
                        end
                    end
                end

                for z = height, maxHeight do
                    _G.Blocks[x][y][z] = {blockInfo = blockTable['Air'], isSpawned = true}
                end
            end
            if math.random(1,3) == 1 then
                Task.Wait()
            end
        end
        Task.Wait()
    end
    WorldGenerator.SpawnBlocks()
end



function WorldGenerator.isBlockSurrounded(x,y,z)
    if x == xStart or y == yStart or x == xEnd or y == yEnd or z == maxHeight or z == maxDown then
        return false
    end
    if _G.Blocks[x+1][y][z].blockInfo.template == nil then
        return false
    elseif _G.Blocks[x-1][y][z].blockInfo.template == nil then
        return false
    elseif _G.Blocks[x][y+1][z].blockInfo.template == nil then
        return false
    elseif _G.Blocks[x][y-1][z].blockInfo.template == nil then
        return false
    elseif _G.Blocks[x][y][z+1].blockInfo.template == nil then
        return false
    elseif _G.Blocks[x][y][z-1].blockInfo.template == nil then
        return false
    end
    return true
end

function WorldGenerator.SpawnSurroundingBlocks(x,y,z)
    if _G.Blocks[x+1][y][z].blockInfo.template ~= nil and not _G.Blocks[x+1][y][z].isSpawned then
        WorldGenerator.SpawnBlock(x+1,y,z,_G.Blocks[x+1][y][z].blockInfo.template)
    end
    if _G.Blocks[x-1][y][z].blockInfo.template ~= nil and not _G.Blocks[x-1][y][z].isSpawned then
        WorldGenerator.SpawnBlock(x-1,y,z,_G.Blocks[x-1][y][z].blockInfo.template)
    end
    if _G.Blocks[x][y+1][z].blockInfo.template ~= nil and not _G.Blocks[x][y+1][z].isSpawned then
        WorldGenerator.SpawnBlock(x,y+1,z,_G.Blocks[x][y+1][z].blockInfo.template)
    end
    if _G.Blocks[x][y-1][z].blockInfo.template ~= nil and not _G.Blocks[x][y-1][z].isSpawned then
        WorldGenerator.SpawnBlock(x,y-1,z,_G.Blocks[x][y-1][z].blockInfo.template)
    end
    if _G.Blocks[x][y][z+1].blockInfo.template ~= nil and not _G.Blocks[x][y][z+1].isSpawned then
        WorldGenerator.SpawnBlock(x,y,z+1,_G.Blocks[x][y][z+1].blockInfo.template)
    end
    if _G.Blocks[x][y][z-1].blockInfo.template ~= nil and not _G.Blocks[x][y][z-1].isSpawned then
        WorldGenerator.SpawnBlock(x,y,z-1,_G.Blocks[x][y][z-1].blockInfo.template)
    end
end


function WorldGenerator.SpawnBlocks()
    for x = xStart, xEnd do
        for y = yStart, yEnd do
            for z = maxDown, maxHeight do
                if not WorldGenerator.isBlockSurrounded(x,y,z) then
                    if _G.Blocks[x][y][z].blockInfo.template ~= nil then
                        WorldGenerator.SpawnBlock(x,y,z,_G.Blocks[x][y][z].blockInfo.template)
                    end
                end
            end
        end
        Task.Wait()
    end
end

function WorldGenerator.SpawnBlock(x,y,z,block)
    local block = World.SpawnAsset(block, {position = Vector3.New(x,y,z) * 100})
    _G.Blocks[x][y][z].isSpawned = true
end

return WorldGenerator

If you want to make a volume swimmable then you need to use the Underwater Post Process volume. I guess you could add one of these to your block template, but I have no idea how that will perform for a large number.

First generate your ground and air blocks as normal.

To determine where to put the water you need to define first where your water volume(s) are, this will depend on factors such as: Do you want all water to have the same surface height (e.g. as island with some lakes and rivers) or isolated lakes at different heights in a mountain range? Do you want water underground?

If we take the easiest, all water one level and not underground, then you just look for air blocks in that volume that do not have ground blocks above them. Once you have turned these to water, turn all air blocks with line of sight to water blocks above them to water (this will ensure your seas go down to the ocean floor, but any caverns are not flooded).

Additional observations:
Your code does not appear to chunk and you will need to. Be aware that blocks (voxels) will be very numerous, very quickly. An area just 100 x 100 x 100 is 1 million blocks.... Core has hard limits on how many instructions you can perform per second, and this does not lend itself well to computationally intensive events (e.g. voxel generation). I recommend you do some tests on a representative size world before committing too much effort to this.

Are you able to give me some example code? cuz i'm pretty new to core (this is not my first time coding btw i have experience from roblox)

I'm sorry I don't mind looking over something that doesn't work, but I don't have time to write a water system for you. You could try asking on the discord server to see what others have to offer.

ok sounds good i go to the discord server