PcoWSkbVqDnWTu_dm2ix
We use cookies on this site to enhance your user experience

Scripting With Terrain: Code Sample 3

Scripting With Terrain: Code Sample 3

Oct 01 2018, 3:15 AM PST

local mouse = game.Players.LocalPlayer:GetMouse()
local terrain = game.Workspace.Terrain
 
local function checkDirection(origin, direction)
	local ray = Ray.new(origin, direction)
	local part, point, normal = game.Workspace:FindPartOnRay(ray, nil, true)
	return part
end
 
local function processDirection(queue, processed, current, direction)
	local nextNode = current + direction
	if not processed[tostring(nextNode)] then
		table.insert(queue, nextNode)
	end
end
 
local function floodFill(voxelPos)
	local region = Region3.new(voxelPos - Vector3.new(2,2,2), voxelPos + Vector3.new(2,2,2))
	local material, occupancy = terrain:ReadVoxels(region, 4)
	if material[1][1][1] ~= Enum.Material.Air then
		print("Could not fill from that voxel: Voxel not empty")
		return
	end
 
	local queue = {}
	local processed = {}
	local success = true
	table.insert(queue, voxelPos)
 
	while #queue > 0 do
		local current = table.remove(queue)
		region = Region3.new(current - Vector3.new(2,2,2), current + Vector3.new(2,2,2))
		material, occupancy = terrain:ReadVoxels(region, 4)
		if material[1][1][1] == Enum.Material.Air then
			if  checkDirection(current, Vector3.new(1000, 0, 0)) and
				checkDirection(current, Vector3.new(-1000, 0, 0)) and
				checkDirection(current, Vector3.new(0, 0, 1000)) and
				checkDirection(current, Vector3.new(0, 0, -1000)) and
				checkDirection(current, Vector3.new(0, -1000, 0)) then			
 
				processed[tostring(current)] = current
 
				processDirection(queue, processed, current, Vector3.new(4,0,0))
				processDirection(queue, processed, current, Vector3.new(-4,0,0))
				processDirection(queue, processed, current, Vector3.new(0,0,4))
				processDirection(queue, processed, current, Vector3.new(0,0,-4))
				processDirection(queue, processed, current, Vector3.new(0,-4,0))
 
			else
				processed = {}
				success = false
				break
			end
		end
	end
 
	if success then
		for _, position in pairs(processed) do
			region = Region3.new(position - Vector3.new(2,2,2), position + Vector3.new(2,2,2))
			material[1][1][1] = Enum.Material.Water
			occupancy[1][1][1] = 1
			terrain:WriteVoxels(region, 4, material, occupancy)
		end
	else
		print("Could not fill from that voxel: Would create infinite fill")
	end
end
 
local function round(num)
	return math.floor(num + .5)
end
 
mouse.Button1Up:Connect(function()
	local hit = mouse.Hit
 
	local x = round(mouse.Hit.p.X)
	x = x - x%4 + 2
	local y = round(mouse.Hit.p.Y)
	y = y - y%4 + 2
	local z = round(mouse.Hit.p.Z)
	z = z - z%4 + 2
 
	floodFill(Vector3.new(x, y, z))
end)