So I was looking at an article about scripting terrain:
https://developer.roblox.com/en-us/articles/Scripting-With-Terrain
Inside the article, there's a flood fill script:
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)
As you can see in line 12 and line 41, Vector3s are used as indexes of the array after the values are converted to string. I have never seen anything like that. I also tried to do that in roblox studio but got an error. However, the codes work when I copied and pasted into studio, then I tried to print out "current" and got Vector3 value as expected.
Does anyone know how that works? Any help will be appreciated :)
